AutoLisp 選擇對象函數 ssget 用法
語法:
(ssget [sel-method] [pt1 [pt2]] [pt-list] [filter-list])
ssget 的參數均為可選參數,需要註意的是可選參數之間的組合條件。
以下語法表示中 <parameter>
尖括號代表必選,[parameter]
方括號代表可選。
一、選擇集的窗口參數
- [sel-method] 字符串類型,不區分大小寫,指定一個選擇方法。
- [pt1 [pt2]] 表類型,由三個數字的點參數表,表示 xyz 坐標,也可以是僅包括xy 的坐標。
- [pt-list] 表類型,由點參數表組成的表。
C 窗交(反選)
如果指定了該參數,則必須跟一對點創建一個矩形窗口,與矩形窗口相交的對象均被加入選擇集。
參數語法: (ssget "c" <pt1> <pt2> [filter-list])
此時,[pt-list] 參數不能出現,否則 ssget 將會返回一個錯誤提示:錯誤的點參數
示例:
(setq pt1 (getpoint "First Pt:"))
(setq pt2 (getpoint "Second Pt:"))
(setq ss (ssget "c" pt1 pt2))
- 1
- 2
- 3
W 窗口(正選)
與 C 參數語法及用法類似,但功能不同,只有在矩形窗口內完整的對象才會被加入選擇集。
參數語法: (ssget "w" <pt1> <pt2> [filter-list])
參數前加下劃線 “_w” 可以使代碼在不同版本的CAD平臺下兼容,建議寫上。
CP 圈交(多邊形反選)
如果指定了該參數,則必須用構成多邊形的點表響應,與多邊形相交的對象被加入選擇集。
參數語法: (ssget "CP" <pt-list> [filter-list])
此時點參數 [pt1] [pt2] 不能出現,而且,CP 參數依賴 <pt-list>
的順序來構成一個多邊形。
例如四個點按順序連接為一個8字型,而不是一個矩形,ssget 將返回一個空選擇集,即使對象與窗口相交。
如果參數為少於3個點的表,也將返回一個 nil。
示例:
(setq pt1 (getpoint "Piont1:"))
(setq pt2 (getpoint "Piont2:"))
(setq pt3 (getpoint "Piont3:"))
(setq pt4 (getpoint "Piont4:"))
(setq ss (ssget "c" (list pt1 pt2 pt4 pt4)))
- 1
- 2
- 3
- 4
- 5
WP 圈圍(多邊形正選)
與 CP 參數語法及用法類似,但只有被多邊形窗口包圍的對象才會被加入選擇集。
參數語法: (ssget "wp" <pt-list> [filter-list])
F 欄選
將參數點表連接為一條折線,與折線相交的對象被加入選擇集。
參數語法: (ssget "f" <pt-list> [filter-list])
pt-list 最少由2個點組成表,CP/WP 參數最少需要 3 個點。
P 前一批創建的圖形
包括 CAD 命令或 LISP 程序創建的圖形對象。
參數語法: (ssget "p" [filter-list])
P 參數不能和 [pt1 [pt2]] [pt-list] 任何一個點參數組合,否則將返回一個錯誤,有的 CAD 版本會返回 nil
當分解(EXPLODE)一個 CAD 圖形時,p 方法特別有用,可以一次性建立分解後的所有對象選擇集。
L 最後一個創建的對象
包括 CAD 命令或 LISP 程序創建的對象,註意和 P 參數的區別。
參數語法: (ssget "l" [filter-list])
在獲取最後一個對象的圖元名時,以下代碼是等價的,但是後者不能提供直接過濾功能。
(ssname (ssget “L”) 0) == (entlast)
I 隱含窗口選擇
參數語法: (ssget “i” [filter-list])
CAD 命令有兩種執行方式,第一種先命令後選擇,第二種先選擇後命令。所以在 Lisp 中也允許先選擇後命令,
而且這方式可以通過系統變量 pickfirst 來關閉(值為 0),此時 I 參數失效,(ssget “i”) 將返回 nil。
選擇對象後,可以用 (sssetfirst nil) 取消選擇集的亮顯狀態。
X 整個文件
在當前打開的CAD文件中選擇所有對象,包括關閉、凍結圖層中的圖元和可見屏幕外的圖元,不分大小寫。
參數語法: (ssget "x" [filter-list])
X 用法與 A 用法等價,(ssget “A”) 也是選擇所有對象。
:E 拾取框
用拾取框選擇對象,此時 ssget 將不再拉出一個矩形窗口,直到點右鍵結束選擇。
參數語法: (ssget ":E" [filter-list])
與 :E 對應的 :N 參數為只能拉出一個矩形窗口選擇,而不能通過點選拾取對象。
:S 僅允許單一選擇集
使用:s參數時,ssget 將點選對象一次就會結束,無論是否選中對象,未選中則返回 nil,可節省一次回車確認。
參數語法: (ssget ":S" [filter-list])
說明: “:S” 參數和 “:E” 可以同時使用,例如: (ssget "_:S:e")
以下參數可以組合使用, “+” 或 “-“,例如:(ssget "_:S+D")
:D 重復選擇
允許同一個對象多次加入選擇集,每選擇一次,則加入一次。
參數語法: (ssget ":D" [filter-list])
例如:畫兩條直線,然後運行代碼 (setq ss (ssget ":D"))
,框選3次直線後。(sslength ss)
返回 6
:L 不選擇鎖定圖層對象
註意: L、:L、-L 的參數是不同的。
參數語法: (ssget ":L" [filter-list])
ssget 默認選擇所有圖層對象,這樣在程序中需判斷圖層是否鎖定,才能編輯,否則 lisp 代碼將返回錯誤。
其他方法還有A :A -A _:V _:U _:R -M -P :P -G -L :?
等參數以及組合用法,有興趣的朋友可以測試。
這些參數的用法官方並未在語法參考裏公布,估計是程序測試留下的接口,CAD 更新時可能被關閉,不建議使用。
註意事項:
- ssget 帶點參數調用時,可能會受到自動捕捉的影響,一般先將系統變量 osmode 置零。
- ssget 點參數包圍的矩形、多邊形應在當前繪圖區域內可見,否則 ssget 僅返回可見區域內的對象選擇集。
- 創建選擇集會消耗 AutoCAD 的臨時文件存儲區,所以 AutoLISP 不允許同時創建多於 128 個選擇集。
例如:畫一個圓,然後執行以下代碼:
(repeat 130 (setq a (cons (ssget "l") a)))
這段程序循環了 130 次,AutoCAD提示 “錯誤: 超出選擇集數量的最大範圍”,如果繼續調用 (ssget) 將返回 nil;此時,只有清空選擇集變量 (setq a nil) 才能繼續調用 ssget。 - ssget 選擇時沒有自定義提示,如果特別需要可用第三方函數,比如飛詩的:
Fsxm-ssget
二、選擇集的過濾條件
[filter-list] 過濾條件,表類型,指定與屬性(DXF 組碼)匹配的對象被加入選擇集。
常用支持過濾的 DXF 組碼:
- 0 實體類型
- -4 條件運算, SSGET 的專用組碼,包括邏輯條件與關系條件
- 1 圖元文字內容
- -3 擴展數據
- 2 屬性標記、塊名
- 6 線型名
- 7 文字樣式
- 8 圖層名
- 40 CIRCLE 直徑或 TEXT 文字高度
- 62 顏色號
0 組碼
指定對象實體類型,語法 ‘((0 . types)),對象類型 types 為字符,不分大小寫,常用的實體類型如下:
"POINT"、"TEXT"、"MTEXT" 點、單行文本、多行文本
"LINE"、"LWPOLYLINE"、"SPLINE" 直線、多段線、樣條曲線
"CIRCLE"、"ARC"、"ELLIPSE" 圓、圓弧、橢圓
"HATCH"、"DIMENSION" 填充、標註
"ATTDEF"、"INSERT" 屬性文字、圖塊
-
“,” 邏輯或,對象類型可多選,名稱用 “,” 分隔。例如,創建直線和文本的選擇集:
(ssget ‘((0 . “TEXT,LINE”)))
框選對象後,將只有直線和文本被選中(亮顯)並加入選擇集。
-
“~” 邏輯非,用來排除某類型。例如:創建除過圖塊的選擇集
(ssget ‘((0 . “~INSERT,LINE”)))
顯然,第二個類型 LINE 毫無意義,因為第一個 ~INSERT 非圖塊類型範圍包含了 LINE 類型。
-
“*” 通配符,用來表示模糊類型。例如,創建所有直線的選擇集:
(ssget ‘((0 . “*LINE”)))
框選對象後,可以將 “LINE”、”LWPOLYLINE”、”SPLINE”、”MLINE” 類型加入選擇集,和以下過濾條件等價:
(ssget ‘((0 . “LINE,LWPOLYLINE,SPLINE,MLINE”)))
通常我們用後者實現精確過濾。
其他:(ssget ‘((0 . “*E”))) 選擇過濾所有直線、圓、橢圓的類型,因為他們的尾字母都是 E。
(ssget ‘((0 . “*”))) 與 (ssget) 等價,相當於全選。
(ssget ‘((0 . “~*”))) Lisp 都不知道你要幹嘛了,因為它什麽也選不上。 -
0 組碼可以和其他組碼組成 list 表過濾。例如,選擇半徑為 20 的圓:
(ssget ‘((0 . “CIRCLE”)(40 . 20)))
通常,對於字符類型組碼均支持通配過濾語法,包括線型名、文字樣式、圖層等。
例如:選擇非 0 層的所有對象(ssget ‘((8 . “~0”)))
-
註意:並不是所有組碼都支持過濾,例如下面過濾條件將返回 nil,即使存在句柄為 “25F” 的圓。
(ssget ‘((0 . “CIRCLE”)(5 . “2*”)))
-4 組碼
邏輯條件運算
用 -4 組碼和邏輯運算符組成表對,將一個或幾個表項包夾。邏輯運算符對大小寫不敏感。
表對必須成對出現,如:(-4 . "<xx")...(-4 . "xx>")
, 常用的邏輯運算符如下:
or 項目並集
and 項目交集
not 不含此項
xor 兩項異或
-
or 並集。例如,選擇直線和文本:
(ssget ‘((-4 . "<or")(0 . "line")(0 . "text")(-4 . "or>")))
顯然與 (ssget ‘((0 . “text,LINE”))) 等價,但後者寫法更簡潔。
例如,選擇顏色為紅色和綠色的文字和直線:(ssget ‘((0 . "TEXT,LINE")(-4 . "<or")(62 . 1)(62 . 3)(-4 . "or>")))
-
and 交集。例如,選擇圖層為 “notes”,顏色為綠色的單行文本:
(ssget ‘((-4 . "<and")(0 . "text")(8 . "notes")(62 . 3)(-4 . "and>")))
-
not 非。例如,選擇非 “notes” 層的實體對象:
(ssget ‘((-4 . "<not")(8 . "notes")(-4 . "not>")))
顯然與 (ssget ‘((8 . “~notes”))) 等價。
註意:非運算只能有一個表項被包夾,否則 ssget 將返回 nil。 -
xor 異或。即半加法,實現二進制加法的不進位運算。邏輯意義: 相同為0,相異為1。
例如,選擇在 “notes” 層不是綠色、或是綠色而不在 “notes” 層的文本對象:(ssget ‘((0 . "text")(-4 . "<xor")(8 . "notes")(62 . 3)(-4 . "xor>")))
註意:異或運算只能有兩項,如果超過兩項或只有一項,ssget 將返回 nil。
- 邏輯運算可以嵌套,組成更復雜的條件運算。
(ssget ‘((0 . "text")
(-4 . "<or")
(-4 . "<and")(8 . "0")(62 . 1)(-4 . "and>")
(-4 . "<and")(8 . "notes")(62 . 3)(-4 . "and>")
(-4 . "or>")
))
- 1
- 2
- 3
- 4
- 5
- 6
關系條件運算
用 -4 組碼和關系運算符組成表對,放在需要比較的表項前。
與成對出現的邏輯條件不同,關系表對單個出現,常用關系運算符如下:
"*" 通配符
"=" 等於
"!=" 不等於
"<>" 不等於
"<" 小於
"<=" 小於或等於
">" 大於
">=" 大於或等於
"&" 按位與
"&=" 按位屏蔽相等(僅適用於組值為整型的組)
例如:選擇半徑大於或等於20的圓
(ssget ‘((0 . "CIRCLE")(-4 . ">=")(40 . 20)))
選擇半徑20的圓,顏色不是紅色
(ssget ‘((0 . "CIRCLE")(-4 . "<and")(-4 . "!=")(62 . 1)(40 . 20)(-4 . "and>")))
對於含有多個元素的比較,如點坐標,可用 “,” 隔開關系運算符。
選擇圓心坐標 x>100, y<120, z=0,圖層名以 cir 開始的圓
(ssget ‘((0 . "CIRCLE")(-4 . ">,<,=")(10 100 120 0)(8 . "cir*")))
選擇圖形顏色不是隨層 (bylayer) 的對象,可用以下代碼
(ssget ‘((-4 . "&")(62 . 255)))
我們知道 CAD 的索引顏色數為 1-255,用 2 個字節表示,隨層的顏色為 0,在 DXF 組碼中並不顯示。
此時如果用 (ssget ‘((-4 . “>”)(62 . 0))) 來過濾是不對的,隨層顏色的圖形也將被選上。
如果用二進制的 8 個 1 與當前顏色數進行邏輯與的位運算 &,其結果都不是 0, 即為真, 2^8=255
1 組碼
文本內容的匹配運算(與 wcmatch 函數語法相同),相當於簡單正則。
對於包含大量文本對象的圖形,有時候需要精確的過濾條件,可以通過以下特殊符號來實現:
"*" 通配符,代表一個或多個任意字符
"|" 管道符,用來連接並列字符,表示或的關系
"?" 占位符,代表一個任意字符
"#" 數字符,代表一個0-9的字符
"@" 字母符,代表一個a-z,A-Z字符
"." 特殊字符,代表一個除字母和數字的其他字符
"~" 符號非運算
"`" 轉義字符(數字 1 左邊那個字符)
"," 分隔兩個模式的表達式
"[]" 限位符,用中括號包括一個表達式,表示一位字符
-
例1: CAD 中有以下 3 組 TEXT 文本
① X=35.614 ② Y=356.201 ③ Z=11.526
-
要求匹配以 “X=” 這兩個字母開始的單行文本
(ssget ‘((0 . “TEXT”) (1 . “X=*”)))
返回第 ① 組文本的選擇集
解讀: “X=” 不是通配運算符,在此表示精確匹配,後面加 “*” 是任意符號。 -
要求匹配以 “X=” 或 “Y=” 這兩個字母開始的單行文本
(ssget ‘((0 . “TEXT”) (1 . “[X|Y]=*”)))
返回第 ①、② 組文本選擇集
解讀: 並列出現的字符,用 “|” 連接。 -
要求匹配 包含數字小於 100 的單行文本
(ssget ‘((0 . “TEXT”) (1 . “@=##[.]*)))
返回第 ①、③ 組文本選擇集
解讀: “##” 代表兩個數字,兩個數字連接最大只能是 99。小數點單獨出現用方括號 [.]
如果僅僅是 “.”,而沒有方括號,則代表任意特殊符號。
-
-
例2: 我們再試驗一組復雜的文本,在 CAD 中寫入以下 10 組 TEXT 文本
① abcde ② 12345 ③ -25.390 ④ *&@125 ⑤ F35
⑥ #54-65 ⑦ 頭文字 ⑧ 36 75 ⑨ F ⑩ /(*&%@!-
要求匹配 包含數字 文本
(ssget ‘((0 . “TEXT”) (1 . “#“)))
以上代碼將選中 ②③④⑤⑥⑧ 包含數字的 6 組文本
解讀: “#” 代表一個數字字符, -
要求匹配 以*開始的 文本
(ssget ‘((0 . “TEXT”) (1 . “`**”)))
以上代碼將選中 ④ 以*開始的 1 組文本
解讀: 因為"*"
是通配符,要匹配語法中的專用字符用轉義"‘*"
-
要求匹配 不含特殊字符 文本
(ssget ‘((0 . “TEXT”) (1 . “~*.*”)))
以上代碼將選中 ①②⑤⑦⑨,註意:負號和小數點也是特殊符號
解讀: “.” 代表一個特殊字符,前後加 “.” 包含一個特殊字符,不含特殊字符就是 “~*.*” -
要求匹配 純數字 的單行文本,包含負號和小數點
(setq ss (ssget ‘((0 . “TEXT”) (1 . “~*[~.–9]*))))
解讀: 負負得正,兩次取非可獲取數字本身,括號內 “[~.-]”, 意為包含小數點和負號。
註意, 220-11 不能參加計算的數字也會被包括其中。
-
-
下面給出常用匹配規則,歡迎測試
匹配數字,不含小數點和正負號: “~*[~0-9]*” 如: 9824
匹配 26 個小寫字母: “~*[~a-z]*” 如: loveu
匹配大寫字母或數字: “~*[~A-Z],~[~0-9]*” 如: NASAA 或 9527
匹配大寫字母和數字混排: “~*[~A-Z|0-9]*” 如: F36D
空格是一個很特殊的字符,用一個空格可以匹配任意個空格,其他字符沒有這個特性。
例如:(wcmatch " " " ")
返回 T
-3 組碼
擴展數據過濾。ALISP 中可以用如下方法給圖形添加擴展數據,增加自定義組碼及表值。
-
第一步,註冊一個擴展對象應用名
(regapp “xapp”)
-
第二步,選擇一個圖元並返回組碼
(setq En (entget (car (entsel))))
-
第三步,定義加入圖元的擴展數據
(setq data ‘((-3 (“xapp” (1000 . “你好中國”)))))
-
第四步,將擴展數據附著更新圖元
(entmod (append En data))
-
完成,我們可以檢查一下擴展數據
(assoc -3 (entget (car (entsel)) ‘(“xapp”)))
結果返回 (-3 (“xapp” (1000 . “你好中國”)))
采用這種方法添加擴展數據,用 EXPLODE 命令不能清除。
與 -3 組碼無關的話題。 用 VLisp 函數給圖元添加數據比較簡單,無需提前註冊名稱,例如 (vlax-ldata-put (car (entsel)) "xa" "你好中國") 查詢數據如下: (vlax-ldata-get (car (entsel)) "xa") 返回 "你好中國" 采用這種方法,用 EXPLODE 命令可以炸開擴展數據,相當於清除圖元的擴展數據。
在某些二次開發的 CAD 程序中,擴展數據被大量使用,用來分類圖元對象(圖層分類法容易被修改)。
這時候的 ssget 方顯英雄本色,用來精確選擇,再適合不過。在參數化制圖時,添加擴展數據,當參數
發生變化時,很容易遍歷修改這些對象,由於擴展數據的不可見和不可分解的特性,不會被用戶誤操作。
這時候只需要用下面代碼即可完成過濾,連對象類別的 0 組碼 都不需要了。
(ssget ‘((-3 (“xapp”))))
AutoLisp 選擇對象函數 ssget 用法