您當(dāng)前的位置:主頁>>AutoCAD>>AutoCAD二次開發(fā)  
           AutoCAD中特定角度及長度捕捉的實現(xiàn)方法

    一、引言 

      在AutoCAD中的角度捕捉只有當(dāng)正交狀態(tài)打開時的直和水平方向,對于其他特殊角度無能為力;另外,其網(wǎng)點捕捉也是相對于X軸和Y軸,無法實現(xiàn)其他方向的特殊長度捕捉,給繪圖帶來極大的不方便。

      在應(yīng)用 AutoCAD 進行設(shè)計制圖的操作中, LINE 和POLYLINE 是使用頻率最高的兩個命令, 經(jīng)常要遇到在某些特定角度上繪制特定長度的簡單線或復(fù)合線的情況,因而實現(xiàn)這兩個捕捉對提高AutoCAD 作圖效率很有實用價值。

二、方法原理

      所謂角度捕捉,是指當(dāng)十字光標(biāo)在某一角度α的一定范圍內(nèi)選取一點時,該點自動落在該α角度線上;當(dāng)我們設(shè)定捕捉角度為α?xí)r,將會以基準(zhǔn)點作為原點、自X軸正方向出發(fā),將整個屏幕劃分為[360/α]個區(qū)間,則NXα角度就是角度捕捉線,其中,0≤N≤[360/α],[360/α]表示不大于360/α的整數(shù)。

      所謂長度捕捉,是在角度捕捉的基礎(chǔ)上,在某一角度線上有一系列捕捉點,該系列點離基準(zhǔn)點的距離為捕捉長度的正整數(shù)倍,當(dāng)選取直線上的一點時,落點自動落到離其最近的捕捉點上。

      實現(xiàn)特定角度和長度捕捉的關(guān)鍵點是:當(dāng)十字光標(biāo)(即十字交叉線)移動時,程序要隨時跟蹤其交叉點的位置,并將該位置與用戶所設(shè)定的捕捉角度與長度對應(yīng)起來,從而計算出在該角度上的落點。

      以下舉例說明該兩個捕捉的實現(xiàn)過程:

      假定捕捉角度為α=30°,捕捉長度為L。

      當(dāng)十字光標(biāo)在任意的某一區(qū)間內(nèi)移動時,比如在第5區(qū)間(120°~150 °)內(nèi)移動時,此時,落點只能在120°或150°線上(該線在圖中并不直接顯示),該兩根角度線的中心線為135°。當(dāng)十字光標(biāo)的中心點處在120°~135°之間時, 則落點應(yīng)在120°線上,該落點的具體位置為由十字光標(biāo)的中心點向120°線作垂線來獲得,其交點D(稱為垂點)即為落點,為直觀起見,此時由基準(zhǔn)點(此處為O點)向落點作一橡筋拖曳線,該橡筋拖曳線隨十字光標(biāo)的移動而相應(yīng)移動,顯示出拖動過程(見圖1);同樣,當(dāng)十字光標(biāo)的中心點處在135°~150°之間時,則落點應(yīng)在150°線上,并顯示相應(yīng)的橡筋拖曳線。該橡筋拖曳線并不是真正的線段, 只是用XOR墨水繪制的一個向量,當(dāng)用XOR墨水重新繪制一遍該向量時,該向量將從屏幕上消失,這就是本程序?qū)崿F(xiàn)光標(biāo)拖動的原理。

      落點落在某一捕捉角度線上時,還得落在捕捉長度L 的整數(shù)倍的點(稱為捕捉點)上,還是針對圖1,其垂點必然處于某兩個捕捉點A與B之間,設(shè)A與B的中點為C,當(dāng)D處于A與C之間時,落點應(yīng)為A;當(dāng)D處于C與B之間時,落點應(yīng)為B (見圖1)。其中:

     -- --

     OA = n XL ; OB = (n + 1) XL

     n: 非負(fù)整數(shù)。

     L: 捕捉長度。 此時,程序通過一定的操作將在屏幕的最上面的坐標(biāo)提示行準(zhǔn)確地顯示落點相對基準(zhǔn)點的偏移長度和偏移角度。用戶可以滑動鼠標(biāo)準(zhǔn)確捕捉到目標(biāo)點。

    至此,已實現(xiàn)某些特定角度及長度的捕捉。為了滿足在程序執(zhí)行過程中能隨時更改捕捉角度和捕捉長度的需要,本程序還增加了相應(yīng)的模塊;另外,本程序中嵌入了窗口放縮功能模塊,通過點取下拉菜單中窗口及漫游子菜單,方便了各種作圖的需要。

三、源程序清單

 ;; OS.LSP源程序

 ;;err(),出錯處理子程序

 (defun err ( msg) 

  (if (/= msg "Function cancelled")

  (princ(strcat "\nError:" msg)) ;打印錯誤內(nèi)容

  ) ;for if

  (setq *error* olderr)

  (setvar "cmdecho" scmd)

  (setvar "osmode" cosmode)

  (setvar "coords" ccoords)

  (princ "n\n\t --多謝使用角度捕捉2.0版,程序非正常結(jié)束--!\n")

  (princ)

 ) ;for defun err

 ;; ant(),設(shè)定捕捉角度子程序

 (defun ant ( / ang0 ang1 )

  (setq ang0 (* an0 (/ 180 pi)) )

  (princ (strcat "\n請輸入捕捉角度:<" (rtos ang0) ">_"))

  (INITGET 4)

  (setq ang1 (getreal))

  (if (not (null ang1))

  (setq an0 (* ang1 (/ pi 180)))

  )

  (princ "\n F2/F3/F4/F5/ESC/Return /下一點:")

 ) ;for defun ant

 ;; leng(),設(shè)定捕捉長度距離子程序

 (defun leng ( / leng0 leng1 )

  (setq leng0 len0)

  (princ (strcat "\n 請輸入捕捉長度距離:<" (rtos leng0) ">_"))

  (INITGET 4)

  (setq leng1 (getreal))

  (if (not (null leng1))

  (setq len0 leng1 )

  )

  (princ "\n F2/F3/F4/F5/ESC/Return /下一點:")

 ) ;for defun lent

 ;; field(),判斷十字光標(biāo)所在區(qū)間,并投影到相應(yīng)的捕捉角度線上

 (defun field ( ps pe ang0 / ang1 n )

  (setq ang1 (angle ps pe))

  (setq n (fix (+ ( / ang1 ang0) 0.5)))

  (setq ang2 (* ang0 n))

 );for defun

 ;; endp(), 十字光標(biāo)投影到相應(yīng)的捕捉角度上后,以用戶設(shè)定的長度

 ;; 捕捉計算落點

 (defun endp ( ps pe ang0 / p1 p2 p3 p4 dis )

  (setq p1 ps 

  p2 (polar ps ang0 1)

  p3 pe

  p4 (polar pe (+ ang0 (/ pi 2)) 1)

  )

  (setq pend (inters p1 p2 p3 p4 nil))

  (setq dis (distance ps pe))

  (if ( / = len0 0)

  (setq dist (* (fix (+ (/ dis len0) 0.5)) len0))

  ;else

  (setq dist dis)

  ) ;for if

  (setq pend (polar ps ang0 dist))

 ) ;for defun endp

 ;; drag(), 對上一次顯示的拖曳線進行"或"操作,使其從屏幕上消失,

 ;; 并繪制下一次拖曳線

 (defun drag ( pold1 pold2 pold3 / ) 

  (if ( / = b2 4)

  (progn

  (grdraw pold1 pold2 -1 0)

  (grdraw pold2 pold3 -1 0)

  )

  ) ;for if

  (grdraw pstart pend -1 0)

  (grdraw pend pframe -1 0)

 ) ;for defun drag

 ;; coord(), 在屏幕的最上一行的坐標(biāo)欄顯示長度和角度

 (defun coord ( / str leng1 leng0 ang0)

  (setq ang0 (* ang2 (/ 180 pi)) )

  (setq str (strcat (rtos dist) ">" (rtos ang0)))

  (grtext -2 str)

 ) ;for defun coord

 ;; init(), 對程序進行初始化

 (defun init ( / )

  (setq scmd (getvar "cmdecho"));保留原命令回顯方式

  (setq ccoords (getvar "coords"));保留原坐標(biāo)顯示方式

  (setq cosmode (getvar "osmode"))

  (setq olderr *error* *error* err) ;出錯處理

  (setvar "cmdecho" 0);不回顯

  (setvar "coords" 0) ;不顯示坐標(biāo)

  (setvar "osmode" 0 ) ;取消捕捉 

  (setq b 0 b1 0 c '(0 0) )

  (setq pstart (getpoint "\n 請輸入直線第一點:"))

  (if (or (null an0 ) (< an0 0) (not (numberp an0)))

  (progn

  (setq an0 (/ pi 6))

  (ant)

  )

  ) ; for if

  (if (or (null len0 ) (< len0 0) (not (numberp len0)))

  (progn

  (setq len0 1)

  (leng)

  ) 

  ) ;for if

  (if (null len0) (leng))

  (princ "\n F2/F3/F4/F5/ESC/Return /下一點::")

  (setq a (grread 2 nil))

  (setq pframe (cadr a))

  (field pstart pframe an0)

  (endp pstart pframe ang2)

  (grdraw pstart pend -1 0)

  (grdraw pend pframe -1 0)

  (setq plast pframe polde pend)

  (setq b (car a))

 ) ;for defun init

  ;; home(), 設(shè)置退出程序的控制變量

 (defun home ( / )

  (setq b 3)

  (setq b1 1)

 ) ;for defun home

 ;; pull(), 接受用戶輸入控制子程序

 (defun pull ( / )

 (setq b1 0)

 (while (/= b 3)

  (progn 

  (setq a (grread 2 nil))

  (coord)

  (if (and (= b 2) (= b2 4)) (setq b 4))

  (setq b2 b)

  (setq b (car a))

  (cond 

  ((or (= b 5) (= b 12) );只移動十字光標(biāo)時

  (progn 

  (setq pframe (cadr a))

  (field pstart pframe an0)

  (endp pstart pframe ang2)

  (if (>= (distance plast pframe) 0.1)

  (progn

  (drag pstart polde plast)

  (setq plast pframe polde pend)

  ) ;for progn

  ) ;for if

  ) ;for progn

  ) ;for cond1

  ( (= b 3);用鼠標(biāo)在屏幕上點取一點時

  (progn 

  (setq pframe (cadr a))

  (field pstart pframe an0)

  (endp pstart pframe ang2)

  (if (>= (distance plast pframe) 0.1)

  (progn

  (grdraw pstart polde -1 0)

  (setq plast pframe polde pend)

  ) ;for progn

  ) ;for if

  ) ;for progn

  ) ;for cond1

  ((= b 2);鍵盤輸入

  (progn

  (setq c1 (cadr a))

  (cond ((= c1 138) (ant)) ;F2

  ((= c1 139) (leng)) ;F3

  ((= c1 140) ;F4

  (progn 

  (setq b2 4)

  (command"zoom" "0.7x")

  ) 

  ) ;for (= c1 140)

  ((= c1 141) ;F5

  (progn 

  (setq b2 4)

  (command"zoom" "1.4x")

  ) 

  ) ;for (= c1 141)

  ((= c1 13) (home))

  ((= c1 27) (home))

  (T (princ "\n 未定義的鍵")) 

  ) ;for cond

  (princ "\n F2/F3/F4/F5/ESC/Return /下一點:")

  );for progn

  );for (cond (= b 2))

  ((= b 4);點取下拉菜單時

  (progn

  (setq c1 (cadr a))

  (princ "\n")

  (cond ((= c1 6005)

  (progn 

  (command"zoom" "w")

  (princ "\n 第一角點:")

  (command pause)

  (princ "\n 第二角點:")

  (command pause)

  )

  ) ;for (= c1 6005)

  ((= c1 6007)

  (command"zoom" "p" ))

  ((= c1 6008)

  (command"zoom" "a" ))

  ((= c1 6011)

  (progn 

  (command"pan")

  (princ "\n 第一參考點:")

  (command pause)

  (princ "\n 第二參考點:")

  command pause)

  )

  ) ;for (= c1 6011)

  ;;else

  (T (princ "\n 未定義的菜單"))

  ) ;for cond

  (princ "\n F2/F3/F4/F5/ESC/Return /下一點:")

  ) ;For PROGN

  ) ;for (cond (= b 4))

  (T (home) ) ;for else

  ) ;for cond

  ) ;for progn

  ) ;for while

 ) ;for defun pull

 ;; draw() , 繪制直線子程序

 (defun draw ( / )

  (while (/= b1 1)

  (progn

  (if (= b 3)

  (progn

  (command"line" pstart pend "")

  (princ "\n F2/F3/F4/F5/ESC/Return /下一點:")

  (setq b 0 b1 1)

  (setq pstart pend)

  );for progn

  ); for if

  (pull)

  ) ;for progn

  ) ;for while

  (grdraw pstart pend -1 0)

  (grdraw pend pframe -1 0)

 ) ;for defun draw

 ;;;;主程序

 (defun c:os ( / b b1 b2 c pstart pend pframe plast ang2 

  dist scmd ccoords olderr cosmode )

  ;;; an0 len0 are defined out program

 (init)

 (draw)

 (princ "\n")

 (command"redraw")

 (setq *error* olderr)

 (setvar "cmdecho" scmd)

 (setvar "osmode" cosmode)

 (setvar "coords" ccoords)

 (princ "\n\n\t ------角度捕捉2.0版------\n") 

 (princ "\n\n\t**寧波大學(xué)建筑設(shè)計研究院--程建華,1996**\n") 

 (princ)

 ) ;for defun os

四、程序的安裝與使用 

 1. 程序的安裝

    以下三種裝載方式,用戶任選一種即可: 在AutoCAD環(huán)境下,將OS.LSP拷至當(dāng)前目錄,再執(zhí)行(LOAD"OS")即可裝載OS.LSP。也可先將OS.LSP拷至\ACAD\SUPPORT\子目錄下,再在\ACAD\SUPPORT\ACADR12.LSP或ACADR13.LSP中加入下面一句語句實現(xiàn)啟動AutoCAD時自動裝載:

      (AUTOLOAD "OS" '("OS"))

    也可將OS.LSP拷至\ACAD\SUPPORT\子目錄下,在\ACAD\SUPPORT\\子目錄下的菜單文件ACAD.MNU中的合適位置加上下面的一句語句,即可直接在菜單中點取角度捕捉操作:

     ·

     ·

     ·

     [角度捕捉]^c^c(load"c:/acad/support/os.lsp") os 

     ·

     ·

     ·

 2. 程序的使用

    在一幅圖中第一次使用該程序時,需要用戶輸入捕捉角度和捕捉長度,第二次調(diào)用本程序時,程序可自動采用上一次最后設(shè)定的捕捉角度和長度作為默認(rèn)值。然后,程序需要用戶選擇輸入一點作為基準(zhǔn)點,此時命令行提示:

     F2/F3/F4/F5/ESC/Return /下一點:

     用戶根據(jù)該提示可任選其中的一種操作,具體解釋如下:

    ① 按F2鍵重新設(shè)定捕捉角度;

    ② 按F3鍵重新設(shè)定捕捉長度;

    ③ 按F4鍵窗口縮小0.7倍;

    ④ 按F5鍵窗口放大1.4倍;

    ⑤ 按ESC鍵、回車鍵、鼠標(biāo)右鍵均可結(jié)束操作,退出程序;

    ⑥ 選取下一點,移動十字光標(biāo)鍵,此時在屏幕的最上面的一行的坐標(biāo)提示欄準(zhǔn)確地顯示出按用戶設(shè)定的捕捉角度和長度所取得的落點相對于基準(zhǔn)點的偏移角度和長度,滑動十字光標(biāo)鍵直至用戶尋找到所需要的下一點并按下鼠標(biāo)左鍵,命令行重又出現(xiàn)上面的提示行,并進行下一輪循環(huán);

    ⑦ 另外,用戶還可以點取View菜單下的Zoom菜單中的Zoom Window 、Zoom Previous、Zoom All等三個子項實現(xiàn)窗口放縮和Pan菜單實現(xiàn)屏幕漫游; 對于其他操作,用戶均可按屏幕命令行的中文提示方便地進行操作。在非漢化AutoCAD 中運行本程序時,只需將程序中有關(guān)的中文提示行改成英文提示即可。 另外,由于不同的機型在AutoCAD環(huán)境下鍵盤返回碼可能稍有區(qū)別,所以要求用戶在應(yīng)用本程序之前對自己的機器鍵盤返回碼按如下方法作一次核實:

      在AutoCAD命令狀態(tài)下輸入(grread)并回車,用戶此時可按下F2或F3、F4、F5鍵:

      第一步:Command:(grread)回車

      第二步:按下F2鍵

      此時,屏幕上回顯剛輸入的鍵值,比如對筆者使用的機器(AST PIII+4/66D)回顯為:(2 1 36)。

      其具體涵義為:第一個數(shù)字"2"表示剛才是鍵盤輸入;第二個數(shù)字"136"表示本機器的"F2"鍵的返回碼。

      按上述步驟依次對FF4、F5鍵的返回碼進行核實,筆者的機器該三鍵的返回碼分別為137、138、139。

      如果核實結(jié)果與上述結(jié)果不符(比如,對某些機型,上述四鍵的返回碼分別為138、139、140、141),則應(yīng)對程序中的相應(yīng)語句作如下修改。

      在"接受用戶輸入控制子程序"pull()中的鍵盤輸入部分的下述語句作對應(yīng)修改:

     (cond ((=c1 136)(ant));F2--此處136改為用戶的F2鍵返回碼

     ((=c1 137)(leng);

     F3--此處137改為用戶的F3鍵返回碼

     ((=c1 138);

     F4--此處138改為用戶的F4鍵返回碼

     ((=c1 139);

     F5--此處139改為用戶的F5鍵返回碼 

      最后,需要指出的是:用戶自己的菜單文件ACAD.MNU可能增刪過菜單項或AutoCAD R13中,會使Zoom Window、Zoom All、Zoom Previous、Pan在菜單中位置發(fā)生改變。這樣,要求用戶在應(yīng)用本程序之前對自己的菜單項回碼按如下方法作一次核實:

      在AutoCAD命令狀態(tài)下輸入(grread)并回車,用戶此時可點取下拉菜單View下的Zoom子菜單中的Window項,對于筆者的菜單其返回值為:(4 6005)。其具體涵義為:第一個數(shù)字"4"表示剛才是下拉菜單輸入;第二個數(shù)字"6005"表示本菜單的Zoom Window菜單項的返回碼。用戶可按同樣的方法找到菜單項Zoom All、Zoom Previous、Pan的返回碼。并相應(yīng)地改變"接受用戶輸入控制子程序"pull()中的"點取下拉菜單"部分的下述語句作對應(yīng)修改:

     (cond ((=c1 6005)--此處6005改為用戶的Zoom Window菜單項返回碼;

     ((=c1 6007)--此處6007改為用戶的Zoom Previous菜單項返回碼;

     ((=c1 6008)--此處6008改為用戶的Zoom All菜單項返回碼;

     ((=c1 6011)--此外6011改為用戶的Pan菜單項返回碼; 

五、結(jié)語

      應(yīng)用本程序,可在制圖過程中很方便地實現(xiàn)某些特定角度和長度的捕捉,簡化了操作步驟和擊鍵次數(shù),根據(jù)目前的使用情況來看,畫線時可提高作圖速度4倍以上。至于AutoCAD內(nèi)部提供的正交和網(wǎng)點捕捉只是本程序當(dāng)捕捉角度為 90°時的一個特例。

      將本程序的畫線子模塊 draw()中語句行

       (command"line" pstart pend "")

民眾工作室.制作      版權(quán)所有