1 package JSci.awt; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.Arrays ; 6 7 11 public final class LineGraph3D extends DoubleBufferedCanvas 12 implements Runnable , 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 mdname = null; 23 private String message = null; 24 25 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 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 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 (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 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; scalefudge+=(prevy-y)/(float)getSize().width; 109 if(scalefudge==0) 110 scalefudge=0.1f; 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 146 protected void offscreenPaint(Graphics g) { 147 if (md != null) { 148 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 setPainted(); 160 } else if (message != null) { 161 g.drawString("Error in model:", 3, 20); 162 g.drawString(message, 10, 40); 163 } 164 } 165 168 public Dimension getPreferredSize() { 169 return getMinimumSize(); 170 } 171 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 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 return nvert++; 231 } 232 233 void addLine(int p1, int p2) { 234 int i = ncon; 235 if (p1 >= nvert || p2 >= nvert) { 236 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 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 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 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 if (lim <= 0 || nvert <= 0) 297 return; 298 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 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 g.drawLine(v[p1], v[p1 + 1],v[p2], v[p2 + 1]); 320 } 321 } 322 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 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 381 Matrix3D () { 382 xx = 1.0f; 383 yy = 1.0f; 384 zz = 1.0f; 385 } 386 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 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 417 void translate(float x, float y, float z) { 418 xo += x; 419 yo += y; 420 zo += z; 421 } 422 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 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 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 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 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 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 toString() { 563 return ("[" + xo + "," + xx + "," + xy + "," + xz + ";" 564 + yo + "," + yx + "," + yy + "," + yz + ";" 565 + zo + "," + zx + "," + zy + "," + zz + "]"); 566 } 567 } 568 569 | Popular Tags |