曲面上の曲線の描画

Last modified: 2018 年 12 月 30 日 03 時

陰線処理された曲面上の曲線の描画と曲面のワイヤーフレーム表示の別法

主な使用関数: Crv3onsfHiddenData, Crv3onsfparadata, Sf3data, Sfbdparadata, Spacecurve.

ワイヤーフレーム Archimedesの螺旋

曲面のプロットデータを得る記法をまとめると、次のようになる:

グラフ型の曲面 $z=f(x,y)\;((x,y)\in[a,b]\times[c,d])$:

fd=list('z=f(x,y)','x=[a,b]','y=[c,d]','ewsn')
(cf. sample:曲面の陰線処理)

領域上のグラフ型の曲面 $z=f(x(u,v),y(u,v))\;((u,v)\in[a,b]\times[c,d])$:

fd=list('z=f(x,y)','x=x(u,v)','y=y(u,v)','u=[a,b]','v=[c,d]','ewsn')
(cf. 本稿 — sample:曲面上の曲線の描画)

パラメータ付けされた曲面 $p(u,v)=(x(u,v), y(u,v), z(u,v))\;((u,v)\in[a,b]\times[c,d])$ :

fd=list('p','x=x(u,v)','y=y(u,v)','z=z(u,v)','u=[a,b]','v=[c,d]',' ')
(cf. sample:パラメータ付けされた曲面の描画)

曲面の描画

視点をSetangle(70,-65)で設定します (tips: 3次元のプロットの視点・投影方向)。曲面 \begin{align*} z=f(x,y)=x^2-y^2 \end{align*} を中心が原点、半径1の円で囲まれる領域上でプロットするには、

fd=list('z=x^2-y^2', 'x=r*cos(t)','y=r*sin(t)','r=[0,1]','t=[0,2*%pi]','e');
surface=Sf3data(fd,50,50,[50,70]);

とし、(陰線処理されていない) ワイヤーフレーム表示された曲面のデータsurfaceを得ます。また、輪郭線をoutline=Sfbdparadata(fd,100)で得ることができます (cf. sample:曲面の陰線処理)。

Setangle(70,-65);
Setwindow([-1.5,1.5], [-1.5,1.5]);

function f=f(x,y)
  f=x^2-y^2;
endfunction
fd=list('z=f(x,y)', 'x=r*cos(t)', 'y=r*sin(t)',..
        'r=[0,1]', 't=[0,2*%pi]', 'e');

surface=Sf3data(fd, 50, 50, [50,70]);

Windisp(Projpara(surface));

outline=Sfbdparadata(fd, 100);

長方形領域 上のように、fd=list('z=f(x,y)', 'x=x(u,v)','y=y(u,v)',uの範囲,vの範囲,境界の指定)とし、Sf3dataに通して、曲面 $z=f(x,y)$ のプロットデータを得られます。sample:曲面の陰線処理との違いは、x,yはパラメータ表示x=x(u,v),y=y(u,v)で指定できる点です。また、境界の指定は、ewsnから選んで指定します。今の場合、xy平面で円周が曲面の境界にあたるので、右図のように、境界'e'、すなわち、 $\{1\}\times\left[0,2\pi\right]$を指定します。
他の関数の詳細は、sample:曲面の陰線処理と同様です。

[このページのトップへ]

曲面上のArchimedesの螺旋

ここでは、Archimedesの螺旋 $r=K^{-1}\theta\;(K=8\pi)$ を曲面上にうつした曲線を考えてみましょう (冒頭右図)。

C=Spacecurve(...)により、曲面上の曲線Cを用意し、Crv=Crv3onsfparadata(C,outline,fd)によって、曲面による陰線処理をした空間曲線Crvを得られます。また、曲面により陰になった部分はhCrv=Crv3onsfHiddenData()で得られます:

Crv sCrv
K=8*%pi;
C=Spacecurve('[theta/K*cos(theta),..
               theta/K*sin(theta),..
               f(theta/K*cos(theta), theta/K*sin(theta))]',..
             'theta=[0,8*%pi]', 'N=300');
Crv=Crv3onsfparadata(C, outline, fd);
hCrv=Crv3onsfHiddenData();

C=Spacecurve('[x(t),y(t),z(t)]','t=[a,b]','N=整数')で、空間曲線 $c(t)=(x(t),y(t),z(t))$ のプロットデータを得ることができます。N=整数のオプションで曲線の折れ線分割の点の数を指定できます (大きいほどなめらかに描画されます)。デフォルトはN=50で、省略可能になっています。

[このページのトップへ]

曲面のワイヤーフレーム表示

次に、この曲面のワイヤーフレーム表示を求めましょう (冒頭左図)。実は、sample:曲面の陰線処理と同様に、Wireparadata関数を使おうとすると、エラーが出ます (Scilab 5.5.1, KETpic 5.1.0)。おそらく、原点周りの計算が原因でしょう。ここでは、Crv3onsfparadataを利用して、お手製のワイヤーフレームを作ることにします。

for文において、原点を中心とし、半径がR=i/Nの円を曲面の関数 $f(x,y)=x^2-y^2$ で移し曲面上の曲線として、Crv3onsfparadataで陰線処理します。また、直線theta=2*%pi/M*iも同様に処理します。

N=8;
LCrv1=list();
for i=1:(N-1)
  R=i/N;
  tmp1=Spacecurve('[R*cos(t), R*sin(t), f(R*cos(t), R*sin(t))]',..
                  't=[0,2*%pi]', 'N=150');
  LCrv1($+1)=Crv3onsfparadata(tmp1, outline, fd);
end

M=20;
LCrv2=list();
for i=1:M
  theta=2*%pi/M*i;
  tmp2=Spacecurve('[r*cos(theta),..
                    r*sin(theta),..
                    f(r*cos(theta), r*sin(theta))]',..
                  'r=[0,1]', 'N=150');
  LCrv2($+1)=Crv3onsfparadata(tmp2, outline, fd);
end

Windisp(Projpara(LCrv1, LCrv2, outline));

[このページのトップへ]

TeXファイルの書き出し

現在のsceファイルのあるディレクトリの下のtexディレクトリにTeXファイルを書き出しします。
前者はワイヤーフレームの描画、後者は(陰線処理した) Archimedesの螺旋を描画したものです。

Openfile('tex/surface_sample2_1.tex');
Beginpicture('1.5cm');
Drwline(Projpara(outline), 1.5);
Drwline(Projpara(LCrv1, LCrv2), 0.5);
Endpicture(0);
Closefile();

Openfile('tex/surface_sample2_2.tex');
Beginpicture('1.5cm');
Drwline(Projpara(outline), 1.5);
Drwline(Projpara(Crv), 0.5);
Setpen(0.5);
Dashline(Projpara(hCrv), 0.4, 0.4);
Endpicture(0);
Closefile();

[このページのトップへ]

ソースコード

scilabファイル(.sce)のダウンロード
tic();

Setangle(70,-65);
Setwindow([-1.5,1.5], [-1.5,1.5]);

function f=f(x,y)
  f=x^2-y^2;
endfunction
fd=list('z=f(x,y)', 'x=r*cos(t)', 'y=r*sin(t)',..
        'r=[0,1]', 't=[0,2*%pi]', 'e');

surface=Sf3data(fd, 50, 50, [50,70]);

Windisp(Projpara(surface));

outline=Sfbdparadata(fd, 100);

K=8*%pi;
C=Spacecurve('[theta/K*cos(theta),..
               theta/K*sin(theta),..
               f(theta/K*cos(theta), theta/K*sin(theta))]',..
             'theta=[0,8*%pi]', 'N=300');
Crv=Crv3onsfparadata(C, outline, fd);
hCrv=Crv3onsfHiddenData();


N=8;
LCrv1=list();
for i=1:(N-1)
  R=i/N;
  tmp1=Spacecurve('[R*cos(t), R*sin(t), f(R*cos(t), R*sin(t))]',..
                  't=[0,2*%pi]', 'N=150');
  LCrv1($+1)=Crv3onsfparadata(tmp1, outline, fd);
end

M=20;
LCrv2=list();
for i=1:M
  theta=2*%pi/M*i;
  tmp2=Spacecurve('[r*cos(theta),..
                    r*sin(theta),..
                    f(r*cos(theta), r*sin(theta))]',..
                  'r=[0,1]', 'N=150');
  LCrv2($+1)=Crv3onsfparadata(tmp2, outline, fd);
end

Windisp(Projpara(LCrv1, LCrv2, outline));

Openfile('tex/surface_sample2_1.tex');
Beginpicture('1.5cm');
Drwline(Projpara(outline), 1.5);
Drwline(Projpara(LCrv1, LCrv2), 0.5);
Endpicture(0);
Closefile();

Openfile('tex/surface_sample2_2.tex');
Beginpicture('1.5cm');
Drwline(Projpara(outline), 1.5);
Drwline(Projpara(Crv), 0.5);
Setpen(0.5);
Dashline(Projpara(hCrv), 0.4, 0.4);
Endpicture(0);
Closefile();


T=toc();
minute=floor(T/60);
second=floor(T-60*minute);
disp(strcat([string(minute), ' minutes ', string(second), ' seconds']));

[このページのトップへ]