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,方便后续截取剩余字符串
- 循环查找分隔符在字符串中的位置,找不到就退出循环
- 每次循环把分隔符前的子串加入列表,然后更新字符串为分隔符后的剩余部分
- 最后把剩下的字符串加入列表,再反转列表(因为之前用
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
相关产品推荐
相关产品推荐

