?? 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 + -