1 36 37 40 41 45 46 import java.applet.Applet ; 47 import java.awt.Image ; 48 import java.awt.Event ; 49 import java.awt.Graphics ; 50 import java.awt.Dimension ; 51 import java.io.*; 52 import java.net.URL ; 53 import java.util.Hashtable ; 54 import java.awt.image.IndexColorModel ; 55 import java.awt.image.ColorModel ; 56 import java.awt.image.MemoryImageSource ; 57 import java.awt.event.*; 58 59 60 class XYZChemModel { 61 float vert[]; 62 Atom atoms[]; 63 int tvert[]; 64 int ZsortMap[]; 65 int nvert, maxvert; 66 67 static Hashtable atomTable = new Hashtable (); 68 static Atom defaultAtom; 69 static { 70 atomTable.put("c", new Atom(0, 0, 0)); 71 atomTable.put("h", new Atom(210, 210, 210)); 72 atomTable.put("n", new Atom(0, 0, 255)); 73 atomTable.put("o", new Atom(255, 0, 0)); 74 atomTable.put("p", new Atom(255, 0, 255)); 75 atomTable.put("s", new Atom(255, 255, 0)); 76 atomTable.put("hn", new Atom(150, 255, 150)); 77 defaultAtom = new Atom(255, 100, 200); 78 } 79 80 boolean transformed; 81 Matrix3D mat; 82 83 float xmin, xmax, ymin, ymax, zmin, zmax; 84 85 86 XYZChemModel () { 87 mat = new Matrix3D(); 88 mat.xrot(20); 89 mat.yrot(30); 90 } 91 92 93 94 XYZChemModel (InputStream is) throws Exception ![JavaDoc](../cmn/javadoc.gif) 95 { 96 this(); 97 StreamTokenizer st = new StreamTokenizer( 98 new BufferedReader(new InputStreamReader(is, "UTF-8"))); 99 st.eolIsSignificant(true); 100 st.commentChar('#'); 101 int slot = 0; 102 103 try 104 { 105 scan: 106 while (true) 107 { 108 switch ( st.nextToken() ) 109 { 110 case StreamTokenizer.TT_EOF: 111 break scan; 112 default: 113 break; 114 case StreamTokenizer.TT_WORD: 115 String name = st.sval; 116 double x = 0, y = 0, z = 0; 117 if (st.nextToken() == StreamTokenizer.TT_NUMBER) 118 { 119 x = st.nval; 120 if (st.nextToken() == StreamTokenizer.TT_NUMBER) 121 { 122 y = st.nval; 123 if (st.nextToken() == StreamTokenizer.TT_NUMBER) 124 z = st.nval; 125 } 126 } 127 addVert(name, (float) x, (float) y, (float) z); 128 while( st.ttype != StreamTokenizer.TT_EOL && 129 st.ttype != StreamTokenizer.TT_EOF ) 130 st.nextToken(); 131 132 } 134 } 136 is.close(); 137 138 } catch( IOException e) {} 140 141 if (st.ttype != StreamTokenizer.TT_EOF) 142 throw new Exception (st.toString()); 143 144 } 146 147 int addVert(String name, float x, float y, float z) { 148 int i = nvert; 149 if (i >= maxvert) 150 if (vert == null) { 151 maxvert = 100; 152 vert = new float[maxvert * 3]; 153 atoms = new Atom[maxvert]; 154 } else { 155 maxvert *= 2; 156 float nv[] = new float[maxvert * 3]; 157 System.arraycopy(vert, 0, nv, 0, vert.length); 158 vert = nv; 159 Atom na[] = new Atom[maxvert]; 160 System.arraycopy(atoms, 0, na, 0, atoms.length); 161 atoms = na; 162 } 163 Atom a = (Atom) atomTable.get(name.toLowerCase()); 164 if (a == null) a = defaultAtom; 165 atoms[i] = a; 166 i *= 3; 167 vert[i] = x; 168 vert[i + 1] = y; 169 vert[i + 2] = z; 170 return nvert++; 171 } 172 173 174 void transform() { 175 if (transformed || nvert <= 0) 176 return; 177 if (tvert == null || tvert.length < nvert * 3) 178 tvert = new int[nvert * 3]; 179 mat.transform(vert, tvert, nvert); 180 transformed = true; 181 } 182 183 184 188 void paint(Graphics g) { 189 if (vert == null || nvert <= 0) 190 return; 191 transform(); 192 int v[] = tvert; 193 int zs[] = ZsortMap; 194 if (zs == null) { 195 ZsortMap = zs = new int[nvert]; 196 for (int i = nvert; --i >= 0;) 197 zs[i] = i * 3; 198 } 199 200 206 207 for (int i = nvert - 1; --i >= 0;) { 208 boolean flipped = false; 209 for (int j = 0; j <= i; j++) { 210 int a = zs[j]; 211 int b = zs[j + 1]; 212 if (v[a + 2] > v[b + 2]) { 213 zs[j + 1] = a; 214 zs[j] = b; 215 flipped = true; 216 } 217 } 218 if (!flipped) 219 break; 220 } 221 222 int lg = 0; 223 int lim = nvert; 224 Atom ls[] = atoms; 225 if (lim <= 0 || nvert <= 0) 226 return; 227 for (int i = 0; i < lim; i++) { 228 int j = zs[i]; 229 int grey = v[j + 2]; 230 if (grey < 0) 231 grey = 0; 232 if (grey > 15) 233 grey = 15; 234 atoms[j/3].paint(g, v[j], v[j + 1], grey); 236 } 239 } 240 241 242 void findBB() { 243 if (nvert <= 0) 244 return; 245 float v[] = vert; 246 float xmin = v[0], xmax = xmin; 247 float ymin = v[1], ymax = ymin; 248 float zmin = v[2], zmax = zmin; 249 for (int i = nvert * 3; (i -= 3) > 0;) { 250 float x = v[i]; 251 if (x < xmin) 252 xmin = x; 253 if (x > xmax) 254 xmax = x; 255 float y = v[i + 1]; 256 if (y < ymin) 257 ymin = y; 258 if (y > ymax) 259 ymax = y; 260 float z = v[i + 2]; 261 if (z < zmin) 262 zmin = z; 263 if (z > zmax) 264 zmax = z; 265 } 266 this.xmax = xmax; 267 this.xmin = xmin; 268 this.ymax = ymax; 269 this.ymin = ymin; 270 this.zmax = zmax; 271 this.zmin = zmin; 272 } 273 } 274 275 276 public class XYZApp 277 extends Applet ![JavaDoc](../cmn/javadoc.gif) 278 implements Runnable , MouseListener, MouseMotionListener { 279 XYZChemModel md; 280 boolean painted = true; 281 float xfac; 282 int prevx, prevy; 283 float xtheta, ytheta; 284 float scalefudge = 1; 285 Matrix3D amat = new Matrix3D(), tmat = new Matrix3D(); 286 String mdname = null; 287 String message = null; 288 Image backBuffer; 289 Graphics backGC; 290 Dimension backSize; 291 292 293 private synchronized void newBackBuffer() { 294 backBuffer = createImage(getSize().width, getSize().height); 295 if (backGC != null) { 296 backGC.dispose(); 297 } 298 backGC = backBuffer.getGraphics(); 299 backSize = getSize(); 300 } 301 302 public void init() { 303 mdname = getParameter("model"); 304 try { 305 scalefudge = Float.valueOf(getParameter("scale")).floatValue(); 306 } catch(Exception e) { 307 }; 308 amat.yrot(20); 309 amat.xrot(20); 310 if (mdname == null) 311 mdname = "model.obj"; 312 resize(getSize().width <= 20 ? 400 : getSize().width, 313 getSize().height <= 20 ? 400 : getSize().height); 314 newBackBuffer(); 315 addMouseListener(this); 316 addMouseMotionListener(this); 317 } 318 319 public void destroy() { 320 removeMouseListener(this); 321 removeMouseMotionListener(this); 322 } 323 324 public void run() { 325 InputStream is = null; 326 try { 327 Thread.currentThread().setPriority(Thread.MIN_PRIORITY); 328 is = new URL (getDocumentBase(), mdname).openStream(); 329 XYZChemModel m = new XYZChemModel (is); 330 Atom.setApplet(this); 331 md = m; 332 m.findBB(); 333 float xw = m.xmax - m.xmin; 334 float yw = m.ymax - m.ymin; 335 float zw = m.zmax - m.zmin; 336 if (yw > xw) 337 xw = yw; 338 if (zw > xw) 339 xw = zw; 340 float f1 = getSize().width / xw; 341 float f2 = getSize().height / xw; 342 xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge; 343 } catch(Exception e) { 344 e.printStackTrace(); 345 md = null; 346 message = e.toString(); 347 } 348 try { 349 if (is != null) 350 is.close(); 351 } catch(Exception e) { 352 } 353 repaint(); 354 } 355 public void start() { 356 if (md == null && message == null) 357 new Thread (this).start(); 358 } 359 public void stop() { 360 } 361 362 public void mouseClicked(MouseEvent e) { 363 } 364 public void mousePressed(MouseEvent e) { 365 prevx = e.getX(); 366 prevy = e.getY(); 367 e.consume(); 368 } 369 public void mouseReleased(MouseEvent e) { 370 } 371 public void mouseEntered(MouseEvent e) { 372 } 373 public void mouseExited(MouseEvent e) { 374 } 375 public void mouseDragged(MouseEvent e) { 376 int x = e.getX(); 377 int y = e.getY(); 378 tmat.unit(); 379 float xtheta = (prevy - y) * (360.0f / getSize().width); 380 float ytheta = (x - prevx) * (360.0f / getSize().height); 381 tmat.xrot(xtheta); 382 tmat.yrot(ytheta); 383 amat.mult(tmat); 384 if (painted) { 385 painted = false; 386 repaint(); 387 } 388 prevx = x; 389 prevy = y; 390 e.consume(); 391 } 392 public void mouseMoved(MouseEvent e) { 393 } 394 395 public void update(Graphics g) { 396 if (backBuffer == null) 397 g.clearRect(0, 0, getSize().width, getSize().height); 398 paint(g); 399 } 400 401 public void paint(Graphics g) { 402 if (md != null) { 403 md.mat.unit(); 404 md.mat.translate(-(md.xmin + md.xmax) / 2, 405 -(md.ymin + md.ymax) / 2, 406 -(md.zmin + md.zmax) / 2); 407 md.mat.mult(amat); 408 md.mat.scale(xfac, -xfac, 16 * xfac / getSize().width); 410 md.mat.translate(getSize().width / 2, getSize().height / 2, 8); 411 md.transformed = false; 412 if (backBuffer != null) { 413 if (!backSize.equals(getSize())) 414 newBackBuffer(); 415 backGC.setColor(getBackground()); 416 backGC.fillRect(0,0,getSize().width,getSize().height); 417 md.paint(backGC); 418 g.drawImage(backBuffer, 0, 0, this); 419 } 420 else 421 md.paint(g); 422 setPainted(); 423 } else if (message != null) { 424 g.drawString("Error in model:", 3, 20); 425 g.drawString(message, 10, 40); 426 } 427 } 428 private synchronized void setPainted() { 429 painted = true; 430 notifyAll(); 431 } 432 433 private synchronized void waitPainted() 434 { 435 while (!painted) 436 { 437 try 438 { 439 wait(); 440 } 441 catch (InterruptedException e) {} 442 } 443 painted = false; 444 } 445 446 public String getAppletInfo() { 447 return "Title: XYZApp \nAuthor: James Gosling \nAn applet to put a Chemical model into a page."; 448 } 449 450 public String [][] getParameterInfo() { 451 String [][] info = { 452 {"model", "path string", "The path to the model to be displayed in .xyz format (see http://chem.leeds.ac.uk/Project/MIME.html). Default is model.obj."}, 453 {"scale", "float", "Scale factor. Default is 1 (i.e. no scale)."} 454 }; 455 return info; 456 } 457 } 459 class Atom { 460 private static Applet applet; 461 private static byte[] data; 462 private final static int R = 40; 463 private final static int hx = 15; 464 private final static int hy = 15; 465 private final static int bgGrey = 192; 466 private final static int nBalls = 16; 467 private static int maxr; 468 469 private int Rl; 470 private int Gl; 471 private int Bl; 472 private Image balls[]; 473 474 static { 475 data = new byte[R * 2 * R * 2]; 476 int mr = 0; 477 for (int Y = 2 * R; --Y >= 0;) { 478 int x0 = (int) (Math.sqrt(R * R - (Y - R) * (Y - R)) + 0.5); 479 int p = Y * (R * 2) + R - x0; 480 for (int X = -x0; X < x0; X++) { 481 int x = X + hx; 482 int y = Y - R + hy; 483 int r = (int) (Math.sqrt(x * x + y * y) + 0.5); 484 if (r > mr) 485 mr = r; 486 data[p++] = r <= 0 ? 1 : (byte) r; 487 } 488 } 489 maxr = mr; 490 } 491 static void setApplet(Applet app) { 492 applet = app; 493 } 494 Atom(int Rl, int Gl, int Bl) { 495 this.Rl = Rl; 496 this.Gl = Gl; 497 this.Bl = Bl; 498 } 499 private final int blend(int fg, int bg, float fgfactor) { 500 return (int) (bg + (fg - bg) * fgfactor); 501 } 502 private void Setup() { 503 balls = new Image [nBalls]; 504 byte red[] = new byte[256]; 505 red[0] = (byte) bgGrey; 506 byte green[] = new byte[256]; 507 green[0] = (byte) bgGrey; 508 byte blue[] = new byte[256]; 509 blue[0] = (byte) bgGrey; 510 for (int r = 0; r < nBalls; r++) { 511 float b = (float) (r+1) / nBalls; 512 for (int i = maxr; i >= 1; --i) { 513 float d = (float) i / maxr; 514 red[i] = (byte) blend(blend(Rl, 255, d), bgGrey, b); 515 green[i] = (byte) blend(blend(Gl, 255, d), bgGrey, b); 516 blue[i] = (byte) blend(blend(Bl, 255, d), bgGrey, b); 517 } 518 IndexColorModel model = new IndexColorModel (8, maxr + 1, 519 red, green, blue, 0); 520 balls[r] = applet.createImage( 521 new MemoryImageSource (R*2, R*2, model, data, 0, R*2)); 522 } 523 } 524 void paint(Graphics gc, int x, int y, int r) { 525 Image ba[] = balls; 526 if (ba == null) { 527 Setup(); 528 ba = balls; 529 } 530 Image i = ba[r]; 531 int size = 10 + r; 532 gc.drawImage(i, x - (size >> 1), y - (size >> 1), size, size, applet); 533 } 534 } 535 | Popular Tags |