網路城邦
上一篇 回創作列表 下一篇   字體:
MetaPost語言﹣宏練習(一)
2013/07/15 01:41:37瀏覽372|回應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 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=paraquat&aid=7943721