這是AutoLisp入門基礎教程的第二部分。在教程的第一部分,我們掌握了如何在AutoCAD中加載一個AutoLisp程序,了解了如何使用defun來定義一個函數(shù)。在下面的內容中,我將結合一個實際工作中的簡單需求并編寫一個程序,以此來展示編程的思路,并重點講述常用的AutoLisp函數(shù)。
工作中有什么需求
在海工結構中,一些房間的墻壁經(jīng)常是由瓦楞板組成的。瓦楞板就是像瓦楞紙一樣的鋼板,如下圖所示。

在設計制圖階段,我們常常用一個曲折的多段線來表示這個瓦楞板,如下圖所示。圖中的幾個長度參數(shù)(x,y和h)決定了瓦楞板的形狀。一般的,為了畫一段長度的瓦楞板,需要確定該多段線的數(shù)十個的控制點。所以,若采用手工方法一個一個地確定控制點地位置來完成一個多段線,那么工作量是無比巨大的。正常人肯定不會這么干!在接觸AutoLisp之前,我也不知道瓦楞板是怎么畫的,但是又不得不畫(不畫就要被領導罵了),所以我就從別人的圖紙中復制一個長長的瓦楞板多段線,然后裁剪成合適的大小。

復制別人圖紙中的東西確實是一個不錯的主意,但是如果瓦楞板的形狀尺寸改變了,就有可能無圖可抄了。我曾經(jīng)思考過很久如何快速地畫這樣一個瓦楞板,有同事說可以設置自定義線型(但是他竟然忘了如何設置了)。接下來,我們嘗試用AutoLisp編程來解決這個問題。
程序的構思
為了方便起見,先將瓦楞板的尺寸固定。程序的預期目標是,在輸入瓦楞板中軸線的起點(ps)和瓦楞板中軸線的終點(pe)后自動畫出一定長度的瓦楞板(即多段線)。從下圖可以看出,瓦楞板是一個循環(huán)的線段,一個循環(huán)單元由四個控制點組成(如圖中的 pa pb pc pd)。如何通過已知點(ps和pe)來確定這四個控制點的位置,是解決問題的關鍵。幸好,Autolisp語言提供了一些非常有用的函數(shù),如下:
(polar pt angle distance)
; 此函數(shù)將返回在pt點的某個方向(angle)上距離長度為distance的點
; angle 是從 x 軸開始的角度,以逆時針方為正
(angle p1 p2)
; 返回從p1到p2的射線與x軸正方向的夾角,單位是弧度
(distance p1 p2)
;返回p1與p2之間的距離
例如,pa在ps的(alpha+pi/2)角度上,距離為h/2;pb在pa的alpha角度上,距離為x;p_temp在pb的(alpha-pi/2)角度上,距離為h;pc在p_temp的alpha角度上,距離為y;pd在pc的alpha角度上,距離為x。這四個關鍵點就全部確定了(p_temp是為了表示方便而構造的變量)。使用polar函數(shù),把已上的陳述翻譯為AutoLisp語言,如下:
(setq
pa (polar ps (+ alpha (/ pi 2)) (/ h 2))
pb (polar pa alpha x)
p_temp (polar pb (- alpha (/ pi 2)) h)
pc (polar p_temp alpha y)
pd (polar pc alpha x)
)

如何AutoLisp中實現(xiàn)循環(huán)呢?方法之一是使用repeat函數(shù)
(repeat n exp...)
; n為正整數(shù),為循環(huán)的次數(shù)。exp...為循環(huán)執(zhí)行的表達式。
最終的程序
最后的程序,程序中的一些細節(jié)沒有講到。先寫這么多吧。
(defun c:wlb ()
;定義瓦楞板的尺寸
(setq x 255 y 66 h 66)
(while
(and
(setq ps (getpoint "\n請輸瓦楞板的起點:"))
(setq pe (getpoint "\n請輸瓦楞板的終點:"))
)
(setq
alpha (angle ps pe)
dstc (distance ps pe)
dstc_e (+ x y x y)
)
(setq nn (1+ (fix (/ dstc dstc_e))))
(setq pa (polar ps (+ alpha (/ pi 2)) (/ h 2)))
(setq oldsnap (getvar "osmode"))
(setvar "osmode" 0)
(command "pline")
(repeat nn
(setq
pb (polar pa alpha x)
p_temp (polar pb (- alpha (/ pi 2)) h)
pc (polar p_temp alpha y)
pd (polar pc alpha x)
)
(command pa pb pc pd)
(setq pa (polar pa alpha dstc_e))
)
(command "")
(setvar "osmode" oldsnap)
(prin1)
)
)
以后接著寫吧。