1 package JSci.swing; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 import java.util.Arrays ; 7 8 import JSci.awt.*; 9 10 14 public final class JLineGraph3D extends JDoubleBufferedComponent 15 implements Runnable , MouseListener, MouseMotionListener, GraphDataListener { 16 17 protected Graph3DModel model; 18 private Model3D md; 19 private boolean painted = true; 20 private float xfac; 21 private int prevx, prevy; 22 private float xtheta, ytheta; 23 private float scalefudge = 1.0f; 24 private Matrix3D amat = new Matrix3D(); 25 private Matrix3D tmat = new Matrix3D(); 26 private String mdname = null; 27 private String message = null; 28 29 32 public JLineGraph3D(Graph3DModel data) { 33 amat.yRotate(20); 34 amat.xRotate(20); 35 setSize(getWidth() <= 20 ? 400 : getWidth(), 36 getHeight() <= 20 ? 400 : getHeight()); 37 addMouseListener(this); 38 addMouseMotionListener(this); 39 setModel(data); 40 } 41 42 43 46 public void setModel(Graph3DModel gm) { 47 if(model!=null) 48 model.removeGraphDataListener(this); 49 model=gm; 50 model.addGraphDataListener(this); 51 dataChanged(new GraphDataEvent(model)); 52 } 53 54 58 public void dataChanged(GraphDataEvent e) { 59 md=new Model3D(); 60 model.firstSeries(); 61 for(int k=0;k<model.seriesLength();k++) { 62 md.addVertex(model.getXCoord(k),model.getYCoord(k),model.getZCoord(k)); 63 } 64 for(int k=1;k<model.seriesLength();k++) { 65 md.addLine(k-1,k); 66 } 67 redraw(); 68 new Thread (this).start(); 69 } 70 71 public void run() { 72 try { 73 md.findBoundingBox(); 74 md.compress(); 75 float xw = md.xmax - md.xmin; 76 float yw = md.ymax - md.ymin; 77 float zw = md.zmax - md.zmin; 78 if (yw > xw) 79 xw = yw; 80 if (zw > xw) 81 xw = zw; 82 float f1 = getWidth() / xw; 83 float f2 = getHeight() / xw; 84 xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge; 85 } catch(Exception e) { 86 md = null; 87 message = e.toString(); 88 e.printStackTrace(); 89 } 90 repaint(); 91 } 92 93 public void mouseClicked(MouseEvent e) { 94 } 95 96 public void mousePressed(MouseEvent e) { 97 prevx = e.getX(); 98 prevy = e.getY(); 99 e.consume(); 100 } 101 102 public void mouseReleased(MouseEvent e) { 103 } 104 105 public void mouseEntered(MouseEvent e) { 106 } 107 108 public void mouseExited(MouseEvent e) { 109 } 110 111 public void mouseDragged(MouseEvent e) { 112 int x = e.getX(); 113 int y = e.getY(); 114 if((e.getModifiers() & MouseEvent.BUTTON3_MASK)!=0) { 115 if(prevy==y) 116 return; scalefudge+=(prevy-y)/(float)getWidth(); 118 if(scalefudge==0) 119 scalefudge=0.1f; float xw = md.xmax - md.xmin; 121 float yw = md.ymax - md.ymin; 122 float zw = md.zmax - md.zmin; 123 if (yw > xw) 124 xw = yw; 125 if (zw > xw) 126 xw = zw; 127 float f1 = getWidth() / xw; 128 float f2 = getHeight() / xw; 129 xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge; 130 131 } 132 if((e.getModifiers() & MouseEvent.BUTTON1_MASK)!=0) { 133 tmat.identity(); 134 float xtheta = (prevy - y) * 360.0f / getWidth(); 135 float ytheta = (x - prevx) * 360.0f / getHeight(); 136 tmat.xRotate(xtheta); 137 tmat.yRotate(ytheta); 138 amat.multiply(tmat); 139 } 140 if (painted) { 141 painted = false; 142 redraw(); 143 } 144 prevx = x; 145 prevy = y; 146 e.consume(); 147 148 } 149 150 public void mouseMoved(MouseEvent e) { 151 } 152 155 protected void offscreenPaint(Graphics g) { 156 if (md != null) { 157 md.mat.identity(); 159 md.mat.translate(-(md.xmin + md.xmax) / 2, 160 -(md.ymin + md.ymax) / 2, 161 -(md.zmin + md.zmax) / 2); 162 md.mat.multiply(amat); 163 md.mat.scale(xfac, -xfac, 16 * xfac / getWidth()); 164 md.mat.translate(getWidth() / 2, getHeight() / 2, 8); 165 md.transformed = false; 166 md.paint(g); 167 setPainted(); 169 } else if (message != null) { 170 g.drawString("Error in model:", 3, 20); 171 g.drawString(message, 10, 40); 172 } 173 } 174 177 public Dimension getPreferredSize() { 178 return getMinimumSize(); 179 } 180 183 public Dimension getMinimumSize() { 184 return new Dimension(400,400); 185 } 186 187 private synchronized void setPainted() { 188 painted = true; 189 notifyAll(); 190 } 191 } 192 193 class Model3D { 194 private static Color greys[]; 195 float vert[]; 196 int tvert[]; 197 int nvert, maxvert; 198 int con[]; 199 int ncon, maxcon; 200 boolean transformed; 201 Matrix3D mat; 202 float xmin, xmax, ymin, ymax, zmin, zmax; 203 private float axes[]=new float[18]; 204 private int taxes[]=new int[18]; 205 206 static { 207 greys=new Color[16]; 208 int gr; 209 for(int i=0;i<greys.length;i++) { 210 gr=(int)(170.0*(1.0-Math.pow(i/15.0,2.3))); 211 greys[i]=new Color(gr,gr,gr); 212 } 213 } 214 215 Model3D() { 216 mat = new Matrix3D(); 217 mat.xRotate(20); 218 mat.yRotate(30); 219 } 220 221 222 223 int addVertex(float x, float y, float z) { 224 int i = nvert; 225 if (i >= maxvert) 226 if (vert == null) { 227 maxvert = 100; 228 vert = new float[maxvert * 3]; 229 } else { 230 maxvert *= 2; 231 float nv[] = new float[maxvert * 3]; 232 System.arraycopy(vert, 0, nv, 0, vert.length); 233 vert = nv; 234 } 235 i *= 3; 236 vert[i] = x; 237 vert[i + 1] = y; 238 vert[i + 2] = z; 239 return nvert++; 241 } 242 243 void addLine(int p1, int p2) { 244 int i = ncon; 245 if (p1 >= nvert || p2 >= nvert) { 246 return; 248 } 249 if (i >= maxcon) 250 if (con == null) { 251 maxcon = 100; 252 con = new int[maxcon]; 253 } else { 254 maxcon *= 2; 255 int nv[] = new int[maxcon]; 256 System.arraycopy(con, 0, nv, 0, con.length); 257 con = nv; 258 } 259 if (p1 > p2) { 260 int t = p1; 261 p1 = p2; 262 p2 = t; 263 } 264 con[i] = (p1 << 16) | p2; 265 ncon = i + 1; 266 } 267 268 void transform() { 269 if (transformed || nvert <= 0) 270 return; 271 mat.transform(axes,taxes,6); 272 if (tvert == null || tvert.length < nvert * 3) 273 tvert = new int[nvert*3]; 274 mat.transform(vert, tvert, nvert); 275 transformed = true; 276 } 277 278 279 void compress() { 280 int limit = ncon; 281 int c[] = con; 282 Arrays.sort(con, 0, ncon); 283 int d = 0; 284 int pp1 = -1; 285 for (int i = 0; i < limit; i++) { 286 int p1 = c[i]; 287 if (pp1 != p1) { 288 c[d] = p1; 289 d++; 290 } 291 pp1 = p1; 292 } 293 ncon = d; 294 } 295 296 void paint(Graphics g) { 297 299 if (vert == null || nvert <= 0) 300 return; 301 transform(); 302 Color lastGrey=null; 303 int lim = ncon; 304 int c[] = con; 305 int v[] = tvert; 306 if (lim <= 0 || nvert <= 0) 308 return; 309 int a[]=taxes; 311 g.setColor(depthColor(a[2],a[5])); 312 g.drawLine(a[0],a[1],a[3],a[4]); 313 g.setColor(depthColor(a[8],a[11])); 314 g.drawLine(a[6],a[7],a[9],a[10]); 315 g.setColor(depthColor(a[14],a[17])); 316 g.drawLine(a[12],a[13],a[15],a[16]); 317 int T,p1,p2; 319 Color grey; 320 for (int i = 0; i < lim; i++) { 321 T = c[i]; 322 p1 = ((T >> 16) & 0xFFFF) * 3; 323 p2 = (T & 0xFFFF) * 3; 324 grey=depthColor(v[p1+2],v[p2+2]); 325 if (grey != lastGrey) { 326 lastGrey = grey; 327 g.setColor(grey); 328 } 329 g.drawLine(v[p1], v[p1 + 1],v[p2], v[p2 + 1]); 331 } 332 } 333 338 private Color depthColor(int z1,int z2) { 339 int gr=z1+z2; 340 if(gr<0) 341 gr=0; 342 else if(gr>15) 343 gr=15; 344 return greys[gr]; 345 } 346 347 348 void findBoundingBox() { 349 if (nvert <= 0) 350 return; 351 float v[] = vert; 352 float xmin = v[0], xmax = xmin; 353 float ymin = v[1], ymax = ymin; 354 float zmin = v[2], zmax = zmin; 355 for (int i = nvert * 3; (i -= 3) > 0;) { 356 float x = v[i]; 357 if (x < xmin) 358 xmin = x; 359 if (x > xmax) 360 xmax = x; 361 float y = v[i + 1]; 362 if (y < ymin) 363 ymin = y; 364 if (y > ymax) 365 ymax = y; 366 float z = v[i + 2]; 367 if (z < zmin) 368 zmin = z; 369 if (z > zmax) 370 zmax = z; 371 } 372 this.xmax = xmax; 373 this.xmin = xmin; 374 this.ymax = ymax; 375 this.ymin = ymin; 376 this.zmax = zmax; 377 this.zmin = zmin; 378 axes[0]=xmax; 379 axes[3]=xmin; 380 axes[7]=ymax; 381 axes[10]=ymin; 382 axes[14]=zmax; 383 axes[17]=zmin; 384 } 385 } 386 387 class Matrix3D { 388 float xx, xy, xz, xo; 389 float yx, yy, yz, yo; 390 float zx, zy, zz, zo; 391 392 Matrix3D () { 393 xx = 1.0f; 394 yy = 1.0f; 395 zz = 1.0f; 396 } 397 398 void scale(float f) { 399 xx *= f; 400 xy *= f; 401 xz *= f; 402 xo *= f; 403 yx *= f; 404 yy *= f; 405 yz *= f; 406 yo *= f; 407 zx *= f; 408 zy *= f; 409 zz *= f; 410 zo *= f; 411 } 412 413 void scale(float xf, float yf, float zf) { 414 xx *= xf; 415 xy *= xf; 416 xz *= xf; 417 xo *= xf; 418 yx *= yf; 419 yy *= yf; 420 yz *= yf; 421 yo *= yf; 422 zx *= zf; 423 zy *= zf; 424 zz *= zf; 425 zo *= zf; 426 } 427 428 void translate(float x, float y, float z) { 429 xo += x; 430 yo += y; 431 zo += z; 432 } 433 434 void yRotate(double theta) { 435 theta *= (Math.PI / 180.0); 436 double ct = Math.cos(theta); 437 double st = Math.sin(theta); 438 439 float Nxx = (float) (xx * ct + zx * st); 440 float Nxy = (float) (xy * ct + zy * st); 441 float Nxz = (float) (xz * ct + zz * st); 442 float Nxo = (float) (xo * ct + zo * st); 443 444 float Nzx = (float) (zx * ct - xx * st); 445 float Nzy = (float) (zy * ct - xy * st); 446 float Nzz = (float) (zz * ct - xz * st); 447 float Nzo = (float) (zo * ct - xo * st); 448 449 xo = Nxo; 450 xx = Nxx; 451 xy = Nxy; 452 xz = Nxz; 453 zo = Nzo; 454 zx = Nzx; 455 zy = Nzy; 456 zz = Nzz; 457 } 458 459 void xRotate(double theta) { 460 theta *= (Math.PI / 180.0); 461 double ct = Math.cos(theta); 462 double st = Math.sin(theta); 463 464 float Nyx = (float) (yx * ct + zx * st); 465 float Nyy = (float) (yy * ct + zy * st); 466 float Nyz = (float) (yz * ct + zz * st); 467 float Nyo = (float) (yo * ct + zo * st); 468 469 float Nzx = (float) (zx * ct - yx * st); 470 float Nzy = (float) (zy * ct - yy * st); 471 float Nzz = (float) (zz * ct - yz * st); 472 float Nzo = (float) (zo * ct - yo * st); 473 474 yo = Nyo; 475 yx = Nyx; 476 yy = Nyy; 477 yz = Nyz; 478 zo = Nzo; 479 zx = Nzx; 480 zy = Nzy; 481 zz = Nzz; 482 } 483 484 void zRotate(double theta) { 485 theta *= (Math.PI / 180.0); 486 double ct = Math.cos(theta); 487 double st = Math.sin(theta); 488 489 float Nyx = (float) (yx * ct + xx * st); 490 float Nyy = (float) (yy * ct + xy * st); 491 float Nyz = (float) (yz * ct + xz * st); 492 float Nyo = (float) (yo * ct + xo * st); 493 494 float Nxx = (float) (xx * ct - yx * st); 495 float Nxy = (float) (xy * ct - yy * st); 496 float Nxz = (float) (xz * ct - yz * st); 497 float Nxo = (float) (xo * ct - yo * st); 498 499 yo = Nyo; 500 yx = Nyx; 501 yy = Nyy; 502 yz = Nyz; 503 xo = Nxo; 504 xx = Nxx; 505 xy = Nxy; 506 xz = Nxz; 507 } 508 509 void multiply(Matrix3D rhs) { 510 float lxx = xx * rhs.xx + yx * rhs.xy + zx * rhs.xz; 511 float lxy = xy * rhs.xx + yy * rhs.xy + zy * rhs.xz; 512 float lxz = xz * rhs.xx + yz * rhs.xy + zz * rhs.xz; 513 float lxo = xo * rhs.xx + yo * rhs.xy + zo * rhs.xz + rhs.xo; 514 515 float lyx = xx * rhs.yx + yx * rhs.yy + zx * rhs.yz; 516 float lyy = xy * rhs.yx + yy * rhs.yy + zy * rhs.yz; 517 float lyz = xz * rhs.yx + yz * rhs.yy + zz * rhs.yz; 518 float lyo = xo * rhs.yx + yo * rhs.yy + zo * rhs.yz + rhs.yo; 519 520 float lzx = xx * rhs.zx + yx * rhs.zy + zx * rhs.zz; 521 float lzy = xy * rhs.zx + yy * rhs.zy + zy * rhs.zz; 522 float lzz = xz * rhs.zx + yz * rhs.zy + zz * rhs.zz; 523 float lzo = xo * rhs.zx + yo * rhs.zy + zo * rhs.zz + rhs.zo; 524 525 xx = lxx; 526 xy = lxy; 527 xz = lxz; 528 xo = lxo; 529 530 yx = lyx; 531 yy = lyy; 532 yz = lyz; 533 yo = lyo; 534 535 zx = lzx; 536 zy = lzy; 537 zz = lzz; 538 zo = lzo; 539 } 540 541 542 void identity() { 543 xo = 0; 544 xx = 1; 545 xy = 0; 546 xz = 0; 547 yo = 0; 548 yx = 0; 549 yy = 1; 550 yz = 0; 551 zo = 0; 552 zx = 0; 553 zy = 0; 554 zz = 1; 555 } 556 560 void transform(float v[], int tv[], int nvert) { 561 float lxx = xx, lxy = xy, lxz = xz, lxo = xo; 562 float lyx = yx, lyy = yy, lyz = yz, lyo = yo; 563 float lzx = zx, lzy = zy, lzz = zz, lzo = zo; 564 for (int i = nvert * 3; (i -= 3) >= 0;) { 565 float x = v[i]; 566 float y = v[i + 1]; 567 float z = v[i + 2]; 568 tv[i ] = (int) (x * lxx + y * lxy + z * lxz + lxo); 569 tv[i + 1] = (int) (x * lyx + y * lyy + z * lyz + lyo); 570 tv[i + 2] = (int) (x * lzx + y * lzy + z * lzz + lzo); 571 } 572 } 573 public String toString() { 574 return ("[" + xo + "," + xx + "," + xy + "," + xz + ";" 575 + yo + "," + yx + "," + yy + "," + yz + ";" 576 + zo + "," + zx + "," + zy + "," + zz + "]"); 577 } 578 } 579 580 | Popular Tags |