明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 892|回复: 13

【BoxGroup】获取实体或对象的WCS/UCS最小边界框

  [复制链接]
发表于 2024-3-2 10:34 | 显示全部楼层 |阅读模式
本帖最后由 kucha007 于 2024-3-23 18:08 编辑

  1. ;返回实体或对象最小边界框的WCS坐标(左下角和右上角)@Gu_xl
  2. (defun K:GetWCSBox (obj / p1 p2 p3 p4 WCSBox)
  3.     (if (eq 'ENAME (type obj))(setq obj (vlax-ename->vla-object obj)))
  4.     (vla-GetBoundingBox obj 'p1 'p3)
  5.     (setq p1 (vlax-safearray->list p1)
  6.           p3 (vlax-safearray->list p3)
  7.           p2 (list (car p1) (cadr p3) (caddr p1))
  8.           p4 (list (car p3) (cadr p1) (caddr p1))
  9.     )
  10.     (if (eq "AcDbSpline" (Vla-Get-ObjectName obj));样条曲线取投影
  11.         (progn
  12.           (setq WCSBox (mapcar
  13.                           '(lambda (a b) (vlax-curve-getClosestPointToProjection obj a b t))
  14.                           (list p1 p2 p3 p4)
  15.                           '((1.0 0 0) (0 -1.0 0) (-1.0 0 0) (0 1.0 0))
  16.                        )
  17.           )
  18.           (list
  19.               (apply 'mapcar (cons 'min WCSBox));表中最小
  20.               (apply 'mapcar (cons 'max WCSBox));表中最大
  21.           )
  22.         )
  23.         (list p1 p3)
  24.     )
  25. )



  1. ;返回实体或对象最小边界框的UCS坐标(左下角和右上角)@Kucha
  2. (defun K:GetUCSBox (obj / K:CvtMatrix UCSBox)
  3.   (if (eq 'ENAME (type obj))(setq obj (vlax-ename->vla-object obj)))
  4.   ;矩阵转换/坐标系转换
  5.   (defun K:CvtMatrix (from to)
  6.     (append
  7.       (mapcar
  8.         (function
  9.           (lambda (v o)
  10.             (append (trans v from to t) (list o))
  11.           )
  12.         )
  13.         '((1.0 0.0 0.0)
  14.           (0.0 1.0 0.0)
  15.           (0.0 0.0 1.0)
  16.         )
  17.         (trans '(0.0 0.0 0.0) to from)
  18.       )
  19.       '((0.0 0.0 0.0 1.0))
  20.     )
  21.   )
  22.   (vla-transformby obj (vlax-tmatrix (K:CvtMatrix 1 0)));对象转换到WCS
  23.   (setq UCSBox (K:GetWCSBox obj));获取转换后的最小矩形框(WCS)
  24.   (vla-transformby obj (vlax-tmatrix (K:CvtMatrix 0 1)));对象转换回UCS
  25.   UCSBox
  26. )



  1. ;获取选择集所有实体的最小边界框表(WCS/UCS)@Kucha
  2. (defun K:SSAllBoxLst (WCS TgtSS / i en SSBox)
  3.     (if TgtSS
  4.         (repeat (setq i (sslength TgtSS))
  5.           (setq en (ssname TgtSS (setq i (1- i))))
  6.           (setq SSBox
  7.                  (cons
  8.                    (if WCS (K:GetWCSBox en) (K:GetUCSBox en))
  9.                    SSBox
  10.                  )
  11.           )
  12.         )
  13.     )
  14.     SSBox
  15. )


  1.   ;获取选择集的最小边界框(WCS/UCS)@Kucha
  2.   (defun K:SSMinBoxLst (WCS TgtSS / i en Box BoxMin BoxMax MinPt MaxPt)
  3.       (if TgtSS
  4.           (repeat (setq i (sslength TgtSS))
  5.               (setq en (ssname TgtSS (setq i (1- i))))
  6.               (setq Box (if WCS (K:GetWCSBox en) (K:GetUCSBox en)))
  7.               (setq BoxMin (car Box) BoxMax (cadr Box))
  8.               (setq MinPt (mapcar 'min BoxMin (cond (MinPt) (BoxMin))))
  9.               (setq MaxPt (mapcar 'max BoxMax (cond (MaxPt) (BoxMax))))
  10.           )
  11.       )
  12.       (list MinPt MaxPt)
  13.   )


  1. ;获取选择集最小边界框表的最小值,即左下角(WCS/UCS)@Kucha
  2. (defun K:SSBoxMinPT (WCS TgtSS / i en BoxMin MinPt)
  3.     (if TgtSS
  4.         (repeat (setq i (sslength TgtSS))
  5.             (setq en (ssname TgtSS (setq i (1- i))))
  6.             (setq BoxMin (car (if WCS (K:GetWCSBox en) (K:GetUCSBox en))))
  7.             (setq MinPt (mapcar 'min BoxMin (cond (MinPt) (BoxMin))))
  8.         )
  9.     )
  10.     MinPt
  11. )

评分

参与人数 6明经币 +6 金钱 +20 收起 理由
hhh454 + 1 + 10 赞一个!
hubeiwdlue + 1 很给力!
zhoupeng220 + 1 很给力!
飞雪神光 + 1 很给力!
ssyfeng + 1 赞一个!
tigcat + 1 + 10 楼主又发布实用程序了!支持

查看全部评分

 楼主| 发表于 2024-3-3 18:33 | 显示全部楼层
本帖最后由 kucha007 于 2024-3-4 13:24 编辑

应用实例:(K:RtnBox4Group 边界框顶点表 允许合并的间隙 行距)
  1. ;矩形分组(矩形分堆),并返回每一个组的包围盒@Tryhi-大海(优化 by Kucha)
  2. (defun K:RtnBox4Group (RecLst Gap SpcTol / K:2RecInters NewLst TmpLst Flag RdoLst BasRec FstRec IntRec a b)
  3.   ;时间复杂度为n(1),测试了17万个图元480组仅10秒
  4.   
  5.   ;如果矩形相交,则返回两矩形的最大边界框
  6.   (defun K:2RecInters (Fst Sec)
  7.     (if
  8.       (not
  9.         (or  ;不可能重叠的四种情况
  10.           (> (car Fst) (caddr Sec)) ;A的左侧比B的右侧大:X
  11.           (> (cadr Fst) (Last Sec)) ;A的下部比B的上部大:Y
  12.           (< (caddr Fst) (car Sec)) ;A的右侧比B的左侧小:X
  13.           (< (Last Fst) (cadr Sec)) ;A的上部比B的下部小:Y
  14.         )
  15.       )
  16.       (list
  17.         (min (car Fst) (car Sec))
  18.         (min (cadr Fst) (cadr Sec))
  19.         (max (caddr Fst) (caddr Sec))
  20.         (max (Last Fst) (Last Sec))
  21.       )
  22.     )
  23.   )
  24.   (if (and RecLst  (setq Gap (/ Gap 2)))
  25.       (progn
  26.           (setq RecLst
  27.               (mapcar
  28.                 '(lambda (XX)
  29.                     (list
  30.                         (nth 0 (car XX)) (nth 1 (car XX))
  31.                         (nth 0 (cadr XX)) (nth 1 (cadr XX))
  32.                     )
  33.                 )
  34.                 RecLst
  35.               )
  36.           );只取XY合并组成新的表,排序时再调整回来
  37.           (setq RecLst (mapcar '(lambda (XX) (mapcar '+ XX (list (- Gap) (- Gap) Gap Gap))) RecLst));矩形扩大
  38.           (progn ;合并矩形
  39.             (setq Flag T RdoLst Nil)
  40.             (while Flag
  41.               (setq BasRec (car RecLst) NewLst Nil)
  42.               (while (setq FstRec (car RecLst)) ;主要耗时点
  43.                 (setq RecLst (cdr RecLst)) ;更新列表
  44.                 (if (setq IntRec (K:2RecInters BasRec (setq FstRec (car RecLst))))
  45.                   (setq BasRec IntRec);RecLst中有和BasRec相交的矩形,更新BasRec
  46.                   (if
  47.                     (setq TmpLst (vl-some
  48.                               '(lambda (a / b)
  49.                                   (if (setq b (K:2RecInters BasRec a))
  50.                                     (list b a)
  51.                                   )
  52.                                 )
  53.                               NewLst
  54.                             )
  55.                     );NewLst中有和BasRec相交的矩形
  56.                     (progn
  57.                       (if (not (eq (car TmpLst) (Last TmpLst)))
  58.                           (setq NewLst (subst (car TmpLst) (Last TmpLst) NewLst))
  59.                       );相交矩形和表中对应元素不同则替换
  60.                       (setq BasRec FstRec)
  61.                     )
  62.                     (setq NewLst (cons BasRec NewLst)
  63.                           BasRec FstRec
  64.                     );收集并更新
  65.                   )
  66.                 )
  67.               )
  68.               (if (eq (length NewLst) (length RdoLst))
  69.                 (setq Flag Nil)
  70.                 (setq RdoLst NewLst
  71.                       RecLst NewLst
  72.                 )
  73.               )
  74.             )
  75.           )
  76.           (setq NewLst (mapcar '(lambda (XX) (mapcar '+ XX (list Gap Gap (- Gap) (- Gap)))) NewLst));矩形缩小
  77.           (vl-sort
  78.             (mapcar
  79.               '(lambda (x)
  80.                     (list
  81.                       (list (car x) (cadr x))
  82.                       (list (caddr x) (cadddr x))
  83.                     )
  84.                 )
  85.               NewLst
  86.             );重新调整LST表的数据结构
  87.             '(lambda (a b)
  88.                 (if (equal (cadr (car a)) (cadr (car b)) SpcTol)  ;Y在容差内相等?
  89.                     (if (equal (car (car a)) (car (car b)))  ;X相等
  90.                       (> (cadr (car a)) (cadr (car b))) ;比较Y
  91.                       (< (car (car a)) (car (car b))) ;比较X
  92.                     )
  93.                     (> (cadr (car a)) (cadr (car b))) ;比较Y
  94.                 )
  95.               )
  96.           );重新排序:先上下后左右
  97.       )
  98.   );矩形分堆得到互不相交的矩形LST
  99. )



发表于 2024-3-2 19:16 | 显示全部楼层
  1. ;返回实体或对象最小边界框的WCS坐标(左下角和右上角)@Gu_xl
  2. (defun K:GetWCSBox (obj / p1 p2 p3 p4 WCSBox)
  3.   (if (eq 'ENAME (type obj)) (setq obj (vlax-ename->vla-object obj)))
  4.   (vla-GetBoundingBox obj 'p1 'p3)
  5.   (setq p1 (vlax-safearray->list p1)
  6.     p3 (vlax-safearray->list p3)
  7.     p2 (list (car p1) (cadr p3) (caddr p1))
  8.     p4 (list (car p3) (cadr p1) (caddr p1))
  9.   )
  10.   (if (eq "AcDbSpline" (Vla-Get-ObjectName obj));样条曲线取投影
  11.     (progn
  12.       (setq WCSBox (mapcar
  13.                      '(lambda (a b) (vlax-curve-getClosestPointToProjection obj a b t))
  14.                      (list p1 p2 p3 p4)
  15.                      '((1.0 0 0) (0 -1.0 0) (-1.0 0 0) (0 1.0 0))
  16.                    )
  17.       )
  18.       (list
  19.          (apply 'mapcar (cons 'min WCSBox));表中最小
  20.          (apply 'mapcar (cons 'max WCSBox));表中最大
  21.       )
  22.     )
  23.     (list p1 p3)
  24.   )
  25. )
  26. ;返回实体或对象最小边界框的UCS坐标(左下角和右上角)@Kucha
  27. (defun K:GetUCSBox (obj / K:CvtMatrix UCSBox)
  28.   (if (eq 'ENAME (type obj)) (setq obj (vlax-ename->vla-object obj)))
  29.   ;矩阵转换/坐标系转换
  30.   (defun K:CvtMatrix (from to)
  31.     (append
  32.        (mapcar
  33.           (function
  34.             (lambda (v o)
  35.               (append (trans v from to t) (list o))
  36.             )
  37.           )
  38.           '((1.0 0.0 0.0)
  39.              (0.0 1.0 0.0)
  40.              (0.0 0.0 1.0)
  41.            )
  42.           (trans '(0.0 0.0 0.0) to from)
  43.          )
  44.        '((0.0 0.0 0.0 1.0))
  45.     )
  46.   )
  47.   (vla-transformby obj (vlax-tmatrix (K:CvtMatrix 1 0)));对象转换到WCS
  48.   (setq UCSBox (K:GetWCSBox obj));获取转换后的最小矩形框(WCS)
  49.   (vla-transformby obj (vlax-tmatrix (K:CvtMatrix 0 1)));对象转换回UCS
  50.   UCSBox
  51. )
  52. ;获取选择集所有实体的最小边界框表(WCS/UCS)@Kucha
  53. (defun K:SSAllBoxLst (WCS TgtSS / i en SSBox)
  54.   (if TgtSS
  55.     (repeat (setq i (sslength TgtSS))
  56.       (setq en (ssname TgtSS (setq i (1- i))))
  57.       (setq SSBox
  58.         (cons
  59.           (if WCS (K:GetWCSBox en) (K:GetUCSBox en))
  60.           SSBox
  61.         )
  62.       )
  63.     )
  64.   )
  65.   SSBox
  66. )
  67. ;获取选择集最小边界框表的最小值,即左下角(WCS/UCS)@Kucha
  68. (defun K:SSBoxMinPT (WCS TgtSS / i en BoxMin MinPt)
  69.   (if TgtSS
  70.     (repeat (setq i (sslength TgtSS))
  71.       (setq en (ssname TgtSS (setq i (1- i))))
  72.       (setq BoxMin (car (if WCS (K:GetWCSBox en) (K:GetUCSBox en))))
  73.       (setq MinPt (mapcar 'min BoxMin (cond (MinPt) (BoxMin))))
  74.     )
  75.   )
  76.   MinPt
  77. )


发表于 2024-3-2 19:16 | 显示全部楼层
这个就是你在ucs下得到的包围盒角点与在wcs下是一致的,同时楼主改进后可以得到选择集的包围盒.不过,这个函数猜测可能会存在缺陷,原因是基础函数用到curve系列函数,该函数在大坐标时,可能出现问题.
发表于 2024-3-2 12:05 | 显示全部楼层
这个挺好的,很多时候用的着
发表于 2024-3-2 16:34 | 显示全部楼层
不错,要是能给个应用实例就好了

 楼主| 发表于 2024-3-3 11:53 | 显示全部楼层
tigcat 发表于 2024-3-2 19:16
这个就是你在ucs下得到的包围盒角点与在wcs下是一致的,同时楼主改进后可以得到选择集的包围盒.不过,这个函 ...

现在是能用比好用重要哈哈哈,大坐标没探索太深
 楼主| 发表于 2024-3-3 11:55 | 显示全部楼层
发表于 2024-3-3 14:50 | 显示全部楼层
kucha007 发表于 2024-3-3 11:53
现在是能用比好用重要哈哈哈,大坐标没探索太深

楼主说的不错
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-3 16:32 , Processed in 0.229579 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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