samer@0
|
1 /*
|
samer@0
|
2 * VectorPlotter.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2000, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 */
|
samer@0
|
11
|
samer@0
|
12 package samer.maths;
|
samer@0
|
13
|
samer@0
|
14 import java.util.*;
|
samer@0
|
15 import java.awt.*;
|
samer@0
|
16 import java.awt.event.*;
|
samer@0
|
17 import samer.core.*;
|
samer@0
|
18 import samer.core.util.*;
|
samer@0
|
19 import samer.core.Agent.*;
|
samer@0
|
20 import samer.tools.*;
|
samer@0
|
21
|
samer@0
|
22 /**
|
samer@0
|
23 A Viewer that draws a variety of graphs from data in a vector
|
samer@0
|
24 */
|
samer@0
|
25
|
samer@0
|
26 public class VectorPlotter extends Plotter implements Agent, Observer
|
samer@0
|
27 {
|
samer@0
|
28 private Vec vector;
|
samer@0
|
29 private boolean autoscale=false;
|
samer@0
|
30 private int type;
|
samer@0
|
31 private Pen pen;
|
samer@0
|
32 private VMap vmap=new VMap(ymap);
|
samer@0
|
33
|
samer@0
|
34 Observable obs;
|
samer@0
|
35 Node node=null;
|
samer@0
|
36
|
samer@0
|
37 public final static int LINE=0;
|
samer@0
|
38 public final static int STEP=1;
|
samer@0
|
39 public final static int FILL=2;
|
samer@0
|
40 public final static int FILL3D=3;
|
samer@0
|
41 public final static int CLOSED=4;
|
samer@0
|
42 public final static int STEPS=5;
|
samer@0
|
43
|
samer@0
|
44 public VectorPlotter(Observable o, Vec s) { this(o); setVec(s); }
|
samer@0
|
45 protected VectorPlotter(Observable o)
|
samer@0
|
46 {
|
samer@0
|
47 obs=o;
|
samer@0
|
48 node=Shell.env().node();
|
samer@0
|
49
|
samer@0
|
50 type = Shell.getInt("type",LINE);
|
samer@0
|
51 setAxes( XAXIS); // no Y axis please
|
samer@0
|
52 // pen = getPen();
|
samer@0
|
53
|
samer@0
|
54 vmap.addObserver(this);
|
samer@0
|
55 ymap = vmap.getMap();
|
samer@0
|
56
|
samer@0
|
57 // attach commands from this agent to this Viewer
|
samer@0
|
58 exposeCommands( this);
|
samer@0
|
59 exposeCommands( vmap);
|
samer@0
|
60 }
|
samer@0
|
61
|
samer@0
|
62 public Dimension getPreferredSize() {
|
samer@0
|
63 int cx=Shell.getInt("cell.width",Shell.getInt("cell.size",2));
|
samer@0
|
64 return new Dimension(cx*vector.size(),96);
|
samer@0
|
65 }
|
samer@0
|
66 protected void realized() { super.realized(); attach(); }
|
samer@0
|
67
|
samer@0
|
68 // .............. Viewer bits .............................
|
samer@0
|
69
|
samer@0
|
70 public void update(Observable o, Object s)
|
samer@0
|
71 {
|
samer@0
|
72 if (s==this) return; // &&&
|
samer@0
|
73 if (s==Viewable.DISPOSING) {
|
samer@0
|
74 Shell.releaseViewer(this);
|
samer@0
|
75 } else if (obs==o) {
|
samer@0
|
76 if (autoscale) scale();
|
samer@0
|
77 repaint();
|
samer@0
|
78 } else if (o==vmap) {
|
samer@0
|
79 if (s==VMap.NEW_MAP) ymap = vmap.getMap();
|
samer@0
|
80 if (autoscale) scale(); repaint();
|
samer@0
|
81 }
|
samer@0
|
82 }
|
samer@0
|
83
|
samer@0
|
84 public void attach() { obs.addObserver(this); }
|
samer@0
|
85 public void detach()
|
samer@0
|
86 {
|
samer@0
|
87 obs.deleteObserver(this);
|
samer@0
|
88 super.detach();
|
samer@0
|
89 }
|
samer@0
|
90
|
samer@0
|
91 // .............. Agent bits ..............................
|
samer@0
|
92
|
samer@0
|
93 public void getCommands(Registry r)
|
samer@0
|
94 {
|
samer@0
|
95 r.add("line",type==LINE)
|
samer@0
|
96 .add("box",type==CLOSED)
|
samer@0
|
97 .add("fill",type==FILL)
|
samer@0
|
98 .add("fill3d",type==FILL3D)
|
samer@0
|
99 .add("steps",type==STEPS);
|
samer@0
|
100 r.add("scale").add("autoscale",autoscale);
|
samer@0
|
101 r.group(); r.add("publish");
|
samer@0
|
102 }
|
samer@0
|
103
|
samer@0
|
104 public void execute(String c, Environment env) throws Exception
|
samer@0
|
105 {
|
samer@0
|
106 if (c.equals("line")) { type=LINE; repaint(); }
|
samer@0
|
107 else if (c.equals("box")) { type=CLOSED; repaint(); }
|
samer@0
|
108 else if (c.equals("fill")) { type=FILL; repaint(); }
|
samer@0
|
109 else if (c.equals("fill3d")) { type=FILL3D; repaint(); }
|
samer@0
|
110 else if (c.equals("steps")) { type=STEPS; repaint(); }
|
samer@0
|
111 else if (c.equals("scale")) { scale(); repaint(); }
|
samer@0
|
112 else if (c.equals("autoscale")) {
|
samer@0
|
113 autoscale = X._bool(env.datum(),!autoscale);
|
samer@0
|
114 if (autoscale) { scale(); repaint(); }
|
samer@0
|
115 } else if (c.equals("publish"))
|
samer@0
|
116 Shell.put(X.string(env.datum(),"plotter"),this);
|
samer@0
|
117 }
|
samer@0
|
118
|
samer@0
|
119 // ................ functionality ...........................
|
samer@0
|
120
|
samer@0
|
121 public void setVec( Vec v)
|
samer@0
|
122 {
|
samer@0
|
123 vector = v;
|
samer@0
|
124 xmap.setDomain(0,vector.size());
|
samer@0
|
125 if (autoscale) scale();
|
samer@0
|
126 }
|
samer@0
|
127
|
samer@0
|
128 public void scale()
|
samer@0
|
129 {
|
samer@0
|
130 double max, min, x;
|
samer@0
|
131
|
samer@0
|
132 Vec.Iterator i=vector.iterator();
|
samer@0
|
133 min=max=i.next();
|
samer@0
|
134 while (i.more()) {
|
samer@0
|
135 x=i.next();
|
samer@0
|
136 if (x>max) max=x;
|
samer@0
|
137 if (x<min) min=x;
|
samer@0
|
138 }
|
samer@0
|
139
|
samer@0
|
140 if (ymap instanceof LinearMap) {
|
samer@0
|
141 // leave some space
|
samer@0
|
142 double delta=max-min;
|
samer@0
|
143 min -= 0.1*delta;
|
samer@0
|
144 max += 0.1*delta;
|
samer@0
|
145 } else if (ymap instanceof LogMap) {
|
samer@0
|
146 // somewhat arbitrarily...
|
samer@0
|
147 if (min==0) min=max/10000;
|
samer@0
|
148 }
|
samer@0
|
149
|
samer@0
|
150 vmap.setDomain(min,max);
|
samer@0
|
151 vmap.changed(this);
|
samer@0
|
152 }
|
samer@0
|
153
|
samer@0
|
154 public void update(Graphics g) {
|
samer@0
|
155 g.clearRect(0,0,width,height);
|
samer@0
|
156 paint(g);
|
samer@0
|
157 }
|
samer@0
|
158
|
samer@0
|
159 public void paint( Graphics g)
|
samer@0
|
160 {
|
samer@0
|
161 Vec.Iterator i=vector.iterator();
|
samer@0
|
162
|
samer@0
|
163 super.paint(g); // draw axes or whatever
|
samer@0
|
164 pen=getPen(g);
|
samer@0
|
165 // pen.assert();
|
samer@0
|
166
|
samer@0
|
167 switch (type) {
|
samer@0
|
168
|
samer@0
|
169 case LINE:
|
samer@0
|
170
|
samer@0
|
171 pen.moveto(0,i.next());
|
samer@0
|
172 for (int j=1; i.more(); j++) {
|
samer@0
|
173 pen.lineto(j,i.next());
|
samer@0
|
174 }
|
samer@0
|
175 break;
|
samer@0
|
176
|
samer@0
|
177 case FILL3D:
|
samer@0
|
178
|
samer@0
|
179 for (int j=0; i.more(); j++) {
|
samer@0
|
180 pen.moveto(j,0);
|
samer@0
|
181 pen.abs(j+1,i.next()).rectify();
|
samer@0
|
182 pen.fill3DRect(true);
|
samer@0
|
183 }
|
samer@0
|
184 break;
|
samer@0
|
185
|
samer@0
|
186 case FILL:
|
samer@0
|
187
|
samer@0
|
188 for (int j=0; i.more(); j++) {
|
samer@0
|
189 pen.moveto(j,0);
|
samer@0
|
190 pen.abs(j+1,i.next()).rectify();
|
samer@0
|
191 pen.fillRect();
|
samer@0
|
192 }
|
samer@0
|
193 break;
|
samer@0
|
194
|
samer@0
|
195 case STEPS:
|
samer@0
|
196
|
samer@0
|
197 pen.moveto(0,i.next());
|
samer@0
|
198 for (int j=1; i.more(); j++) {
|
samer@0
|
199 pen.rel(1,0).lineto();
|
samer@0
|
200 pen.abs(j,i.next()).lineto();
|
samer@0
|
201 }
|
samer@0
|
202 pen.rel(1,0).lineto();
|
samer@0
|
203 break;
|
samer@0
|
204
|
samer@0
|
205 case CLOSED:
|
samer@0
|
206
|
samer@0
|
207 for (int j=0; i.more(); j++) {
|
samer@0
|
208 pen.moveto(j,0);
|
samer@0
|
209 pen.abs(j+1,i.next()).rectify();
|
samer@0
|
210 pen.rect();
|
samer@0
|
211 }
|
samer@0
|
212 break;
|
samer@0
|
213
|
samer@0
|
214 }
|
samer@0
|
215 }
|
samer@0
|
216 }
|