G01 正四面体

現在,GeoGebraでは3Dグラフィクスも扱えるようになっています。したがって,「GeoGebra日本」の「GeoGebra実例」「G01 正四面体」の記事はそういう意味では古いのですが,3Dグラフィクスの考え方を学ぶ意味ではよいでしょう。

Cinderella.2(Cindyscript)そのものには空間座標を扱う関数はありません。3Dグラフィクスを扱うには,プラグインの Cindy3D を使うか,CinderellaJapanが提供している SpaceCindy を使うか,あるいは,KeTCindy3Dを使うかのいずれかになります。

Cindy3D はレイトレーシングによる曲面の描画が可能です。

SpaceCindyとKeTCindyには空間座標を扱うための多くの関数が用意されています。KeTCindyはTeXの挿入図を作成するためのものですが,インタラクティブな点の操作も若干は可能です。

ここでは,空間座標を扱うための基本的な準備だけを行います。

回転行列

x,y,z 各軸周りの回転行列を用意します。

rtx(θ):=[[1,0,0],[0,cos(θ),-sin(θ)],[0,sin(θ),cos(θ)]];

rty(θ):=[[cos(θ),0,sin(θ)],[0,1,0],[-sin(θ),0,cos(θ)]];

rtz(θ):=[[cos(θ),-sin(θ),0],[sin(θ),cos(θ),0],[0,0,1]];

スライダを2つ用意して,これらを組み合わせます。

たとえば,図のようにして,点Dと点Eで回転ができるようにします。

透視投影と平行投影

数学の教科書では平行投影が主体ですが,透視投影の方が実物らしく見せることが可能です。どちらかを指定して3Dの見え方を設定します。スライダによる回転もこの中でやります。

setview3d(flag,v,z):=(

if(flag==1,Perspective=true,Perspective=false);

Viewpoint3d=v+0.001; // 視点のy座標 整数にしない

Zoom3d=z; // 拡大率

th1=(D.y-5)*pi/10;

th2=(E.x+4)*pi/10;

Mat3d=rtx(th1+pi/12)*rty(th2-2*pi/3)*rtx(-pi/2);

Currentviewpoint=inverse(Mat3d)*[0,0,100];

);

空間から平面への投影

空間座標 (x,y,z) を描画面の座標に変換して返します。

map3d(p):=(

regional(mp,ret);

p=Mat3d*p;

if(Perspective,

mp=p/(Viewpoint3d-p_3);

ret=Zoom3d*[mp.x,mp.y];

,

ret=Zoom3d/Viewpoint3d*[p_1,p_2]; // 1点透視に合わせてサイズを調整

);

ret;

);

以上は,実行時に一度だけ実行すればよいので,Initialization スロットに書いておきます。

以下は Draw スロットに書きます。

座標軸の表示

まず,透視法と現在の視点を setview3d() で設定します。

つぎに,軸上の適当な点をとり,map3d()で変換して描画します。

setview3d(0,15,30);

x0=map3d([-3,0,0]);

x1=map3d([3,0,0]);

y0=map3d([0,-3,0]);

y1=map3d([0,3,0]);

z0=map3d([0,0,-2]);

z1=map3d([0,0,3]);

draw(x0,x1,color->[1,0,0]);

draw(y0,y1,color->[0,0,1]);

draw(z0,z1,color->[0,0,0]);

ここでは x軸を赤,y軸を青,z軸を黒で表示していますが,いろいろ方法はあるでしょう。

正四面体を描く

4つの頂点の座標を適当に設定します。たとえば,

p1=[2*sqrt(3)/3,0,0];

p2=[-sqrt(3)/3,1,0];

p3=[-sqrt(3)/3,-1,0];

p4=[0,0,2*sqrt(6)/3];

とします。これを平面に投影し,辺を描きます。

頂点の座標をリストにして,リスト処理で2点ずつのペアをとるのが簡明です。

v3=[p1,p2,p3,p4];

v2=apply(v3,map3d(#));

seg=pairs(v2);

forall(seg,draw(#,size->2));

apply(list,処理) は,listの各要素に対して処理をしたリストを返します。

forall(list,処理)は,listの各要素に対して処理をします。draw(#) で#は2点のペアなので線分が引かれます。

面を塗るのであれば,fillpoly()を用い,alpha で透明度を指定して薄く塗ります。

fillpoly([v2_1,v2_2,v2_3],alpha->0.2);

スライダを動かして視点を変えることができます。


CinderellaJapanが提供しているSpaceCindyはこれをベースに,いろいろな描画関数を用意しています。