当前位置: 首页 > news >正文

python lisp语言Autocad二次开发经验分享----Autolisp

和我的python帖子一样,能用AI解决的,能很容易查到资料的内容不多赘述

1.圆弧半径标注与缩放ZOOM(e)

(command "zoom" "e")

存在圆弧半径标注时,一旦范围缩放,必定包含圆心位置,所以在半径很大,圆心很远的时候,整个缩放会往圆心的另一侧偏移。当然,没有缩放需求用不到,这里我是在切换到图纸空间后需要在视口中调整模型空间中内容的位置。

关于后续如解决这个问题,我的方案是直接将圆弧半径标注使用多重引线替代。

;; 使用多重引线标注半径(文字格式为 R+数值) (defun ut_mleader_radius (arc_pt landing_pt r_val dim_text / mleader_text dir_angle ext_pt mleader_obj) ;; 消除后续零 (setvar "dimzin" 8) ;; 构造标注文字 (setq mleader_text (if (and dim_text (vl-string-search "<>" dim_text)) (vl-string-subst (strcat "R" (rtos r_val 2 3)) "<>" dim_text) (strcat "R" (rtos r_val 2 3)) ) ) ;; 沿arc_pt→landing_pt方向延伸作为引线落点 (setq dir_angle (angle arc_pt landing_pt)) (setq ext_pt (polar arc_pt dir_angle (if ut_mleader_ext_len ut_mleader_ext_len (/ a0 4)))) (command "mleader" arc_pt ext_pt "" mleader_text) ;; 应用 "Underline_Leader" 样式 (setq mleader_obj (vlax-ename->vla-object (entlast))) (vl-catch-all-apply 'vla-put-StyleName (list mleader_obj "Underline_Leader")) )

附上视口创建的lisp代码

(defun create_simple_viewport (save_path / vp_center vp_width vp_height vp_ent vp_obj doc) ;; 创建视口,然后设置比例 ;; 使用标准视口位置和大小 (setq vp_center (list 5 15)) ; A4图纸中心 (setq vp_width 250) ; 视口宽度 (setq vp_height 180) ; 视口高度 ;; 创建视口 (command "mview" vp_center (list (+ (car vp_center) vp_width) (+ (cadr vp_center) vp_height))) ;; 等待命令完成 (ut_wait_cmd) ;; 将视口对象移动到"视口"图层 (setq vp_ent (entlast)) (command "change" vp_ent "" "p" "la" "视口" "") ;; 获取文档对象和视口对象(ActiveX) (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))) (setq vp_obj (vlax-ename->vla-object vp_ent)) ;; 使用 vl-catch-all-apply 激活视口,防止 ActiveX 类型不匹配错误 (if (and doc vp_obj) (progn (vl-catch-all-apply 'vla-put-ActiveViewport (list doc vp_obj)) (vl-catch-all-apply 'vla-put-MSpace (list doc :vlax-true)) ) ) ;; 设置注释比例与视口自定义比例,这里的变量可以自己定义。 (if (and vp_obj ut_vp_scale) (progn (setvar "CANNOSCALE" ut_scale) (vl-catch-all-apply 'vla-put-CustomScale (list vp_obj ut_vp_scale)) (vl-catch-all-apply 'vla-update (list vp_obj)) ) ) ;; 返回图纸空间(使用 vl-catch-all-apply 防止错误) (if doc (vl-catch-all-apply 'vla-put-MSpace (list doc :vlax-false)) ) )

可能大家不太理解注释性:注释性的标注可以在视口中设置注释比例和视口比例:

假设视口比例1:1,注释比例为1或者1:1,则注释的文字大小,箭头大小,视口中的图形都和模型空间中相同,

设置视口比例2:1,注释比例为2:1,则注释性的文字大小,箭头大小同上,保持不变,但视口中的图形大小扩大为两倍

(setvar "CANNOSCALE" ut_scale) ;;这个是注释性标注对象的比例 (vl-catch-all-apply 'vla-put-CustomScale (list vp_obj ut_vp_scale)) ;;这里设置的是自定义视口比例

上面的视口创建代码中并未使用到zoom,e,原因如下:

MVIEW 创建视口时的"缩放至范围"

视口是这么建的(create_simple_viewport开头):

(command "mview" vp_center (list (+ (car vp_center) vp_width) (+ (cadr vp_center) vp_height)))

AutoCAD 在新建一个图纸空间视口时,默认会把该视口内的视图初始化为"显示模型空间全部内容并居中"(相当于对视口内部做了一次zoom extents)。

所以时序是这样的:

① MVIEW 创建视口
→ 视口"视图中点"被自动设为模型空间内容的中心
→ 此时内容已经居中

② vla-put-CustomScale ut_vp_scale
→ 只改变缩放倍数,但围绕①中已固定的"视图中点"缩放
→ 中心点没变,所以无论放大缩小都保持居中

这种居中其实是一种隐式依赖

  • 如果模型空间里除了目标图形外还有别的实体(残留辅助线、参考块等),zoom extents会把它们也框进来,中心就会跑偏。
  • 一旦内容中心 ≠ 视口视图中点,这里就不会居中

2.python和lisp联动的方式

具体实现可以使用AI,但我觉得这个思路有时候还是挺有用的。

from pyautocad import Autocad # 连接到AutoCAD应用程序 acad = Autocad() print(f"正在控制: {acad.doc.Name}") # 1. 发送纯LISP代码 # 在AutoCAD中画一条从 (0,0) 到 (10,10) 的直线 lisp_code = '(command "LINE" "0,0" "10,10" "")' acad.SendCommand(f"(progn {lisp_code})\n") # 用 progn 包裹确保执行 # 2. 加载并执行外部的 .lsp 文件 # 假设你的脚本是 C:/my_scripts/my_tool.lsp,其中定义了一个 C:MYCOMMAND 命令 lisp_file_path = r'C:/my_scripts/my_tool.lsp' # 加载文件 acad.SendCommand(f'(load "{lisp_file_path}")\n') # 执行文件中定义的命令 (注意命令名要大写) acad.SendCommand('MYCOMMAND\n')
from pyautocad import Autocad acad = Autocad() # 1. 画一条线 (命令行输入: LINE 0,0 10,10 回车) acad.SendCommand('LINE 0,0 10,10 \n') # 2. 执行LISP函数 (比如获取当前图层名并弹窗显示) acad.SendCommand('(alert (getvar "CLAYER")) \n') # 3. 设置一个系统变量 (比如把十字光标大小设为50) acad.SendCommand('CURSORSIZE 50 \n')

这种方式基本上就是直接向命令行发送简短的lisp代码段了。对于不想花大量时间和lisp纠缠,并且希望主要使用python一种语言开发是很友好的。一些使用python效果不好的代码实现,比如:

# 设置点样式 (PDMODE) 和点大小 (PDSIZE)[reference:0][reference:1][reference:2] acad.ActiveDocument.SetVariable("PDMODE", 35) acad.ActiveDocument.SetVariable("PDSIZE", 10) # 开启/关闭栅格显示 (GRIDMODE)[reference:3][reference:4] acad.ActiveDocument.SetVariable("GRIDMODE", 1) # 1为开启,0为关闭

这只是一个示例,有些变量设置是生效的,有些不生效,我也没测试过。假设遇到不生效的情况,这个时候可以使用:

from pyautocad import Autocad acad = Autocad() doc = acad.ActiveDocument # 1. 清空用户系统变量 USERS1(设为空字符串) doc.SendCommand('(setvar "USERS1" "")\n') # 2. 假设有一个字典 global_vars global_vars = { "my_int": 123, "my_float": 3.14, "my_str": 'Hello "world"', # 包含双引号 "my_none": None, } # 3. 注入全局变量(按类型生成 LISP 语句) for var_name, var_value in global_vars.items(): if var_value is None: doc.SendCommand(f'(setq {var_name} nil)\n') elif isinstance(var_value, (int, float)): doc.SendCommand(f'(setq {var_name} {var_value})\n') else: # 字符串:转义双引号 escaped = str(var_value).replace('"', '\\"') doc.SendCommand(f'(setq {var_name} "{escaped}")\n')

3.关于SendCommand方法

1.使用pyautocad

from pyautocad import Autocad acad = Autocad() acad.SendCommand('(setvar "USERS1" "")\n') # ✅ 完全正确,官方推荐简写

pyautocadAutocad对象本身就封装了SendCommand方法,它内部会自动指向当前文档,所以可以直接写。

在某些需要明确指定文档的场景(比如有多个打开的图纸)我会写成doc.SendCommand。但如果用的是pyautocad且只操作当前文档,直接用acad.SendCommand更简洁。

2.直接使用win32com接口

import win32com.client acad = win32com.client.Dispatch("AutoCAD.Application") doc = acad.ActiveDocument doc.SendCommand('(setvar "USERS1" "")\n') # ✅ 必须用 doc.SendCommand # acad.SendCommand(...) # ❌ 这样写会报错(AttributeError)

直接操作 COM 对象时,acad是 Application(应用程序)对象,它没有SendCommand方法,必须通过当前文档(ActiveDocument)来发送:

4.为什么我会使用到lisp以及好不好用

在稳定性和速度上确实远超python的com接口方法。但是对于我的电脑配置荣耀magicbook art14 U7-155H,32G,实测区别不大,速度体感差距很小。

在开发难度上:python面向对象的编程设计毋庸置疑非常方便,想实现代码模块化或者调用各种python库,尤其是添加数值运算逻辑非常方便。

lisp虽然也有vla方法提供面向对象,实际使用非常麻烦,数学运算更不用说了,非常不符合日常习惯。

我也是“人生苦短,我用python”的信徒,但现有项目是基于lisp开发的,加上有AI协助,所以大部分内容使用lisp完成。

注意,lisp如果想要模块化,需要先在AutoCAD中加载所有所需模块文件,才可以调用主函数运行。

所以我把项目拆成了若干lisp文件模块之后,就很少手动load或者appload加载了,直接使用python一次性打包加载完成所有模块。

综上:

我的建议是,在电脑性能足够的时候,大型项目,复杂绘图逻辑直接使用python开发,lisp适合作为小组件使用sendcommand发送,或者使用python调用一些别人已开发的lisp脚本。
http://www.jsqmd.com/news/1389571/

相关文章:

  • 同传新手真正高效的突破方式,是分层训练、逐级加压。基础不稳就回归梯度影子跟读,打磨听说联动节奏;逻辑混乱就专项练习意群拆分、顺句驱动;输出卡顿就集中打磨衔接句式、优化语流。针对性补齐短板,而非泛泛练习
  • 计算机技术与科学毕设容易的题目分享
  • PyInstaller打包DLL加载失败:从blspy案例到通用解决方案
  • 从混淆矩阵到ROC曲线:量化机器学习分类中的误报与漏报权衡
  • Python批量图片处理实战:本地化压缩、水印、格式转换与重命名
  • MolmoWeb:基于视觉模型的网页自动化本地部署与实战指南
  • 深度解析:兴安盟建设局网站作为公众获取权威资讯与政务服务的核心平台价值探讨
  • Codex平台集成GPT-5.5与视觉模型,重塑AI编程工作流
  • APMCM数学建模竞赛全流程实战指南:从审题到论文写作
  • 2026年8月潍坊全屋定制/潍坊大平层全屋定制优质厂家推荐_潍坊中百益家园装饰 - 品牌宣传支持者
  • Android系统属性添加实战:从原理到SELinux权限配置全解析
  • Windows开机密码遗忘?5种主流解锁方案全解析
  • AI时代程序员价值重构:从代码生产者到系统设计者
  • 基于WorkBuddy与edge-tts打造本地化TTS自动化配音流水线
  • CUDA生态核心组件解析:cuBLAS、cuDNN、NCCL、Triton与CUTLASS实战指南
  • 网站建设服务器篇:如何选择稳定高效服务器助力企业数字化转型与在线发展
  • 数学建模竞赛通知解读:从规则理解到团队协作的实战指南
  • 数学建模竞赛:从理论到实践的工程化思维与数据驱动方法
  • 利用Python实现酒店评论的情感分析
  • CentOS/Rocky Linux更换国内yum源:清华与阿里云镜像配置全指南
  • 2026年8月Facebook海外社媒运营/江门Linkedin海外社媒运营技术团队选哪家_江门市华企立方科技有限公司 - 行业平台推荐
  • BetterGI 终极指南:5分钟学会原神自动化辅助工具
  • 知识星球备份实战:把付费内容变成随身 PDF 电子书
  • 蓝桥杯国赛C++ B组题解:算法实战复盘与核心思路拆解
  • 庐山市防水补漏维修有哪些常见套路和陷阱_外墙漏水维修本地避坑指南注意事项全解析 - 雨婺虹修缮
  • AI Agent Harness设计哲学解析:从工具集成到分布式通信的四种架构选择
  • LabVIEW系统部署:NI自启动服务功能详解与优化配置指南
  • Agent 之间怎么对话?A2A 协议全景解析:从概念到 Java 落地
  • Linux进程资源监控:从top/ps命令到pidstat与/proc的深度诊断指南
  • 沃创云优选商机|GEO 获客利器