您當(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)所有 |