📄 molecule1.java
字号:
// by Liu Peng, Nov.18, 2000
import java.lang.Math.*;
import java.awt.Graphics;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.event.WindowAdapter;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.mouse.*;
import com.sun.j3d.utils.behaviors.keyboard.*;
import com.sun.j3d.utils.behaviors.picking.*;
public class molecule1 extends Applet implements ActionListener, Runnable {
Thread timer;
Transform3D globalTransform3D;
Transform3D globalTransform3DBackup;
TransformGroup globalTransformGroup;
SharedGroup shared;
boolean timerFlag=true;
Group group;
double radius=0.2;
float angle = 0.0f;
int currentLink=0, currentVert=0;
int prevLink=0, prevVert=0;
boolean activateState=true;
Button activateB = new Button("Stop/Move");
Button normalB = new Button("Normal");
Button rotateBX = new Button("RotateX");
Button rotateBY = new Button("RotateY");
Button rotateBZ = new Button("RotateZ");
class Links_c {
double x0, y0, z0; // 起始坐标
int numVert; // 需要创建的分子数
boolean dx,dy,dz;
// 如果dx是true,则向X方向扩展;否则向-X方向扩展。dy,dz类似。
double probability;
// 按dx,dy,dz规定的方向扩展的概率,取值范围必须在[0, 1]之间。
// probability取值为0.5时,最易聚簇; 为1或0时,最易散开
// 只不过为1时,是按指定的方向散开;为0时,是按相反的方向散开
public void init(double ix0,double iy0,double iz0,int inumVert,
boolean idx,boolean idy,boolean idz, double iprobability)
{
x0=ix0; y0=iy0; z0=iz0; numVert=inumVert;
dx=idx; dy=idy; dz=idz; probability=iprobability;
}
};
Links_c links[];
int numLink;
Point3d pointPosition[][];
Transform3D pointTransform3D[][];
TransformGroup pointTransformGroup[][];
// 以一种随机和加方向性控制的方式,生成数条分子链的每个分子的坐标
//
private void createVert()
{
double x,y,z, p;
boolean dx,dy,dz;
// 此处应该和links一起改,否则会出错
numLink=3;
links =new Links_c[numLink];
for (int i=0; i<numLink; i++)
links[i] = new Links_c();
// 此处应该和numLink一起改,否则会出错
links[0].init(-0.5, -0.5, 0.2, 28, false, false, true, 0.6);
links[1].init(0.6, -0.6, 0, 22, true, true, false, 0.8);
links[2].init(0, 0.5, -0.2, 26, false, true, false, 0.65);
pointPosition = new Point3d[numLink][];
for (int l=0; l<numLink; l++)
{
pointPosition[l]=new Point3d[links[l].numVert];
for (int i=0; i<links[l].numVert; i++)
pointPosition[l][i]=new Point3d();
pointPosition[l][0].x=links[l].x0;
pointPosition[l][0].y=links[l].y0;
pointPosition[l][0].z=links[l].z0;
p=links[l].probability;
dx=links[l].dx;
dy=links[l].dy;
dz=links[l].dz;
for (int i=1;i<links[l].numVert;i++)
{
x=Math.random()*radius;
x=sign(x,p,dx);
y=Math.sqrt(radius*radius-x*x) * Math.random();
// Y的值不能也在0-radius范围内随意取值:
// 因为在X、Y平面上,当X、Y都取radius时,
// 点(X,Y)就跑到了圆x^2+y^2=r^2的外面了。
// 所以X、Y坐标必须满足这个约束。
y=sign(y,p,dy);
z=Math.sqrt(radius*radius-x*x-y*y);
z=sign(z,p,dz);
pointPosition[l][i].x=pointPosition[l][i-1].x+x;
pointPosition[l][i].y=pointPosition[l][i-1].y+y;
pointPosition[l][i].z=pointPosition[l][i-1].z+z;
}
}
}
// 依次改变所有分子链中每个分子的坐标(每次改一个)
private void changeAVert()
{
double x,y,z, p;
boolean dx,dy,dz;
int l=currentLink;
int i=currentVert;
prevLink=l;
prevVert=i;
i++;
if (i==links[l].numVert) // 本条链结束,下次从下条链开始
{
i=0;
l++;
}
if (l==numLink) // 所有链结束,重新开始一轮
{
l=0;
}
currentLink=l;
currentVert=i;
p=links[l].probability;
dx=links[l].dx;
dy=links[l].dy;
dz=links[l].dz;
if (i==0)
{
pointPosition[l][0].x=links[l].x0;
pointPosition[l][0].y=links[l].y0;
pointPosition[l][0].z=links[l].z0;
} else
{
x=Math.random()*radius;
x=sign(x,p,dx);
y=Math.sqrt(radius*radius-x*x) * Math.random();
// Y的值不能也在0-radius范围内随意取值:
// 因为在X、Y平面上,当X、Y都取radius时,
// 点(X,Y)就跑到了圆x^2+y^2=r^2的外面了。
// 所以X、Y坐标必须满足这个约束。
y=sign(y,p,dy);
z=Math.sqrt(radius*radius-x*x-y*y);
z=sign(z,p,dz);
pointPosition[l][i].x=pointPosition[l][i-1].x+x;
pointPosition[l][i].y=pointPosition[l][i-1].y+y;
pointPosition[l][i].z=pointPosition[l][i-1].z+z;
}
}
private double sign(double v, double p, boolean direction)
{
double ret;
if (p>=Math.random()) // 以给定的概率遵照扩展方向的约定
{
if (direction)
ret=v;
else
ret=-v;
} else // 落在规定的概率之外,则与扩展的方向相反
{
if (direction)
ret=-v;
else
ret=v;
}
return ret;
}
// 将一个坐标系中的任意物体旋向(x,y,z)指定的任意方向(坐标原点不变)
//
// 输入:给定旧坐标系中的一点A,它的坐标为(x,y,z)。
// 输出:两个坐标系之间的转换矩阵(OXYZ-->OX"Y"Z")
// 要求:旋转后OA为新坐标系中的Y"轴。(如此旋转后,原来与Y轴平行的物体,
// 将与Y"轴平行,其他位置的物体也将作相应的非扭曲旋转)
// 旋转方法:
// 假设OA在ZOX平面的投影为OA'。ZOA'夹角为angle1。则第一步旋转为:
// 以Y轴为转轴,将ZOX平面旋转angle1度,此时坐标系变为OX'YZ'(A'
// 处于Z'轴上了);
// 由于X'垂直于YOZ'平面(X'亦垂直于OA及OA')。假设YOA的夹角为angle2,
// 则第二步旋转为:以X'为轴,将YOZ'平面旋转angle2度,则此时Y轴与OA
// 轴重合,记为Y",另外记新的Z坐标为Z",还有X"(是与X'重合的)。
// 经过上述两次坐标轴旋转,坐标系中的物体也就转向了指定的任意方向。
private Transform3D transForm(double x, double y,double z)
{
double r = Math.sqrt(x*x+y*y+z*z);
double angle1 = Math.atan(x/z);
double angle2 = Math.acos(y/r);
//
// angle1 调整旋转的角度:
//
// Angle1是从+Z向Z'旋转的实际角度(范围:0-360度),Z'是(x,y,z)点在XOZ平面的投影线。
// Z X Angle1
// ------------------------------------
// +(or 0) +(or 0) angle1 (angle1此时为正)
// +(or 0) - 2*PI+angle1 (angle1此时为负)
// - +(or 0) PI+angle1 (angle1此时为负)
// - - PI+angle1 (angle1此时为正)
double Angle1,Angle2;
if (z>=0)
{
if (x>=0)
Angle1=angle1;
else
Angle1=2*Math.PI+angle1;
} else
{
if (x>=0)
Angle1=Math.PI+angle1;
else
Angle1=Math.PI+angle1;
}
//
// angle2 调整旋转的角度:
//
// Angle2 是从+Y向Z'旋转的实际角度(范围:0-180度)
// Y Angle2
// ---------------------------------
// +(or 0) angle2 (angle2此时为正)
// - angle2 (angle2此时为负)
if (y>=0)
Angle2=angle2;
else
Angle2=angle2;
Transform3D rot1 = new Transform3D();
Transform3D rot2 = new Transform3D();
rot1.rotY(Angle1);
rot2.rotX(Angle2);
Transform3D newTransform = new Transform3D();
newTransform.mul(rot1);
newTransform.mul(rot2);
return newTransform;
}
private Group moleculeLinks()
{
group=new Group();
createVert();
shared = new SharedGroup();
shared.addChild(aMolecule());
pointTransform3D = new Transform3D[numLink][];
pointTransformGroup = new TransformGroup[numLink][];
for (int l=0; l<numLink; l++)
{
pointTransform3D[l]=new Transform3D[links[l].numVert];
pointTransformGroup[l]=new TransformGroup[links[l].numVert];
for (int i=0;i<links[l].numVert; i++)
{
if (i==links[l].numVert-1)
{
pointTransform3D[l][i] = transForm(
pointPosition[l][i-1].x - pointPosition[l][i].x,
pointPosition[l][i-1].y - pointPosition[l][i].y,
pointPosition[l][i-1].z - pointPosition[l][i].z
);
} else
{
pointTransform3D[l][i] = transForm(
pointPosition[l][i+1].x - pointPosition[l][i].x,
pointPosition[l][i+1].y - pointPosition[l][i].y,
pointPosition[l][i+1].z - pointPosition[l][i].z
);
}
pointTransform3D[l][i].setTranslation(new Vector3d(
pointPosition[l][i].x, pointPosition[l][i].y, pointPosition[l][i].z));
pointTransformGroup[l][i] = new TransformGroup(pointTransform3D[l][i]);
pointTransformGroup[l][i].setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -