ㄘ丶转裑ㄧ灬 发表于 2025-10-22 08:57:36

线段批量转块-平面布置

本帖最后由 ㄘ丶转裑ㄧ灬 于 2025-11-30 14:49 编辑

一般用于平面图,把分隔线段替换为制作好的块,块会安装线段角度相应旋转;
用AI写的,两次就正常运行了,还不错;
另外大伙如果对这个功能有更多的想法,可扩展完善后发源码出来。

;;;;;;*****************************************批量布块(遵循线的角度)

(defun c:HT_310 (/ blk blk_data blk_name ss i pline obj pt1 pt2 ang adjusted_ang
                  insert_point vertex_choice success_count end_param)
(HT_START)

; 选择要插入的块(增加块类型校验)
(setq blk (car (entsel "\n选择要插入的块(竖向块): ")))
(if (not blk)
    (progn (alert "未选择块!") (exit)))

; 验证选中的是块(INSERT类型实体)
(setq blk_data (entget blk))
(if (not (= (cdr (assoc 0 blk_data)) "INSERT"))
    (progn (alert "选中的实体不是块,请重新选择!") (exit)))
(setq blk_name (cdr (assoc 2 blk_data)))

; 选择插入点位置
(initget "First Second")
(setq vertex_choice (getkword "\n选择插入点位置 [第一个顶点(F)/第二个顶点(S)] <第一个顶点>: "))
(setq vertex_choice (if vertex_choice vertex_choice "First")) ; 默认第一个顶点

; 选择多段线(支持轻量多段线和二维多段线)
(setq ss (ssget '((0 . "LWPOLYLINE,POLYLINE"))))
(if (not ss)
    (progn (alert "未选择多段线!") (exit)))

; 初始化计数器(i=多段线索引,success_count=成功插入次数)
(setq i 0 success_count 0)

; 遍历所有选中的多段线(核心修复:循环逻辑修正)
(repeat (sslength ss)
    (setq pline (ssname ss i))
    (setq obj (vlax-ename->vla-object pline))
   
    ; 检查多段线顶点数(至少2个顶点才计算角度)
    (setq end_param (vlax-curve-getEndParam obj))
    (if (>= end_param 1) ; param从0开始,>=1表示至少2个顶点
      (progn
      ; 根据用户选择确定插入点和角度参考点
      (cond
          ((= vertex_choice "First")
            (setq insert_point (vlax-curve-getStartPoint obj)) ; 插入点:第一个顶点
            (setq pt2 (vlax-curve-getPointAtParam obj 1))      ; 参考点:第二个顶点
          )
          ((= vertex_choice "Second")
            (setq insert_point (vlax-curve-getPointAtParam obj 1)) ; 插入点:第二个顶点
            (setq pt2 (vlax-curve-getStartPoint obj))             ; 参考点:第一个顶点
          )
      )
      
      ; 计算多段线方向角度(弧度),调整为块需要的角度(减90°)
      (setq ang (angle insert_point pt2))
      (setq adjusted_ang (- ang (/ pi 2)))
      (setq adjusted_ang_deg (* adjusted_ang (/ 180 pi))) ; 转为角度(AutoCAD命令要求)
      
      ; 插入块(使用实数角度,避免字符串格式问题)
      (command "_.INSERT" blk_name insert_point 1 1 adjusted_ang_deg)
      
      (setq success_count (1+ success_count)) ; 成功插入计数+1
      )
      (progn
      ; 顶点数不足提示
      (princ (strcat "\n多段线" (itoa (1+ i)) "(索引" (itoa i) ")顶点数不足2个,跳过!"))
      )
    )
   
    (setq i (1+ i)) ; 每次循环仅递增1次(核心修复)
)

; 输出结果提示
(princ (strcat "\n批量插入完成!共处理 " (itoa (sslength ss)) " 条多段线,成功插入 " (itoa success_count) " 个块。"))
(princ "\n提示:若块方向错误,可重新运行并选择「第二个顶点(S)」作为插入点。")
(HT_END)
(princ)
)


;;*************************************************************************************************************************************************
;;;
;;;>>>>>>>>>>>>>>--出错处理_HT-->>>>>>>>>>>>>>>>所用位置:HT_401、402、部分三维改造(因老顾的错误处理对部分用pause的程序不起作用,有的又可以,奇怪)
;;(HT_START)
;;(HT_END)

(defun HT_START ()
(vl-load-com)
    (defun error_new (msg)
      (if os_old (setvar "osmode" os_old))
      (if cmd_old (setvar "cmdecho" cmd_old))
      (if DYN1_old (setvar "DYNmode" DYN1_old))
      (if DYN2_old (setvar "DYNprompt" DYN2_old))
      (if DEL_old (setvar "DELobj" DEL_old))
      (if SUB_old (setvar "SUBobjSELECTionmode" SUB_old))
      (if CUL_old (setvar "CULlingOBJselection" CUL_old))
      (if error_old (setq *error* error_old))      
      (if (wcmatch (strcase msg t) "*break,*cancel*,*exit*,*取消*")
      (redraw)
      )
      (while (/= 0 (getvar "cmdactive"))(command ""))
      (vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
      (prompt "*程序错误或用户按ESC取消*")
      (princ)
    )
(vla-startUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq error_old *error*)   
(setq *error* error_new)
(setq os_old (getvar "osmode"))
(setq cmd_old (getvar "cmdecho"))
(setq DYN1_old (getvar "DYNmode"))
(setq DYN2_old (getvar "DYNprompt"))
(setq DEL_old (getvar "DELobj"))
(cond ((>= (atof (getvar "ACADVER")) 18.2 );;判断CAD版本是否大于2012
      (setq SUB_old (getvar "SUBobjSELECTionmode"));;过滤选择
      (setq CUL_old (getvar "CULlingOBJselection"));;是否可选隐藏对象
      )
)
)

(defun HT_END ()
(if os_old (setvar "osmode" os_old))
(if cmd_old (setvar "cmdecho" cmd_old))
(if DYN1_old (setvar "DYNmode" DYN1_old))
(if DYN2_old (setvar "DYNprompt" DYN2_old))
(if DEL_old (setvar "DELobj" DEL_old))
(if SUB_old (setvar "SUBobjSELECTionmode" SUB_old))
(if CUL_old (setvar "CULlingOBJselection" CUL_old))
(if error_old (setq *error* error_old))
(vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
;(vlax-invoke Scriptshell "SendKeys" "+^1") ;启用英文输入法
)

lxl217114 发表于 2025-10-22 09:03:48

谢谢分享
页: [1]
查看完整版本: 线段批量转块-平面布置