zyx1029 发表于 2025-9-10 10:22:34

批量提取直线和多段线顶点坐标并输出到DAT文件

本帖最后由 zyx1029 于 2025-9-11 08:45 编辑


自己写了一部分,效果不太好。又让AI给加工了一下

;; 批量提取直线和多段线顶点坐标并输出到DAT文件,同时标注点号和多段线(或直线)编号
(defun C:TQZB (/ *error* ss filename file i ent_tqzb objType vertexList_tqzb allVertices pointCounter j vertexData textHeight lineCounter polylineCounter oldOSMODE)
    ;; 错误处理函数
    (defun *error* (msg)
      (if (and msg (not (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")))
            (princ (strcat "\n错误: " msg))
      )
      (if file (close file))
      (setvar "OSMODE" oldOSMODE) ; 恢复捕捉模式
      (princ)
    )

    (vl-load-com)
    (setq oldOSMODE (getvar "OSMODE")) ; 保存当前捕捉模式

    ;; 获取文本高度
    (setq textHeight (getdist "\n请输入点号文本高度<1>: "))
    (if (not textHeight)
      (setq textHeight 1.0) ; 默认文本高度
    )

    ;; 提示用户选择直线和多段线
    (setq ss (ssget '((0 . "LINE,LWPOLYLINE,POLYLINE"))))
    (if (not ss)
      (progn
            (princ "\n未选择任何对象。")
            (exit)
      )
    )

    ;; 获取输出文件名
    (setq filename (getfiled "指定输出DAT文件" "" "dat" 1))
    (if (not filename)
      (progn
            (princ "\n未指定输出文件。")
            (exit)
      )
    )

    ;; 打开文件用于写入
    (setq file (open filename "w"))
    (if (not file)
      (progn
            (princ "\n无法创建文件。")
            (exit)
      )
    )

    (setq allVertices nil)
    (setq pointCounter 1) ; 初始化全局点号计数器
    (setq lineCounter 1) ; 初始化直线编号计数器
    (setq polylineCounter 1) ; 初始化多段线编号计数器

    ;; 遍历选择集中的每个图元
    (setq i 0)
    (while (< i (sslength ss))
      (setq ent_tqzb (ssname ss i))
      (setq objType (cdr (assoc 0 (entget ent_tqzb))))
      
      ;; 根据图元类型获取顶点列表
      (cond
            ;; 处理直线
            ((= objType "LINE")
                (setq vertexList_tqzb (list
                  (cdr (assoc 10 (entget ent_tqzb))) ; 起点
                  (cdr (assoc 11 (entget ent_tqzb))) ; 终点
                ))
            )
            ;; 处理轻量多段线和多段线
            ((or (= objType "LWPOLYLINE") (= objType "POLYLINE"))
                (setq vertexList_tqzb (get-polyline-vertices ent_tqzb))
            )
      )

      ;; 将当前图元的顶点信息添加到总列表
      (setq allVertices (cons (list objType vertexList_tqzb) allVertices))
      (setq i (1+ i))
    )

    ;; 反转列表以保持选择顺序
    (setq allVertices (reverse allVertices))

    ;; 关闭捕捉模式
    (setvar "OSMODE" 0)

    ;; 写入顶点数据到文件并标注点号
    (setq i 0)
    (foreach entity allVertices
      (setq objType (car entity))
      (setq vertexList_tqzb (cadr entity))
      (setq vertexCount (length vertexList_tqzb))
      
      ;; 根据对象类型确定标注类型
      (cond
            ((= objType "LINE")
                ;; 处理直线
                (setq centerPoint (get-line-center_tqzb vertexList_tqzb))
                (setq angle (get-line-angle vertexList_tqzb))
                (setq offsetPoint (get-offset-point_tqzb centerPoint angle (* textHeight 1.5)))
               
                ;; 在DAT文件中写入直线编号
                (write-line (strcat "直线" (itoa lineCounter)) file)
               
                ;; 在偏移位置添加编号文本标注,方向与线平行
                (create-text_tqzb-at-point_tqzb offsetPoint (strcat "直线" (itoa lineCounter)) textHeight angle)
               
                (setq lineCounter (1+ lineCounter))
            )
            ((or (= objType "LWPOLYLINE") (= objType "POLYLINE"))
                ;; 处理多段线
                (if (= vertexCount 2)
                  (progn
                        ;; 两个顶点的多段线,处理方式类似直线
                        (setq centerPoint (get-line-center_tqzb vertexList_tqzb))
                        (setq angle (get-line-angle vertexList_tqzb))
                        (setq offsetPoint (get-offset-point_tqzb centerPoint angle (* textHeight 1.5)))
                        
                        ;; 在DAT文件中写入多段线编号
                        (write-line (strcat "多段线" (itoa polylineCounter)) file)
                        
                        ;; 在偏移位置添加编号文本标注,方向与线平行
                        (create-text_tqzb-at-point_tqzb offsetPoint (strcat "多段线" (itoa polylineCounter)) textHeight angle)
                  )
                  (progn
                        ;; 三个顶点以上的多段线
                        (write-line (strcat "多段线" (itoa polylineCounter)) file)
                        
                        ;; 在多段线中心位置添加编号文本标注
                        (setq centerPoint (get-polyline-center_tqzb vertexList_tqzb))
                        (create-text_tqzb-at-point_tqzb centerPoint (strcat "多段线" (itoa polylineCounter)) textHeight 0)
                  )
                )
               
                (setq polylineCounter (1+ polylineCounter))
            )
      )
      
      (setq localPointCounter 1) ; 每条多段线独立的点号计数器,从1开始
      
      (setq j 0)
      (foreach vertex vertexList_tqzb
            ;; 创建点号文本(格式: J1, J2, J3, ...)
            (setq pointText (strcat "J" (itoa localPointCounter)))
            
            ;; 在顶点位置创建文本标注
            (create-text_tqzb-at-point_tqzb vertex pointText textHeight 0)
            
            ;; 格式化坐标数据(用于文件输出)
            (setq vertexData (strcat
                pointText ; 地块点号
                ",,"
                (rtos (car vertex) 2 3) ; X坐标
                ","
                (rtos (cadr vertex) 2 3) ; Y坐标
                ",0.00" ; 固定高程值
            ))
            
            ;; 写入到文件
            (write-line vertexData file)
            
            (setq j (1+ j))
            (setq localPointCounter (1+ localPointCounter)) ; 递增局部点号计数器
            (setq pointCounter (1+ pointCounter)) ; 递增全局点号计数器
      )
      
      ;; 在多段线/直线数据之间添加空行(除非是最后一个)
      (if (< i (1- (length allVertices)))
            (write-line "" file)
      )
      
      (setq i (1+ i))
    )

    ;; 关闭文件
    (close file)
    (setq file nil)

    ;; 恢复捕捉模式
    (setvar "OSMODE" oldOSMODE)

    (princ (strcat "\n成功提取并保存了 " (itoa (1- pointCounter)) " 个顶点到 " filename))
    (princ)
)

;; 获取多段线的所有顶点坐标
(defun get-polyline-vertices (ent_tqzb / entData vertices vertex)
    (setq entData (entget ent_tqzb))
    (setq vertices '())
   
    ;; 遍历图元数据表,提取所有顶点(组码10)
    (foreach item entData
      (if (= (car item) 10)
            (progn
                (setq vertex (cdr item))
                ;; 确保顶点有Z坐标(如果没有,设为0.0)
                (if (< (length vertex) 3)
                  (setq vertex (list (car vertex) (cadr vertex) 0.0))
                )
                (setq vertices (cons vertex vertices))
            )
      )
    )
   
    ;; 返回反转的顶点列表(保持原始顺序)
    (reverse vertices)
)

;; 计算多段线的大致中心点
(defun get-polyline-center_tqzb (vertexList_tqzb / minX maxX minY maxY)
    (setq minX (apply 'min (mapcar 'car vertexList_tqzb))
          maxX (apply 'max (mapcar 'car vertexList_tqzb))
          minY (apply 'min (mapcar 'cadr vertexList_tqzb))
          maxY (apply 'max (mapcar 'cadr vertexList_tqzb)))
    (list (/ (+ minX maxX) 2) (/ (+ minY maxY) 2) 0.0)
)

;; 计算直线的中心点
(defun get-line-center_tqzb (vertexList_tqzb)
    (list
      (/ (+ (car (nth 0 vertexList_tqzb)) (car (nth 1 vertexList_tqzb))) 2.0)
      (/ (+ (cadr (nth 0 vertexList_tqzb)) (cadr (nth 1 vertexList_tqzb))) 2.0)
      0.0
    )
)

;; 计算直线的角度(弧度)
(defun get-line-angle (vertexList_tqzb)
    (setq p1 (nth 0 vertexList_tqzb)
          p2 (nth 1 vertexList_tqzb))
    (atan (- (cadr p2) (cadr p1)) (- (car p2) (car p1)))
)

;; 计算偏移点(垂直于直线方向)
(defun get-offset-point_tqzb (center_tqzb angle distance)
    (list
      (+ (car center_tqzb) (* distance (cos (+ angle (/ pi 2)))))
      (+ (cadr center_tqzb) (* distance (sin (+ angle (/ pi 2)))))
      0.0
    )
)

;; 在指定点创建文本
(defun create-text_tqzb-at-point_tqzb (point_tqzb text_tqzb height_tqzb angle / oldOSMODE)
    (setq oldOSMODE (getvar "OSMODE")) ; 保存当前捕捉模式
    (setvar "OSMODE" 0) ; 关闭捕捉模式
   
    (command "_.text"
      "_J" "_MC" ; 中间中心对齐
      point_tqzb ; 插入点
      height_tqzb ; 文字高度
      (* (/ angle pi) 180) ; 旋转角度(转换为度)
      text_tqzb ; 文本内容
    )
   
    (setvar "OSMODE" oldOSMODE) ; 恢复捕捉模式
)

;; 加载提示
(princ "\n输入命令 TQZB 开始提取顶点坐标并标注点号和多段线(或直线)编号。")
(princ)


zyx1029 发表于 2025-9-11 08:43:37

luoyiandy 发表于 2025-9-10 11:30
可以,不错,挺好用,要是能直接生成表格在CAD上就更好了

安排一个,两种模式可选!

zyx1029 发表于 2025-9-12 12:39:03

bai2000 发表于 2025-9-12 12:08
指定基点,以基点绘制其余点到基点的相对x/y的相对坐标值

我好像没明白

zyx1029 发表于 2025-9-12 12:01:35

bai2000 发表于 2025-9-12 10:44
不错,能指定基点,绘制相对坐标么?

提取指定点的坐标到文件或表格?

luoyiandy 发表于 2025-9-10 11:30:09

可以,不错,挺好用,要是能直接生成表格在CAD上就更好了

qifeifei 发表于 2025-9-10 21:10:44

非常好用 感谢分享

不一样地设计 发表于 2025-9-10 21:43:54

感谢分享。

czb203 发表于 2025-9-11 08:39:22


感谢分享。

zjy2999 发表于 2025-9-11 09:30:58

多谢分享!!!!!!

依然小小鸟 发表于 2025-9-11 14:04:04

不错 加油 支持你

bai2000 发表于 2025-9-12 10:44:05

zyx1029 发表于 2025-9-11 08:43
安排一个,两种模式可选!

不错,能指定基点,绘制相对坐标么?
页: [1] 2
查看完整版本: 批量提取直线和多段线顶点坐标并输出到DAT文件