多面体

多面体を描く

多面体を描きます。KeTCindyではレイトレーシングによる色付けは行わないので,折れ線だけで描くこともできますが,きちんと陰線処理を行うには面としての処理をする必要があります。この意味を,正四面体の例で説明します。

まず,正四面体の4つの頂点の座標を計算して4点をとります。たとえば,原点を底面の重心とする1辺が4の正四面体とします。座標軸はコメント行にして非表示にしておきます。

//Xyzax3data("","x=[-5,5]","y=[-5,5]","z=[-5,5]");

Putpoint3d("A",[0,0,4*sqrt(6)/3]);

Putpoint3d("B",[4/sqrt(3),0,0]);

Putpoint3d("C",[-2/sqrt(3),2,0]);

Putpoint3d("D",[-2/sqrt(3),-2,0]);

Spaceline("1",[A,B,C,A,D,C]);

Spaceline("2",[B,D],["do"]);

Letter([A,"nw","A",B,"sw","B",C,"se","C",D,"ne","D"]);

ここで, Spaceline("2",[B,D],["do"]); が陰線を点線で表していますが,隠れるかどうかは人間が判断していますので,視点が変われば書き直す必要があります。

このように折れ線で描くのではなく,正四面体の各面の面データを作って表示すれば,陰線処理はコンピュータが行いますので,視点を変えてもコードを書き直す必要はありません。

面データは,面の頂点のリストと,描画順のリストの2つで作ります。たとえば,三角形ABCは,[A,B,C] と [1,2,3] の2つのリストです。正四面体の場合は,頂点データは[A,B,C,D] の1つですが,描画順を各面について作って,[[1,2,3],[1,2,4],[1,3,4],[2,3,4]] という4つの要素のリストとします。ここで,数字は、順に点A,B,C,Dに対応し,始点はどこでもかまわず,[1,2,3]と[2,3,1] は同じです。

このデータを作るのは,番号の対応付けが結構面倒なのですが,関数 Concatobj() を使うと各面の頂点リストから上記の面データを作成します。Concatobj([[A,B,C],[A,B,D],[A,C,D],[B,C,D]]) とすると,面データ [[A,B,C,D],[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]] が返されます。この戻り値を,VertexEdgeFace() で使えば4つの面が描けます。TeXにデータを書き出すには,"Edg=nogeo" オプションをつけます。

VertexEdgeFace() では,描画のための3つのデータphe3d,phv3d,phf3d を作成しますが,このうち phf3d を使って陰線処理を行うのが Nohiddenbyfaces() です。データには VertexEdgeFace(name,・・) で指定した name が付加されますので,念のためコンソールの表示を見て, Nohiddenbyfaces() を使います。

前述のスクリプトの, Spaceline() の2行を,次のように変えます。

face=Concatobj([[A,B,C],[A,B,D],[A,C,D],[B,C,D]]);

VertexEdgeFace("1",face);

Nohiddenbyfaces("1","phf3d1");

立方体と切断面

立方体を平面で切断した図は中学校の内容ですが,ここでは,切断した上部を取り去った図も描いてみましょう。

切断面をインタラクティブに決められるように,幾何点を作って,ドラッグすれば切断面を変えられるようにします。

いま,辺の長さを3とし,座標軸も利用することにして4つの点をとります。

Putpoint3d("A",[3,3,0]);

Putpoint3d("B",[3,0,3]);

Putpoint3d("C",[3,3,3]);

Putpoint3d("D",[0,3,3]);

これと,座標軸上の点O,X,Y,Zで点が8つです。座標軸上の点X,Y,Zを原点から3の距離に置くために,Putaxes3d(); の引数を3にします。この8つの点で面データを作って立方体を表示します。

Putaxes3d(3);

Xyzax3data("","x=[-5,5]","y=[-5,5]","z=[-5,5]");

Putpoint3d("A",[3,3,0]);

Putpoint3d("B",[3,0,3]);

Putpoint3d("C",[3,3,3]);

Putpoint3d("D",[0,3,3]);

face=Concatobj([[O,X,A,Y],[A,C,B,X],[A,Y,D,C],[O,Y,D,Z],[O,Z,B,X],[Z,B,C,D]]);

VertexEdgeFace("1",face);

Nohiddenbyfaces("1","phf3d1");

完成図では座標軸はいらないので,あとで Xyzax3data(・・)の先頭に // をつけてコメント化します。

さて,この立方体の辺上に3点をとり,その3点をとおる平面で切断します。この3点は,辺XB,ZB,ZD上に取ることにします。線分上に天を作る関数は Putonseg3d() です。4点A,B,C,Dを作ったコマンドの次に入れます。初期位置はそれぞれの線分の中点になりますが,これらの点はその線分にインシデントとなり,線分上だけを動かすことができます。

Putonseg3d("E",X,B);

Putonseg3d("F",Z,B);

Putonseg3d("G",Z,D);

この3点を通る平面と,残りの辺との交点を作ります。平面と直線の交点を作る関数は IntersectsgpL(点名,直線,面,描画方法) です。直線と面はそれらを定義する2点,3点で表し,描画方法を “put” にすると幾何点が作成されます。いまは,辺ACおよびYDと,平面EFGの交点を求めるので次のようにします。

IntersectsgpL("M","A-C","E-F-G","put");

IntersectsgpL("N","D-Y","E-F-G","put");

E,F,Gの位置によっては辺の外に交点ができますので,E,F,Gをドラッグして適当な位置にしましょう。

これらの点は幾何点なので,Cinderellaの描画面上(平面上)の点と考えて,Listplot() で閉曲線を作って色塗りができます。

Listplot("1",[E,F,G,N,M,E]);

Shade(["sg1"],["Color=[0,0,0.2,0]"]);

 

さて,このままですと,E,F,Gの位置によっては点Mが辺AC上から外れてしまい,具合の悪いことになります。

そこで,XAとAYの交点も作り,Mの [~] 座標が負のときは,こちらの交点で断面を作るようにしましょう。前述のように,座標軸をコメント化して非表示にすればできあがりです。頂点の名前も入れましょう。画面上の点名と,書き出す点名はもちろん異なってかまいません。

Putaxes3d(3);

//Xyzax3data("","x=[-5,5]","y=[-5,5]","z=[-5,5]");

Putpoint3d("A",[3,3,0]);

Putpoint3d("B",[3,0,3]);

Putpoint3d("C",[3,3,3]);

Putpoint3d("D",[0,3,3]);

Putonseg3d("E",X,B);

Putonseg3d("F",Z,B);

Putonseg3d("G",Z,D);

IntersectsgpL("M","A-C","E-F-G","put");

IntersectsgpL("N","D-Y","E-F-G","put");

IntersectsgpL("P","X-A","E-F-G","put");

IntersectsgpL("Q","A-Y","E-F-G","put");

face=Concatobj([[O,X,A,Y],[A,C,B,X],[A,Y,D,C],[O,Y,D,Z],[O,Z,B,X],[Z,B,C,D]]);

VertexEdgeFace("1",face);

Nohiddenbyfaces("1","phf3d1");

if(M3d_3>0,

Listplot("1",[E,F,G,N,M,E]);

,

Listplot("1",[E,F,G,N,Q,P,E]);

);

Shade(["sg1"],["Color=[0,0,0.2,0]"]);

Letter([Z,"ne","A",B,"nw","B",C,"sw","C",D,"ne","D",O,"ne","E",X,"nw","F",A,"sw","G",Y,"ne","H"]);

ただし,面EFGが辺EHと交わる場合は別途対策が必要ですが,これは読者の課題としましょう。

次に,立方体を平面EFGで切断し,上方を切り取った図にします。

いま,簡単のため,辺AC上(Cinderellaの画面上のAC)で交わる場合の図を作ります。要するに,上方を取り去ったときにできる面をすべて定義して Concatobj() で面データを作ればよいのです。次のように書き換えます。

face=Concatobj([[O,X,A,Y],[X,A,M,E],[A,Y,N,M],[Y,N,G,Z,O],[O,Z,F,E,X],[Z,F,G],[E,M,N,G,F]]);

多面体データ polyhedrons_obj を使う

小林・鈴木・三谷による多面体データ polyhedrons_obj というものがあります。http://mitani.cs.tsukuba.ac.jp/polyhedron/

このデータファイルを、例えばユーザホームのketcindyフォルダにダウンロードしてを使うことができます。

たとえば,切頂二十面体(通称サッカーボール)はデータ番号が s06 なので,次のようにして使うことができます。

Setdirectory( Dirhead+"/data/polyhedrons_obj");

face=Readobj("s06.obj",["size=3"]);

Setdirectory(Dirwork);

VertexEdgeFace("1",face);

Nohiddenbyfaces("1","phf3d1");

面の陰線処理(陰面処理)には Phparadata() もあります。こちらは,隠れた面の処理をする関数で,初期設定では隠れた面を非表示にします。 Nohiddenbyfaces() のかわりに Phparadata("1","1") にすると次のようになります。この関数を使ったとき,Cinderellaの画面では頂点だけが表示され,辺は表示されません。

 

オプションには,辺と隠線の線種指定があり, [”Hidden=線種” ] で隠線の指定ができるので,Phparadata("1","1",["Hidden=do"]) とすると, Nohiddenbyfaces() を使ったときと同じ図ができます。

なお,主な多面体データは次のようになっています。

番号 名称. 番号 名称 番号 名称

r01 正四面体 s02 二十・十二面体 s08 斜立方八面体

r02 正八面体 s03 切頭四面体 s09 斜十二・二十面体

r03 正六面体 s04 切頭八面体 s10 切頭立方八面体

r04 正十二面体 s05 切頭立方体 s11 頭切二十・十二面体

r05 正二十面体 s06 切頭二十面体 s12L/R 変形立方体

s01 立方八面体 s07 切頭十二面体 s13L/R 変形十二面体

この他,n01〜n92まで整面凸多面体があります。

< 戻る >