view src/samer/maths/FunctionPlotter.java @ 5:b67a33c44de7

Remove some crap, etc
author samer
date Fri, 05 Apr 2019 21:34:25 +0100
parents bf79fb79ee13
children
line wrap: on
line source
/*
 *	FunctionPlotter.java	
 *
 *	Copyright (c) 2000, Samer Abdallah, King's College London.
 *	All rights reserved.
 *
 *	This software is provided AS iS and WITHOUT ANY WARRANTY; 
 *	without even the implied warranty of MERCHANTABILITY or 
 *	FITNESS FOR A PARTICULAR PURPOSE.
 */

package samer.maths;

import samer.maths.Vec.Iterator;
import samer.core.*;
import samer.core.util.*;
import samer.core.types.*;
import samer.core.Agent.*;
import samer.tools.*;
import java.util.*;
import java.awt.*;

public class FunctionPlotter extends Plotter implements Agent, Observer
{
	private VFunction	vfunc;
	private VMap		vmap, xvmap;
	private boolean	autoscale=false;
	private int			type;
	private Pen			pen;
	private int w, h;

	Node		node=null;
	int		numPoints;

	public final static int LINE=0;
	public final static int STEP=1;
	public final static int FILL=2;
	public final static int FILL3D=3;
	public final static int CLOSED=4;
	public final static int STEPS=5;
											  
	public FunctionPlotter(VFunction vf) 
	{ 
		vfunc=vf; 
		node=Shell.env().node(); 

		w = Shell.getInt("width",240);
		h = Shell.getInt("height",120);
		type = Shell.getInt("type", LINE);

		setAxes( XAXIS|YAXIS); 
		// pen = getPen();

		Shell.push("y");
		vmap=new VMap(ymap);
		Shell.pop();

		Shell.push("x");
		xvmap=new VMap(xmap);
		Shell.pop();

		vmap.addObserver(this);
		xvmap.addObserver(this);
		ymap = vmap.getMap();
		xmap = xvmap.getMap();

		numPoints = Shell.getInt("numpoints",256);

		// attach commands from this agent to this Viewer
		exposeCommands( this);
		exposeCommands( vmap);
		exposeCommands( xvmap);
		Shell.registerAgent(this);
	}

	protected void realized() 
	{ 
		super.realized();
		vfunc.addObserver(this);
	}

	// .............. Viewer bits .............................

	public void update(Observable o, Object s) 
	{ 
		if (s==this) return; // &&&
		if (s==Viewable.DISPOSING) {
			Shell.releaseViewer(this);
		} else if (o==vmap) {	
			if (s==VMap.NEW_MAP) ymap = vmap.getMap();
			autoscale(); repaint();
		} else if (o==xvmap) {	
			if (s==VMap.NEW_MAP) xmap = xvmap.getMap();
			autoscale(); repaint();
		} else if (vfunc==o) {
			autoscale(); repaint();
		}
	}
 
	public void detach()
	{
		Shell.deregisterAgent(this);
		if (node!=null) { node=null; }
		if (vfunc!=null) { vfunc.deleteObserver(this); vfunc=null; }
		super.detach();
	}

	// .............. Agent bits ..............................

	public void getCommands(Registry r)
	{	
		r.add("update").add("points");
		r.add("line").add("box").add("fill").add("fill3d").add("steps");
		r.add("scale").add("autoscale",autoscale);
	}

	public void execute(String c, Environment env) throws Exception
	{
		if      (c.equals("points"))	{ numPoints=X._int(env.datum(),numPoints); repaint(); }
		else if (c.equals("line"))		{ type=LINE; repaint(); }
		else if (c.equals("box"))		{ type=CLOSED; repaint(); }
		else if (c.equals("fill"))		{ type=FILL; repaint(); }
		else if (c.equals("fill3d"))	{ type=FILL3D; repaint(); }
		else if (c.equals("steps"))	{ type=STEPS; repaint(); }
		else if (c.equals("scale"))	{ scale(); repaint(); }
		else if (c.equals("autoscale")) {
			autoscale = X._bool(env.datum(),!autoscale);
			if (autoscale) { scale(); repaint(); }
		}
	}

	private class FunctionIterator implements Iterator {
		int i=0, n=numPoints;
		double x=xmap.inverse(0);
		double dx=(xmap.inverse(1)-x)/n;
		Function function=vfunc.getFunction();

		public boolean more() { return i<=n; }
		public double  next() { 
			double y=function.apply(x); 
			x+=dx; i++; return y;
		}
	}

	// ................ functionality ...........................

	public void autoscale() { if (autoscale) scale(); }
	public void scale()
	{
		double	max, min, x;

		Iterator i=new FunctionIterator();

		min=max=i.next();
		while (i.more()) {
			x=i.next();
			if (x>max) max=x;
			if (x<min) min=x;
		}

		if (ymap instanceof LinearMap) {
			// leave some space
			double delta=max-min;
			min -= 0.1*delta;
			max += 0.1*delta;
		} else if (ymap instanceof LogMap) {	
			// somewhat arbitrarily...			
			if (min==0) min=max/10000;
		}

		vmap.setDomain(min,max);
		vmap.changed(this);
	}

	synchronized public void paint( Graphics g)
	{
		super.paint(g); // draw axes or whatever

		FunctionIterator i=new FunctionIterator();
		double	x, y;

		pen=getPen(g);
		// pen.assert();
		switch (type) {

			case LINE:

				x=i.x;
				pen.moveto(x,i.next());
				while (i.more()) {
					x=i.x;
					pen.lineto(x,i.next());
				}
				break;

			case FILL3D:

				while (i.more()) {
					pen.moveto(i.x,0); y=i.next();
					pen.abs(i.x,y).rectify();
					pen.fill3DRect(true);
				}
				break;

			case FILL:

				while (i.more()) {
					pen.moveto(i.x,0); y=i.next();
					pen.abs(i.x,y).rectify();
					pen.fillRect();
				}
				break;

		}
	}

	public Dimension getPreferredSize() {
		return new Dimension(w,h);
	}
}