view src/samer/maths/VectorPlotter.java @ 8:5e3cbbf173aa tip

Reorganise some more
author samer
date Fri, 05 Apr 2019 22:41:58 +0100
parents bf79fb79ee13
children
line wrap: on
line source
/*
 *	VectorPlotter.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 java.util.*;
import java.awt.*;
import java.awt.event.*;
import samer.core.*;
import samer.core.util.*;
import samer.core.Agent.*;
import samer.tools.*;

/**
	A Viewer that draws a variety of graphs from data in a vector
  */

public class VectorPlotter extends Plotter implements Agent, Observer
{
	private Vec			vector;
	private boolean	autoscale=false;
	private int			type;
	private Pen			pen;
	private VMap		vmap=new VMap(ymap);

	Observable	obs;
	Node			node=null;

	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 VectorPlotter(Observable o, Vec s) { this(o); setVec(s); }
	protected VectorPlotter(Observable o)
	{
		obs=o;
		node=Shell.env().node();

		type = Shell.getInt("type",LINE);
		setAxes( XAXIS); // no Y axis please
		// pen = getPen();

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

		// attach commands from this agent to this Viewer
		exposeCommands( this);
		exposeCommands( vmap);
	}

	public Dimension getPreferredSize() {
		int cx=Shell.getInt("cell.width",Shell.getInt("cell.size",2));
		return new Dimension(cx*vector.size(),96);
	}
	protected void realized() { super.realized(); attach(); }

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

	public void update(Observable o, Object s)
	{
		if (s==this) return; // &&&
		if (s==Viewable.DISPOSING) {
			Shell.releaseViewer(this);
		} else if (obs==o) {
			if (autoscale) scale();
			repaint();
		} else if (o==vmap) {
			if (s==VMap.NEW_MAP) ymap = vmap.getMap();
			if (autoscale) scale(); repaint();
		}
	}

	public void attach() { obs.addObserver(this); }
	public void detach()
	{
		obs.deleteObserver(this);
		super.detach();
	}

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

	public void getCommands(Registry r)
	{
		r.add("line",type==LINE)
			.add("box",type==CLOSED)
			.add("fill",type==FILL)
			.add("fill3d",type==FILL3D)
			.add("steps",type==STEPS);
		r.add("scale").add("autoscale",autoscale);
		r.group(); r.add("publish");
	}

	public void execute(String c, Environment env) throws Exception
	{
		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(); }
		} else if (c.equals("publish"))
			Shell.put(X.string(env.datum(),"plotter"),this);
	}

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

	public void setVec( Vec v) 
	{ 
		vector = v; 
		xmap.setDomain(0,vector.size()); 
		if (autoscale) scale();
	}

	public void scale()
	{
		double	max, min, x;
	
		Vec.Iterator i=vector.iterator();
		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);
	}

	public void update(Graphics g) {
		g.clearRect(0,0,width,height);
		paint(g);
	}
	
	public void paint( Graphics g)
	{
		Vec.Iterator i=vector.iterator();

		super.paint(g); // draw axes or whatever
		pen=getPen(g);
		// pen.assert();

		switch (type) {

			case LINE:

				pen.moveto(0,i.next());
				for (int j=1; i.more(); j++) {
					pen.lineto(j,i.next());
				}
				break;

			case FILL3D:

				for (int j=0; i.more(); j++) {
					pen.moveto(j,0);
					pen.abs(j+1,i.next()).rectify();
					pen.fill3DRect(true);
				}
				break;

			case FILL:

				for (int j=0; i.more(); j++) {
					pen.moveto(j,0);
					pen.abs(j+1,i.next()).rectify();
					pen.fillRect();
				}
				break;

			case STEPS:

				pen.moveto(0,i.next());
				for (int j=1; i.more(); j++) {
					pen.rel(1,0).lineto();
					pen.abs(j,i.next()).lineto();
				}
				pen.rel(1,0).lineto();
				break;

			case CLOSED:

				for (int j=0; i.more(); j++) {
					pen.moveto(j,0);
					pen.abs(j+1,i.next()).rectify();
					pen.rect();
				}
				break;

		}
	}
}