You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AutoLISP程序排障:基于GPS文本文件插入带属性块

AutoLISP程序问题修复与解析

核心需求与现存问题

我写了一段AutoLISP程序读取GPS点TXT文件,自动在CAD中插入指定块,但目前遇到两个问题:

  • 只能识别Notes字段为纯HP的行,无法处理HP后带数字、字母的情况(比如HP22A)
  • 代码存在冗余,且搞不懂Lee Mac写的字符串转列表函数的逻辑

程序预期实现的功能:

  • 读取格式为#,Easting,Northing,Elevation,Notes的TXT文件
  • 仅处理Notes以HP开头的行
  • 在Easting/Northing/Elevation坐标插入CWood_Pole_D.dwg块
  • 在该点左侧5单位处插入POLENA.dwg块,块的两个属性从Notes字段的空格分隔内容提取
  • 统计成功插入的块对数量

原程序代码

(defun c:poleid ( / fn fp lst l)
;; String to list convertor. This will separate coordinates and values by comma and store them in a variable as a list
    (defun LM:str->lst ( str del / len lst pos )
        (setq len (1+ (strlen del)))
        (while (setq pos (vl-string-search del str))
            (setq lst (cons (substr str 1 pos) lst)
                str (substr str (+ pos len))
            )
        )
        (reverse (cons str lst))
    )
    ;; Prompt the user to select a .TXT file.
    (setq fn (getfiled "Select UTM GPS file" "" "txt" 4))

    ;; Open the file and create an empty list
    (setq fp (open fn "r") lst '())

    ;; Iterate the file, writing each line to the list (as a string)
    (while (setq l (read-line fp))
        (setq lst (cons l lst))
    )
    ;; Close the file.
    (close fp)

    ;; Reverse the list
    (setq lst (reverse lst))

    ;; At this point, the data is stored in a variable (lst) and the file is closed.

    ;; Save current OSNAP MODE and turn off
    (setq os (getvar 'osmode))
    (setvar "osmode" 0)
    
    ;;Set pcount to 0
    (setq pcount 0)
    ;; Iterate the list and draw a point
    ;; entity at each coordinate
    (foreach item lst ;; For each line in lst
        (setq items (LM:str->lst item ",")) ;;set variable items as a list of item, separated by commas. Set the las
        (setq ptx (nth 2 items) pty (nth 1 items) ptz (nth 3 items) idn (nth 4 items)) ;; Set the pole (pt) x, y and z values from the 2nd, 3rd and 4th values of each line. Set notes to idn (as a string). UTM values are provided to this program as y,x,z
        (setq idr (LM:str->lst idn " ") idn (nth 0 idr) idr (nth 1 idr)) ;;Set idr (Pole ID) as a list of idn, then set idn as the first half of the note (HP#) and idr as the second half
        (cond ((wcmatch idn "HP") ;; Only process lines that have HP in the 5th value
            (
                (printc idn)
                (setq ptxyz (strcat ptx "," pty "," ptz)) ;;Make the pole x, y, and z value into a single string, separated by commas
                (setq idx (atof ptx) idx (- idx 5.0) idx (rtos idx)) ;;set the idx as real number version of ptx, subtract 5 from it, then convert back to a string
                (setq idxyz (strcat idx "," pty "," ptz)) ;;Make the ID x, y, and z value into a single string, separated by commas
        
                ;;Insert pole and ID block at xyz coords, with idn as the HP number and idr as the pole ID
                (command "insert" "G:\\Shared drives\\Project Tools\\Customized Tools\\CAD\\prog\\CWood_Pole_D.dwg" ptxyz "508" "508" "0") ;; Pole symbol set to an x/y scale of 20
                (command "insert" "G:\\Shared drives\\Project Tools\\Customized Tools\\CAD\\prog\\POLENA.dwg" idxyz "25.4" "25.4" "0" idn idr) ;; Pole ID block set to an x/y scale of 1, with the top half showing the HP# and the bottom half showing the pole ID
                (setq pcount (+ pcount 1)) ;;Add 1 to counter
            ))
        )
    )
    ;; Restore OSNAP MODE and close with count of poles inserted
    (setvar 'osmode os)
    (setq pcount (write-to-string pcount))
    (princ pcount)
    (princ " pole(s) have been successively added")
    (princ)
)

测试文本内容

1000,1,2,3,HP
1001,10.000,2.000,3.000,HP21 blah
1002,15.000,2.000,3.000,HP22 2gt3
1003,20.000,2.000,3.000,CU

问题修复与代码优化

1. 解决HP开头匹配问题

原代码用(wcmatch idn "HP")只能匹配纯HP,改成通配符匹配(wcmatch notes "HP*"),就能识别所有以HP开头的字符串,包括HP21、HP22A这类情况。

2. 优化冗余代码

  • 原代码把坐标转成字符串再传给command,直接用实数坐标列表更高效,还能避免字符串转换出错
  • 处理Notes字段没有空格的情况(比如纯HP),给杆ID默认空字符串,防止块属性插入失败
  • 变量命名更清晰,提升代码可读性

3. 解析Lee Mac的LM:str->lst函数逻辑

这个函数的作用是把字符串按指定分隔符拆分成列表,步骤很简单:

  1. 计算分隔符长度+1,方便后续截取剩余字符串
  2. 循环查找分隔符在字符串中的位置,找不到就退出循环
  3. 每次循环把分隔符前的子串加入列表,然后更新字符串为分隔符后的剩余部分
  4. 最后把剩下的字符串加入列表,再反转列表(因为之前用cons是往前加,顺序反了),得到正确顺序的拆分列表

优化后的完整代码

(defun c:poleid ( / fn fp lst l os pcount)
    ;; 字符串转列表函数:按指定分隔符拆分字符串
    (defun LM:str->lst ( str del / len lst pos )
        (setq len (1+ (strlen del)))
        (while (setq pos (vl-string-search del str))
            (setq lst (cons (substr str 1 pos) lst)
                  str (substr str (+ pos len))
            )
        )
        (reverse (cons str lst))
    )

    ;; 选择TXT文件
    (if (setq fn (getfiled "选择UTM GPS文件" "" "txt" 4))
        (progn
            ;; 读取文件内容到列表
            (setq fp (open fn "r") lst '())
            (while (setq l (read-line fp))
                (setq lst (cons l lst))
            )
            (close fp)
            (setq lst (reverse lst))

            ;; 保存并关闭对象捕捉
            (setq os (getvar 'osmode))
            (setvar "osmode" 0)
            (setq pcount 0)

            ;; 遍历每一行数据
            (foreach item lst
                (setq items (LM:str->lst item ","))
                ;; 提取坐标和Notes字段(对应文件格式:#,Easting,Northing,Elevation,Notes)
                (setq easting (atof (nth 1 items))
                      northing (atof (nth 2 items))
                      elevation (atof (nth 3 items))
                      notes (nth 4 items)
                )
                ;; 匹配以HP开头的Notes
                (if (wcmatch notes "HP*")
                    (progn
                        ;; 拆分Notes为HP标识和杆ID,处理无空格的情况
                        (setq note-parts (LM:str->lst notes " "))
                        (setq hp-id (nth 0 note-parts)
                              pole-id (if (nth 1 note-parts) (nth 1 note-parts) "")
                        )
                        ;; 杆的坐标列表
                        (setq pole-pt (list easting northing elevation))
                        ;; ID块的坐标(左侧5单位)
                        (setq id-pt (list (- easting 5.0) northing elevation))

                        ;; 插入杆块
                        (command "insert" "G:\\Shared drives\\Project Tools\\Customized Tools\\CAD\\prog\\CWood_Pole_D.dwg" pole-pt "508" "508" "0")
                        ;; 插入ID块
                        (command "insert" "G:\\Shared drives\\Project Tools\\Customized Tools\\CAD\\prog\\POLENA.dwg" id-pt "25.4" "25.4" "0" hp-id pole-id)
                        (setq pcount (1+ pcount))
                    )
                )
            )

            ;; 恢复对象捕捉并输出统计
            (setvar 'osmode os)
            (princ (strcat (itoa pcount) " 组杆与ID块已成功插入"))
            (princ)
        )
        (princ "\n未选择任何文件")
    )
    (princ)
)

内容的提问来源于stack exchange,提问作者Fizscy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 17:40:52