提交 12e00c83 编写于 作者: M mrkam

7027686: /applets/MoleculeViewer demo needs to be improved

Reviewed-by: alexp
上级 eae7f2e0
/*
* Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -29,22 +29,23 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*/
/** A fairly conventional 3D matrix object that can transform sets of
3D points and perform a variety of manipulations on the transform */
3D points and perform a variety of manipulations on the transform */
class Matrix3D {
float xx, xy, xz, xo;
float yx, yy, yz, yo;
float zx, zy, zz, zo;
static final double pi = 3.14159265;
/** Create a new unit matrix */
Matrix3D () {
Matrix3D() {
xx = 1.0f;
yy = 1.0f;
zz = 1.0f;
}
/** Scale by f in all dimensions */
void scale(float f) {
xx *= f;
......@@ -60,6 +61,7 @@ class Matrix3D {
zz *= f;
zo *= f;
}
/** Scale along each axis independently */
void scale(float xf, float yf, float zf) {
xx *= xf;
......@@ -75,12 +77,14 @@ class Matrix3D {
zz *= zf;
zo *= zf;
}
/** Translate the origin */
void translate(float x, float y, float z) {
xo += x;
yo += y;
zo += z;
}
/** rotate theta degrees about the y axis */
void yrot(double theta) {
theta *= (pi / 180);
......@@ -106,6 +110,7 @@ class Matrix3D {
zy = Nzy;
zz = Nzz;
}
/** rotate theta degrees about the x axis */
void xrot(double theta) {
theta *= (pi / 180);
......@@ -131,6 +136,7 @@ class Matrix3D {
zy = Nzy;
zz = Nzz;
}
/** rotate theta degrees about the z axis */
void zrot(double theta) {
theta *= (pi / 180);
......@@ -156,6 +162,7 @@ class Matrix3D {
xy = Nxy;
xz = Nxz;
}
/** Multiply this matrix by a second: M = M*R */
void mult(Matrix3D rhs) {
float lxx = xx * rhs.xx + yx * rhs.xy + zx * rhs.xz;
......@@ -204,6 +211,7 @@ class Matrix3D {
zy = 0;
zz = 1;
}
/** Transform nvert points from v into tv. v contains the input
coordinates in floating point. Three successive entries in
the array constitute a point. tv ends up holding the transformed
......@@ -216,11 +224,13 @@ class Matrix3D {
float x = v[i];
float y = v[i + 1];
float z = v[i + 2];
tv[i ] = (int) (x * lxx + y * lxy + z * lxz + lxo);
tv[i] = (int) (x * lxx + y * lxy + z * lxz + lxo);
tv[i + 1] = (int) (x * lyx + y * lyy + z * lyz + lyo);
tv[i + 2] = (int) (x * lzx + y * lzy + z * lzz + lzo);
}
}
@Override
public String toString() {
return ("[" + xo + "," + xx + "," + xy + "," + xz + ";"
+ yo + "," + yx + "," + yy + "," + yz + ";"
......
/*
* Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -29,37 +29,43 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*/
/*
* A set of classes to parse, represent and display Chemical compounds in
* .xyz format (see http://chem.leeds.ac.uk/Project/MIME.html)
*/
import java.applet.Applet;
import java.awt.Image;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Dimension;
import java.io.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.net.URL;
import java.util.Hashtable;
import java.awt.image.IndexColorModel;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/*
* A set of classes to parse, represent and display Chemical compounds in
* .xyz format (see http://chem.leeds.ac.uk/Project/MIME.html)
*/
/** The representation of a Chemical .xyz model */
class XYZChemModel {
final class XYZChemModel {
float vert[];
Atom atoms[];
int tvert[];
int ZsortMap[];
int nvert, maxvert;
static Hashtable atomTable = new Hashtable();
static final Map<String, Atom> atomTable = new HashMap<String, Atom>();
static Atom defaultAtom;
static {
atomTable.put("c", new Atom(0, 0, 0));
atomTable.put("h", new Atom(210, 210, 210));
......@@ -70,58 +76,51 @@ class XYZChemModel {
atomTable.put("hn", new Atom(150, 255, 150)); /* !!*/
defaultAtom = new Atom(255, 100, 200);
}
boolean transformed;
Matrix3D mat;
float xmin, xmax, ymin, ymax, zmin, zmax;
XYZChemModel () {
XYZChemModel() {
mat = new Matrix3D();
mat.xrot(20);
mat.yrot(30);
}
/** Create a Cehmical model by parsing an input stream */
XYZChemModel (InputStream is) throws Exception
{
/** Create a Chemical model by parsing an input stream */
XYZChemModel(InputStream is) throws Exception {
this();
StreamTokenizer st = new StreamTokenizer(
new BufferedReader(new InputStreamReader(is, "UTF-8")));
st.eolIsSignificant(true);
st.commentChar('#');
int slot = 0;
try
{
scan:
while (true)
{
switch ( st.nextToken() )
{
try {
scan:
while (true) {
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF:
break scan;
default:
break;
case StreamTokenizer.TT_WORD:
String name = st.sval;
double x = 0, y = 0, z = 0;
if (st.nextToken() == StreamTokenizer.TT_NUMBER)
{
double x = 0,
y = 0,
z = 0;
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
x = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER)
{
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
y = st.nval;
if (st.nextToken() == StreamTokenizer.TT_NUMBER)
if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
z = st.nval;
}
}
}
addVert(name, (float) x, (float) y, (float) z);
while( st.ttype != StreamTokenizer.TT_EOL &&
st.ttype != StreamTokenizer.TT_EOF )
while (st.ttype != StreamTokenizer.TT_EOL
&& st.ttype != StreamTokenizer.TT_EOF) {
st.nextToken();
}
} // end Switch
......@@ -130,17 +129,19 @@ scan:
is.close();
} // end Try
catch( IOException e) {}
catch (IOException e) {
}
if (st.ttype != StreamTokenizer.TT_EOF)
if (st.ttype != StreamTokenizer.TT_EOF) {
throw new Exception(st.toString());
}
} // end XYZChemModel()
/** Add a vertex to this model */
int addVert(String name, float x, float y, float z) {
int i = nvert;
if (i >= maxvert)
if (i >= maxvert) {
if (vert == null) {
maxvert = 100;
vert = new float[maxvert * 3];
......@@ -154,8 +155,11 @@ scan:
System.arraycopy(atoms, 0, na, 0, atoms.length);
atoms = na;
}
Atom a = (Atom) atomTable.get(name.toLowerCase());
if (a == null) a = defaultAtom;
}
Atom a = atomTable.get(name.toLowerCase());
if (a == null) {
a = defaultAtom;
}
atoms[i] = a;
i *= 3;
vert[i] = x;
......@@ -166,30 +170,33 @@ scan:
/** Transform all the points in this model */
void transform() {
if (transformed || nvert <= 0)
if (transformed || nvert <= 0) {
return;
if (tvert == null || tvert.length < nvert * 3)
}
if (tvert == null || tvert.length < nvert * 3) {
tvert = new int[nvert * 3];
}
mat.transform(vert, tvert, nvert);
transformed = true;
}
/** Paint this model to a graphics context. It uses the matrix associated
with this model to map from model space to screen space.
The next version of the browser should have double buffering,
which will make this *much* nicer */
void paint(Graphics g) {
if (vert == null || nvert <= 0)
if (vert == null || nvert <= 0) {
return;
}
transform();
int v[] = tvert;
int zs[] = ZsortMap;
if (zs == null) {
ZsortMap = zs = new int[nvert];
for (int i = nvert; --i >= 0;)
for (int i = nvert; --i >= 0;) {
zs[i] = i * 3;
}
}
/*
* I use a bubble sort since from one iteration to the next, the sort
......@@ -209,24 +216,26 @@ scan:
flipped = true;
}
}
if (!flipped)
if (!flipped) {
break;
}
}
int lg = 0;
int lim = nvert;
Atom ls[] = atoms;
if (lim <= 0 || nvert <= 0)
if (lim <= 0 || nvert <= 0) {
return;
}
for (int i = 0; i < lim; i++) {
int j = zs[i];
int grey = v[j + 2];
if (grey < 0)
if (grey < 0) {
grey = 0;
if (grey > 15)
}
if (grey > 15) {
grey = 15;
}
// g.drawString(names[i], v[j], v[j+1]);
atoms[j/3].paint(g, v[j], v[j + 1], grey);
atoms[j / 3].paint(g, v[j], v[j + 1], grey);
// g.drawImage(iBall, v[j] - (iBall.width >> 1), v[j + 1] -
// (iBall.height >> 1));
}
......@@ -234,47 +243,55 @@ scan:
/** Find the bounding box of this model */
void findBB() {
if (nvert <= 0)
if (nvert <= 0) {
return;
}
float v[] = vert;
float xmin = v[0], xmax = xmin;
float ymin = v[1], ymax = ymin;
float zmin = v[2], zmax = zmin;
float _xmin = v[0], _xmax = _xmin;
float _ymin = v[1], _ymax = _ymin;
float _zmin = v[2], _zmax = _zmin;
for (int i = nvert * 3; (i -= 3) > 0;) {
float x = v[i];
if (x < xmin)
xmin = x;
if (x > xmax)
xmax = x;
if (x < _xmin) {
_xmin = x;
}
if (x > _xmax) {
_xmax = x;
}
float y = v[i + 1];
if (y < ymin)
ymin = y;
if (y > ymax)
ymax = y;
if (y < _ymin) {
_ymin = y;
}
if (y > _ymax) {
_ymax = y;
}
float z = v[i + 2];
if (z < zmin)
zmin = z;
if (z > zmax)
zmax = z;
}
this.xmax = xmax;
this.xmin = xmin;
this.ymax = ymax;
this.ymin = ymin;
this.zmax = zmax;
this.zmin = zmin;
if (z < _zmin) {
_zmin = z;
}
if (z > _zmax) {
_zmax = z;
}
}
this.xmax = _xmax;
this.xmin = _xmin;
this.ymax = _ymax;
this.ymin = _ymin;
this.zmax = _zmax;
this.zmin = _zmin;
}
}
/** An applet to put a Chemical model into a page */
public class XYZApp
extends Applet
implements Runnable, MouseListener, MouseMotionListener {
@SuppressWarnings("serial")
public class XYZApp extends Applet implements Runnable, MouseListener,
MouseMotionListener {
XYZChemModel md;
boolean painted = true;
float xfac;
int prevx, prevy;
float xtheta, ytheta;
float scalefudge = 1;
Matrix3D amat = new Matrix3D(), tmat = new Matrix3D();
String mdname = null;
......@@ -283,7 +300,6 @@ public class XYZApp
Graphics backGC;
Dimension backSize;
private synchronized void newBackBuffer() {
backBuffer = createImage(getSize().width, getSize().height);
if (backGC != null) {
......@@ -293,16 +309,18 @@ public class XYZApp
backSize = getSize();
}
@Override
public void init() {
mdname = getParameter("model");
try {
scalefudge = Float.valueOf(getParameter("scale")).floatValue();
} catch(Exception e) {
};
} catch (Exception ignored) {
}
amat.yrot(20);
amat.xrot(20);
if (mdname == null)
if (mdname == null) {
mdname = "model.obj";
}
resize(getSize().width <= 20 ? 400 : getSize().width,
getSize().height <= 20 ? 400 : getSize().height);
newBackBuffer();
......@@ -310,62 +328,84 @@ public class XYZApp
addMouseMotionListener(this);
}
@Override
public void destroy() {
removeMouseListener(this);
removeMouseMotionListener(this);
}
@Override
public void run() {
InputStream is = null;
try {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
is = new URL(getDocumentBase(), mdname).openStream();
XYZChemModel m = new XYZChemModel (is);
XYZChemModel m = new XYZChemModel(is);
Atom.setApplet(this);
md = m;
m.findBB();
float xw = m.xmax - m.xmin;
float yw = m.ymax - m.ymin;
float zw = m.zmax - m.zmin;
if (yw > xw)
if (yw > xw) {
xw = yw;
if (zw > xw)
}
if (zw > xw) {
xw = zw;
}
float f1 = getSize().width / xw;
float f2 = getSize().height / xw;
xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
} catch(Exception e) {
e.printStackTrace();
} catch (Exception e) {
Logger.getLogger(XYZApp.class.getName()).log(Level.SEVERE, null, e);
md = null;
message = e.toString();
}
try {
if (is != null)
if (is != null) {
is.close();
} catch(Exception e) {
}
} catch (Exception ignored) {
}
repaint();
}
@Override
public void start() {
if (md == null && message == null)
if (md == null && message == null) {
new Thread(this).start();
}
}
@Override
public void stop() {
}
/* event handling */
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
prevx = e.getX();
prevy = e.getY();
e.consume();
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
int x = e.getX();
int y = e.getY();
......@@ -383,15 +423,20 @@ public class XYZApp
prevy = y;
e.consume();
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void update(Graphics g) {
if (backBuffer == null)
if (backBuffer == null) {
g.clearRect(0, 0, getSize().width, getSize().height);
}
paint(g);
}
@Override
public void paint(Graphics g) {
if (md != null) {
md.mat.unit();
......@@ -404,53 +449,50 @@ public class XYZApp
md.mat.translate(getSize().width / 2, getSize().height / 2, 8);
md.transformed = false;
if (backBuffer != null) {
if (!backSize.equals(getSize()))
if (!backSize.equals(getSize())) {
newBackBuffer();
}
backGC.setColor(getBackground());
backGC.fillRect(0,0,getSize().width,getSize().height);
backGC.fillRect(0, 0, getSize().width, getSize().height);
md.paint(backGC);
g.drawImage(backBuffer, 0, 0, this);
}
else
} else {
md.paint(g);
}
setPainted();
} else if (message != null) {
g.drawString("Error in model:", 3, 20);
g.drawString(message, 10, 40);
}
}
private synchronized void setPainted() {
painted = true;
notifyAll();
}
private synchronized void waitPainted()
{
while (!painted)
{
try
{
wait();
}
catch (InterruptedException e) {}
}
painted = false;
}
@Override
public String getAppletInfo() {
return "Title: XYZApp \nAuthor: James Gosling \nAn applet to put a Chemical model into a page.";
return "Title: XYZApp \nAuthor: James Gosling \nAn applet to put"
+ " a Chemical model into a page.";
}
@Override
public String[][] getParameterInfo() {
String[][] info = {
{"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."},
{"scale", "float", "Scale factor. Default is 1 (i.e. no scale)."}
{ "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." },
{ "scale", "float", "Scale factor. Default is 1 (i.e. no scale)." }
};
return info;
}
} // end class XYZApp
class Atom {
private static Applet applet;
private static byte[] data;
private final static int R = 40;
......@@ -459,7 +501,6 @@ class Atom {
private final static int bgGrey = 192;
private final static int nBalls = 16;
private static int maxr;
private int Rl;
private int Gl;
private int Bl;
......@@ -475,24 +516,29 @@ class Atom {
int x = X + hx;
int y = Y - R + hy;
int r = (int) (Math.sqrt(x * x + y * y) + 0.5);
if (r > mr)
if (r > mr) {
mr = r;
}
data[p++] = r <= 0 ? 1 : (byte) r;
}
}
maxr = mr;
}
static void setApplet(Applet app) {
applet = app;
}
Atom(int Rl, int Gl, int Bl) {
this.Rl = Rl;
this.Gl = Gl;
this.Bl = Bl;
}
private final int blend(int fg, int bg, float fgfactor) {
private int blend(int fg, int bg, float fgfactor) {
return (int) (bg + (fg - bg) * fgfactor);
}
private void Setup() {
balls = new Image[nBalls];
byte red[] = new byte[256];
......@@ -502,7 +548,7 @@ class Atom {
byte blue[] = new byte[256];
blue[0] = (byte) bgGrey;
for (int r = 0; r < nBalls; r++) {
float b = (float) (r+1) / nBalls;
float b = (float) (r + 1) / nBalls;
for (int i = maxr; i >= 1; --i) {
float d = (float) i / maxr;
red[i] = (byte) blend(blend(Rl, 255, d), bgGrey, b);
......@@ -512,9 +558,10 @@ class Atom {
IndexColorModel model = new IndexColorModel(8, maxr + 1,
red, green, blue, 0);
balls[r] = applet.createImage(
new MemoryImageSource(R*2, R*2, model, data, 0, R*2));
new MemoryImageSource(R * 2, R * 2, model, data, 0, R * 2));
}
}
void paint(Graphics gc, int x, int y, int r) {
Image ba[] = balls;
if (ba == null) {
......
......@@ -6,7 +6,7 @@
<h1>MoleculeViewer (example 1)</h1>
<hr>
<applet code=XYZApp.class width=300 height=300>
<param name=model value=models/HyaluronicAcid.xyz>
<param name=model value="models/HyaluronicAcid.xyz">
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
......
......@@ -6,7 +6,7 @@
<h1>MoleculeViewer (example 2)</h1>
<hr>
<applet code=XYZApp.class width=300 height=300>
<param name=model value=models/buckminsterfullerine.xyz>
<param name=model value="models/buckminsterfullerine.xyz">
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
......
......@@ -6,25 +6,25 @@
<h1>MoleculeViewer (example 3)</h1>
<hr>
<applet code=XYZApp.class width=100 height=100>
<param name=model value=models/water.xyz>
<param name=model value="models/water.xyz">
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
<p>
<applet code=XYZApp.class width=100 height=100>
<param name=model value=models/benzene.xyz>
<param name=model value="models/benzene.xyz">
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
<p>
<applet code=XYZApp.class width=100 height=100>
<param name=model value=models/ethane.xyz>
<param name=model value="models/ethane.xyz">
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
<p>
<applet code=XYZApp.class width=100 height=100>
<param name=model value=models/cyclohexane.xyz>
<param name=model value="models/cyclohexane.xyz">
alt="Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason."
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册