切頂多面体
切頂多面体とは、多面体の各頂点を同じ割合で切り取った多面体です。切頭多面体ともいいます。有名なものはサッカーボールの形でしょう。切頂二十面体です。
では、正多面体に対して切頂多面体を描く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にすると,冒頭のサッカーボール型ができます。
< 戻る >