明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 3982|回复: 21

[源码] 多组条件过滤选择【2022.02.10更新】

[复制链接]
发表于 2019-6-22 14:02:37 | 显示全部楼层 |阅读模式
本帖最后由 masterlong 于 2022-2-10 21:45 编辑

看到群里经常有讨论多组条件过滤选择
可能是程序本身要求比较简单
所以采用的方法也略显粗糙
当然这也没啥不对
程序能用就行

不过我的观点是
随着编程水平的提高
程序也会越复杂
相应用到复杂过滤分组的可能性也越大
掌握一个相对灵活易用的方法
更有利于把精力
投入到程序主要功能的编写上

;------------------------------------------------------------------------------------------------------

发一个自己用的多组条件过滤选择的函数
选择后分组
(ssgetsome( mode ptlist someflist divmode))
返回
所有图元选择集  or  (所有图元选择集 (第1条件图元列表)   (第2条件图元列表)  ... )



  1. ;999```多组条件过滤选择    ;;(ssgetsome   mode ptlist someflist divmode)
  2. ;|
  3. 第1个参数为字符,指定选择方式; 第2个参数为多点表(WCS坐标,点表不作校验)或图元;
  4. ""  ——手动;    ——任意格式(始终忽略)
  5. "x" ——全图;    ——任意格式(始终忽略)
  6. "p" ——前一选择;  ——任意格式(始终忽略)
  7. "w" ——窗口内选择;  ——点表(3点以上自动转换为最小正交包围盒两点) ——图元(自动转换为正交包围盒两点)
  8. "wp" ——多边形选择;  ——多点表              ——闭合PL线(自动转换PL线节点为多点表[忽略圆弧段]),其它图元取最小正交包围盒四点
  9. "c" ——窗口交叉选择; ——点表(3点以上自动转换为最小正交包围盒两点) ——图元(自动转换为最小包围盒两点)
  10. "cp" ——多边形交叉选择;——多点表              ——闭合PL线(自动转换PL线节点为多点表,忽略圆弧段),其它图元取最小正交包围盒四点

  11. 第3个参数为由多个过滤条件组成的复合表。
  12. 例:
  13. '(
  14. ((0 . "insert")(2 . "灯1*"))
  15. ((0 . "text")(8 . "f_hide"))
  16. )
  17. 自动转换为ssget可以识别的过滤条件,传递给ssget进行一次选择
  18. '( (-4 . "<or")
  19.   (-4 . "<and") (0 . "text")(8 . "f_hide") (-4 . "and>")
  20.   (-4 . "<and") (0 . "insert")(2 . "灯1*") (-4 . "and>")
  21. (-4 . "or>")
  22. )
  23. 选择完成后,再根据子表进行二次过滤分组

  24. 第4个参数 T/nil ,控制是否细分
  25. 未选择到任何图元,函数返回nil
  26. 成功选择
  27. ————要求细分时,函数返回一个复合表。第一个子表为本次选择的所有图元选择集,其后子表均为图元列表或nil,并与第3个参数子表一一对应
  28. ————不要求时,函数返回选择集
  29. 【注意1】
  30. 若过滤条件复合表中各子表过滤条件之间有交叉,返回子表中的图元也是交叉存在的(即存在重复)。
  31. 【注意2】
  32. 第2个参数提供图元时,即使该图元本身符合过滤条件,该图元也将被自动排除。
  33. 【注意3】
  34. WP/CP模式时,若点表参数提供闭合PL线时,真假闭合均可,但是PL线节点数需>=3,同时非自交(自交点表不符合ssget‘WP/CP的执行条件)。
  35. |;
  36. ;;使用教程
  37. ;|
  38. ;555````先建立多组过滤条件列表,各组条件之间不用考虑 <-4`and> + <-4`or> 的组合,此由函数自动完成拼接
  39. (setq somefi
  40.   '(
  41.    ((0 . "INSERT") (2 . "AAA*") (8 . "非打印云线"))
  42.    ((0 . "INSERT") (2 . "BBB*") (-4 . "!=")(62 . 6))
  43.    ((-4 . "<not")  (2 . "AAA*,BBB*") (-4 . "not>"))
  44.   )
  45. )
  46. ;555````调用函数进行过滤选择
  47. (setq somess (ssgetsome "" nil somefi T))
  48. ;555````选择后分组调用
  49. (setq ss0 (nth 0 somess)
  50.   ss1 (nth 1 somess)
  51.   ss2 (nth 2 somess)
  52.   ss3 (nth 3 somess)
  53. )
  54. |;
  55. ;
  56. ;999```多组条件过滤选择    ;;(ssgetsome   mode ptlist someflist divmode)
  57. ;
  58. (defun ssgetsome( mode ptlist someflist divmode / box pt1 pt2 ss tmp temp1 temp2 someselsslist )
  59. (setq mode (strcase mode))
  60. ;;点表处理
  61. (cond
  62.   ((or (= mode "W") (= mode "C"))
  63.    (if (= (type ptlist) 'ENAME)
  64.     (setq box (entbox ptlist)
  65.       pt1 (car  box)
  66.       pt2 (cadr box)
  67.     )
  68.     (setq box (npt2box ptlist)
  69.       pt1 (car  box)
  70.       pt2 (cadr box)
  71.     )
  72.    )
  73.   )
  74.   ((or (= mode "WP") (= mode "CP"))
  75.    (if (= (type ptlist) 'ENAME)
  76.     (if (= (dxf 0 ptlist) "LWPOLYLINE")
  77.      (setq tmpl ptlist
  78.        ptlist (massoc 10 (entget ptlist))
  79.        box (npt2box ptlist)
  80.      )
  81.      (setq box (entbox ptlist))
  82.     )
  83.     (setq box ptlist)
  84.    )
  85.   )
  86. )
  87. (if box
  88.   (progn
  89.    (zoomsave)
  90.    (zoomptlist box 3)
  91.   )
  92. )
  93. ;;过滤表处理
  94. (setq temp1 (mapcar ''((x) (append '((-4 . "<and")) x '((-4 . "and>")))) someflist))
  95. (setq temp2 '())
  96. (mapcar ''((x) (setq temp2 (append x temp2))) temp1)
  97. (setq oped_someflist (append '((-4 . "<or")) temp2 '((-4 . "or>"))))
  98. ;;执行过滤
  99. (cond
  100.   ((= mode "")   (setq ss (ssget oped_someflist)))
  101.   ((= mode "X")   (setq ss (ssget "X"  oped_someflist)))
  102.   ((= mode "P")   (setq ss (ssget "P"  oped_someflist)))
  103.   ((= mode "W")   (setq ss (ssget "W"  pt1 pt2 oped_someflist)))
  104.   ((= mode "WP")  (setq ss (ssget "WP" ptlist  oped_someflist)))
  105.   ((= mode "C")   (setq ss (ssget "C"  pt1 pt2 oped_someflist)))
  106.   ((= mode "CP")  (setq ss (ssget "CP" ptlist  oped_someflist)))
  107. )
  108. (if box (zoomload))
  109. ;;选择集首先排除用于点表参数的图元本身
  110. (if (and ss tmpl (ssmemb tmpl ss))
  111.   (setq ss (ssdel tmpl ss)   tmpl (print "!!!"))
  112. )
  113. ;;细分
  114. (if (and ss divmode)
  115.   (progn
  116.    ;;按过滤条件分类
  117.    ;;由于在过滤条件中,可能存在通配符或者其它测试条件存在。分类分组的方式,不方便采用vl-remove-if-not去筛选
  118.    ;;所以采用的多次ssget'P方式。速度会慢一点,但是省去了大量的代码
  119.        ;;(setq someselsslist (mapcar ''((x) (oldss2act ss) (ssget "p" x)) someflist))    ;;希望返回子表为选择集时
  120.    (setq someselsslist (mapcar ''((x) (oldss2act ss) (ss2list (ssget "p" x))) someflist))
  121.    (oldss2act ss)
  122.    (cons ss someselsslist)
  123.   )
  124.   ss
  125. )
  126. )
  127. ;999当前视窗save   ----(getvar "viewctr")得到的是UCS坐标
  128. (defun zoomsave()
  129. (setq zoom*savelist (list (getvar "ctab") (vlax-3D-Point (trans (getvar "viewctr") 1 0)) (getvar "viewsize")))
  130. )
  131. ;999当前视窗load
  132. (defun zoomload()
  133. (if zoom*savelist
  134.   (progn
  135.    (setvar "ctab" (car zoom*savelist))
  136.    (vla-ZoomCenter *acad* (cadr zoom*savelist) (caddr zoom*savelist))
  137.   )
  138. )
  139. )
  140. ;999公共函数
  141. ;;单个物体的最小(正交)包围框---------------------------------这个程序在遇到无法显示的图元时,还是会出错的,比如形。天正图元会不会也不支持,未测试
  142. (defun entbox ( ent / ll ur )
  143. (vla-getboundingbox (vlax-ename->vla-object ent) 'll 'ur)
  144. (mapcar 'vlax-safearray->list (list ll ur))
  145. )
  146. ;999公共函数
  147. ;;求n个点的正交包围框
  148. ;;(setq npt (list p1 p2 p3 p4 ... ))
  149. (defun npt2box( npt )
  150. (list
  151.   (apply 'mapcar (cons 'min npt))
  152.   (apply 'mapcar (cons 'max npt))
  153. )
  154. )
  155. ;999公共函数
  156. ;;dxf  获取图元某个dxf组码(内参不限种类顺序::: n ent [entget ent] )
  157. (defun dxf( n ent / temp )
  158. (if (/= (type n) 'int)
  159.   (setq temp  ent
  160.     ent n  
  161.     n  temp
  162.   )
  163. )
  164. (if (= (type ent) 'ENAME)
  165.   (setq temp (entget ent))
  166.   (setq temp ent)
  167. )
  168. (cdr (assoc n temp))
  169. )
  170. ;999公共函数
  171. ;;返回包含每一出现在列表中的指定键的cdr(点对的后部分)的列表<适合处理pl线>
  172. ;;例 (massoc 40 (entget (car (entsel)))) 每个顶点的宽度
  173. ;;返回 (0.0 0.0 200.0 0.0)
  174. (defun massoc( key alist / x nlist)
  175. (if (= (type alist) 'ename)
  176.   (setq nlist (entget alist))
  177.   (setq nlist alist)
  178. )
  179. (mapcar 'cdr (vl-remove-if-not ''((x) (= (car x) key)) nlist))
  180. )
  181. ;999公共函数
  182. ;;以指定点表的包围框中心,缩放窗口——————主要用来保证后续可执行 (ssget 'CP/'WP ptlist)
  183. (defun zoomptlist( ptlist sc / box x midpo )
  184. (setq box (npt2box ptlist))
  185. (setq midpo (getmidpo box))
  186. (vla-ZoomCenter (vlax-get-acad-object) (vlax-3d-point midpo) (* sc (- (cadr (cadr box)) (cadr (car box)))))
  187. box
  188. )
  189. ;999公共函数
  190. ;;求点对中点
  191. (defun getmidpo( pts / P1 P2 X Y )
  192. (setq p1 (car pts) p2 (cadr pts))
  193. (if (= (length p1) (length p2))
  194.   nil
  195.   (setq p1 (list (car p1) (cadr p1))
  196.     p2 (list (car p2) (cadr p2))
  197.   )
  198. )
  199. (mapcar '(lambda (X Y) (/ (+ X Y) 2.0)) P1 P2)
  200. )
  201. ;999公共函数
  202. ;;选择集转为图元列表
  203. (defun ss2list ( ss / n i elist )
  204. (cond
  205.   ((= (type ss) 'Pickset)
  206.    (setq n  (sslength ss)
  207.      i n
  208.      elist '()
  209.    )
  210.    (repeat n
  211.     (setq i (1- i))
  212.     ;;如果没有这个if,那么选择集中被删除的图元,也会被加入到列表之中————但是极其偶尔也有可能,图元不存在但是能entget(遇到过一次,原因不明,或许是CAD的BUG)
  213.     (if (entget (ssname ss i))
  214.      (setq elist (cons (ssname ss i) elist))
  215.     )
  216.    )
  217.    elist
  218.   )
  219.   ((= (type ss) 'ename)
  220.    (list ss)
  221.   )
  222.   ((= (type ss) 'list)
  223.    (vl-remove-if-not ''((x) (and (= (type x) 'ename) (entget x))) ss)
  224.   )
  225.   ( T NIL)
  226. )
  227. )
  228. ;999公共函数
  229. ;;图元列表转为选择集(判断图元是否存在,空表时返回空选择集)
  230. (defun list2ss( biao / ss )
  231. (cond
  232.   ((= (type biao) 'list)
  233.    (setq biao (vl-remove-if-not ''((x) (and (= (type x) 'ename) (entget x))) biao))
  234.    (setq ss (ssadd))
  235.    (mapcar '(lambda (x) (if (entget x) (setq ss (ssadd x ss)))) biao)
  236.    (if ss ss (ssadd))
  237.   )
  238.   ((= (type biao) 'ename)
  239.    (ssadd biao)
  240.   )
  241.   ((= (type biao) 'Pickset)
  242.    (setq biao (ss2list biao))
  243.    (setq biao (vl-remove-if-not ''((x) (and (= (type x) 'ename) (entget x))) biao))
  244.    (setq ss (ssadd))
  245.    (mapcar ''((x) (setq ss (ssadd x ss))) biao)
  246.    ss
  247.   )
  248.   ( T (ssadd))
  249. )
  250. )
  251. ;999公共函数
  252. ;;一个已存在的选择集,设置成当前选择集
  253. (defun oldss2act( oldss )
  254. (sssetfirst Nil oldss)  ;;将选择集设为夹点显示模式
  255. (ssget "i")
  256. (sssetfirst nil nil)  
  257. )







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
"觉得好,就打赏"
还没有人打赏,支持一下
 楼主| 发表于 2022-2-10 21:25:36 | 显示全部楼层
这个函数的编写思路

首先是尽量模拟ssget本身的书写格式

其次可以根据指定的选择方式
传递一个图元转化为点表
比如指定“WP”同时传递一个PL图元
函数会提取PL的顶点进行多边形选择

第三是简化多组过滤条件的编写

具体的详见函数开头的注释部分
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2019-6-22 14:03:53 | 显示全部楼层
本帖最后由 masterlong 于 2022-2-10 21:00 编辑

首次使用代码模式发帖
结果是这样?

总算掌握了代码发帖的奥义  
发表于 2019-6-23 12:11:07 | 显示全部楼层
谢谢分享,对我有帮助
发表于 2019-6-24 09:38:43 | 显示全部楼层
[code="lisp]要为单独的一行才行
 楼主| 发表于 2019-6-24 19:41:19 | 显示全部楼层
本帖最后由 masterlong 于 2019-6-24 19:45 编辑

实验半天不成功

 楼主| 发表于 2019-6-24 19:45:51 | 显示全部楼层
还是不成功
是浏览器的问题?
算了不管了
发表于 2019-6-24 20:16:45 | 显示全部楼层
好像是有点问题,不是总能成功的加入代码并语法高亮
发表于 2019-6-28 21:08:39 | 显示全部楼层
虽然现在不知道怎么使用,但感谢楼主的无私分享!
 楼主| 发表于 2022-2-10 20:50:10 | 显示全部楼层
做了点更新重新上传
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 15:26 , Processed in 0.208456 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表