import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Color;
/**惑星形成シミュレーション ver 0.3
* ワン・クラス・高速タイプ+作用反作用&エネルギー正規化
*/
//
public class PlanetarySystem3 extends Applet implements Runnable{
//汎用定数
public double G = 6.672*Math.pow(10,-11); //万有引力定数
public double mAU = 149597870; //天文単位/1000
//Applet用定数など
public static final int APPLET_WIDTH =300;//アプレットウィンドウ幅
public static final int APPLET_HEIGHT=300;//アプレットウィンドウ高さ
public static final int APPLET_DEPTH =300;//アプレットウィンドウ仮想奥行き
public static final Color bgColor = Color.black; //初期背景色
public static final Color clearColor= Color.white; //消去色
public static final Color fillColor = Color.red; //描画色
public Thread thread;//スレッド
public Graphics graphics;//画像
//観測する系のフィールド
public int minorbodies; //メンバ小天体数
public boolean conflictionSwitch; //衝突イベントスイッチ
public boolean reflectionSwitch; //壁反射イベントスイッチ
public boolean energyNormalizationSwitch;//エネルギー正規化スイッチ
//観測者のフィールド
public double dt; //微少時間
public long time; //累積時間
public double RANDOM_PATTERNS=10000;//乱数パターン数
//天体データ配列
public double[] x; //x座標
public double[] y; //y座標
public double[] z; //z座標
public double[] px; //運動量x成分
public double[] py; //運動量y成分
public double[] pz; //運動量z成分
public double[] m; //質量
public double[] r; //半径
public int[] xx; //2DApplet表示用x座標
public int[] yy; //2DApplet表示用y座標
public int[] zz; //2DApplet表示用z座標
public boolean[] isSeen;//2DApplet表示フラグ
public boolean[] isConflicted;//衝突フラグ
//ウィンドウ変数
public double scale;//表示される領域の幅(=高さ=奥行き)
public double CX;//表示領域センターx座標
public double CY;//表示領域センターy座標
public double CZ;//表示領域センターz座標
public double WX0;//表示領域始点x座標
public double WY0;//表示領域始点y座標
public double WZ0;//表示領域始点z座標
public double WX1;//表示領域終点x座標
public double WY1;//表示領域終点y座標
public double WZ1;//表示領域終点z座標
//Applet初期化
public void init(){
time=0;
//コンピュータ時間によるMath.random()空回し
for(int i=0;i<(int)(System.currentTimeMillis()%RANDOM_PATTERNS);i++){
Math.random();
}
initialize(); //フィールドの初期化
initWindowCtoW(); //ウィンドウ初期化
graphics = this.getGraphics();//画像クラス取得
}
//------------------INITIALIZATION--------------------------------------------
public void initialize(){
CX=0;//宇宙のセンターをフォーカス
CY=0;//宇宙のセンターをフォーカス
CZ=0;//宇宙のセンターをフォーカス
scale=10*mAU;//1画面=10ミリ天文単位
dt=5000; //微少時間
conflictionSwitch = true;//衝突スイッチ=ON
reflectionSwitch = true;//壁反射スイッチ=ON
energyNormalizationSwitch = false;//エネルギー正規化スイッチ=OFF
minorbodies = 300;//天体数300個
x=new double[minorbodies];
y=new double[minorbodies];
z=new double[minorbodies];
px=new double[minorbodies];
py=new double[minorbodies];
pz=new double[minorbodies];
m=new double[minorbodies];
r=new double[minorbodies];
xx=new int[minorbodies];
yy=new int[minorbodies];
zz=new int[minorbodies];
isSeen=new boolean[minorbodies];
isConflicted=new boolean[minorbodies];
for(int i=0;i0.0 && yy_>0.0 && xx_<1.0 && yy_<1.0){//画面内なら
g.setColor(clearColor);
g.fillOval(xx[i]-(int)zz[i]/2,yy[i]-(int)zz[i]/2,(int)zz[i],(int)zz[i]);//消去
xx[i]=(int)(xx_*APPLET_WIDTH ); //2d変換
yy[i]=(int)(yy_*APPLET_HEIGHT); //2d変換
zz[i]=(int)(zz_*APPLET_DEPTH )/20;//2d変換
if(zz_<0){
zz[i]=1;
}
g.setColor(fillColor);
g.fillOval(xx[i]-(int)zz[i]/2,yy[i]-(int)zz[i]/2,(int)zz[i],(int)zz[i]);//描画
}
}
String displayedString = longToString((time )/31557600,0) + "Y "//時間・天体数文字列計算
+longToString((time%31557600)/ 86400,3) + "D "
+longToString((time% 86400)/ 3600,2) + "°"
+longToString((time% 3600)/ 60,2) + "\' "
+longToString((time% 60)/ 1,2) + "\" 天体数:"
+Integer.toString(minorbodies);
//時間・天体数表示座標決定
int countx = g.getFontMetrics().stringWidth(displayedString);
int county = g.getFontMetrics().getHeight();
g.setColor(clearColor);//時間・天体数消去
g.fillRect(300-countx,300-county-5,countx,county+5);
g.setColor(fillColor);//時間・天体数表示
g.drawString(displayedString,300-countx,300-5);
}
//longのString化(前に0をつける) len=文字数
public String longToString(long n,int len){
if(len==0){
return Long.toString(n);
}else{
String s = "0000" + Long.toString(n);
return s.substring(s.length()-len,s.length());
}
}
/**小天体メソッド*///------------------------------------
/**aのbによる万有引力による運動量変化(dtによる近似)及び衝突
形式 : beEffected(相手の小天体クラス)
戻り値 : = 衝突したか */
public boolean beEffectedAndMove(int a,int b){
double dxx=x[b]-x[a];//2天体距離x成分
double dyy=y[b]-y[a];//2天体距離y成分
double dzz=z[b]-z[a];//2天体距離z成分
double l2= dxx*dxx + dyy*dyy + dzz*dzz;//2乗距離
double dpx,dpy,dpz; //運動量微小変化
boolean ans=false; //戻り値
double E0,Er; //前エネルギー・エネルギー増加率
//衝突判定
if(conflictionSwitch){
if(l2<(r[b]+r[a])*(r[b]+r[a])){//衝突したとき
px[a] = px[a]+px[b];
py[a] = py[a]+py[b];
pz[a] = pz[a]+pz[b];
x[a] = (x[a]*m[a]+x[b]*m[b])/(m[a]+m[b]);//重心の位置を新天体の位置に
y[a] = (y[a]*m[a]+y[b]*m[b])/(m[a]+m[b]);//重心の位置を新天体の位置に
z[a] = (y[a]*m[a]+z[b]*m[b])/(m[a]+m[b]);//重心の位置を新天体の位置に
m[a] = m[a]+m[b];
r[a] = Math.pow(r[a]*r[a]*r[a]+r[b]*r[b]*r[b] , 1.0/3.0);//体積から計算
isConflicted[b] = true;//相手の衝突フラグを立てる
return true;//---return
}
}
//エネルギー計算
E0=getEnergy(a,b,l2);
//運動量変化
dpx = G*m[a]*m[b]/l2 * dxx/Math.abs(dxx) * dt/2.0;
dpy = G*m[a]*m[b]/l2 * dyy/Math.abs(dyy) * dt/2.0;
dpz = G*m[a]*m[b]/l2 * dzz/Math.abs(dzz) * dt/2.0;
px[a] += dpx; py[a] += dpy; pz[a] += dpz;
px[b] -= dpx; py[b] -= dpy; pz[b] -= dpz;
//天体移動
x[a]+=px[a]/m[a]*dt/2.0;
y[a]+=py[a]/m[a]*dt/2.0;
z[a]+=pz[a]/m[a]*dt/2.0;
x[b]+=px[b]/m[b]*dt/2.0;
y[b]+=py[b]/m[b]*dt/2.0;
z[b]+=pz[b]/m[b]*dt/2.0;
//壁反射
if(reflectionSwitch){
if(x[a]WX1){x[a]=WX1;px[a]=-Math.abs(px[a])*0;}
if(y[a]>WX1){y[a]=WY1;py[a]=-Math.abs(py[a])*0;}
if(z[a]>WX1){z[a]=WZ1;pz[a]=-Math.abs(pz[a])*0;}
if(x[b]WX1){x[b]=WX1;px[b]=-Math.abs(px[b])*0;}
if(y[b]>WX1){y[b]=WY1;py[b]=-Math.abs(py[b])*0;}
if(z[b]>WX1){z[b]=WZ1;pz[b]=-Math.abs(pz[b])*0;}
}
//エネルギー再計算
if(energyNormalizationSwitch){
l2 = (x[b]-x[a])*(x[b]-x[a]) + (y[b]-y[a])*(y[b]-y[a]) + (z[b]-z[a])*(z[b]-z[a]);
Er = Math.abs(getEnergy(a,b,l2)/E0);
//正規化
px[a]=px[a]/Math.sqrt(Er*0.5);
py[a]=py[a]/Math.sqrt(Er*0.5);
pz[a]=pz[a]/Math.sqrt(Er*0.5);
px[b]=px[b]/Math.sqrt(Er*0.5);
py[b]=py[b]/Math.sqrt(Er*0.5);
pz[b]=pz[b]/Math.sqrt(Er*0.5);
}
return false;
}
//エネルギー計算
public double getEnergy(int a,int b,double l2){
return (px[a]*px[a] + py[a]*py[a] + pz[a]*pz[a])/(2*m[a])//運動エネルギー
+(px[b]*px[b] + py[b]*py[b] + pz[b]*pz[b])/(2*m[b])//運動エネルギー
-G*m[a]*m[b]/Math.sqrt(l2); //万有引力ポテンシャル
}
//計算-----------------------------------------------
public void calc(){
//運動量変化・衝突計算
for(int i=0;i