曲面
空間内に曲面を描くとき,3Dグラフィックスでは,ワイヤフレームモデルとサーフェスモデルの2つの描き方があります。球面でいうと,ワイヤフレームモデルは経線と緯線が描かれた地球儀のようなものです。サーフェスモデルの場合はレイトレーシングという方法を用いて,光が当たっているような表面を描きます。また,隠れている線を表示しない「陰線処理」も行います。
KeTCindyでは,陰線処理は行いますが,レイトレーシングは行いません。したがって,球面のサーフェスモデルでは単に円にしか見えないものになります。放物面なども同様です。しかも,サーフェスモデルでは,陰線処理が複雑になるため,描画に非常に時間がかかります。曲面によっては描画されるまで2分以上かかるものもあります。この問題を解決するために,Cコンパイラを起動して描く方法をサポートしています。Cコンパイラの環境を設定する方法は,付録の「ダウンロードとインストール」を参照してください。以下では,C言語(gcc)の環境があるものとして進めます。
曲面描画の手続き
曲面は Sf3data() で陰線処理のないワイヤフレームモデルが描かれます。およその形状はこれでわかりますが,きちんと陰線処理を行うには, Sfbdparadata(),Wireparadata(),Crvsfparadata()を使います。ただし,単にこれを使うだけでは曲面は描画できません。次のような描画手続が必要です。
(1) Startsurf() で陰線処理をした面描画の宣言をする。 (2) 描画関数でプロットデータを作る。 (3) ExeccmdC() で,C 言語を用いてまとめて描画する。
これで描けますが,描画後にスライダで視点を変えようとすると動きが遅くなります。そのために,スライダ上の点を選択したかどうかを判定する関数Isangle() を用意しています。角度スライダを選択しているときは true そうでないときは false を返します。
そこで,Drawスロットのページには次のようなひな形を作っておくのがよいでしょう。
Putaxes3d(5);
Xyzax3data("","x=[-5,5]","y=[-5,5]","z=[-5,5]");
fd=["z=4-(x^2+y^2)","x=r*cos(t)","y=r*sin(t)",
"r=[0,2]","t=[0,2*pi]","e"];
if(Isangle(),
Sf3data("1",fd);
,
Startsurf();
Sfbdparadata("1",fd);
// Wireparadata("1","sfbd3d1",fd,12,12);
Crvsfparadata("1","ax3d","sfbd3d1",fd);
ExeccmdC("1");
);
fd が曲面の方程式です。下図左のような,座標軸を陰線処理した回転放物面が描かれます。 Wireparadata を有効にして, Crvsfparadata をコメント化すると,右のような陰線処理されたワイヤフレームモデルが表示されます。下のスライダで視点を変えている間は,陰線処理のないワイヤフレームモデルが表示されます。
 

曲面の切断
曲面を平面で切断する例として,円錐曲線の描画をします。曲面と平面の交線を求めるには,Sfcutparadatacdy() を使います。
Sfcutparadatacdy(name,equation,list,options)
equation は切断する平面の方程式,list は曲面の式です。
fd=[
"p",
"x=r*cos(t)","y=r*sin(t)","z=2*(2-r)",
"r=[0,2]","t=[0,2*pi]","e"
];
Startsurf();
Sfbdparadata("1",fd);
Sfcutparadatacdy("1","y+2*z=3",fd);
ExeccmdC("1");
これだけで,円錐を描き,断面の楕円を描くことができます。
 
断面を陰線処理するには,Sfcutparadatacdy() に “nodsip” オプションをつけて非表示にしておき,Crvsfparadata() で陰線処理して表示します。ここで,切断面は sfc1n13d です。
Startsurf();
Sfbdparadata("1",fd);
Sfcutparadatacdy("1","y+2*z=3",fd,[“nodisp”]);
Crvsfparadata("1","sfc1n13d","sfbd3d1",fd);
ExeccmdC("1");

この円錐は,底面が半径2の円,頂点が (0,0,4) ですので,平面の法線ベクトルを (0,2,1) にして,方程式を 2*y+z=2 にすれば断面は放物線になり,y=-1 にすれば双曲線になります。
次に断面のプロットデータを閉曲線になるように作り,色を塗ります。プロットデータ sfc1n13d を Paraptで画面上の座標に変換し,Listplot()で輪郭を描いてShadeで色塗りします。
Startsurf();
Sfbdparadata("1",fd);
Sfcutparadatacdy("1","y+2*z=3",fd,["nodisp"]);
ExeccmdC("1");
pd=apply(sfc1n13d,Parapt(#));
Listplot("1",pd);
Shade(["sg1"],["Color=[0,0,0.2,0]"]);

次に,断面だけでなく,切断している面も表示するようにしましょう。切断面は法線ベクトルを使って表します。
Startsurf();
Putpoint3d("A",[0,-1,2],["fix"]);
nv=[0,1,2]; // 法線ベクトル
Perpplane("B-C","A",nv,"put");
v1=B3d-A3d;
v2=C3d-A3d;
P1=A3d+3*v1+2*v2;
P2=A3d+(-3)*v1+2*v2;
P3=A3d+(-3)*v1-4*v2;
P4=A3d+3*v1-4*v2;
VertexEdgeFace("1",[P1,P2,P3,P4],["Edg=nogeo"]);
Sfbdparadata("1",fd);
Sfcutparadatacdy("1","y+2*z=3",fd,["nodisp"]);
ExeccmdC("1");
pd=apply(sfc1n13d,Parapt(#));
Listplot("1",pd);
Shade(["sg1"],["Color=[0,0,0.2,0]"]);

切断面を変えたら,方程式に合わせて法線ベクトルを変えれば,放物線,双曲線も描けます。
nv=[0,2,1] nv=[0,1,0]
2*y+z=0 y=-1
<.戻る >