KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > awt > LineGraph3D


1 package JSci.awt;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import java.util.Arrays JavaDoc;
6
7 /**
8 * A 3D line graph AWT component.
9 * @author Daniel Lemire
10 */

11 public final class LineGraph3D extends DoubleBufferedCanvas
12   implements Runnable JavaDoc, MouseListener, MouseMotionListener, GraphDataListener {
13     protected Graph3DModel model;
14     private Model3D md;
15     private boolean painted = true;
16     private float xfac;
17     private int prevx, prevy;
18     private float xtheta, ytheta;
19     private float scalefudge = 1.0f;
20     private Matrix3D amat = new Matrix3D();
21     private Matrix3D tmat = new Matrix3D();
22     private String JavaDoc mdname = null;
23     private String JavaDoc message = null;
24
25         /**
26         * Constructs a 3D line graph.
27         */

28     public LineGraph3D(Graph3DModel data) {
29       amat.yRotate(20);
30       amat.xRotate(20);
31       setSize(getSize().width <= 20 ? 400 : getSize().width,
32              getSize().height <= 20 ? 400 : getSize().height);
33       addMouseListener(this);
34       addMouseMotionListener(this);
35       setModel(data);
36     }
37
38
39     /**
40     * Sets the data plotted by this graph to the specified data.
41     */

42     public void setModel(Graph3DModel gm) {
43             if(model!=null)
44               model.removeGraphDataListener(this);
45             model=gm;
46             model.addGraphDataListener(this);
47             dataChanged(new GraphDataEvent(model));
48     }
49
50         /**
51         * Implementation of GraphDataListener.
52         * Application code will not use this method explicitly, it is used internally.
53         */

54     public void dataChanged(GraphDataEvent e) {
55       md=new Model3D();
56       model.firstSeries();
57       for(int k=0;k<model.seriesLength();k++) {
58         md.addVertex(model.getXCoord(k),model.getYCoord(k),model.getZCoord(k));
59       }
60       for(int k=1;k<model.seriesLength();k++) {
61         md.addLine(k-1,k);
62       }
63       redraw();
64       new Thread JavaDoc(this).start();
65     }
66
67     public void run() {
68       try {
69           md.findBoundingBox();
70           md.compress();
71           float xw = md.xmax - md.xmin;
72           float yw = md.ymax - md.ymin;
73           float zw = md.zmax - md.zmin;
74           if (yw > xw)
75         xw = yw;
76           if (zw > xw)
77         xw = zw;
78           float f1 = getSize().width / xw;
79           float f2 = getSize().height / xw;
80           xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
81       } catch(Exception JavaDoc e) {
82           md = null;
83           message = e.toString();
84           e.printStackTrace();
85       }
86         repaint();
87     }
88
89     public void mouseClicked(MouseEvent e) {
90     }
91     public void mousePressed(MouseEvent e) {
92         prevx = e.getX();
93         prevy = e.getY();
94         e.consume();
95     }
96     public void mouseReleased(MouseEvent e) {
97     }
98     public void mouseEntered(MouseEvent e) {
99     }
100     public void mouseExited(MouseEvent e) {
101     }
102     public void mouseDragged(MouseEvent e) {
103       int x = e.getX();
104       int y = e.getY();
105       if((e.getModifiers() & MouseEvent.BUTTON3_MASK)!=0) {
106         if(prevy==y)
107           return; //don't need to do anything
108
scalefudge+=(prevy-y)/(float)getSize().width;
109         if(scalefudge==0)
110           scalefudge=0.1f;//arbitrary
111
float xw = md.xmax - md.xmin;
112         float yw = md.ymax - md.ymin;
113         float zw = md.zmax - md.zmin;
114         if (yw > xw)
115           xw = yw;
116         if (zw > xw)
117           xw = zw;
118         float f1 = getSize().width / xw;
119         float f2 = getSize().height / xw;
120         xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
121
122       }
123       if((e.getModifiers() & MouseEvent.BUTTON1_MASK)!=0) {
124           tmat.identity();
125           float xtheta = (prevy - y) * 360.0f / getSize().width;
126           float ytheta = (x - prevx) * 360.0f / getSize().height;
127           tmat.xRotate(xtheta);
128           tmat.yRotate(ytheta);
129           amat.multiply(tmat);
130       }
131       if (painted) {
132           painted = false;
133           redraw();
134       }
135       prevx = x;
136       prevy = y;
137       e.consume();
138
139     }
140
141     public void mouseMoved(MouseEvent e) {
142     }
143         /**
144         * Paint the graph.
145         */

146         protected void offscreenPaint(Graphics g) {
147                 if (md != null) {
148 // System.out.println("painting");
149
md.mat.identity();
150                         md.mat.translate(-(md.xmin + md.xmax) / 2,
151                                 -(md.ymin + md.ymax) / 2,
152                                 -(md.zmin + md.zmax) / 2);
153                         md.mat.multiply(amat);
154                         md.mat.scale(xfac, -xfac, 16 * xfac / getSize().width);
155                         md.mat.translate(getSize().width / 2, getSize().height / 2, 8);
156                         md.transformed = false;
157                         md.paint(g);
158 // System.out.println("painting done");
159
setPainted();
160                 } else if (message != null) {
161                         g.drawString("Error in model:", 3, 20);
162                         g.drawString(message, 10, 40);
163                 }
164         }
165         /**
166         * Returns the preferred size of this component.
167         */

168         public Dimension getPreferredSize() {
169                 return getMinimumSize();
170         }
171         /**
172         * Returns the minimum size of this component.
173         */

174         public Dimension getMinimumSize() {
175                 return new Dimension(400,400);
176         }
177
178     private synchronized void setPainted() {
179         painted = true;
180         notifyAll();
181     }
182 }
183
184 class Model3D {
185         private static Color greys[];
186         float vert[];
187         int tvert[];
188         int nvert, maxvert;
189         int con[];
190         int ncon, maxcon;
191         boolean transformed;
192         Matrix3D mat;
193         float xmin, xmax, ymin, ymax, zmin, zmax;
194         private float axes[]=new float[18];
195         private int taxes[]=new int[18];
196
197         static {
198                 greys=new Color[16];
199                 int gr;
200                 for(int i=0;i<greys.length;i++) {
201                         gr=(int)(170.0*(1.0-Math.pow(i/15.0,2.3)));
202                         greys[i]=new Color(gr,gr,gr);
203                 }
204         }
205
206     Model3D() {
207     mat=new Matrix3D();
208     mat.xRotate(20);
209     mat.yRotate(30);
210     }
211
212     /** Add a vertex to this model */
213     int addVertex(float x, float y, float z) {
214     int i = nvert;
215     if (i >= maxvert)
216         if (vert == null) {
217         maxvert = 100;
218         vert = new float[maxvert * 3];
219         } else {
220         maxvert *= 2;
221         float nv[] = new float[maxvert * 3];
222         System.arraycopy(vert, 0, nv, 0, vert.length);
223         vert = nv;
224         }
225     i *= 3;
226     vert[i] = x;
227     vert[i + 1] = y;
228     vert[i + 2] = z;
229 // System.out.println("added a vertex "+nvert);
230
return nvert++;
231     }
232     /** Add a line from vertex p1 to vertex p2 */
233     void addLine(int p1, int p2) {
234     int i = ncon;
235     if (p1 >= nvert || p2 >= nvert) {
236 // System.out.println("Line from "+p1+" to "+p2+" will not be drawn. ("+nvert+")");
237
return;
238   }
239     if (i >= maxcon)
240         if (con == null) {
241         maxcon = 100;
242         con = new int[maxcon];
243         } else {
244         maxcon *= 2;
245         int nv[] = new int[maxcon];
246         System.arraycopy(con, 0, nv, 0, con.length);
247         con = nv;
248         }
249     if (p1 > p2) {
250         int t = p1;
251         p1 = p2;
252         p2 = t;
253     }
254     con[i] = (p1 << 16) | p2;
255     ncon = i + 1;
256     }
257     /** Transform all the points in this model */
258     void transform() {
259     if (transformed || nvert <= 0)
260         return;
261         mat.transform(axes,taxes,6);
262     if (tvert == null || tvert.length < nvert * 3)
263         tvert = new int[nvert*3];
264     mat.transform(vert, tvert, nvert);
265     transformed = true;
266     }
267
268     /** eliminate duplicate lines */
269     void compress() {
270     int limit = ncon;
271     int c[] = con;
272     Arrays.sort(con, 0, ncon);
273     int d = 0;
274     int pp1 = -1;
275     for (int i = 0; i < limit; i++) {
276         int p1 = c[i];
277         if (pp1 != p1) {
278         c[d] = p1;
279         d++;
280         }
281         pp1 = p1;
282     }
283     ncon = d;
284     }
285
286     void paint(Graphics g) {
287 // System.out.println("painting model 3D");
288
if (vert == null || nvert <= 0)
289           return;
290         transform();
291         Color lastGrey=null;
292         int lim = ncon;
293         int c[] = con;
294         int v[] = tvert;
295 // System.out.println(lim+" "+nvert);
296
if (lim <= 0 || nvert <= 0)
297           return;
298 // draw axes
299
int a[]=taxes;
300                 g.setColor(depthColor(a[2],a[5]));
301                 g.drawLine(a[0],a[1],a[3],a[4]);
302                 g.setColor(depthColor(a[8],a[11]));
303                 g.drawLine(a[6],a[7],a[9],a[10]);
304                 g.setColor(depthColor(a[14],a[17]));
305                 g.drawLine(a[12],a[13],a[15],a[16]);
306 // draw points
307
int T,p1,p2;
308                 Color grey;
309                 for(int i=0;i<lim;i++) {
310                         T=c[i];
311                         p1=((T >> 16) & 0xFFFF)*3;
312                         p2=(T & 0xFFFF)*3;
313                         grey=depthColor(v[p1+2],v[p2+2]);
314                         if(grey!=lastGrey) {
315                                 lastGrey=grey;
316                                 g.setColor(grey);
317                         }
318 // System.out.println("drawing line "+v[p1]+" "+v[p1 + 1]+" "+v[p2]+" "+v[p2 + 1]);
319
g.drawLine(v[p1], v[p1 + 1],v[p2], v[p2 + 1]);
320                 }
321         }
322         /**
323         * Converts z coordinates to shades of grey.
324         * @param z1 z coord of start of line.
325         * @param z2 z coord of end of line.
326         */

327         private Color depthColor(int z1,int z2) {
328                 int gr=z1+z2;
329                 if(gr<0)
330                         gr=0;
331                 else if(gr>15)
332                         gr=15;
333                 return greys[gr];
334         }
335
336     /** Find the bounding box of this model */
337     void findBoundingBox() {
338     if (nvert <= 0)
339         return;
340     float v[] = vert;
341     float xmin = v[0], xmax = xmin;
342     float ymin = v[1], ymax = ymin;
343     float zmin = v[2], zmax = zmin;
344     for (int i = nvert * 3; (i -= 3) > 0;) {
345         float x = v[i];
346         if (x < xmin)
347         xmin = x;
348         if (x > xmax)
349         xmax = x;
350         float y = v[i + 1];
351         if (y < ymin)
352         ymin = y;
353         if (y > ymax)
354         ymax = y;
355         float z = v[i + 2];
356         if (z < zmin)
357         zmin = z;
358         if (z > zmax)
359         zmax = z;
360     }
361     this.xmax = xmax;
362     this.xmin = xmin;
363     this.ymax = ymax;
364     this.ymin = ymin;
365     this.zmax = zmax;
366     this.zmin = zmin;
367         axes[0]=xmax;
368         axes[3]=xmin;
369         axes[7]=ymax;
370         axes[10]=ymin;
371         axes[14]=zmax;
372         axes[17]=zmin;
373     }
374 }
375
376 final class Matrix3D {
377     float xx, xy, xz, xo;
378     float yx, yy, yz, yo;
379     float zx, zy, zz, zo;
380     /** Create a new identity matrix */
381     Matrix3D () {
382     xx = 1.0f;
383     yy = 1.0f;
384     zz = 1.0f;
385     }
386     /** Scale by f in all dimensions */
387     void scale(float f) {
388     xx *= f;
389     xy *= f;
390     xz *= f;
391     xo *= f;
392     yx *= f;
393     yy *= f;
394     yz *= f;
395     yo *= f;
396     zx *= f;
397     zy *= f;
398     zz *= f;
399     zo *= f;
400     }
401     /** Scale along each axis independently */
402     void scale(float xf, float yf, float zf) {
403     xx *= xf;
404     xy *= xf;
405     xz *= xf;
406     xo *= xf;
407     yx *= yf;
408     yy *= yf;
409     yz *= yf;
410     yo *= yf;
411     zx *= zf;
412     zy *= zf;
413     zz *= zf;
414     zo *= zf;
415     }
416     /** Translate the origin */
417     void translate(float x, float y, float z) {
418     xo += x;
419     yo += y;
420     zo += z;
421     }
422     /** rotate theta degrees about the y axis */
423     void yRotate(double theta) {
424     theta *= (Math.PI / 180.0);
425     double ct = Math.cos(theta);
426     double st = Math.sin(theta);
427
428     float Nxx = (float) (xx * ct + zx * st);
429     float Nxy = (float) (xy * ct + zy * st);
430     float Nxz = (float) (xz * ct + zz * st);
431     float Nxo = (float) (xo * ct + zo * st);
432
433     float Nzx = (float) (zx * ct - xx * st);
434     float Nzy = (float) (zy * ct - xy * st);
435     float Nzz = (float) (zz * ct - xz * st);
436     float Nzo = (float) (zo * ct - xo * st);
437
438     xo = Nxo;
439     xx = Nxx;
440     xy = Nxy;
441     xz = Nxz;
442     zo = Nzo;
443     zx = Nzx;
444     zy = Nzy;
445     zz = Nzz;
446     }
447     /** rotate theta degrees about the x axis */
448     void xRotate(double theta) {
449     theta *= (Math.PI / 180.0);
450     double ct = Math.cos(theta);
451     double st = Math.sin(theta);
452
453     float Nyx = (float) (yx * ct + zx * st);
454     float Nyy = (float) (yy * ct + zy * st);
455     float Nyz = (float) (yz * ct + zz * st);
456     float Nyo = (float) (yo * ct + zo * st);
457
458     float Nzx = (float) (zx * ct - yx * st);
459     float Nzy = (float) (zy * ct - yy * st);
460     float Nzz = (float) (zz * ct - yz * st);
461     float Nzo = (float) (zo * ct - yo * st);
462
463     yo = Nyo;
464     yx = Nyx;
465     yy = Nyy;
466     yz = Nyz;
467     zo = Nzo;
468     zx = Nzx;
469     zy = Nzy;
470     zz = Nzz;
471     }
472     /** rotate theta degrees about the z axis */
473     void zRotate(double theta) {
474     theta *= (Math.PI / 180.0);
475     double ct = Math.cos(theta);
476     double st = Math.sin(theta);
477
478     float Nyx = (float) (yx * ct + xx * st);
479     float Nyy = (float) (yy * ct + xy * st);
480     float Nyz = (float) (yz * ct + xz * st);
481     float Nyo = (float) (yo * ct + xo * st);
482
483     float Nxx = (float) (xx * ct - yx * st);
484     float Nxy = (float) (xy * ct - yy * st);
485     float Nxz = (float) (xz * ct - yz * st);
486     float Nxo = (float) (xo * ct - yo * st);
487
488     yo = Nyo;
489     yx = Nyx;
490     yy = Nyy;
491     yz = Nyz;
492     xo = Nxo;
493     xx = Nxx;
494     xy = Nxy;
495     xz = Nxz;
496     }
497     /** Multiply this matrix by a second: M = M*R */
498     void multiply(Matrix3D rhs) {
499     float lxx = xx * rhs.xx + yx * rhs.xy + zx * rhs.xz;
500     float lxy = xy * rhs.xx + yy * rhs.xy + zy * rhs.xz;
501     float lxz = xz * rhs.xx + yz * rhs.xy + zz * rhs.xz;
502     float lxo = xo * rhs.xx + yo * rhs.xy + zo * rhs.xz + rhs.xo;
503
504     float lyx = xx * rhs.yx + yx * rhs.yy + zx * rhs.yz;
505     float lyy = xy * rhs.yx + yy * rhs.yy + zy * rhs.yz;
506     float lyz = xz * rhs.yx + yz * rhs.yy + zz * rhs.yz;
507     float lyo = xo * rhs.yx + yo * rhs.yy + zo * rhs.yz + rhs.yo;
508
509     float lzx = xx * rhs.zx + yx * rhs.zy + zx * rhs.zz;
510     float lzy = xy * rhs.zx + yy * rhs.zy + zy * rhs.zz;
511     float lzz = xz * rhs.zx + yz * rhs.zy + zz * rhs.zz;
512     float lzo = xo * rhs.zx + yo * rhs.zy + zo * rhs.zz + rhs.zo;
513
514     xx = lxx;
515     xy = lxy;
516     xz = lxz;
517     xo = lxo;
518
519     yx = lyx;
520     yy = lyy;
521     yz = lyz;
522     yo = lyo;
523
524     zx = lzx;
525     zy = lzy;
526     zz = lzz;
527     zo = lzo;
528     }
529
530     /** Reinitialize to the identity matrix */
531     void identity() {
532     xo = 0;
533     xx = 1;
534     xy = 0;
535     xz = 0;
536     yo = 0;
537     yx = 0;
538     yy = 1;
539     yz = 0;
540     zo = 0;
541     zx = 0;
542     zy = 0;
543     zz = 1;
544     }
545     /** Transform nvert points from v into tv. v contains the input
546         coordinates in floating point. Three successive entries in
547     the array constitute a point. tv ends up holding the transformed
548     points as integers; three successive entries per point */

549     void transform(float v[], int tv[], int nvert) {
550     float lxx = xx, lxy = xy, lxz = xz, lxo = xo;
551     float lyx = yx, lyy = yy, lyz = yz, lyo = yo;
552     float lzx = zx, lzy = zy, lzz = zz, lzo = zo;
553     for (int i = nvert * 3; (i -= 3) >= 0;) {
554         float x = v[i];
555         float y = v[i + 1];
556         float z = v[i + 2];
557         tv[i ] = (int) (x * lxx + y * lxy + z * lxz + lxo);
558         tv[i + 1] = (int) (x * lyx + y * lyy + z * lyz + lyo);
559         tv[i + 2] = (int) (x * lzx + y * lzy + z * lzz + lzo);
560     }
561     }
562     public String JavaDoc toString() {
563     return ("[" + xo + "," + xx + "," + xy + "," + xz + ";"
564         + yo + "," + yx + "," + yy + "," + yz + ";"
565         + zo + "," + zx + "," + zy + "," + zz + "]");
566     }
567 }
568
569
Popular Tags