vlisp代码详解
;;;功能:多段线(包括轻量多段线和旧式多段线),转换为样条曲线。(defun c:PL2SPL (/ *error* acadApp acadDoc modelSpace ss i ent obj pts pt param endparam ptlist splinepts successCount totalCount ) (vl-load-com);; 错误处理函数 (defun *error* (msg) (if (not (member msg ' ("Function cancelled""quit / exit abort") ) ) (princ (strcat"\n错误: " msg)) ) (princ) );; 获取当前文档和模型空间 (setq acadApp (vlax-get-acad-object)) (setq acadDoc (vla-get-activedocument acadApp) ) (setq modelSpace (vla-get-modelspace acadDoc) );; 提示用户选择多段线(允许多选) (princ"\n选择一条或多条多段线: ") (setq ss (ssget '((0 . "*POLYLINE")))) (if ss (progn (setq totalCount (sslength ss)) (setq successCount 0);; 遍历选择集中的每个对象 (setq i 0) (while (< i totalCount) (setq ent (ssname ss i)) (setq obj (vlax-ename->vla-object ent));; 获取多段线顶点坐标 (setq pts nil) (setq param 0) (setq endparam (vlax-curve-getendparam obj) );; 遍历所有顶点 (while (<= param endparam) (setq pt (vlax-curve-getpointatparam obj param) );; 去除 Z 坐标值(强制设为 0,转换为二维点) (setq pt (list (car pt)(cadr pt) 0.0)) (setq pts (cons pt pts)) (setq param (1+ param)) );; 反转点列表(因为我们是反向收集的) (setq pts (reverse pts));; 检查是否有足够多的点创建样条曲线(至少需要 2 个点) (if (>= (length pts) 2) (progn;; 创建样条曲线 (setq splinepts (vlax-make-safearray vlax-vbDouble (cons0 (- (*3 (length pts)) 1)) ) );; 填充点数组 (setq ptlist (apply 'append pts)) (vlax-safearray-fill splinepts ptlist) (vla-addspline modelSpace splinepts (vlax-3d-point '(000)) ; 起点切线方向 (vlax-3d-point '(000)) ; 终点切线方向 ) (setq successCount (1+ successCount)) ) (princ (strcat"\n警告: 第 " (itoa (1+ i)) " 条多段线顶点数量不足,已跳过。" ) ) ) (setq i (1+ i)) );; 输出结果统计 (princ (strcat"\n转换完成!成功转换 " (itoa successCount) "/" (itoa totalCount) " 条多段线。" ) ) ) (princ"\n未选择多段线或选择对象无效。") ) (princ));;;加载后,提示(princ"\nPL2SPL 命令已加载,输入 PL2SPL 使用。")(princ)
1. 命令定义和变量声明
(defun c:PL2SPL (/ *error* acadApp acadDoc modelSpace ss i ent obj pts pt param endparam ptlist splinepts successCount totalCount)
- 「
defun c:PL2SPL」: 定义一个名为 PL2SPL 的 AutoCAD 命令,前缀 c: 表示这是可执行的 CAD 命令 - 「
(/ *error* acadApp ...)」: 声明函数的所有局部变量,包括: obj: VLA(Visual Lisp ActiveX)对象splinepts: 安全数组,用于存储样条曲线点
2. 加载 ActiveX 支持
(vl-load-com)
- 加载 Visual LISP 的 ActiveX 支持,这是使用 VLA 对象方法的前提条件
3. 错误处理函数定义
(defun *error* (msg) (if (not (member msg '("Function cancelled""quit / exit abort"))) (princ (strcat"\n错误: " msg)) ) (princ))
(if (not (member msg ...)): 检查错误消息是否为以下特定类型(这些通常是用户主动取消的情况):- "Function cancelled": 函数被取消
- "quit / exit abort": 退出或中止
(princ): 静默退出,不显示多余的 nil 值
4. 获取 AutoCAD 应用程序和文档对象
(setq acadApp (vlax-get-acad-object))(setq acadDoc (vla-get-activedocument acadApp))(setq modelSpace (vla-get-modelspace acadDoc))
(vlax-get-acad-object): 获取当前 AutoCAD 应用程序对象(vla-get-activedocument acadApp): 获取当前活动文档对象(vla-get-modelspace acadDoc): 获取模型空间对象,用于在其中创建新实体
5. 提示用户选择多段线
(princ"\n选择一条或多条多段线: ")(setq ss (ssget '((0 . "*POLYLINE"))))
(ssget ...): 显示选择提示,让用户选择对象'((0 . "*POLYLINE")): 选择过滤器,只允许选择多段线类型对象(包括轻量多段线和旧式多段线)
6. 检查选择集是否有效
(if ss (progn ... ) (princ"\n未选择多段线或选择对象无效。"))
(progn ...): 如果选择集有效,则顺序执行多个表达式
7. 初始化计数器
(setq totalCount (sslength ss))(setq successCount 0)
(sslength ss): 获取选择集中对象的数量
8. 开始遍历选择集
(setq i 0)(while (< i totalCount)
(while (< i totalCount) ...): 当 i 小于总对象数时,继续循环
9. 获取当前对象信息
(setq ent (ssname ss i))(setq obj (vlax-ename->vla-object ent))
(ssname ss i): 通过索引获取选择集中的图元名(vlax-ename->vla-object ent): 将图元名转换为 VLA 对象,以便使用 ActiveX 方法
10. 初始化变量准备提取顶点
(setq pts nil)(setq param 0)(setq endparam (vlax-curve-getendparam obj))
(vlax-curve-getendparam obj): 获取曲线的结束参数值(对于多段线,这通常是顶点数减1)
11. 遍历多段线所有顶点
(while (<= param endparam) (setq pt (vlax-curve-getpointatparam obj param));; 去除 Z 坐标值(强制设为 0,转换为二维点) (setq pt (list (car pt) (cadr pt) 0.0)) (setq pts (cons pt pts)) (setq param (1+ param)))
(while (<= param endparam) ...): 遍历所有参数点(vlax-curve-getpointatparam obj param): 根据参数值获取曲线上的点(setq pt (list (car pt) (cadr pt) 0.0)): 将三维点转换为二维点(Z坐标设为0)(setq pts (cons pt pts)): 将点添加到列表头部(注意:这会创建逆序列表)(setq param (1+ param)): 参数值加1,移动到下一个点
12. 反转点列表
(setq pts (reverse pts))
- 由于之前使用
cons 添加点到列表头部,点列表是逆序的,需要反转以得到正确的顺序
13. 检查顶点数量是否足够
(if (>= (length pts) 2) (progn ... ) (princ (strcat"\n警告: 第 " (itoa (1+ i)) " 条多段线顶点数量不足,已跳过。" ) ))
- 检查顶点列表长度是否大于等于2(样条曲线至少需要2个点)
(itoa (1+ i)): 将整数转换为字符串,显示当前处理的第几条多段线
14. 创建样条曲线点数组
(setq splinepts (vlax-make-safearray vlax-vbDouble (cons0 (- (*3 (length pts)) 1)) ))
(vlax-make-safearray vlax-vbDouble ...): 创建双精度类型的安全数组(cons 0 (- (* 3 (length pts)) 1)): 定义数组索引范围- 终点索引:
(* 3 (length pts)) - 1(每个点有X、Y、Z三个坐标)
15. 准备点数据并填充数组
(setq ptlist (apply 'append pts))(vlax-safearray-fill splinepts ptlist)
(apply 'append pts): 将嵌套的点列表展平为一维列表(例如:((x1 y1 z1) (x2 y2 z2)) 变成 (x1 y1 z1 x2 y2 z2))(vlax-safearray-fill splinepts ptlist): 用点数据填充安全数组
16. 创建样条曲线
(vla-addspline modelSpace splinepts (vlax-3d-point '(000)) ; 起点切线方向 (vlax-3d-point '(000)) ; 终点切线方向)
(vla-addspline ...): 在模型空间创建样条曲线- 起点切线方向(设为(0,0,0)表示AutoCAD自动计算)
- 终点切线方向(设为(0,0,0)表示AutoCAD自动计算)
17. 更新成功计数器
(setq successCount (1+ successCount))
18. 循环计数器递增
(setq i (1+ i))
19. 循环结束,输出统计信息
(princ (strcat"\n转换完成!成功转换 " (itoa successCount) "/" (itoa totalCount) " 条多段线。" ))
20. 如果没有选择集,显示提示
(princ"\n未选择多段线或选择对象无效。")
21. 静默退出
(princ)
22. 加载提示信息
(princ"\nPL2SPL 命令已加载,输入 PL2SPL 使用。")(princ)
- 当LISP文件加载时显示的提示信息,告诉用户如何使用这个命令
总结
这个LISP程序是一个实用的CAD工具,可以将一条或多条多段线(包括轻量多段线和旧式多段线)转换为样条曲线。程序的主要流程如下:
- 「加载ActiveX支持」:启用Visual LISP的ActiveX功能
- 「获取AutoCAD对象」:获取应用程序、文档和模型空间对象
程序的特点包括: