LISP中 remove-if-not 及 remove-if



CL-USER> (remove-if-not #'evenp '(1 2 3 4 ))
(2 4)



CL-USER> (remove-if #'evenp '(1 2 3 4 ))
(1 3)

(defun c:OrthoDim ( / *error* ss plObj closedPts refPt dir dimLayer dimStyle upperPts lowerPts leftPts rightPts) (vl-load-com) ;; 错误处理函数 (defun *error* (msg) (if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\n错误: " msg)) ) (setvar "CMDECHO" 1) (princ) ) ;; 选择闭合多段线 (princ "\n选择闭合多段线: ") (setq ss (ssget ":S" '((0 . "LWPOLYLINE")))) (if (null ss) (progn (alert "未选择对象或选择无效!") (exit)) ) (setq plObj (vlax-ename->vla-object (ssname ss 0))) ;; 检查是否闭合 (if (not (vlax-get-property plObj 'Closed)) (progn (alert "所选多段线未闭合!") (exit)) ) ;; 获取顶点坐标 (setq closedPts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (vlax-vla-object->ename plObj)) ) ) ) ;; 移除重复的闭合点 (if (equal (car closedPts) (last closedPts) 1e-6) (setq closedPts (reverse (cdr (reverse closedPts)))) ) ;; 获取参照点 (setq refPt (getpoint "\n在轮廓线上拾取参照点: ")) (if (null refPt) (exit)) ;; 选择标注方向 (initget "H V") (setq dir (getkword "\n选择标注方向 [H水平/V垂直]: ")) (if (not dir) (setq dir "H")) ;; 获取当前标注样式和图层 (setq dimLayer (getvar "CLAYER")) (setq dimStyle (getvar "DIMSTYLE")) (setvar "CMDECHO" 0) (cond ((= dir "H") ; 水平方向标注 ;; 分组点集: 上方点(Y ≥ refPt Y) 和 下方点(Y ≤ refPt Y) (setq upperPts (vl-sort (vl-remove-if-not '(lambda (pt) (>= (cadr pt) (cadr refPt))) closedPts ) '(lambda (a b) (< (car a) (car b))) ) ) (setq lowerPts (vl-sort (vl-remove-if-not '(lambda (pt) (<= (cadr pt) (cadr refPt))) closedPts ) '(lambda (a b) (< (car a) (car b))) ) ) ;; 去重处理 (setq upperPts (LM:Unique upperPts)) (setq lowerPts (LM:Unique lowerPts)) ;; 计算标注位置 (setq upperY (apply 'max (mapcar 'cadr upperPts))) (setq lowerY (apply 'min (mapcar 'cadr lowerPts))) (setq upperDimLineY (+ upperY 30)) (setq lowerDimLineY (- lowerY 30)) ;; 创建上方标注 (if (> (length upperPts) 1) (progn (command "_.DIMLINEAR" (car upperPts) (cadr upperPts) (list (car (car upperPts)) upperDimLineY) ) (command "_.DIMCONTINUE") (foreach pt (cddr upperPts) (command pt) ) (command "") ) ) ;; 创建下方标注 (if (> (length lowerPts) 1) (progn (command "_.DIMLINEAR" (car lowerPts) (cadr lowerPts) (list (car (car lowerPts)) lowerDimLineY) ) (command "_.DIMCONTINUE") (foreach pt (cddr lowerPts) (command pt) ) (command "") ) ) ) ((= dir "V") ; 垂直方向标注 ;; 分组点集: 右侧点(X ≥ refPt X) 和 左侧点(X ≤ refPt X) (setq rightPts (vl-sort (vl-remove-if-not '(lambda (pt) (>= (car pt) (car refPt))) closedPts ) '(lambda (a b) (< (cadr a) (cadr b))) ) ) (setq leftPts (vl-sort (vl-remove-if-not '(lambda (pt) (<= (car pt) (car refPt))) closedPts ) '(lambda (a b) (< (cadr a) (cadr b))) ) ) ;; 去重处理 (setq rightPts (LM:Unique rightPts)) (setq leftPts (LM:Unique leftPts)) ;; 计算标注位置 (setq rightX (apply 'max (mapcar 'car rightPts))) (setq leftX (apply 'min (mapcar 'car leftPts))) (setq rightDimLineX (+ rightX 30)) (setq leftDimLineX (- leftX 30)) ;; 创建右侧标注 (if (> (length rightPts) 1) (progn (command "_.DIMLINEAR" (car rightPts) (cadr rightPts) (list rightDimLineX (cadr (car rightPts))) ) (command "_.DIMCONTINUE") (foreach pt (cddr rightPts) (command pt) ) (command "") ) ) ;; 创建左侧标注 (if (> (length leftPts) 1) (progn (command "_.DIMLINEAR" (car leftPts) (cadr leftPts) (list leftDimLineX (cadr (car leftPts))) ) (command "_.DIMCONTINUE") (foreach pt (cddr leftPts) (command pt) ) (command "") ) ) ) ) (setvar "CMDECHO" 1) (princ "\n正交标注创建完成!") (princ) ) ;; 辅助函数: 列表去重 (defun LM:Unique (l / x r) (while l (setq x (car l) l (vl-remove x (cdr l)) r (cons x r) ) ) (reverse r) )
最新发布
06-29
<think>这是一个AutoLISP程序,用于在AutoCAD中为闭合多段线创建正交标注(水平或垂直方向)。程序允许用户选择一条闭合的多段线,然后根据用户选择的参照点和标注方向(水平或垂直)自动创建连续标注。 ###程序功能:1.选择一条闭合的多段线。2.在轮廓线上拾取一个参照点,用于确定标注的分组(例如,参照点上方和下方用于水平标注,左侧和右侧用于垂直标注)。3.选择标注方向(水平或垂直)。4.自动将多段线的顶点按照参照点分组(水平方向分为上下两组,垂直方向分为左右两组),然后对每组点进行排序。5.为每组点创建连续标注(DIMCONTINUE),标注线位于多段线轮廓外一定距离(30个单位)。 ###代码分析:####1.错误处理函数 `*error*`-用于捕获错误,当用户取消或发生错误时恢复系统变量并显示错误信息。####2.选择闭合多段线-使用 `ssget`选择单个闭合多段线(LWPOLYLINE)。-检查所选对象是否闭合,如果不闭合则退出。 ####3.获取多段线顶点-使用`entget`获取多段线的图元数据,过滤出顶点(组码10)。-移除重复的闭合点(如果首尾点相同,则移除尾点)。####4.获取参照点和标注方向-使用 `getpoint`获取参照点。-使用`initget`和`getkword`让用户选择水平(H)或垂直(V)标注方向。 ####5.分组顶点-水平标注(H):-将顶点分为两组:Y坐标大于等于参照点Y坐标的(上方点)和小于等于的(下方点)。-每组按X坐标升序排序。-垂直标注(V):-将顶点分为两组:X坐标大于等于参照点X坐标的(右侧点)和小于等于的(左侧点)。-每组按Y坐标升序排序。-使用辅助函数 `LM:Unique`去除重复点(确保每个点只出现一次)。 ####6.计算标注位置-水平标注:-上方标注线位于最高点的上方30单位处。-下方标注线位于最低点的下方30单位处。-垂直标注:-右侧标注线位于最右点的右侧30单位处。-左侧标注线位于最左点的左侧30单位处。 ####7.创建连续标注-使用`DIMLINEAR`创建第一个标注,然后使用`DIMCONTINUE`创建连续的标注。-对每组点(至少两个点)创建连续标注。 ####8.辅助函数`LM:Unique`-用于去除列表中的重复元素。 ###使用示例:1.加载程序后,在AutoCAD命令行输入 `OrthoDim`。 2.选择一条闭合多段线。 3.在多段线上拾取一个参照点(该点用于确定分组边界)。 4.选择标注方向(水平或垂直)。5.程序自动创建标注。 ###注意事项: -该程序假设多段线是闭合的,且为轻量多段线(LWPOLYLINE)。 -标注的偏移距离固定为30个单位,可以根据需要修改。 -程序使用当前标注样式和当前图层。###改进建议: 1.允许用户输入标注线的偏移距离。 2.处理非轻量多段线(如旧式的POLYLINE)。 3.考虑多段线可能有圆弧段(当前程序只处理直线段,因为只获取了顶点,圆弧段需要另外处理)。###相关问题:§§相关问题§§: 1.如何修改程序以支持用户自定义标注偏移距离?2.如何处理多段线中的圆弧段(即如何获取圆弧段的端点)?3.如何使标注文字始终朝外(避免被多段线轮廓遮挡)?4.如何扩展程序以支持非闭合多段线?</think>这个AutoLISP程序用于在AutoCAD中为闭合多段线创建正交标注。我将详细解释其工作原理并提供优化建议: ### 程序功能分析 1. **核心功能**:为闭合多段线创建水平/垂直方向的连续尺寸标注 2. **工作流程**: - 选择闭合多段线 - 拾取参照点确定标注区域 - 选择水平(H)或垂直(V)标注方向 - 自动分组顶点并创建连续标注 ### 关键代码解析 ```lisp ;; 错误处理函数 (defun *error* (msg) (if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\n错误: " msg)) ) (setvar "CMDECHO" 1) (princ) ) ``` - 错误处理逻辑:过滤用户中断操作,恢复系统变量 ```lisp ;; 获取多段线顶点 (setq closedPts (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) ; 筛选组码10(顶点坐标) (entget (vlax-vla-object->ename plObj)) ) ) ) ``` - 使用AutoLISP图元数据处理函数提取多段线顶点 ```lisp ;; 水平标注分组逻辑 (setq upperPts (vl-sort (vl-remove-if-not '(lambda (pt) (>= (cadr pt) (cadr refPt))) ; Y坐标≥参照点 closedPts ) '(lambda (a b) (< (car a) (car b))) ; 按X坐标排序 ) ) ``` - 基于参照点将顶点分为上下两组 - 使用vl-sort进行坐标排序 ```lisp ;; 创建连续标注 (command "_.DIMLINEAR" (car upperPts) (cadr upperPts) (list (car (car upperPts)) upperDimLineY) ; 标注线位置 ) (command "_.DIMCONTINUE") (foreach pt (cddr upperPts) (command pt) ) ``` - 使用DIMLINEAR创建首个标注 - DIMCONTINUE创建连续标注链 ### 优化建议 1. **增加用户交互**: ```lisp ;; 添加标注偏移距离输入 (setq offset (getdist "\n标注线偏移距离 <30>: ")) (if (null offset) (setq offset 30)) ``` 2. **改进顶点处理**: ```lisp ;; 处理带圆弧的多段线 (setq coords (vlax-invoke plObj 'Coordinates)) (setq closedPts nil) (repeat (/ (length coords) 2) (setq closedPts (cons (list (car coords) (cadr coords)) closedPts)) (setq coords (cddr coords)) ) ``` 3. **标注位置计算优化**: ```lisp ;; 动态计算标注位置 (setq bbox (vla-getBoundingBox plObj 'minpt 'maxpt)) (setq upperDimLineY (+ (cadr (vlax-safearray->list maxpt)) offset)) ``` ### 使用说明 1. 加载程序后在CAD输入`OrthoDim` 2. 选择闭合多段线 3. 在轮廓线上拾取参照点 4. 选择标注方向(H/V) 5. 程序自动生成正交连续标注 ### 注意事项 - 仅适用于直线段组成的闭合LWPOLYLINE - 标注样式使用当前DIMSTYLE - 标注图层使用当前图层
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值