A User’s Manual for MEPOTEX ∼ METAPOST in TEX ver 3.52 → 3.80 ∼ みなも このリーフレットでは,前々回 ( 2011/01/15 ) , 前回 ( 2012/12/21 ) および今回 ( 2014/04/04 ) のバージョンアップ で追加された新機能を中心に説明します。 新機能一覧 1 1.1 ver3.70 → 3.80 — 2014/04/02 ● Y =mptLabel 命令を拡張しました。「ラベルをつけたい位置が混雑しているとき,少し離れた位置にラベルを配置し て,ラベルとラベルが指すものを矢印などでつなぐ」といったことが簡単にできるようになりました。 ● 逆三角関数を定義しました。度数法で返す Arcsind , Arccosd , Arctand と弧度法で返す Arcsin , Arccos , Arctan です。 ● 前回のバージョンアップで導入した xfill と xfilldraw で,色指定に numeric 値を使えるようにしました。 たとえば,xfill(0.8) pth; は xfill(0.8white) pth; の意味です。つまり,グレー指定を簡単にするための拡 張です。 ● グラフなどで,点の x 座標,y 座標を表示する際,点から座標軸に垂線を引くことがよくあると思いますが,その 垂線 ( path 値 ) を生成する命令 Pline , Pxline , Pyline を作りました。 ● TEX 側がコマンド Y =mag を使って文書全体を拡大・縮小している場合 — 奥村さんの js∼.cls などで採用されて いる手法です — には,当然,図も拡大・縮小されるため,たとえば Y =begin{MPpic}<1cm>(3,4)(0,0) としても 単位長は 1cm にはなりません。 Y =mag を使っている場合,TEX では実寸法を 1cm とするには 1truecm のように単位の前に true をつければいい のですが,METAPOST では truecm 等が ( デフォルトでは ) 定義されていないので,MEPOTEX で truecm 等を 使うとエラーになります。そこで今回,MEPOTEX で truecm 等を使えるように, 「定義」を追加しました∗1 。 これによって,Y =begin{MPpic}<1truecm>(3,4)(0,0) とか Y =mptLabel{(w,0)}[b]<0truemm,0.5truemm>{1} な どの指定が可能になります。 なお,今回定義したのは,truecm , truemm , truept , truebp , truein の 5 つの単位です。 ● true つき単位の定義に伴い,各種デフォルト値を true つき単位で定義するか,true なし単位で定義するか,と いう問題が発生します。一例を挙げると,座標軸の矢印の長さは 6pt と定義されているのですが,これは Y =mag で 文字を大きくした場合, ( たとえば x 軸なら ) 座標を示す x の文字が大きくなったとき,それに追従して矢印も大きくすべき なのか 図形の一種だから図が実寸大なら矢印も実寸大にすべき なのか,どちらも考え方としてはアリです。 そこで,今回パッケージオプションに defaultTP を新設しました。( オプション名の由来は「デフォルト値を truept で定義」のつもりです。) MEPOTEX では通常デフォルト値を pt 単位で定義していますが,Y =usepackage[defaultTP]{MePoTeX} とすれ ば,デフォルト値が truept で定義されます∗2 。 ∗1 T X 側で Y =mag の値を読み取って,それをもとに cm 等を補正したものを truecm としただけですので, 「真の寸法」ではなく「補正寸法を補正し E たもの」ですけど。 ∗2 なお,この機能を実現するために,寸法レジスタを 1 個新設しています。 1 ● 一部の処理系では, 「第 1 象限以外がカットされる」という現象が起こるようです。以前,画像の取り込みに使って いる graphicx.sty の取り込み命令の clip オプションの関係で,同様の現象が起こり,それには ( オプションを 明確に指定することで ) 対処したのですが,対処済みバージョンを使ってもなお「第 1 象限以外がカットされる」 処理系があるようです。 処理系側の設定で何とかなるはずだとは思うのですが,うちの処理系とは別のものですので実験ができないことと, 今後 ( いまうまく働いている ) 処理系のデフォルトもそういった仕様に変わる可能性がなきにしもあらずですの で,MEPOTEX 側で対応するすべを用意しました。 具体的には Y =usepackage[shiftOrigin]{MePoTeX} のように shiftOrigin オプションをつけて MEPOTEX を呼 び出します∗3 。こうしておけば,METAPOST 側で画像全体が第 1 象限に収まるよう原点 ( origin ) を移動 ( shift ) し,移動量を別ファイルに保存します。で,保存された移動量を TEX 側で読み込んで,原点を本来の位置に戻し て画像を貼り付けます∗4 。 ● パッケージオプションの makesubdir , Makesubdir ( 生成するファイルをサブディレクトリをつくってそこに入 れるオプション ) は,かなり前から事実上使えなくなっていますので,今回廃止しました∗5 。 これに伴い,OS 依存が無くなりましたので,WinXP , Win , DOS , UNIX の各種オプションも廃止となります。 1.2 ver3.60 → 3.70 — 2012/12/21 ● グラフの端点に描く白丸や黒丸を生成する命令を新設。 ● 破線・点線の指定法をちょっと簡略化。 ● 線を描くときに,線の太さ,色,線種を指定できるようにした xdraw , 塗りつぶすときに色を指定できるようにし た xfill , これら 2 つの機能を合わせた xfilldraw などを新設。従来の withcolor ∼ とかの指定より大分楽に 指定できるはずです。 ● 従来 mpt3D.mp 所収の kansuQ を使うためには,使う前に setunitlength 命令で単位長を指定する必要がありま したが,単位長が指定されていないときは,単位長を ( x , y , z 方向とも ) w と解釈するよう kansuQ の定義を書 き換えました。( これで setunitlength の使用頻度は激減すると思います。) ● 空間内の 2 パラメータで表された曲面を描く命令 drawSurface を新設。もちろん曲面を描くといっても実際には 細かい「長方形」( 辺は曲線ですが ) に分割して多面体として描いているに過ぎません。これに関して,多面体の 描画方法指定命令に,SetPolyUra , SetPolyOmote , SetPolyBoth を追加。 ● dir , Dir で角度の単位が弧度法になったものを新設。名前は Asymptote の同種命令に合わせて expi , Expi に しました∗6 . また,円柱座標での空間ベクトル ( color 値 ) の指定ができるよう,rdh , rrh という命令を新設しました∗7 . ver3.52 → 3.60 — 2011/01/15 ● 3 辺の長さ ( の比 ) をもとに,三角形の 3 頂点の相対位置を設定する METAPOST マクロを新設。 ● 空間図形で,座標軸を描く TEX マクロを新設。平面の Y =mptXaxis 等に対応するマクロです。 ● 空間で z 軸以外の向きを「北極方向」と見なした「緯度・経度」から単位方向ベクトルを生成する METAPOST マ クロを新設。 ∗3 shiftOrigin の O は大文字です。 オプション使用時には移動量を保存したファイルが生成されます。ファイル名は leavefile オプション指定時は 「@ ベースファイル名. 画像番号」,そうでないときは, 「@ベースファイル名.sft」です。 ∗5 セキュリティーの問題で,現在の T X では「サブディレクトリの生成を T X ソースからの命令で行う」といった類のことを禁止しています。 E E 禁止しているといっても「禁止する設定がデフォルト」というだけですので,禁止を解除することは不可能ではないはずですが,セキュリティーに穴 を空けてまで実現したい機能でもないと思いますので,今回すっぱり廃止しました。 ∗6 名前の由来はオイラーの公式 exp(iθ) = cos θ + i sin θ と思われます。 ∗7 名前の由来はごく単純に,radius degree(radian) height の頭文字です。 ∗4 この仕様のため,shiftOrigin 2 ● 「空間内の平面」を表現するときの path を生成する METAPOST マクロを新設。 ● 空間内のボールの影付きを表現するグラデーションで,分割数を設定できるようにしました。 ● 電子回路図で,抵抗が昔風のぎざぎざではなく箱で表現する ( 世界共通 ? ) ことが,学校現場でも一般的になって 来つつあるようですので,箱タイプも出力できるようにしました。 ● これは新機能ではなくバグフィックスですが,角柱・角錐マクロで,( 俯角が大きいときなど ) 「すべての母線が 表側」あるいは「すべての母線が裏側」にくるときの処理を入れ忘れていたので,その処理を追加。 角数が多いときはあまり起こりませんが,三角錐 ( 四面体 ) ではむしろすべての母線を表側に描くことの方が多い ので,結構起こります。 ● 角柱・角錐・正多面体マクロで,既存の「枠線のみ」「面塗りつぶし」に加え, 「何も描かない」をデフォルトで用 意しました。頂点のみ設定して,辺は自分で描く場合にご利用下さい — 特定の辺を取り去った図や,隠線処理を 細かくやりたいときに便利です。 マクロ紹介とサンプル ver3.70 → 3.80 — 2014/04/02 2 2.1 Y =mptLabel の拡張 — MePoTeX.sty に収録 今回 TEX 側のマクロに関する変更は Y =mptLabel の機能拡張だけです。 =mptLabel は従来 Y Y =mptLabel{配置点}[ラベル位置]<横補正, 縦補正>{ラベル文字列} Y =mptLabel[key=val 列]{配置点}{ラベル文字列} のいずれかの形で用いていましたが,これに加え, Y =mptLabel{配置点}[ラベル位置][key=val 列]<横補正, 縦補正>{ラベル文字列} も可能となりました。 新たな形式における key=val 列 は従来の key=val 列 と同じものが使えます。たとえば,デフォルトでは文字の背 景を白抜きするようになっていますが,白抜きを止めたいときには,たとえば Y =mptLabel{(w,0)}[b][fillcolor=none]<0mm,0.5mm>{1} のようにできます。 また,key=val 列 に使える「キー」も,以下の通りいくつか新設しています。 • dist 指定した値だけ,ラベルを配置点から離して置き,ラベルと配置点とを線で結びます∗8 。離す量は,METAPOST が理解できる pair 値ならなんでも OK ですが,コンマを含むときは,値全体を {} で囲うことを忘れないでくだ さい∗9 。 例えば,dist=5mm*dir35 とか dist={(5mm,7mm)} とかです。 • dist 関連のキー dist キーを使用するとき, 「ラベルと配置点とを結ぶ線」については,Y =mptDrawPath と同じく linetype , linecolor , pensize , pen , arrowtype , arrowlength , arrowangle , arrowcurve , arrowdiradj の「キー」 も有効です∗10 。ただし,pensize ( 線の太さ ) のデフォルト値は,Y =mptDrawPath とは異なり 0.4pt です。 また,線を曲げるために arcdir キーも使えます。たとえば,arcdir=10 とすれば,線の射出方向が 10◦ ずれ,曲 線を描いて目標点 ( 配置点 ) に達します∗11 。 ∗8 線で結ぶところが xshift 等と違うところです。 key=val の境界と誤認されるためです。 ∗10 それぞれの意味については,マニュアルの Y =mptDrawPath の項目をお読みください。 ∗11 デフォルトは 0 で,この場合「直線」となります。 ∗9 囲っていないと,コンマが 3 • shift これは,従来からあった xshift , yshift をまとめて指定するためのもので, xshift=1mm,yshift=2mm は shift={1mm,2mm} と同じ です。値を { } で囲うのを忘れないでください。 2.2 xfill , xfilldraw の拡張 — MePoTeX.mp に収録 塗りつぶしの色指定について,グレーを簡単に指定できるように,numeric 値を使えるようにしました。 たとえば,xfill(0.8) pth; は xfill(0.8white) pth; の意味です。 以下のサンプルも参照してください。 2.3 逆三角関数 — mptMath.mp に収録 METAPOST にはもともと「ベクトルから方向角を求める」という,実質的に逆三角関数と等価な機能があるのですが, これを,より初等関数の逆三角関数に近い形で使えるようにしたものを用意しました。 度数法で返す Arcsind , Arccosd , Arctand と弧度法で返す Arcsin , Arccos , Arctan です。 これらは単項演算子として機能しますので,sqrt などと同様に使えます。 2.4 座標軸への垂線 — mptMath.mp に収録 グラフなどで,点の x 座標,y 座標を表示する際,点から座標軸に垂線を引くことがよくあると思いますが,その垂 線 ( path 値 ) を生成する命令を作りました∗12 。 Pline(点) — 指定した点 ( pair 値 ) から x 軸,y 軸に引いた垂線を生成します。 Pxline(点) — 指定した点 ( pair 値 ) から x 軸に引いた垂線を生成します。 Pyline(点) — 指定した点 ( pair 値 ) から y 軸に引いた垂線を生成します。 使い方は以下のサンプルを参照してください。 2.5 今回改訂の命令のサンプル y サンプルは,右図のようになります ( ソースは以下の通り )。 Y =mptLabel{(x0,0)}[t]<0mm,-0.5mm>{$a$} Y =mptLabel{(x1,0)}[t]<0mm,-0.5mm>{$b$} b2 a2 Y =begin{MPpic}<12mm>(0,0)(2,2) Y =sendMP{xfill(0.8) kansu(t*t)(-1/1.1,1.1,50)--cycle; z0=(-w/1.1,h/1.21); z1=(1.1w,1.21h);} 1 S a O Y =mptLabel{(0,h)}[br]<-0.5mm,0mm>{1} Y =mptLabel{(0,y0)}[b][dist=8mm*dir140,arcdir=-30,arrowtype=->]<0mm,0.5mm>{$a^2$} Y =mptLabel{(0,y1)}[b][dist=5mm*dir50,arcdir=20,arrowtype=->]<0mm,0.5mm>{$b^2$} Y =mptLabel{(0.5w,0.5h)}[l][dist=10mm*dir10,arrowtype=-*,arrowlength=3pt]<0.5mm,0mm>{$S$} Y =mptLabel{origin}[tr]<-0.5mm,-0.5mm>{O} Y =mptXaxis|-1.5w==1.5w>[l]<0.5mm,0mm>{$x$} Y =mptYaxis|-0.5h==2h>[b]<0mm,0.5mm>{$y$} Y =sendMP{xdraw(0.8pt) kansu(t*t)(-sqrt2,sqrt2,80); xdraw(0.8pt) extLine(z0,z1)(0.25,0.25); for n=0,1: xdraw(0.4pt,hasen()) Pline(z[n]); endfor} Y =end{MPpic} ∗12 命令の先頭の P が大文字であることに注意してください。 4 b x マクロ紹介とサンプル ver3.60 → 3.70 — 2012/12/21 3 3.1 tanten と Tanten — MePoTeX.mp に収録 指定した点に,白丸を描く命令が tanten , 黒丸を描く命令が Tanten です。次の書式で使います。 tanten(座標); Tanten(座標); (座標) は tanten(3w,2h) のように (x 座標,y 座標) の形の 2 つの numeric 値で書くことも,(z1) のように 1 つ の pair 値で書くこともできます。 丸のサイズは標準で半径 2pt , 白丸の線の太さは標準で 0.4pt ですが,これは変更できます。変更するときは, tanten(座標)(半径); tanten(座標)(半径, 線の太さ); Tanten(座標)(半径); のいずれかの形で使います。半径 , 線の太さ はどちらも numeric 値です。 サンプルは,3.3 の項目でまとめて挙げます。 3.2 hasen と tensen — MePoTeX.mp に収録 METAPOST 本来の命令で破線を引くには,たとえば, draw (0,0)--(w,w) dashed evenly; などとします。 dashed は線種を変える命令∗13 です。 「破線」を指定しているのは evenly の部分∗14 で,これは METAPOST の dashpattern という命令で生成される picture 値定数です。 picture 値ですので拡大縮小もできます。たとえば,evenly は 3pt の線分と 3pt の空白を繰り返すのですが,これ を 1/2 に圧縮 ( 1.5pt の線分と 1.5pt の空白に ) したいなら,evenly scaled1/2 とします。 さて,この破線なのですが,A4 用紙に大きく図を描く場合は evenly で十分なのですが,高校数学のように B5 や A5 を基準とする冊子に使う図としては目が粗すぎます。かといって evenly scaled1/2 では入力が面倒です。そこで今回, これを短縮した命令を作りました。 まず,hasen(倍率) について。これは 1.5pt の線分と 1.5pt の空白で作られた破線を,倍率 倍したものを作ります。 倍率 は numeric 値です。(倍率) の部分を () のように空欄にすることもでき,この場合は 倍率 に 1 が指定されたも のとみなします。 次に,tensen(倍率) について。これは 2.5pt の空白と現在のペンの太さの点で作られた点線を,倍率 倍したものを 作ります。使い方は hasen と同様です。 これらは evenly 等の代わりに使えますが,次項の命令と組み合わせて使うとさらに便利だと思います。というわけ で,サンプルは次の項目とまとめて挙げます。 3.3 拡張描画命令 xdraw , xfill , xfilldraw — MePoTeX.mp に収録 METAPOST で線を描くとき,線の太さや色,線種などをフルに指定すると,かなり冗長な表現になります。たとえば, 直径 1pt の丸ペンで赤い破線を座標 (0,0) から (w,w) まで引くには,次のような命令を書く必要がありました。 draw (0,0)--(1,1) withpen pencircle scaled 1pt withcolor red dashed evenly; これを多少なりとも簡略化しようと,今回いくつかの命令を新設しました。 たとえば今回新設した命令を使うと,上の例は xdraw(1pt,red,evenly) (0,0)--(1,1); と記述でき,かなり簡略化できているのがわかると思います。 今回新設した「拡張描画命令」は次の 3 つです。 xdraw(属性列) , xfill(色) , xfilldraw(色)(属性列) まず,xdraw(属性列) について。 属性列 とは,線の太さや色,線種 ( 破線とか点線とか ) を,コンマで区切って並べたものです。もう少し具体的にい うと,1pt のような numeric 値は線の太さ,red や (1,0,0) のような color 値は線の色,evenly や前述の hasen() ∗13 英語で dash line は破線ですが,破線以外でも METAPOST では dashed を使うので,ここの dashed は線種を変える命令ぐらいに思って下さ い。あと,さらに細かいことをいうと,dashed は単独で使える命令ではなく, 「draw 巡回パス dashed ∼ ;」という形で使う draw 命令の一部です。 ∗14 evenly は,破線を構成する線分と空白の長さを「均等に」という意味です。 5 などの picture 値は線種を表すものとして解釈されます。これらを順不同で並べます。線の太さだけとか,線の太さと 色だけとかでも構いません。同種の指定が複数ある場合は,最後の指定が有効になります ( たとえば xdraw(1pt,2pt) は xdraw(2pt) と同じです。) 次に xfill(色) ですが,これは単純に塗りつぶしの色を指定するだけです ( 色 はもちろん color 値 ) . たとえば, xfill(0.8white) circle(origin,w) は fill circle(origin,w) withcolor 0.8white と同じです。 最後に,xfilldraw(色)(属性列) ですが,これは xfill(色) で塗りつぶした後,xdraw(属性列) で境界線を引くの に相当します。METAPOST が本来もっている filldraw では,塗りつぶしの色と境界線の色が同じになってしまいます が,xfilldraw なら 1 つの命令で塗りつぶしの色と境界線の色が異なる図形を描けます。 なお,MEPOTEX では,新しく確保した picture 値変数に図を描き込む drawpic などの命令を用意していますが,こ れの「拡張描画」版も新設しました。たとえば,picture 値変数 pct に「拡張描画」するには, xdrawpic(pct)(属性列) , などとします。 xfillpic(pct)(色) , xfilldrawpic(pct)(色)(属性列) これまでの命令でサンプルを作ると,右図のようになります ( ソースは以下の通り ) . Y =begin{MPpic}<5mm,3mm>(7.5,6|5)(-2.5,0) Y =mptLabel{(w,0)}[b]<0mm,0.5mm>{1}% y 最初の 4 行は座標の書き込み O Y =mptLabel{(3w,0)}[tl]<0mm,-0.5mm>{3} Y =mptLabel{(0,-3h)}[r]<-0.5mm,-0.5mm>{$-3$} 1 3 Y =mptLabel{(0,-4h)}[r]<-0.5mm,-0.5mm>{$-4$} Y =mptLabel{origin}[br]<-0.5mm,0.5mm>{O}% 原点に O を書き込み Y =sendMP{xfill(0.8white) kansu(t*t-2t-3)(-1,3,50)--cycle;}% x −3 −4 塗りつぶし Y =mptXaxis|==>[l]<0.5mm,0mm>{$x$} Y =mptYaxis|==>[b]<0mm,0.5mm>{$y$}% 座標軸描画 Y =sendMP{xdraw(hasen(1.5)) kansu(t*t-2t-3)(-2.1,4.1,70);% グラフ (粗めの破線) xdraw(0.8pt) kansu(t*t-2t-3)(0,3,50);% グラフ (定義域内:太実線) xdraw(0.4pt,hasen()) (w,0)--(w,-4h)--(0,-4h);% 座標の数値と結ぶ細破線 tanten(0,-3h); Tanten(3w,0);}% 端点の白丸,黒丸 Y =end{MPpic} 3.4 odraw — MePoTeX.mp に収録 空間でねじれの位置にある 2 直線を紙の上の平面図として表現する際に,よく,手前の直線で奥の直線を切るという ことを行います。このためには,奥の線を引いた後 「手前の線を太い白線∗15 で書く」「手前の線を本来の太さで書く」 の 2 つの操作が必要ですが,これをまとめてやってくれる命令を新設しました。 命令の書式は odraw(始点除外, 終点除外, 消し幅)(属性列) です。このうち,(属性列) については前項で説明した xdraw のそれと同じ意味ですので,ここでは (始点除外, 終点除 外, 消し幅) について説明します。 消し幅 は「太い白線」の幅です。3pt などの numeric 値で指定します。 始点除外 , 終点除外 は「太い白線」を始点,終点付近に引かないようにするためのパラメータで,0 から 1 の numeric 値で指定します。 「手前の線」で切りたい「奥の線」以外に, 「手前の線」に「接続する線」がある場合, 「手前の線」の端 から端まで「太い白線」を引いてしまうと, 「接続する線」が欠けてしまうため,始点,終点付近に「太い白線」を引き たくありません。この場合にこれを使います。例えば,始点除外 , 終点除外 をともに 0.1 に設定すると,始点,終点そ れぞれから「手前の線」の length の 10 % だけ「太い白線」の引かれない部分ができます。 ∗15 正確には background 色の線です。background は通常 white になっているので,結果的に白線になるわけです。background が別の色に設定 されていれば当然その色になります。 6 なお,(始点除外, 終点除外, 消し幅) は値を省略してデフォルト値にお任せすることもできます。デフォルト値は,始 点除外 , 終点除外 がともに 0 ( 除外部分なし ) , 消し幅 が 3pt です。(始点除外, 終点除外, 消し幅) が () のように空欄 であればすべてデフォルト値,(0.2) のように 1 つだけ numeric 値が入っていれば 始点除外 のみの設定,(0.2,0.3) のように 2 つだけ numeric 値が入っていれば 始点除外 , 終点除外 のみの設定となります。 サンプルは次の通りです。手前にある辺 AC が奥にある線分 BD を切っていることにご注意下さい。( rdh について は次項で説明します。) A Y =begin{MPpic}<10mm>(5,3.2|1)(-2.2,0) Y =sendMP{SetProjDir(20,110)(blue);}% 射影方向指定 Y =mptPoint{z.A}[A][b]<0mm,0.5mm>{proj(rdh(0,0,3w))}% この 4 行は Y =mptPoint{z.B}[B][r]<-0.5mm,0.5mm>{proj(rdh(2w,0,0))}% 頂点の指定 Y =mptPoint{z.C}[C][t]<0mm,-0.5mm>{proj(rdh(2w,130,0))}% rdh は次項で Y =mptPoint{z.D}[D][l]<0.5mm,0mm>{proj(rdh(2w,200,0))}% 説明する命令 Y =sendMP{xdraw(0.4pt) z.B--z.D;% 奥の辺 BD を細線で B D C xdraw(0.8pt) z.A--z.B--z.C--z.D--cycle;% 辺 AB,BC,CD,DA odraw(0.1,0.1)(0.8pt) z.A--z.C;}% 辺 BD を切りながら辺 AC A Y =end{MPpic} ちなみに下の図は,参考までに「太い白線」で消された部分を,白ではなく灰色で 表示することで目立たせたものです。 なお,odraw にも,任意の picture 値変数に書き込む odrawpic(picture 値変数)(始点除外, 終点除外, 消し幅)(属性列) B D という形式を用意しています。 C 円柱座標 rdh , rrh — mpt3D.mp に収録 3.5 xyz 座標空間で,x , y 座標を極座標に変えたものを円柱座標といいます。この形式で空間内の点やベクトル ( color 値 ) を指定するための命令 rdh , rrh を新設しました。使い方は, rdh(半径, 角度, 高さ) あるいは rrh(半径, 角度, 高さ) で前者は角度の単位が度数,後者は弧度法です。 数式で表現すると,rdh(r,θ,h) は (r*cosd θ, r*sind θ, h) に相当します。 サンプルについては,前項のものを参照して下さい。 なお,今回この命令を作る際に,dir , Dir , RelDir で角度の単位が弧度法になったものがまだなかったことに気付 きましたので,それらを作りました。名前は Asymptote の同種命令に合わせて expi , Expi , RelExpi です。名前が違 うことと角度の単位が弧度法であること以外は dir , Dir , RelDir と同じ使い方です。 なお,expi は mptMath.mp に,Expi と RelExpi は mpt3D.mp に収録されています。 空間内の曲面の描画 drawSurface — mpt3Dex.mp に収録 3.6 2 パラメータで表された空間内の曲面を描画する命令を新設しました。イメージでいうと,平面曲線に対する kansuP の空間版といった感じです。ただし,処理が複雑なため,( kansuP のように path を生成するのではなく ) いきなり描 画します。 使い方は drawSurface(関数式)(始, 終, 分割数)(始, 終, 分割数) です。 (関数式) の部分は曲面上の点のパラメータ表示を s , t の 2 変数をパラメータとして表現します。たとえば,曲面 2 x + y2 = z2 + 1 は √ √ ( x , y , z ) = ( t2 + 1 cos s , t2 + 1 sin s , t ) とパラメータ表示できますので,(関数式) の部分は 7 ((t++1)*cosd s,(t++1)*sind t,t) √ となります。( t++1 は t2 + 12 を意味します。) 次に,(始, 終, 分割数) の部分ですが,これはパラメータの定義域と分割数を表します。 始 — パラメータの定義域の始点 ( 下限 ) 終 — パラメータの定義域の終点 ( 上限 ) 分割数 — その分割数です。 (始, 終, 分割数) は 2 つありますが,前にある方が s についての設定,後ろにある方が t についての設定です。例え ば先の例で, (0,360,30)(-2,2,10) とすれば,s について 0 から 360 を 30 個の区間に分割,t について -2 から 2 を 10 個の区間に分割して, s=0,12,24,36,· · ·,336,348,360 , t=-2,-1.6,-1.2,· · ·,1.6,2 に対応する 31 × 11 個の点をつなぐ線で作られる「多面体」( 「辺」は曲線ですが ) で,立体を表現します。 なお,この「多面体」の各面は表面と裏面を自動で判定して描画方法を変えています。ここで, 「表」とは何かですが, 右手を「フレミングの法則」の形にして,親指の向きを s の増える向き,人差し指の向きを t の増える向きに向けたと き,中指の向きが SetProjDir で指定した射影方向から見て手前に迫ってくる面が表,奥に遠ざかる面が裏という判定 です。( それが実際の裏表に一致するよう s , t を設定して下さい — そうなってないときは s , t の役割を入れ替えて 下さい。) 次に,描画方法の切り替えですが,これはすでに ver3.50 からある「多面体の描画」と同様,omoteLine , uraLine , fillface を再定義することで行います。ただ,実際には「裏面の辺を描く」 「表面の内部を白 ( background 色 ) で塗り つぶして表面の辺を描く」でたいていうまく行くと思いますので, 「裏面の辺 ( だけ ) を描く」ことを指定する SetPolyUra と「表面の内部を白で塗りつぶして表面の辺を描く」ことを指定する SetPolyOmote を用意していますから,omoteLine などを個別に指定する必要はありません。 言葉で説明するだけではわかりにくいと思いますので,実際に描いてみましょう。 まず,SetPolyUra を指定してから drawSurface で裏面が描かれます。 Y =begin{MPpic}<8mm>(5,2.5|2.5)(-2.5,0) Y =sendMP{SetProjDir(10,0)(blue);% 射影方向の指定 SetPolyUra;% 裏面だけ描くよう指定 drawSurface((t++1)*cosd s,(t++1)*sind s,t)(0,360,30)(-2,2,10);}% 曲面描画 Y =end{MPpic} 次に,SetPolyOmote を指定してから drawSurface で表面が描かれます。 Y =begin{MPpic}<8mm>(5,2.5|2.5)(-2.5,0) Y =sendMP{SetProjDir(10,0)(blue);% 射影方向の指定 background:=0.8white;% 実験のため background 色を灰色に SetPolyOmote;% 表面だけ描くよう指定 drawSurface((t++1)*cosd s,(t++1)*sind s,t)(0,360,30)(-2,2,10);}% 曲面描画 Y =end{MPpic} 上の例では,面内を background 色で塗りつぶしているのがわかりやすいよう, background:=0.8white; ( 薄い灰色 ) としています ( 通常は白です ) . この 2 つを合わせると,目的の曲面が完成します。 Y =begin{MPpic}<8mm>(5,2.5|2.5)(-2.5,0) Y =sendMP{SetProjDir(10,0)(blue);% 射影方向の指定 SetPolyUra;% 裏面だけ描くよう指定 drawSurface((t++1)*cosd s,(t++1)*sind s,t)(0,360,30)(-2,2,10);% 曲面描画 SetPolyOmote;% 表面だけ描くよう指定 drawSurface((t++1)*cosd s,(t++1)*sind s,t)(0,360,30)(-2,2,10);}%曲面描画 Y =end{MPpic} 8 ちなみに想像はつくと思いますが,パラメータの開始位置をうまく設定すれば, 「裏面から描き始めて表面に達する」 ようにできます。これなら一度の drawSurface で図が完成します。( ただし,うまい開始位置を見つけるのは面倒です が。) この目的のために「裏面は辺だけ,表面は内部を白で塗りつぶして辺を描く」ことを指定する SetPolyBoth も定 義しています。 Y =begin{MPpic}<8mm>(5,2.5|2.5)(-2.5,0) Y =sendMP{SetProjDir(10,0)(blue);% 射影方向の指定 SetPolyBoth;% 裏面・表面両方描くよう指定 drawSurface((t++1)*cosd s,(t++1)*sind s,t)(100,460,30)(-2,2,10);}% 曲面描画 Y =end{MPpic} もちろん,これまでにあった SetPolySolid 等も使えます。 Y =begin{MPpic}<8mm>(5,2.5|2.5)(-2.5,0) Y =sendMP{SetProjDir(10,0)(blue);% 射影方向の指定 SetPolySolid(70,100);% 光源の方向を指定して影付きで描くよう指定 drawSurface((t++1)*cosd s,(t++1)*sind s,t)(100,460,30)(-2,2,10);}% 曲面描画 Y =end{MPpic} (注) 入力を簡略化するため,正多面体マクロに比べ,裏表のチェックを少し手抜きして います。表と裏で線種を変えると,表裏の境で期待と異なる線種が選択されるかも知れません。( 先の四面体でいうと面 ABD は裏側だけど辺は表から見えています。) 正多面体マクロでは,面単位ではなく辺単位できっちり判定しています — 正多面体は「中心」があるので精密に判定できます — が,一般の曲面ではそうも行きません。これをきっちりする と,曲面の指定方法が面倒になるため妥協しました。 あと,a ≤ s ≤ b , c ≤ t ≤ d という st 平面上の長方形に対応する曲面しか描けません。( s , t の範囲が相互に依存す るようなものには対応していません。) マクロ紹介とサンプル ver3.52 → 3.60 — 2011/01/15 4 4.1 SetTriangle — mptMath.mp に収録 3 辺の長さ ( の比 ) をもとに,三角形の 3 頂点の相対位置を設定します。次の書式で使います。 SetTriangle(頂点 A, 頂点 B, 頂点 C, 辺 a, 辺 b, 辺 c) 頂点と辺の関係は,高校数学の三角比でよく使われている「頂点 A の対辺の長さが a」という形式です。あと,A , B , C の順に反時計まわりとします。なお,辺 a , 辺 b , 辺 c は辺の長さの「比」です。( 実寸でもいいですが,内部で余弦定 理を用いている関係上辺の長さの 2 乗を計算しますので,実寸だと下手をすればオーバーフローするかもしれません。) 実際に使うときは,SetTriangle に加えて 2 頂点の位置を与え,これによって第 3 の頂点を決定することになります。 連立方程式の一部として機能するマクロですので, 「SetTriangle」と「2 頂点の設定」はどちらが先でもかまいません。 サンプルは,次の通りです。 A Y =begin{MPpic}<10mm>(0,0)(3.5,2) Y =sendMP{SetTriangle(z.A,z.B,z.C,5,4,3);}% 3 頂点の相対位置設定 Y =mptPoint{z.B}[B][r]<-0.5mm,0mm>{origin}% 2 頂点を与える (1 つ目) Y =mptPoint{z.C}[C][l]<0.5mm,0mm>{3w*dir5}% 2 頂点を与える (2 つ目) 4 3 B C 5 Y =mptPoint{z.A}[A][b]<0mm,0.5mm>{z.A}% すでに z.A は決定されているので定義はダミー Y =mptDrawPath{z.A--z.B--z.C--cycle}% 以下,図形の描画 Y =mptFromTo[label=5]{z.C}{z.B} Y =mptFromTo[label=4]{z.A}{z.C} Y =mptFromTo[label=3]{z.B}{z.A} Y =mptRightAngleMark{z.B}{z.A}{z.C} Y =end{MPpic} 9 4.2 Y =mptXTaxis 等 — MePoTeX.sty に収録 空間図形で,座標軸を描くマクロです。次の書式で使います∗16 。 Y =mptXTaxis|始点の x 座標=(y 座標,z 座標)=終点の x 座標>[ラベル位置]<横補正, 縦補正>{ラベル文字列} Y =mptYTaxis|始点の y 座標=(z 座標,x 座標)=終点の y 座標>[ラベル位置]<横補正, 縦補正>{ラベル文字列} Y =mptZTaxis|始点の z 座標=(x 座標,y 座標)=終点の z 座標>[ラベル位置]<横補正, 縦補正>{ラベル文字列} 平面の Y =mptXaxis , Y =mptYaxis とほぼ同じ使い方です。ただし,Y =mptXaxis , Y =mptYaxis では MPpic 環境のサイズ から「始点・終点の座標」をデフォルト値として取得していましたが,空間の座標軸をサイズいっぱい伸ばすと返って 邪魔なことの方が多いので,始点の座標,終点の座標 は省略不可の引数として直接指定することになっています。もち ろん,Y =mptXaxis , Y =mptYaxis と同じく ラベル文字列 も省略不可です。 あと,例えば Y =mptXTaxis において (y 座標,z 座標) は「x 軸」の y , z 座標です。つまり (y 座標,z 座標) に (a,b) を設定すれば,直線 y = a かつ z = b を x 軸にします。省略すれば「本来」の x 軸に対応する (0,0) になります。 サンプルは,次の通りです。 Y =begin{MPpic}<25mm>(0,0)(1.6,1.7) Y =sendMP{SetProjDir(20,20)(blue);} Y =mptPoint{z.O}[O][tl]<0.5mm,-1mm> Y =mptPoint{z.A}[A][br]<-0.5mm,0mm> z D {proj(0,0,0)} {proj(w,0,0)} G E Y =mptPoint{z.B}[B][tl]<0.5mm,-0.5mm>{proj(w,w,0)} Y =mptPoint{z.C}[C][tl]<0mm,-1mm> {proj(0,w,0)} Y =mptPoint{z.D}[D][bl]<0.5mm,0.5mm> {proj(0,0,w)} Y =mptPoint{z.E}[E][r] <-0.5mm,0mm> Y =mptPoint{z.F}[F][tl]<0.5mm,0mm> {proj(w,0,w)} {proj(w,w,w)} Y =mptPoint{z.G}[G][l] <0.5mm,0mm> {proj(0,w,w)} Y =mptXTaxis|-0.2w==1.5w>[t]<0mm,-0.5mm>{$x$} Y =mptYTaxis|-0.2w==1.4w>[l]<0.5mm,0mm> {$y$} F O C A x y B Y =mptZTaxis|-0.2w==1.3w>[b]<0mm,0.5mm> {$z$} Y =sendMP[3pt]{undraw z.E--z.F--z.B;}% この 2 行は ver3.70 を使うともう少し簡略化できます。 Y =sendMP[0.8pt]{draw z.E--z.A--z.B--z.C--z.G--z.D--z.E--z.F--z.G; draw z.B--z.F;} Y =end{MPpic} 4.3 RelDir , SetRelProjDir — mpt3D.mp に収録 以前から mpt3D.mp に収録されている Dir(緯度, 経度) は,z 軸の正の向きを北極の向きとして — より具体的に言 えば,xy 平面を緯度 0◦ , zx 平面をの x > 0 の部分を経度 0◦ として — 与えられた緯度と経度からその向きの単位ベ クトルを生成するマクロですが,これを北極の向きを任意に設定できるように拡張したものが RelDir(北極)(緯度, 経 度) です。 機能はおおよそ想像できると思いますが,原点を通り 北極 に指定した向きを法線ベクトルとする平面が緯度 0◦ , こ の平面と xy 平面の交線∗17 ( 北極 ベクトルの xy 平面への正射影を 90◦ 回転した向き ) を経度 0◦ として,与えられた 緯度と経度からその向きの単位ベクトルを生成するマクロです。 引数のうち,北極 は北極向きの 3 次元ベクトルを与える color 値か,北極の向きの (緯度, 経度) を与える pair 値に なります。 また,引数のうち 緯度 , 経度 はそれぞれ numeric 値です。 このマクロが活躍するのは,z 軸方向以外を上向きにして図を描くときで,射影方向を微調整するときなど特に役立 ちます。( 射影方向を回転してベストポジションを選ぶとき,z 軸方向以外が「上向き」の場合,z 軸まわりに回したり xy 平面を基準に俯角をとったりでは,なかなか思ったように動かせません。) したがって,mpt3D.mp に収録されている SetProjDir と組み合わせて使うのが主になると思うのですが,それなら いっそ埋め込んでしまえ,ということでつくったのが SetRelProjDir です。次の書式で使います。 SetRelProjDir(法線)(上方向)(原点補正) ∗16 ちなみに ∗17 北極 Y =mptXTaxis の T は Three Dimension の T です。 が z 軸方向のときは x 軸の正の向きを経度 0◦ とします。 10 引数のうち 上方向 , 原点補正 は SetProjDir と同じです。法線 は SetProjDir と異なり∗18 ,(緯度, 経度) 形式限 定で,これは RelDir(上方向)(緯度, 経度) と解釈されます。 サンプルについては次項にまとめて挙げます。 4.4 groundpath — mpt3D.mp に収録 z 軸以外を北極方向に定めれば,当然 xy 平面以外を水平面に定めることになります。このとき,この「水平面」に相 当する平行四辺形の path 値を生成するマクロが groundpath です。次の書式で使います。 groundpath(中央, 頂点方向 1, 頂点方向 2, 倍率 1, 倍率 2) 引数のうち 中央 は平行四辺形の中央の点の空間座標です。 頂点方向 1 は平行四辺形の中央から 1 つ目の頂点への方向ベクトル,頂点方向 2 は平行四辺形の中央から 2 つ目の頂 点 ( 1 つ目のとなりの頂点 ) への方向ベクトルです∗19 。( 内部で正規化されますので,ベクトルの大きさは 0 でなけれ ば何でもかまいません。) また,倍率 1 は平行四辺形の中央から 1 つ目の頂点までの距離,倍率 2 は平行四辺形の中央から 2 つ目の頂点までの 距離になります。倍率 2 は 0 を指定することもでき,この場合は 1 つ目の頂点と 2 つ目の頂点を結ぶ辺が紙面上真横に 向くよう,倍率 2 ( に相当する内部パラメータ ) を自動で設定します。 サンプルは,次の通りです。 F Y =begin{MPpic}<25mm>(0,0)(1.6,2) Y =sendMP{color n,u,v; n:=(1,1,2);% n は北極方向=上方向 u:=RelDir(n)(0,30); v:=RelDir(n)(0,110);% u,v は水平方向 SetRelProjDir(12,75)(n);}% 射影方向の設定 Y =mptPoint{z.O}[O][r]<-1mm,-0.5mm> {proj(0,0,0)} y Y =mptPoint{z.A}[A][tl]<0.5mm,0mm> {proj(w,0,0)} Y =mptPoint{z.B}[B][l]<0.5mm,1mm> {proj(w,w,0)} Y =mptPoint{z.C}[C][tr]<0mm,-0.5mm> {proj(0,w,0)} Y =mptPoint{z.D}[D][tl]<0.5mm,-0.5mm>{proj(0,0,w)} Y =mptPoint{z.E}[E][l] <0.5mm,0mm> {proj(w,0,w)} G E z B x D C M Y =mptPoint{z.F}[F][b]<0mm,0.5mm> Y =mptPoint{z.G}[G][r] <-0.5mm,0mm> {proj(w,w,w)} {proj(0,w,w)} Y =mptPoint{z.H}[H][t] <0mm,-0.5mm> Y =mptPoint{z.M}[M][t] <0mm,-0.5mm> Y =mptPoint{z.N}[N][t] <0mm,-0.5mm> {proj Asi((w,0,0),black,u,v)} {proj Asi((0,w,0),black,u,v)} {proj Asi((0,0,w),black,u,v)} A H O N Y =sendMP[0.4pt]{draw groundpath(black,u,v,2w,0);}% 水平面の描画 Y =sendMP[3pt]{undraw z.A--z.O--z.C;}% この 5 行は ver3.70 を使うともう少し簡略化できます。 Y =sendMP[0.4pt]{draw z.A--z.B--z.C; draw z.B--z.F;} Y =sendMP[3pt]{undraw z.G--z.D--z.E; undraw z.D--proj(0,0,1.5w);} Y =sendMP[0.8pt]{draw z.O--z.C--z.G--z.F--z.E--z.A--z.O--z.D--z.E; draw z.D--z.G;} Y =mptXTaxis|-0.2w==1.5w> [l]<0.5mm,0mm> {$x$} Y =mptYTaxis|-0.15w==1.4w>[r]<-0.5mm,0mm>{$y$} Y =mptZTaxis|-0.2w==1.5w> [b]<0mm,0.5mm> {$z$} Y =sendMP[3pt]{undraw extLine(z.A,z.H)(-0.1,0); undraw extLine(z.C,z.M)(-0.1,0); undraw extLine(z.D,z.N)(-0.2,0);} Y =sendMP{draw z.A--z.H; draw z.C--z.M; draw z.D--z.N;} Y =mptRightAngleMark{z.A}{z.H}{z.H+right} Y =mptRightAngleMark{z.C}{z.M}{z.M+right} Y =mptRightAngleMark{z.D}{z.N}{z.N+right} Y =end{MPpic} ∗18 SetProjDir は 法線 に 3 次元ベクトル ( color 値 ) , (緯度, 経度) 形式 ( pair 値 ) のいずれの指定も受け付けます。 RelDir を使えば — 緯度 0◦ が「水平面」ですので — 簡単に生成できます。 ∗19 ちなみに,これらの方向ベクトルは,前項の 11 4.5 mptBallgrad — mpt3D.mp に収録 これはマクロではなく,numeric 値の定数です。空間内のボール ( Y =mptBall で生成 ) の影付きを表現するグラデー ションで,分割数に相当します。以前は 50 で固定だったんですが,結晶格子でボールをたくさん描くときに 50 分割で グラデーションなんてやってると,タイプセットや PDF 化にめちゃくちゃ時間がかかるので,状況に応じて減らせるよ うにしました。そもそも結晶格子に使うボールは小さいので,5 ∼ 10 分割で十分です。以下のサンプルでは,分割数を 8 にしています。 S2− Zn2+ Y =begin{MPpic}<20mm>(6.2,1|2.5)(-1,0) Y =sendMP{mptBallgrad:=8; % グラデーションの分割数を設定 SetVarProjDir(0.7dir-150)(right)(up); bccFrame;% 体心立方格子 (枠型) SetProjDir(10,30)(blue)(2w,0); NaClCut;% 岩塩型結晶 (切断型) ProjOrigin(4w*right); CrstLength:=w/2; hcpBall;% 六方最密構造 (球型) CrstLength:=w; ProjOrigin(0,-1.7h); ZnSFrame;% 閃亜鉛鉱型結晶 (枠型) def mpthen = _mpthen(0,0)() enddef;% 枠型の線種変更 def mptHen = _mpthen(0.4pt,1.8pt)(dashed evenly scaled1/2) enddef;% 枠型の線種変更 VarProjOrigin(2w,-1.7h); CaFFFrame;% 蛍石型結晶 (枠型) SetVarProjDir(0.45dir-160)(2/3,0)(0,(4sqrt6)/9)(4w,-1.7h); hcpFrame;%六方最密構造 (枠型) ionOption(-1.3w,-1.3h); IONOption(-1.3w,-h);}% 説明のための球 Y =mptLabel{(-w,-1.3h)}{Zn$^{2+}$} Y =mptLabel{(-w,-h)}{S$^{2-}$}% 説明 Y =end{MPpic} 4.6 drawR — mptPhys.mp に収録 これは新マクロではなく,従来からあるマクロですが,ちょっと機能を拡張しました。 drawR 番号 (形式) の (形式) の部分は,電球を表す (b) または (B) とスピーカーを表す (SP) および「ギザギザの 抵抗記号」を表す (自然数) ( 指定された数だけギザギザがある ) が可能だったのですが,これに (0) ( ゼロ ) を追加し ました。(0) を指定すると「箱形の抵抗記号」になります。 サンプルは,次の通りです。 Y =begin{MPpic}<15mm>(0,0)(2.1,1.5) Y =sendMP{% ↓端子の位置を指定 R1a=R4a=origin; R1k=R2a=E1a=(w,h); R2k=R3k=(2w,0); R4k=R3a=E1k=(w,-h); drawR1; drawR2(0); drawR3(5); drawR4(0); % 新旧取り混ぜて抵抗 drawVarr R1; drawVarr R4; drawEm1("G");} % 可変抵抗の矢印と検流計 Y =mptLabel{R1m}[br]<-1mm,1mm>{R$_1$} Y =mptLabel{R2m}[bl]<1mm,1mm> {R$_2$} Y =mptLabel{R3m}[tl]<1mm,-1mm>{R$_3$} Y =mptLabel{R4m}[tr]<-1mm,-1mm>{R$_4$} Y =end{MPpic} 12 R1 R2 R4 R3 4.7 SetPolyNone — mpt3Dex.mp に収録 角柱・角錐・正多面体マクロの描画設定で,既存の「枠線のみ ( SetPolyFrame)」「面塗りつぶし ( SetPolySolid )」 に加え, 「何も描かない ( SetPolyNone )」を用意しました。何らかの理由で,自動で描かずに手動で描きたいときなど にどうぞ。 以下のサンプルでは,正二十面体の上部を切って作った「容器」を表現しています。 Y =begin{MPpic}<20mm>(0,0)(1,1) Y =sendMP{SetProjDir(5,5)(blue); z0=origin; % 射影方向と中心を指定 SetPolyNone; icosahedron(z0)(w);}% 描画なしで正二十面体の頂点を設定 Y =sendMP[0.4pt]{draw z0v12--z0v11--z0v10--z0v5--z0v11--z0v4--z0v7--z0v11 dashed evenly scaled1/2;} Y =sendMP[3pt]{undraw z0v8--z0v9--z0v6--z0v2--z0v3--z0v8--z0v2--z0v9;} Y =sendMP[0.4pt]{draw z0v6--z0v10--z0v12--z0v7--z0v3--z0v8--z0v2--z0v9--z0v6--z0v6; draw z0v10--z0v9--z0v8--z0v7; draw z0v8--z0v12--z0v9;} Y =sendMP[0.8pt]{draw z0v2--z0v3--z0v4--z0v5--z0v6--cycle;} Y =end{MPpic} 13
© Copyright 2024