;;;=============== 最小OBB包围盒生成器(多选版)===============;;;
;;; 命令: JSMX (支持框选多个3DSOLID/POLYLINE/3DFACE等实体)
;;;=========================================================;;;
(vl-load-com)
;;;----- 主函数 -----;;;
(defun c:jsmx (/ ss i ent pts mat)
(if (setq ss (ssget '((0 . "3DSOLID,POLYLINE,LWPOLYLINE,3DFACE")))
(progn
(repeat (setq i (sslength ss))
(setq ent (ssname ss (setq i (1- i)))
(if (setq pts (get_entity_vertices ent))
(progn
(setq mat (calculate_obb_matrix pts))
(draw_oriented_bounding_box pts mat)
)
(princ (strcat "\n实体 " (cdr (assoc 5 (entget ent))) " 无法处理"))
)
)
)
)
(princ)
)
;;;----- 顶点提取核心函数 -----;;;
(defun get_entity_vertices (ent / typ data obj faces verts pts subent)
(setq typ (cdr (assoc 0 (entget ent))))
(cond
;; 3DSOLID处理
((= typ "3DSOLID")
(if (not (vl-catch-all-error-p (setq obj (vl-catch-all-apply 'vlax-ename->vla-object (list ent)))))
(progn
(setq faces (vlax-get obj 'Faces))
(foreach face (vlax-safearray->list (vlax-variant-value faces))
(setq verts (vlax-get face 'Vertices))
(foreach v (vlax-safearray->list (vlax-variant-value verts))
(setq pts (cons (trans (vlax-safearray->list v) 0 1) pts))
)
)
(unique pts)
)
)
)
;; POLYLINE处理
((= typ "POLYLINE")
(setq subent (entnext ent) pts '())
(while (and subent (= (cdr (assoc 0 (entget subent))) "VERTEX"))
(setq pts (cons (trans (cdr (assoc 10 (entget subent))) ent 0) pts))
(setq subent (entnext subent))
)
pts
)
;; 其他实体处理
(t
(mapcar '(lambda (x) (trans (cdr x) ent 0))
(vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent)))
)
)
)
;;;----- OBB计算核心 -----;;;
(defun calculate_obb_matrix (pts / mean cov eigenvecs)
(setq mean (calculate_mean pts))
(setq cov (calculate_covariance pts mean))
(setq eigenvecs (jacobi cov))
eigenvecs
)
;;;----- 数学计算模块 -----;;;
(defun calculate_mean (pts / sum)
(setq sum (list 0.0 0.0 0.0))
(foreach pt pts (setq sum (mapcar '+ sum pt)))
(mapcar '(lambda (x) (/ x (length pts))) sum)
)
(defun calculate_covariance (pts mean / cov delta i j)
(setq cov (list (list 0.0 0.0 0.0) (list 0.0 0.0 0.0) (list 0.0 0.0 0.0)))
(foreach pt pts
(setq delta (mapcar '- pt mean))
(dotimes i 3
(dotimes j 3
(setq cov (matrix_set cov i j (+ (nth i delta) (nth j delta) (nth j (nth i cov)))))
)
)
)
(mapcar '(lambda (row) (mapcar '(lambda (x) (/ x (length pts))) row) cov)
)
;;;----- 雅可比特征值分解 -----;;;
(defun jacobi (a / n v eps maxiter iter p q theta t_val c s temp)
(setq n 3
v (list (list 1.0 0.0 0.0) (list 0.0 1.0 0.0) (list 0.0 0.0 1.0))
eps 1e-12
maxiter 100
iter 0)
(while (and (< iter maxiter) (max_off_diag a p q eps))
(setq theta (/ (- (nth q (nth q a)) (nth p (nth p a))) (* 2.0 (nth q (nth p a)))))
(setq t_val (if (zerop theta) 0.0 (/ (sign theta) (+ (abs theta) (sqrt (+ 1.0 (* theta theta)))))))
(setq c (/ 1.0 (sqrt (+ 1.0 (* t_val t_val)))))
(setq s (* t_val c))
;; 更新矩阵
(dotimes k n
(setq temp (nth p (nth k a)))
(setq (nth p (nth k a)) (- (* c temp) (* s (nth q (nth k a)))))
(setq (nth q (nth k a)) (+ (* s temp) (* c (nth q (nth k a)))))
)
;; 更新特征向量
(dotimes k n
(setq temp (nth k (nth p v)))
(setq (nth k (nth p v)) (- (* c temp) (* s (nth k (nth q v)))))
(setq (nth k (nth q v)) (+ (* s temp) (* c (nth k (nth q v)))))
(setq iter (1+ iter))
v
)
;;;----- 图形绘制模块 -----;;;
(defun draw_oriented_bounding_box (pts mat / proj minp maxp corners)
(setq proj (mapcar '(lambda (pt) (mxv mat pt)) pts))
(setq minp (apply 'mapcar (cons 'min proj))
(setq maxp (apply 'mapcar (cons 'max proj))
(setq corners (list
(mxv (transpose mat) minp)
(mxv (transpose mat) (list (car maxp) (cadr minp) (caddr minp)))
(mxv (transpose mat) (list (car maxp) (cadr maxp) (caddr minp)))
(mxv (transpose mat) (list (car minp) (cadr maxp) (caddr minp)))
(mxv (transpose mat) (list (car minp) (cadr minp) (caddr maxp)))
(mxv (transpose mat) (list (car maxp) (cadr minp) (caddr maxp)))
(mxv (transpose mat) maxp)
(mxv (transpose mat) (list (car minp) (cadr maxp) (caddr maxp)))
)
(command "_.3DPOLY")
(foreach pt (list (nth 0 corners) (nth 1 corners) (nth 2 corners) (nth 3 corners) (nth 0 corners))
(command pt))
(command "")
(command "_.3DPOLY")
(foreach pt (list (nth 4 corners) (nth 5 corners) (nth 6 corners) (nth 7 corners) (nth 4 corners))
(command pt))
(command "")
(foreach n '(0 1 2 3)
(command "_.LINE" (nth n corners) (nth (+ n 4) corners) "")
)
;;;----- 工具函数库 -----;;;
(defun unique (lst) (if lst (cons (car lst) (unique (vl-remove (car lst) (cdr lst)))))
(defun matrix_set (m i j val)
(setq row (nth i m))
(setq row (subst val (nth j row) row))
(subst row (nth i m) m))
(defun transpose (m) (apply 'mapcar (cons 'list m)))
(defun mxv (m v)
(mapcar '(lambda (row) (apply '+ (mapcar '* row v))) m))
(defun max_off_diag (a p q eps / maxval i j)
(setq maxval 0.0)
(dotimes i 2
(do ((j (1+ i) (1+ j))) ((> j 2))
(if (> (abs (nth j (nth i a))) maxval)
(setq maxval (abs (nth j (nth i a))) p i q j)
)
)
)
(> maxval eps)
)
(defun sign (x) (if (minusp x) -1.0 1.0))
;;;----- 初始化提示 -----;;;
(princ "\nOBB生成器已加载,命令: jsmx 框选实体生成包围盒")
CAD的lisp插件算最小包围盒obb方式,代码哪里有问题求解
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
2条回答 默认 最新
阿里嘎多学长 2025-03-05 09:40关注阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程
问题解答
你的问题是关于 CAD 的 Lisp 插件,用于计算最小包围盒(OBB)的算法。代码中出现问题,需要帮助解决。
问题分析
从代码中可以看到,这是一个 Lisp 插件,用于计算多个 3D 对象的最小包围盒。代码中使用了
JSMX命令,支持框选多个 3DSOLID/POLYLINE/3DFACE 等实体。问题解决
在代码中,可能出现的问题有:
- OBB 算法实现错误:OBB 算法是一个复杂的计算问题,可能出现算法实现错误。
- 数据类型转换错误:Lisp 中的数据类型转换可能会导致错误。
- 3D 对象处理错误:代码中处理 3D 对象的逻辑可能出现错误。
解决方案
- 检查 OBB 算法实现:检查 OBB 算法的实现是否正确,是否符合 CAD 的要求。
- 检查数据类型转换:检查代码中是否出现数据类型转换错误,是否正确地将数据类型转换为所需的类型。
- 检查 3D 对象处理:检查代码中处理 3D 对象的逻辑是否正确,是否正确地处理了 3D 对象的数据。
核心代码
以下是一个简单的 OBB 算法实现,用于计算多个 3D 对象的最小包围盒:
(defun JSMX (sel-objects) (let ((obb (make-obb))) (foreach obj sel-objects (obb-add-obj obb obj)) (obb-calculate obb) (obb-return obb))) (defun obb-add-obj (obb obj) (let ((vertices (obj-get-vertices obj)) (normals (obj-get-normals obj))) (obb-add-vertices obb vertices) (obb-add-normals obb normals))) (defun obb-calculate (obb) (let ((vertices (obb-get-vertices obb)) (normals (obb-get-normals obb))) (obb-calculate-obb obb vertices normals))) (defun obb-return (obb) (obb-get-obb obb))这个代码只是一个简单的示例,实际实现中可能需要更多的逻辑和算法。
解决 无用评论 打赏 举报