- 使用したフリーアプリについては、こちらをどうぞ。
- 3次元グラフ様のスケルトンオブジェクトをアニメーションGIFで動かしてみる。
- 対象
- スケルトンオブジェクトは、見えない部分のことなどを気にする必要がないので、面倒がない
- 点を直線で結んだものがスケルトンオブジェクト
- 点と直線の座標は3次元で与えられる
- 手順
- スケルトンオブジェクトをjava で作る
- グラフとしてデータを格納する
- 頂点(ノード)を登録し、それに3次元座標を与える
- 頂点間を結ぶ辺を登録する
- 視点を変えて眺める
- 3次元に対応する3本の正規直行座標の単位ベクトルの射影ベクトルをオイラー角にて与える
public static double[][] GetCoord(double[][] c,double[] a){
double[][] ret = new double[c.length][2];
double[] cos = {Math.cos(a[0]*Math.PI),Math.cos(a[1]*Math.PI),Math.cos(a[2]*Math.PI)};
double[] sin = {Math.sin(a[0]*Math.PI),Math.sin(a[1]*Math.PI),Math.sin(a[2]*Math.PI)};
for(int i=0;i<ret.length;i++){
ret[i][0]=c[i][0]*(cos[0]*cos[1]*cos[2]-sin[0]*sin[2])+
c[i][1]*(sin[0]*cos[1]*cos[2]+cos[0]*sin[2])+
c[i][2]*(-sin[1]*cos[2]);
ret[i][1]=c[i][0]*(-sin[0]*cos[2]-cos[0]*cos[1]*sin[2])+
c[i][1]*(cos[0]*cos[2]-sin[0]*cos[1]*sin[2])+
c[i][2]*(sin[1]*sin[2]);
}
return ret;
}
-
-
-
- yz軸についてのみの回転をさせたい、などの特別な用途には
public static double[][] GetCoordYZrotation(double[][] c, double a){
double[][] ret = new double[c.length][2];
double cos = Math.cos(a*Math.PI);
double sin = Math.sin(a*Math.PI);
for(int i=0;i<ret.length;i++){
ret[i][0]=c[i][0];
ret[i][1]=c[i][1]*cos+c[i][2]*sin;
}
return ret;
}
public static String Circle(double[] c,double f){
String ret="";
ret+="<circle cx=\"";
ret+=c[0];
ret+="\" cy=\"";
ret+=c[1];
ret+="\" r=\"";
double scale=50;
scale*=f;
ret+=scale;
ret+="\" fill=\"gray\"/>\n";
return ret;
}
public static String Line(double[] c1, double[] c2,double width,int colorType){
String ret="<line x1=\"";
ret+=c1[0];
ret+="\" y1=\"";
ret+=c1[1];
ret+="\" x2=\"";
ret+=c2[0];
ret+="\" y2=\"";
ret+=c2[1];
ret+="\" stroke-width=\"5\" stroke=\"";
String[] color={"yellow","red","blue"};
ret+=color[colorType];
ret+="\"/>\n";
return ret;
}
-
-
-
- svgファイルのヘッダ・フッタつきで、ファイルに出力させる(少し、色やら大きさやらについて、カスタマイズした部分があるので、シンプルなスケルトンにするには、それを取り除いて作ればよい)
- この後、gifファイル形式に変換するが、そのとき、svgのキャンパスサイズなどが小さ過ぎると、まったく実用にならないgifファイルができてしまうので、適当に調整すること(ヘッダの、width, height, viewBox)。
public void PrintSVG(double[] a,String outfile)throws IOException{
String header="<?xml version=\"1.0\" standalone=\"no\"?>\n"+"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"+
"<svg width=\"500pt\" height=\"500pt\" viewBox=\"-1000 -1000 2000 2000\" xmlns=\"http://www.w3.org/2000/svg\">";
String footer="</svg>";
BufferedWriter[] bw = new BufferedWriter[1];
bw[0] = new BufferedWriter(new FileWriter(outfile));
double[][] prevcoord=new double[3][2];
double[][] postcoord=new double[3][2];
try{
bw[0].write(header);
for(int i=0;i<edgeWidth.length;i++){
prevcoord=GetCoord(coord[i],a);
postcoord=GetCoord(coord[i+1],a);
for(int j=0;j<prevcoord.length;j++){
String tmpCircle=Circle(prevcoord[j],freq[i][j]);
bw[0].write(tmpCircle);
}
for(int j=0;j<prevcoord.length;j++){
for(int k=0;k<postcoord.length;k++){
int colorType=0;
if(j==k){
colorType=2;
if(j==1 && k==1){
colorType=1;
}
}
String tmpLine=Line(prevcoord[j],postcoord[k],edgeWidth[i][j][k],colorType);
bw[0].write(tmpLine);
}
}
}
bw[0].write(footer);
bw[0].close();
}catch(Exception e){
System.out.println(e);
}
}
public void PrintSVGrotationYZ(double a,String outfile)throws IOException{
String header="<?xml version=\"1.0\" standalone=\"no\"?>\n"+"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"+
"<svg width=\"500pt\" height=\"500pt\" viewBox=\"-1000 -1000 2000 2000\" xmlns=\"http://www.w3.org/2000/svg\">";
String footer="</svg>";
BufferedWriter[] bw = new BufferedWriter[1];
bw[0] = new BufferedWriter(new FileWriter(outfile));
double[][] prevcoord=new double[3][2];
double[][] postcoord=new double[3][2];
try{
bw[0].write(header);
for(int i=0;i<edgeWidth.length;i++){
prevcoord=GetCoordYZrotation(coord[i],a);
postcoord=GetCoordYZrotation(coord[i+1],a);
for(int j=0;j<prevcoord.length;j++){
String tmpCircle=Circle(prevcoord[j],freq[i][j]);
bw[0].write(tmpCircle);
}
for(int j=0;j<prevcoord.length;j++){
for(int k=0;k<postcoord.length;k++){
int colorType=0;
if(j==k){
colorType=2;
if(j==1 && k==1){
colorType=1;
}
}
String tmpLine=Line(prevcoord[j],postcoord[k],edgeWidth[i][j][k],colorType);
bw[0].write(tmpLine);
}
}
}
bw[0].write(footer);
bw[0].close();
}catch(Exception e){
System.out.println(e);
}
}
-
-
-
-
- アニメーションのために、視点を変化させた複数ファイルを作成する
- 下記の例は、グラフオブジェクトを作ったうえで、YZ軸について、0からラジアンまで、刻みで視点を変えて、それにcounter番号つきで出力させたもの
Plot3DforSNP t=new Plot3DforSNP(freq,coord,edge);
String outfile="test6";
double kizami=0.1;
int counter=0;
for(double a=0;a<2;a+=kizami){
String outfile2=outfile+"for"+counter+".svg";
t.PrintSVGrotationYZ(a, outfile2);
counter++;
}
mogrify -format gif *.svg
-
-
-
-
- アニメーションgifにまとめる
- Animation GIF Maker に出力ファイルを渡して、「まとめる」
- 出来上がり!