明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 3633|回复: 44

[【高飞鸟】] 任意角度或UCS下的物体包围盒

    [复制链接]
发表于 2024-6-20 18:05:05 | 显示全部楼层 |阅读模式
本帖最后由 highflybird 于 2024-6-20 20:01 编辑

以前写了一个任意角度或者UCS下的物体包围盒的求法,现把源码贡献上来:

下面是演示效果

运行命令 : ttt
求出了每个物体在当前UCS下的包围盒, 然后再画出了选中物体的当前UCS下的包围盒。

对线段、曲线,文字,块均适用。

本帖子中包含更多资源

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

x

评分

参与人数 20明经币 +20 金钱 +85 收起 理由
CAD智能@未来 + 1
竹天 + 1
zhoupeng220 + 1 很给力!
tomonkey239 + 1 赞一个!
LPACMQ + 1 很给力!
yerenyu@qq.com + 1 很给力!
1028695446 + 1 + 5 你们一大早就来逛明经哇,我的评论与支持已.
baitang36 + 1 很给力!
start4444 + 1 很给力!
开心68602 + 1 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2024-6-20 23:59:32 | 显示全部楼层
本帖最后由 尘缘一生 于 2024-6-21 05:55 编辑
highflybird 发表于 2024-6-20 19:09
我应该有个计算物体最小面积的包围盒程序。你搜索一下看看。


我组织了下子,测试,

1:本贴取得角度办法较快,但面积不是最小的包容:
2:从前 minarearectangle 函数办法较慢,但面积是最小的包容
  1. ;;;--------------------------
  2. ;;; 功能: 旋转点
  3. ;;; 输入: 点p,角度ang  
  4. ;;; 输出: 中点位置      
  5. ;;;-------------------------
  6. (defun geo:rotbyangle (p ang / c s)
  7.   (setq c (cos ang))
  8.   (setq s (sin ang))
  9.   (list
  10.     (- (* c (car p)) (* s (cadr p)))
  11.     (+ (* s (car p)) (* c (cadr p)))
  12.   )
  13. )
  14. ;;;------------------------
  15. ;;; 功能: 沿某一个方向的点集的包围盒   
  16. ;;; 输入: pts--点集     
  17. ;;; ang--方向与x轴夹角   
  18. ;;; 输出: 包围盒点(wcs)
  19. ;;;--------------------------
  20. (defun geo:getboxbyset (pts ang / pmin pmax)
  21.   (setq pts (mapcar (function (lambda (p) (geo:rotbyangle p (- ang)))) pts))
  22.   (setq pmin (apply 'mapcar (cons 'min pts)))
  23.   (setq pmax (apply 'mapcar (cons 'max pts)))
  24.   (mapcar
  25.     (function (lambda (p) (geo:rotbyangle p ang)))
  26.     (list
  27.       (list (car pmin) (cadr pmin))
  28.       (list (car pmax) (cadr pmin))
  29.       (list (car pmax) (cadr pmax))
  30.       (list (car pmin) (cadr pmax))
  31.     )
  32.   )
  33. )
  34. ;点积(内积):p1p2 p1p3是否垂直,垂直为0;锐角为正,钝角为负 By Highflybird
  35. ;;定义向量的点积函数(向量A投影在向量B上的长度,但是它还要乘上B的长度)
  36. (defun dot (p1 p2 p3 / x1 y1)
  37.   (setq  x1 (car p1)
  38.     y1 (cadr p1)
  39.   )
  40.   (+ (* (- (car p2) x1) (- (car p3) x1))
  41.     (* (- (cadr p2) y1) (- (cadr p3) y1))
  42.   )
  43. )
  44. ;;叉积(外积) By Highflybird
  45. ;;1 三角形之倍面积
  46. ;;2 p1 p2 p3 逆时针为正。
  47. ;;3 三点共线为0
  48. (defun det (p1 p2 p3 / x2 y2)
  49.   (setq  x2 (car p2) y2 (cadr p2))
  50.   (- (* (- x2 (car p3)) (- y2 (cadr p1))) (* (- x2 (car p1)) (- y2 (cadr p3))))
  51. )
  52. ;;;========================================
  53. ;;;求凸壳直径的参数      
  54. ;;;参数:逆时针的凸壳 h-------注意逆时针!!!
  55. ;;;返回值: (pair ang maxd) ((p1 p2) 角度、直径) modify qq:15290049
  56. ;;;========================================
  57. (defun max-ang-distance (h / d m maxd p pair ang q u v w)
  58.   (setq q (cdr (append h h (list (car h)))))        ;构造一个首尾循环的凸集,且起始点为凸壳的第二点
  59.   (setq maxd 0.0)              ;初始化最小距离为0
  60.   (foreach u h                ;依次检查凸壳的边
  61.     (setq v (car q))              ;循环集的第一点
  62.     (setq w (cadr q))              ;循环集的第二点
  63.     (setq m (sl:mid v w))            ;这两点的中点
  64.     (while (> (dot m u v) 0.0)      ;如果夹角小于90度(即点积大于0)
  65.       (setq q (cdr q))              ;循环集推进
  66.       (setq v (car q))              ;取下一点
  67.       (setq w (cadr q))              ;下下一点
  68.       (setq m (sl:mid v w))        ;这两点的中点
  69.     )
  70.     (setq d (distance u v))            ;计算这时的最大距离
  71.     (if  (> d maxd)              ;如果大于前面的最大距离
  72.       (setq maxd d              ;就替换前面的最大距离
  73.         pair (list u v)          ;并记录这对点
  74.       )
  75.     )
  76.   )
  77.   (setq ang (angle (car pair) (cadr pair))) ;modify qq:15290049
  78.   (list pair ang maxd)              ;返回这对点和角度、最大距离 ;modify qq:15290049
  79. )
  80. ;;;==================
  81. ;;;graham扫描法求逆时针凸包
  82. ;;;==================
  83. (defun graham-scan (plis / hullpt maxxpt sortpt p q)
  84.   (if (< (length plis) 3)            ;3点以下
  85.     plis                ;是本集合
  86.     (progn
  87.       (setq maxxpt (assoc (apply 'max (mapcar 'car plis)) plis))  ;最右边的点
  88.       (setq sortpt (sort-by-angle-distance plis maxxpt))     ;分类点集
  89.       (setq hullpt (list (cadr sortpt) maxxpt))        ;开始的两点      
  90.       (foreach n (cddr sortpt)            ;从第3点开始
  91.         (setq hullpt (cons n hullpt))          ;把pi加入到凸集
  92.         (setq p (cadr hullpt))            ;pi-1
  93.         (setq q (caddr hullpt))            ;pi-2
  94.         (while (and q (> (det n p q) -1e-6))         ;如果左转
  95.           (setq hullpt (cons n (cddr hullpt)))         ;删除pi-1点
  96.           (setq p (cadr hullpt))          ;得到新的pi-1点
  97.           (setq q (caddr hullpt))          ;得到新的pi-2点
  98.         )
  99.       )
  100.       (reverse hullpt)              ;返回凸集
  101.     )
  102.   )
  103. )
  104. ;;求中点函数-------(一级)------
  105. (defun sl:mid (p1 p2)
  106.   (list (* (+ (car p1) (car p2)) 0.5) (* (+ (cadr p1) (cadr p2)) 0.5))
  107. )
  108. ;;;以某点为基点,按照角度和距离分类点集
  109. (defun sort-by-angle-distance (plis pt / )
  110.   (vl-sort plis
  111.     (function
  112.       (lambda (e1 e2 / ang1 ang2 )
  113.         (setq ang1 (angle pt e1))
  114.         (setq ang2 (angle pt e2))
  115.         (if (= ang1 ang2)
  116.           (< (distance pt e1) (distance pt e2))
  117.           (< ang1 ang2)
  118.         )
  119.       )
  120.     )
  121.   )
  122. )
  123. ;;以下测试用(函数)---


  124. ;点表生成多段线--------(一级)-------
  125. ;线宽=nil,线宽为0  ;是否闭合=nil,不闭合 ;图层=nil,为当前图层 ;颜色=nil,为当前图层颜色  ;线型比例=nil,为1
  126. ;(slch:lwpolyline 点表 是否闭合 线宽 图层 颜色 线型比例)
  127. ;(slch:lwpolyline (list (1 2) (2 3)) T 2 "中心线" 6 5)
  128. (defun slch:lwpolyline (lst dxf70 plwid lay lwplcol lwplbili)
  129.   (entmake
  130.     (append
  131.       (list
  132.         '(0 . "LWPOLYLINE")
  133.         '(100 . "AcDbEntity")
  134.         '(100 . "AcDbPolyline")
  135.         (cons 90 (length lst)) ;点表
  136.         (if (= dxf70 T)
  137.           (cons 70 1)  ;闭合与不闭合
  138.           (cons 70 0)
  139.         )
  140.         (if plwid
  141.           (cons 43 plwid)      ;线宽
  142.           (cons 43 0)
  143.         )
  144.         (if lay
  145.           (cons 8 lay) ;图层
  146.           (cons 8 (getvar "CLAYER"))
  147.         )
  148.         (if lwplcol
  149.           (cons 62 lwplcol)    ;颜色
  150.           (cons 62 256)
  151.         )
  152.         (if lwplbili
  153.           (cons 48 lwplbili)   ;线型比例
  154.           (cons 48 (* 0.01 (getvar "DIMLFAC")))
  155.         )
  156.       )
  157.       (mapcar '(lambda (pt) (cons 10 pt)) lst)
  158.     )
  159.   )
  160. )
  161. ;;测试主程序1--
  162. ;;结果:耗时较快
  163. (defun c:tt (/ plis sel t0 ang)
  164.   (setq t0 (getvar "MILLISECS"))
  165.   (setq plis (Graham-scan (getpt (ssget))))        ;construct the CCW Hull of this set.
  166.   (setq ang (cadr (max-ang-distance plis))) ;modify qq:15290049
  167.   (setq plis (geo:getboxbyset plis ang))      ;qq:15290049
  168.   (slch:lwpolyline plis t nil nil nil nil)
  169.   (prompt (strcat "耗时" (rtos (/ (- (getvar "MILLISECS") t0) 1000.) 2 5) "秒"))
  170.   (princ)
  171. )
  172. ;;测试主程序2--
  173. ;;结果:耗时较慢
  174. (defun c:tt1 (/ plis sel t0 ang)
  175.   (setq t0 (getvar "MILLISECS"))
  176.   (setq plis (Graham-scan (getpt (ssget))))        ;construct the CCW Hull of this set.
  177.   (if (or (< (length plis) 3) (and (>= (length plis) 3) (<= (dot (car plis) (cadr plis) (caddr plis)) 0.0)))
  178.     (setq plis (reverse plis))
  179.   )
  180.   (setq plis (car (minarearectangle plis))) ;这是高飞大师的,最小面积包容较慢
  181.   (slch:lwpolyline plis t nil nil nil nil)
  182.   (prompt (strcat "耗时" (rtos (/ (- (getvar "MILLISECS") t0) 1000.) 2 5) "秒"))
  183.   (princ)
  184. )

本帖子中包含更多资源

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

x
发表于 2024-6-21 05:58:16 | 显示全部楼层
highflybird 发表于 2024-6-21 00:04
这两个目的不一样。一个是求最小的包围盒,一个是求指定角度下的包围盒。

嗯,高大师,那么面积最小时候这个角度求出来的函数,能组织个,就可以加快速度了不是?因为面积最小时候的凸包,用的多。
发表于 2024-6-20 18:33:56 | 显示全部楼层
对于角度的取值,对于点集的话,最好能有个判定点集那个角度的包容盒所围成的面积最小,自动求得这个角度。

记得大师有哪个集成,如果和这个集成合并下子,做个点集,取这个角度的函数,单独取这个角度,就方便了。
发表于 2024-6-20 18:12:30 | 显示全部楼层
版主,您好
这个代码是否对三维立体图形也有效呢?
发表于 2024-6-20 18:18:40 | 显示全部楼层
感谢高飞鸟大佬的分享~
发表于 2024-6-20 18:20:11 | 显示全部楼层
谢谢高飞老师的无私分享。
发表于 2024-6-20 18:27:41 | 显示全部楼层
感谢无私分享~
 楼主| 发表于 2024-6-20 18:29:04 | 显示全部楼层
yaokui25 发表于 2024-6-20 18:12
版主,您好
这个代码是否对三维立体图形也有效呢?

也有效。不过要稍微处理一下。
发表于 2024-6-20 18:30:31 | 显示全部楼层

谢谢高飞老师的无私分享。
发表于 2024-6-20 18:37:17 | 显示全部楼层
highflybird 发表于 2024-6-20 18:29
也有效。不过要稍微处理一下。

嘿嘿
麻烦版主可否出一版可对三维立体图形有效的,可以计算出最小立方体呢
 楼主| 发表于 2024-6-20 18:39:50 | 显示全部楼层
yaokui25 发表于 2024-6-20 18:37
嘿嘿
麻烦版主可否出一版可对三维立体图形有效的,可以计算出最小立方体呢

算最小立方体的,恐怕有点麻烦。不能用这个计算。否则很慢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-12-27 06:50 , Processed in 0.181793 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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