切頂多面体

切頂多面体とは、多面体の各頂点を同じ割合で切り取った多面体です。切頭多面体ともいいます。有名なものはサッカーボールの形でしょう。切頂二十面体です。


では、正多面体に対して切頂多面体を描くCindyアプリケーションを作りましょう。

まず設計をします。

設計

正多面体の各辺について、頂点からある距離dの点を取ります。それらの点を頂点とする多面体を描けば、それが切頂多面体になります。そこで、

(1) 正多面体の辺のデータを取得する。

(2) 各辺を一定の割合で分割して切頂多面体の頂点データを取得する。割合はスライダを作って指定する。

(3) 頂点データから多面体を描く。

ということにします。

まず、正多面体でやってみます。

正多面体の辺のデータを取得する

正多面体の辺のデータは,rpolyhedron() の戻り値として得られる面データから作ります。

「正多面体の切断」で解説したものと同じですが,再掲しておきます。

== 再掲 : 辺データの取得 ここから ==

(1) 正多面体の辺のデータを取得する。

rpolyhedron() は面を塗った多面体を描くので,オプション "nodisp" をつけて,戻り値の面データを取得し,その第1要素の頂点リストを使ってVertexEdgeFace() で描きます。Nohiddenbyfaces() で陰線処理もしましょう。なお,後の都合があるので,1辺を2としたら,原点が中に入らないよう,頂点データを中心を(2,2,2)になるように平行移動したものをpdとしておきます。

fd=rpolyhedron("1",6,2*sqrt(3),["nodisp"]);

pd=translate3d(fd_1,[2,2,2]);

VertexEdgeFace("1",[pd,fd_2]);

Nohiddenbyfaces("1","phe3d1","phf3d1",["dr,2"],["do"]);

println(pd);

とすると,頂点リストが確かめられます。

[[0,0,4],[4,0,4],[4,4,4],[0,4,4],[0,0,0],[4,0,0],[4,4,0],[0,4,0]]

とコンソールに表示されます。

fd の第2要素は面を表すデータです。これも println(fd_2) で表示してみましょう。

[[4,3,7,8],[4,8,5,1],[4,1,2,3],[6,2,1,5],[6,5,8,7],[6,7,3,2]]

立方体の6つの面を表しています。それぞれの数は,頂点の番号です。

この面を表すデータを用いて,12個の辺のリストを作ります。

まず,面ごとに隣り合う2つづつをとって辺データを作ります。

辺のリストを sidelist とします。1つの面について4つの辺データを作り,これを6つの面についておこないます。

sidelist=[];

repeat(length(fd_2),s,

sd=append(fd_2_s,fd_2_s_1);

repeat(length(sd)-1,t,

v1=sd_t;

v2=sd_(t+1);

sidelist=append(sidelist,[pd_v1,pd_v2]);

);

);

ここで,3行目で sd=append(fd_2_s,fd_2_s_1); としているのは,始点を末尾に追加しているのです。

たとえば,面を表すデータが [1,2,3,4] のとき,辺は [1,2],[2,3],[3,4],[4,1] の4つになります。この4番目のペアを取得するためです。

これで24個のデータができます。(println(sidelist) で表示できます。)辺の数は12ですが、各辺とも2回ずつ数えているので24個になるのです。

これを整理してもいいですが、面倒なので、そのままにしましょう。平面との交点を調べるときに、同じものが2つづつできることになりますが、そのあとで処理します。

== 再掲 ここまで ==

できた辺データ sidelist を println(sidelist) で表示するとつぎのようになります。

[[[0,4,4],[4,4,4]],[[4,4,4],[4,4,0]],[[4,4,0],[0,4,0]],[[0,4,0],[0,4,4]],[[0,4,4],[0,4,0]],[[0,4,0],[0,0,0]],[[0,0,0],[0,0,4]],[[0,0,4],[0,4,4]],[[0,4,4],[0,0,4]],[[0,0,4],[4,0,4]],[[4,0,4],[4,4,4]],[[4,4,4],[0,4,4]],[[4,0,0],[4,0,4]],[[4,0,4],[0,0,4]],[[0,0,4],[0,0,0]],[[0,0,0],[4,0,0]],[[4,0,0],[0,0,0]],[[0,0,0],[0,4,0]],[[0,4,0],[4,4,0]],[[4,4,0],[4,0,0]],[[4,0,0],[4,4,0]],[[4,4,0],[4,4,4]],[[4,4,4],[4,0,4]],[[4,0,4],[4,0,0]]]

ここで、各辺が AB ,BA と逆順ですべて出てきているところがポイントです。

(2) 切頂多面体の頂点データを取得する。

さて、すべての辺が、それぞれ逆順で出てくることがわかりました。したがって、たとえば、辺ABについては,Aから距離dのところと Bから距離dのところに点を取るわけですから、これを、 辺ABについてAからd 、辺BAについてBからd とすればちょうどいいことになります。

スライダを作って分割比を決めます。Cinderellaの描画ツールで線分とその上に点をとります。線分がAB,点がCだとすると、

ratio=|A,C|/|A,B|/2;

で比を決めることができます。|A,C| は点Aと点Cの距離です。2で割っているのは、0から0.5まででよいからです。

スライダの下に「分割比」、点の横に比の値を表示しておきます。

ratio=|A,C|/|A,B|/2;

drawtext([-10,5.5],"分割比",size->16);

drawtext(C.xy+[0.5,-0.2],ratio);

このスライダは,座標軸を回転させると同時に傾いてしまいますが,機能には変わりありません。

この比を使って、各辺を分割します。sidelist のそれぞれの要素を加工してリストを作るので apply()が便利です。

vertex=apply(sidelist,#_1+ratio*(#_2-#_1));

これで、切頂多面体の頂点リストができます。

(3) 頂点データから多面体を描く。

Cindyscriptの関数 convexhull3d() を使って面データを作り、polyhedron() で描きます。

pd0=convexhull3d(vertex);

fd=polyhedron("1",pd0,["Color=[0,0,0.2,0]"]);

VertexEdgeFace("2",fd);

Nohiddenbyfaces("2","phe3d2","phf3d2",["dr,3","Color=blue"],["do"]);

このようになりました。立方体の角が切断されているのがわかります。

仕上げとして、もとの立方体は消して、切頂多面体だけを描きましょう。

始めの方の

VertexEdgeFace("1",[pd,fd_2]);

Nohiddenbyfaces("1","phe3d1","phf3d1",["dr,2"],["do"]);

で、もとの立方体が描かれているので、先頭に // をつけ,コメント化します。

以上をまとめると次のようなスクリプトになります。座標軸は非表示にしておきましょう。

============================================

fd=rpolyhedron("1",6,2*sqrt(3),["nodisp"]);

pd=translate3d(fd_1,[2,2,2]);

//VertexEdgeFace("1",[pd,fd_2]);

//Nohiddenbyfaces("1","phe3d1","phf3d1",["dr,2"],["do"]);

sidelist=[];

repeat(length(fd_2),s,

sd=append(fd_2_s,fd_2_s_1);

repeat(length(sd)-1,t,

v1=sd_t;

v2=sd_(t+1);

sidelist=append(sidelist,[pd_v1,pd_v2]);

);

);

ratio=|A,C|/|A,B|/2;

drawtext([-5.5,-0.5],"分割比",size->16);

drawtext(C.xy+[0.4,-0.1],ratio);

vertex=apply(sidelist,#_1+ratio*(#_2-#_1));

pd0=convexhull3d(vertex);

fd=polyhedron("2",pd0,["Color=[0,0,0.2,0]"]);

VertexEdgeFace("2",fd);

Nohiddenbyfaces("2","phe3d2","phf3d2",["dr,3","Color=blue"],["do"]);

============================================

次の図はfd=polyhedron("2",pd0,["Color=[0,0,0.2,0]"]);

に "nodisp" オプションをつければ,色を塗らないものができます。

1行目の fd=rpolyhedron("1",6,2*sqrt(3),["nodisp"]);

の第1引数の6を、4,8,1,2,20 に変えるだけで他の正多面体の切頂多面体ができます。大きさも sqrt(3)でなく、2でよいでしょう。

四面体

二十面体 面が多くなると描画に時間がかかります。

分割比を 3分の1にすると,冒頭のサッカーボール型ができます。

< 戻る >