字體:小 中 大 | |
|
|
2013/07/15 01:41:37瀏覽386|回應0|推薦0 | |
%非程式碼的部分,使用了"%"註解符號,這樣方便朋友試驗,可以直接「拷貝」文章後試驗。 %前面介紹的宏的定義。現在來用實例來練習宏的用法,宏的最大目的就是使程式容易閱讀,而且也可以簡化程式碼。這是MetaPost手冊中的例子,定義了幾個宏來方便繪出簡單的幾合圖: marksize=4pt; def draw_mark(expr p, a)= begingroup save t, dm; pair dm; t=artictime a of p; dm=marksize*unitvector direction t of p rotated 90; draw (-.5dm .. .5dm) shifted point t of p; endgroup enddef; %這個部分,可以看出draw_mark定義了它可以傳入二個值,一個是path p和numeric a。 %a是path p上面的某個長度值,用 arctime a of p 可以得到 p在 a長度時的t值。 %然後再用t來換算 path p 上面要做記號的端點位罝和線段的角度: %dm=marksize* unitvector direction t of p rotated 90; %direction t of p可以得到 p在 t 時的向量;而unitvector 是把向量變成單位向量,這樣和其他的單位相乘(如本例的4pt)時,才不會出錯。而rotated 90 就是把這個長度4pt的向量逆時針旋轉90度,故可以和 path 在其t 時位置的方向垂直。繪出這個垂直線段平移到t值時的位置。 %接下來是如何使用這個draw_mark宏: def draw_marked(expr p, n) = begingroup save amid; amid = .5 arclength p; for i=-(n-1)/2 upto (n-1)/2: draw_mark(p, amid+.6marksize*i); endfor draw p; endgroup enddef; %這個 draw_marked定義了這個path要畫上幾條記號線: %上面定義了要在一半長度的位置上做記號,並以中點為中心,向兩旁以0.6*4pt的距離來畫出draw_mark線。 %接下來是定義畫角的記號線: angle_radius=8pt; def mark_angel(expr a, b, c, n)= begingroup save s, p; path p; p=unitvector(a-b){(a-b)rotated 90}..unitvector(c-b); s= .9marksize/length(point 1 of p-point 0 of p); if s < angle_radius: s:=angle_radius; fi draw_marked(p scaled s shifted b, n); endgroup enddef; %draw_angle定義了要在三個點a, b, c中,角b的弧線記號上面要畫幾條draw_mark線。弧線的定義很簡單,就是a-b就是ba線段的向量;而c-b就是bc線段的向量。而用上unitvactor是為了後來這個弧線後來的的放大(scaled s)運算而用的。然後再決定弧線半徑s的長度是多少。最後,就是用draw_marked把要繪的p scaled s shifted b; 以及要畫幾條draw_mark線繪出。 %畫直角的記號: def mark_rt_angle(expr a,b,c) = draw ((1,0)--(1,1)--(0,1)) zscaled (angle_radius*unitvector(a-b)) shifted b enddef; %zscaled 具有放大與旋轉的功能。 %現在是實際上繪圖: beginfig(1); pair a,b,c,d; b=(0,0); c=(1.5in,0); a=(0,.6in); d-c=(a-b) rotated 25; dotlabel.lft("a", a); dotlabel.lft("b",b); dotlabel.bot("c",c); dotlabel.llft("d",d); z0=.5[a,d]; z1=.5[b,c]; (z.p-z0) dotprod (d-a)=0; (z.p-z1) dotprod (c-b)=0; draw a--d; draw b--c; draw z0--z.p--z1; draw_marked(a--b,1);%畫出ab線段,並上面畫一條draw_mark draw_marked(c--d,1); draw_marked(a--z.p, 2); draw_marked(d--z.p,2); draw_marked(b--z.p,3); draw_marked(c--z.p,3); mark_angle(z.p,b,a,1); mark_angle(z.p,c,d,1); mark_angle(z.p,c,b,2); mark_angle(c,b,z.p,2); mark_rt_angle(z.p,z0,a); mark_rt_angle(z.p,z1,b); endfig; |
|
( 興趣嗜好|電腦3C ) |