3次元グラフ表面の色づけ

通常の方法

3次元グラフの表面はsplotの後にwith pm3dをつけることで色をつけることができます。この場合、色はz座標で指定されます。

実行例を以下に示します。

set xrange [-1*pi:1*pi]
set yrange [-1*pi:1*pi]

set isosamples 50

splot sin(x)*sin(y) with pm3d

上の例のset isosamples 50という部分では、メッシュの数を指定しています。デフォルト値は10なので、これを多少増やしておかないと下のように見栄えのよくない図になってしまいます。

媒介変数表示の場合も同様です。ただし、視点に近い部分がちゃんと手前に来るように描画するように、set pm3d depthorderというコマンドを追加しています。

set parametric
set urange [0:pi]
set vrange [0:2*pi]
set isosamples 50
set pm3d depthorder
set view 75,45

set xrange [-1:1]
set yrange [-1:1]
set zrange [-1:1]
splot sin(u)*cos(v),sin(u)*sin(v),cos(u) with pm3d

より自由な色指定

3次元グラフの表面の色をもっと自由に指定したい場合は、usingの4つ目の引数で色を指定します。ただし、この機能はusingを使うので、当然データファイルのプロットにしか使えません。ある関数をプロットする場合は擬似ファイル"+""++"を使う(gnuplot4.3以降)か、set tableを使っていったん別にデータファイルを作っておく必要があります。

まず、擬似ファイル"++"を使うやり方を紹介します。擬似ファイル"++"はgnuplot4.3以降に新しく加わった機能で、xrangeyrangeで指定した範囲内にset samples(x方向の点数)とset isosamples(y方向の点数)で指定した数の点のファイルがあるものとして解釈されます。下の例ではusingの4番目の引数に(sin($1+$2*2))を指定しているので、sin(x+2*y)の値で決まる色が表面につきます。

set xrange [-1*pi:1*pi]
set yrange [-1*pi:1*pi]

set samples 50
set isosamples 50

splot "++" using 1:2:(sin($1)*sin($2)):(sin($1+$2*2)) with pm3d

次に、set tableを使ってデータファイルを別に作っておく例を示します。下の例ではset table "table.dat"というコマンドを使って、"table.dat"というファイルにいったんsin(x)*sin(y)をプロットした結果を出力しています。その後、unset tableでデータファイルへの出力を解除し、その後グラフを出力しています。出力結果は上の例と全く同じになります。

set xrange [-1*pi:1*pi]
set yrange [-1*pi:1*pi]

set samples 50
set isosamples 50

set table "table.dat"
splot sin(x)*sin(y)
unset table

splot "table.dat" using 1:2:3:(sin($1+$2*2)) with pm3d

媒介変数で表すようなグラフの場合は、set tableを使うほうがよさそうです。下の例では、"table2.dat"というファイルにデータを書き出していますが、媒介変数表示の場合はxとyの値(後で図を出力するときには媒介変数uとvとしてそれぞれ使われる)しか必要ないので、定数関数0をデータファイルに出力しています。その後xrangeなどを指定しなおしてから図を出力しています。

set xrange [0:pi]
set yrange [0:2*pi]

set samples 100
set isosamples 100
set pm3d depthorder

set table "table2.dat"
splot 0
unset table

set xrange [-1:1]
set yrange [-1:1]
set zrange [-1:1]

splot "table2.dat" using (sin($1)*cos($2)):(sin($1)*sin($2)):(cos($1)):(sin($2*2)) \\
      with pm3d

高度な色指定の例(光が当たっている物体)

上のような4つ目のusingパラメータを使用した表面色指定の例として、光の当たっているように見える色のつけ方を紹介します。

媒介変数形式で指定されている曲面

を考えます。この曲面に光がベクトル

で表される方向から当たっているとします。ここでは、この曲面の色は光の方向sと曲面の法線nとの内積で決まるという簡単なモデルを考えます。媒介変数で表される曲面の場合は法線nは曲面の2つの接線

の外積

で表すことができます。従って、usingの第4引数には

を与えればいいわけです。

一つ例を示します。set palette defined ( 0 "dark-blue" , 1 "cyan")で、濃い青から水色へと徐々に変わっていく色使いを指定しています。light(u,v)関数で三項演算子を使っているのは、接線ベクトルのうちの一方がゼロになってしまう場合を回避するためです。もし法線ベクトルが定義できない場合、わずかにずれた場所のlight(u,v)で代用します。

# 表面の媒介変数関数
Fx(u,v)=sin(u)*cos(v)
Fy(u,v)=sin(u)*sin(v)
Fz(u,v)=cos(u)

# 光の方向
sx=1.0
sy=1.0
sz=1.0

# 微分用の微小数
h=0.000001

# Fx,Fy,Fzのuおよびvによる偏微分
dFxu(u,v)=(Fx(u+h,v)-Fx(u-h,v))/(2.0*h)
dFyu(u,v)=(Fy(u+h,v)-Fy(u-h,v))/(2.0*h)
dFzu(u,v)=(Fz(u+h,v)-Fz(u-h,v))/(2.0*h)
dFxv(u,v)=(Fx(u,v+h)-Fx(u,v-h))/(2.0*h)
dFyv(u,v)=(Fy(u,v+h)-Fy(u,v-h))/(2.0*h)
dFzv(u,v)=(Fz(u,v+h)-Fz(u,v-h))/(2.0*h)

# 法線ベクトルの各成分 n = lu x lv
nx(u,v)=dFyu(u,v)*dFzv(u,v)-dFyv(u,v)*dFzu(u,v)
ny(u,v)=dFzu(u,v)*dFxv(u,v)-dFzv(u,v)*dFxu(u,v)
nz(u,v)=dFxu(u,v)*dFyv(u,v)-dFxv(u,v)*dFyu(u,v)

# 光の方向ベクトルsの長さ
s_length=sqrt(sx**2+sy**2+sz**2)
# 法線ベクトルnの長さ
n_length(u,v)=sqrt(nx(u,v)**2+ny(u,v)**2+nz(u,v)**2)

# 光の方向ベクトルsと表面の法線ベクトルnの内積で色を決める
light(u,v)=(n_length(u,v)!=0.0 ? \
           (sx*nx(u,v)+sy*ny(u,v)+sz*nz(u,v))/(s_length*n_length(u,v)) :\
           light(u+h,v+h))

set xrange [0:pi]
set yrange [0:2*pi]
set samples 100
set isosamples 100

# いったんパラメータファイルを作る
tablefile="table3.dat"
set table tablefile
splot 0
unset table


set xrange [-1:1]
set yrange [-1:1]
set zrange [-1:1]
set pm3d depthorder
set view 60,30

# 色使いの指定
set palette defined ( 0 "dark-blue" , 1 "cyan")

splot tablefile using (Fx($1,$2)):(Fy($1,$2)):(Fz($1,$2)):(light($1,$2)) \
      with pm3d

上のように光が当たっている感じの出ている球になりました。

関数を変える場合はFx(u,v),Fy(u,v),Fz(u,v)を変更すればOKです。以下では

Y(u,v)=sqrt(5.0/(4.0*pi))*0.5*(3.0*cos(u)**2-1) # 球面調和関数
Fx(u,v)=sin(u)*cos(v)*abs(Y(u,v))
Fy(u,v)=sin(u)*sin(v)*abs(Y(u,v))
Fz(u,v)=cos(u)*abs(Y(u,v))

のように球面調和関数(l=2,m=0)に変更した場合の例を示します。(各方向のrange[-0.65:0.65]に変更しています。)

このように立体感のある球面調和関数が描けました。