本帖最后由 f4800 于 2025-11-7 18:06 编辑

用ai生成了一个批量修剪的lsp
有别于ET工具 Extrim ,但是用途类似,可以选择需要修剪的对象

目标:
1、选择一条直线或 PL 线作为裁剪边界
2、在需要裁剪的一侧点击任意点
3、选择裁剪对象(直线或PL线)
4、然后裁剪选择的对象


欢迎测试体验、继续完善

  1. ; 快捷命令
  2. (defun c:ttt () (c:sidecut))
  3. (defun c:trr () (c:sidecut))

  4. (princ "\n命令已加载,输入 SIDECUT 或 trr 启动")
  5. (princ)

  6. (defun c:sidecut (/ *error* boundary pt1 pt2 side-pt is-left
  7.                    target-ents i ent int-points)
  8.   (vl-load-com)
  9.   
  10.   ; 错误处理
  11.   (defun *error* (msg)
  12.     (if (not (member msg '("Function cancelled" "quit / exit abort" "")))
  13.       (princ (strcat "\n错误: " msg))
  14.     )
  15.     (princ)
  16.   )
  17.   
  18.   ; 1. 选择裁剪边界线
  19.   (setq boundary nil)
  20.   (while (not boundary)
  21.     (princ "\n选择裁剪边界线(直线/LWPOLYLINE/PLINE): ")
  22.     (setq temp-sel (entsel))
  23.     (if temp-sel
  24.       (progn
  25.         (setq ent (car temp-sel)
  26.               ent-type (cdr (assoc 0 (entget ent))))
  27.         (if (member ent-type '("LINE" "LWPOLYLINE" "POLYLINE"))
  28.           (setq boundary ent)
  29.           (princ "\n无效对象!请选择直线或多段线。")
  30.         )
  31.       )
  32.       (princ "\n未选择,请重新选择。")
  33.     )
  34.   )

  35.   ; 获取端点
  36.   (setq pt1 (vlax-curve-getStartPoint boundary)
  37.         pt2 (vlax-curve-getEndPoint boundary))
  38.   
  39.   ; 2. 指定裁剪侧
  40.   (princ "\n在需要裁剪的一侧点击任意点: ")
  41.   (setq side-pt (getpoint))
  42.   (if (not side-pt) (progn (princ "\n已取消") (exit)))
  43.   
  44.   ; 3. 判断点在直线的左侧还是右侧 - 使用叉积计算(避免 let 语法问题)
  45.   (setq dx1 (- (car pt2) (car pt1)))
  46.   (setq dy1 (- (cadr pt2) (cadr pt1)))
  47.   (setq dx2 (- (car side-pt) (car pt1)))
  48.   (setq dy2 (- (cadr side-pt) (cadr pt1)))
  49.   (setq is-left (> (* dx1 dy2) (* dy1 dx2)))
  50.   (princ (strcat "\n裁剪侧: " (if is-left "左侧" "右侧")))
  51.   
  52.   ; 4. 选择待裁剪对象
  53.   (princ "\n选择需要裁剪的对象(直线/PL线等): ")
  54.   (setq target-ents (ssget))
  55.   (if (not target-ents) (progn (princ "\n未选择对象") (exit)))
  56.   
  57.   ; 5. 裁剪指定侧部分
  58.   (setq i 0)
  59.   (repeat (sslength target-ents)
  60.     (setq ent (ssname target-ents i))
  61.     (setq int-points (get-intersections ent boundary))
  62.    
  63.     (if (and int-points (> (length int-points) 0))
  64.       (progn
  65.         (princ (strcat "\n对象" (itoa (1+ i)) "找到" (itoa (length int-points)) "个交点"))
  66.         ; 调用基于TRIM的裁剪函数
  67.         (trim-with-trim ent boundary pt1 pt2 is-left)
  68.       )
  69.       (princ (strcat "\n对象" (itoa (1+ i)) "与边界线无交点,跳过"))
  70.     )
  71.     (setq i (1+ i))
  72.   )
  73.   
  74.   (princ "\n裁剪完成!")
  75.   (princ)
  76. )

  77. ; 辅助函数1:获取交点
  78. (defun get-intersections (obj boundary / obj-vla bnd-vla ints points i)
  79.   (vl-catch-all-apply
  80.     (function (lambda ()
  81.       (setq obj-vla (vlax-ename->vla-object obj)
  82.             bnd-vla (vlax-ename->vla-object boundary)
  83.             ints (vlax-invoke obj-vla 'IntersectWith bnd-vla acExtendNone)
  84.             points nil
  85.             i 0
  86.       )
  87.       (while (< i (length ints))
  88.         (setq points (cons (list (nth i ints) (nth (1+ i) ints)) points))
  89.         (setq i (+ i 3))
  90.       )
  91.       (reverse points)
  92.     ))
  93.     nil
  94.   )
  95. )

  96. ; 核心改进:使用TRIM命令裁剪
  97. (defun trim-with-trim (obj boundary pt1 pt2 is-left /
  98.                        obj-type obj-data pts int-points segs new-ents)
  99.   (setq obj-type (cdr (assoc 0 (entget obj))))
  100.   
  101.   ; 仅处理直线和LWPOLYLINE(简化)
  102.   (cond
  103.     ; ===== 处理直线 =====
  104.     ((= obj-type "LINE")
  105.       (setq pts (list (cdr (assoc 10 (entget obj))) (cdr (assoc 11 (entget obj)))))
  106.       (setq int-points (get-intersections obj boundary))
  107.       (if (and int-points (= (length int-points) 1))
  108.         (progn
  109.           (setq segs (split-line-at-point pts (car int-points)))
  110.           (process-segments segs pt1 pt2 is-left obj)
  111.         )
  112.         (princ "\n直线交点数量异常,跳过")
  113.       )
  114.     )
  115.    
  116.     ; ===== 处理 LWPOLYLINE(简化:只处理无弧段的)=====
  117.     ((= obj-type "LWPOLYLINE")
  118.       (princ "\n警告:LWPOLYLINE 裁剪暂未实现(可扩展)")
  119.       ; 这里可以后续扩展,先跳过
  120.     )
  121.    
  122.     (t
  123.       (princ "\n不支持的对象类型,跳过")
  124.     )
  125.   )
  126. )

  127. ; 将直线按交点拆分为两段
  128. (defun split-line-at-point (pts ip)
  129.   (list (list (car pts) ip) (list ip (cadr pts)))
  130. )

  131. ; 判断并保留/删除线段,同时复制原对象属性
  132. (defun process-segments (segs pt1 pt2 is-left orig-ent /
  133.                          ent-data new-ents layer lt ltype color lw weight)
  134.   ; 获取原对象的所有DXF组码数据
  135.   (setq ent-data (entget orig-ent))
  136.   
  137.   ; 提取常用属性(如果存在)
  138.   (setq layer  (cdr (assoc 8  ent-data)))   ; 图层
  139.   (setq lt     (cdr (assoc 6  ent-data)))   ; 线型(LTYPE)
  140.   (setq color  (cdr (assoc 62 ent-data)))   ; 颜色(0=ByLayer, 正数=索引色, 负数=真彩色)
  141.   (setq lw     (cdr (assoc 370 ent-data)))  ; 线宽(可选)
  142.   (setq weight (cdr (assoc 39 ent-data)))   ; 厚度(可选)
  143.   
  144.   (foreach seg segs
  145.     (setq mid-pt (midpoint (car seg) (cadr seg)))
  146.     (setq pt-is-left (is-point-left-of-line mid-pt pt1 pt2))
  147.     ; 如果中点所在侧 ≠ 要裁剪的侧,则保留该段
  148.     (if (/= pt-is-left is-left)
  149.       (progn
  150.         ; 构建新直线的DXF数据列表
  151.         (setq new-line-data
  152.           (list
  153.             '(0 . "LINE")
  154.             (cons 10 (car seg))    ; 起点
  155.             (cons 11 (cadr seg))   ; 终点
  156.           )
  157.         )
  158.         
  159.         ; 有条件地添加属性(避免 nil 值)
  160.         (if layer  (setq new-line-data (append new-line-data (list (cons 8 layer)))))
  161.         (if lt     (setq new-line-data (append new-line-data (list (cons 6 lt)))))
  162.         (if color  (setq new-line-data (append new-line-data (list (cons 62 color)))))
  163.         (if lw     (setq new-line-data (append new-line-data (list (cons 370 lw)))))
  164.         (if weight (setq new-line-data (append new-line-data (list (cons 39 weight)))))
  165.         
  166.         ; 创建新实体
  167.         (entmake new-line-data)
  168.         (setq new-ents (cons (entlast) new-ents))
  169.       )
  170.     )
  171.   )
  172.   
  173.   ; 删除原始对象
  174.   (entdel orig-ent)
  175.   new-ents
  176. )

  177. ; 计算两点中点
  178. (defun midpoint (p1 p2)
  179.   (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p1 p2)
  180. )

  181. ; 辅助函数3:判断点是否在直线左侧
  182. (defun is-point-left-of-line (pt line-pt1 line-pt2)
  183.   (> (- (* (- (car line-pt2) (car line-pt1)) (- (cadr pt) (cadr line-pt1)))
  184.         (* (- (cadr line-pt2) (cadr line-pt1)) (- (car pt) (car line-pt1))))
  185.     0
  186.   )
  187. )






网友答: 本帖最后由 guosheyang 于 2025-11-2 10:47 编辑

extrim命令(et)就可以满足你了

网友答: 搞定了。。。。




  1. ; 快捷命令
  2. (defun c:ttt () (c:sidecut))
  3. (defun c:trr () (c:sidecut))

  4. (princ "\n命令已加载,输入 SIDECUT 或 trr 启动")
  5. (princ)




  6. (defun c:sidecut (/ *error* boundary pt1 pt2 side-pt is-left
  7.                    target-ents i ent int-points)
  8.   (vl-load-com)
  9.   
  10.   ; 错误处理保持不变
  11.   (defun *error* (msg)
  12.     (if (not (member msg '("Function cancelled" "quit / exit abort" "")))
  13.       (princ (strcat "\n错误: " msg))
  14.     )
  15.     (princ)
  16.   )
  17.   
  18. ; 1. 选择裁剪边界线(必须选中有效对象)
  19. (setq boundary nil)
  20. (while (not boundary)
  21.   (princ "\n选择裁剪边界线(直线/LWPOLYLINE/PLINE): ")
  22.   (setq temp-sel (entsel))
  23.   (if temp-sel
  24.     (progn
  25.       (setq ent (car temp-sel)
  26.             ent-type (cdr (assoc 0 (entget ent))))
  27.       (if (member ent-type '("LINE" "LWPOLYLINE" "POLYLINE"))
  28.         (setq boundary ent)
  29.         (princ "\n无效对象!请选择直线或多段线。")
  30.       )
  31.     )
  32.     (princ "\n未选择,请重新选择。")
  33.   )
  34. )

  35. ; 获取端点
  36. (setq pt1 (vlax-curve-getStartPoint boundary)
  37.       pt2 (vlax-curve-getEndPoint boundary))
  38.   
  39.   ; 2. 指定裁剪侧(保持不变)
  40.   (princ "\n在需要裁剪的一侧点击任意点: ")
  41.   (setq side-pt (getpoint))
  42.   (if (not side-pt) (progn (princ "\n已取消") (exit)))
  43.   
  44.   (setq is-left
  45.     (> (- (* (- (car pt2) (car pt1)) (- (cadr side-pt) (cadr pt1)))
  46.          (* (- (cadr pt2) (cadr pt1)) (- (car side-pt) (car pt1))))
  47.       0)
  48.   )
  49.   (princ (strcat "\n裁剪侧: " (if is-left "左侧" "右侧")))
  50.   
  51.   ; 3. 选择待裁剪对象(保持不变)
  52.   (princ "\n选择需要裁剪的对象(直线/PL线等): ")
  53.   (setq target-ents (ssget))
  54.   (if (not target-ents) (progn (princ "\n未选择对象") (exit)))
  55.   
  56.   ; 4. 裁剪指定侧部分(核心修改:使用TRIM命令)
  57.   (setq i 0)
  58.   (repeat (sslength target-ents)
  59.     (setq ent (ssname target-ents i))
  60.     (setq int-points (get-intersections ent boundary))
  61.    
  62.     (if (and int-points (> (length int-points) 0))
  63.       (progn
  64.         (princ (strcat "\n对象" (itoa (1+ i)) "找到" (itoa (length int-points)) "个交点"))
  65.         ; 调用基于TRIM的裁剪函数
  66.         (trim-with-trim ent boundary pt1 pt2 is-left)
  67.       )
  68.       (princ (strcat "\n对象" (itoa (1+ i)) "与边界线无交点,跳过"))
  69.     )
  70.     (setq i (1+ i))
  71.   )
  72.   
  73.   (princ "\n裁剪完成!")
  74.   (princ)
  75. )

  76. ; 辅助函数1:获取交点(保持不变)
  77. (defun get-intersections (obj boundary / obj-vla bnd-vla ints points i)
  78.   (vl-catch-all-apply
  79.     (function (lambda ()
  80.                 (setq obj-vla (vlax-ename->vla-object obj)
  81.                   bnd-vla (vlax-ename->vla-object boundary)
  82.                   ints (vlax-invoke obj-vla 'IntersectWith bnd-vla acExtendNone)
  83.                   points nil
  84.                   i 0
  85.                 )
  86.                 (while (< i (length ints))
  87.                   (setq points (cons (list (nth i ints) (nth (1+ i) ints)) points))
  88.                   (setq i (+ i 3))
  89.                 )
  90.                 (reverse points)
  91.               ))
  92.     nil
  93.   )
  94. )

  95. ; 核心改进:使用TRIM命令裁剪
  96. ; 替换原来的 trim-with-trim 函数
  97. (defun trim-with-trim (obj boundary pt1 pt2 is-left /
  98.                         obj-type obj-data pts int-points segs new-ents)
  99.   (setq obj-type (cdr (assoc 0 (entget obj))))
  100.   
  101.   ; 仅处理直线和LWPOLYLINE(简化)
  102.   (cond
  103.     ; ===== 处理直线 =====
  104.     ((= obj-type "LINE")
  105.       (setq pts (list (cdr (assoc 10 (entget obj))) (cdr (assoc 11 (entget obj)))))
  106.       (setq int-points (get-intersections obj boundary))
  107.       (if (and int-points (= (length int-points) 1))
  108.         (progn
  109.           (setq segs (split-line-at-point pts (car int-points)))
  110.           (process-segments segs pt1 pt2 is-left obj)
  111.         )
  112.         (princ "\n直线交点数量异常,跳过")
  113.       )
  114.     )
  115.    
  116.     ; ===== 处理 LWPOLYLINE(简化:只处理无弧段的)=====
  117.     ((= obj-type "LWPOLYLINE")
  118.       (princ "\n警告:LWPOLYLINE 裁剪暂未实现(可扩展)")
  119.       ; 这里可以后续扩展,先跳过
  120.     )
  121.    
  122.     (t
  123.       (princ "\n不支持的对象类型,跳过")
  124.     )
  125.   )
  126. )

  127. ; 将直线按交点拆分为两段
  128. (defun split-line-at-point (pts ip)
  129.   (list (list (car pts) ip) (list ip (cadr pts)))
  130. )

  131. ; 判断并保留/删除线段
  132. ; 判断并保留/删除线段,同时复制原对象属性
  133. (defun process-segments (segs pt1 pt2 is-left orig-ent /
  134.                           ent-data new-ents layer lt ltype color lw weight)
  135.   ; 获取原对象的所有DXF组码数据
  136.   (setq ent-data (entget orig-ent))
  137.   
  138.   ; 提取常用属性(如果存在)
  139.   (setq layer  (cdr (assoc 8  ent-data)))   ; 图层
  140.   (setq lt     (cdr (assoc 6  ent-data)))   ; 线型(LTYPE)
  141.   (setq color  (cdr (assoc 62 ent-data)))   ; 颜色(0=ByLayer, 正数=索引色, 负数=真彩色)
  142.   (setq lw     (cdr (assoc 370 ent-data)))  ; 线宽(可选)
  143.   (setq weight (cdr (assoc 39 ent-data)))   ; 厚度(可选)
  144.   
  145.   (foreach seg segs
  146.     (setq mid-pt (midpoint (car seg) (cadr seg)))
  147.     (setq pt-is-left (is-point-left-of-line mid-pt pt1 pt2))
  148.     ; 如果中点所在侧 ≠ 要裁剪的侧,则保留该段
  149.     (if (/= pt-is-left is-left)
  150.       (progn
  151.         ; 构建新直线的DXF数据列表
  152.         (setq new-line-data
  153.           (list
  154.             '(0 . "LINE")
  155.             (cons 10 (car seg))    ; 起点
  156.             (cons 11 (cadr seg))   ; 终点
  157.           )
  158.         )
  159.         
  160.         ; 有条件地添加属性(避免 nil 值)
  161.         (if layer  (setq new-line-data (append new-line-data (list (cons 8 layer)))))
  162.         (if lt     (setq new-line-data (append new-line-data (list (cons 6 lt)))))
  163.         (if color  (setq new-line-data (append new-line-data (list (cons 62 color)))))
  164.         (if lw     (setq new-line-data (append new-line-data (list (cons 370 lw)))))
  165.         (if weight (setq new-line-data (append new-line-data (list (cons 39 weight)))))
  166.         
  167.         ; 创建新实体
  168.         (entmake new-line-data)
  169.         (setq new-ents (cons (entlast) new-ents))
  170.       )
  171.     )
  172.   )
  173.   
  174.   ; 删除原始对象
  175.   (entdel orig-ent)
  176.   new-ents
  177. )



  178. ; 计算两点中点
  179. (defun midpoint (p1 p2)
  180.   (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p1 p2)
  181. )

  182. ; 辅助函数3:判断点是否在直线左侧(保持不变)
  183. (defun is-point-left-of-line (pt line-pt1 line-pt2)
  184.   (> (- (* (- (car line-pt2) (car line-pt1)) (- (cadr pt) (cadr line-pt1)))
  185.        (* (- (cadr line-pt2) (cadr line-pt1)) (- (car pt) (car line-pt1))))
  186.     0)
  187. )
















网友答: 这个和TRT有什么区别

网友答:
guosheyang 发表于 2025-11-2 10:39
extrim命令(et)就可以满足你了

可行  这个不错 一直没发现

网友答: 这个和TRT有什么区别


网友答:
阿猪蛋 发表于 2025-11-3 15:32
这个和TRT有什么区别

TRT ?  我这没有这个命令。。。。。。。。。。

网友答:
guosheyang 发表于 2025-11-2 10:39
extrim命令(et)就可以满足你了

厉害了哥,一直想找这个功能的插件,没想到,这是CAD自带的吗?非常感谢

网友答: 好像只能用于裁剪直线

网友答:
nzdog 发表于 2025-11-4 12:35
好像只能用于裁剪直线

也是新手 还在摸索阶段
  • 上一篇:多重插入块炸不开
  • 下一篇:没有了