明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 231|回复: 11

[源码] 取得多行文本各单行/段落包围框-源码

[复制链接]
发表于 10 小时前 | 显示全部楼层 |阅读模式
本帖最后由 wzg356 于 2025-4-25 14:57 编辑

;取得多行文本各单行/段落包围框
适用各种对正/左缩进/悬挂

;有缩进/自然换行的炸取配合取得,其他的不用炸取

各单行/段落包围框首/尾/底边也是准确的,框高度是人为设定为1.2倍文字高

本意是放在查找替换工具http://bbs.mjtd.com/thread-192381-1-1.html
但大篇幅文本效率还是慢,主要是(entupd ent)效率本身

查找替换工具mtext包围框还是采用简单高效的纯炸取法经适当校正使用-http://bbs.mjtd.com/thread-192381-1-1.html






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

点评

最好能提供一个dwg文件测试  发表于 7 小时前

评分

参与人数 2明经币 +2 收起 理由
USER2128 + 1 赞一个!
fangmin723 + 1 赞一个!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
回复

使用道具 举报

发表于 9 小时前 | 显示全部楼层
本帖最后由 fangmin723 于 2025-4-25 14:07 编辑

在中望CAD2014中,旋转角度后,右中对齐


添加 (command "none" (car ps)),使多段线闭口

  1. (vl-load-com)
  2. ;(setq e(car(entsel)))
  3. ;取得多行文本各单行包围框
  4. ;有缩进/自然换行的炸取配合取得
  5. (defun Mtextsubboxs (e / ang ang0 boxs czmstr2stri czmstr2text czreplacestr d d0 d1 e1 es exp1 explodedata getmtextbox h hids hids1 mstr ob p01 p02 p03 p04 p1 p11 p12 p2 polarps pos ps putstr2getbox sjd str1 verrot2d)
  6.   (progn
  7.     (vl-load-com)
  8.     ;正则表达式字符串替换
  9.     ;lst: (list(list n1 o1)(list n2 o2))
  10.     (defun CZReplacestr (str lst / regex)
  11.       (if lst
  12.         (progn
  13.           (setq regex (vlax-create-object "Vbscript.RegExp")) ;引用正则表达式控件
  14.           (vlax-put-property regex "IgnoreCase" 0) ;不忽略大小写
  15.           (vlax-put-property regex "Global" 1) ;匹配方式,全文字匹配
  16.           (foreach x lst
  17.             (vlax-put-property regex "Pattern" (cadr x))
  18.             (setq str (vlax-invoke-method regex "Replace" str (car x))) ;匹配替换
  19.           )
  20.           (vlax-release-object regex)
  21.         )
  22.       )
  23.       str
  24.     )
  25.     ;多行文本取得单行字符(类似炸开后取得的结果-自然换行没识别)
  26.     (defun CZmstr2text (str / a l2 text1)
  27.       (setq str
  28.         (CZReplacestr
  29.           str
  30.           '(("\001" "\\\\\\\\")
  31.              ("\002" "\\\\{")
  32.              ("\003" "\\\\}")
  33.              ("\t" "\\\\p(.[^;]*);")
  34.              ("$2\t" "\\\\S(\\^|#)(.[^;]*);")
  35.              ("$1\t" "\\\\S(.[^;]*)(\\^|#);")
  36.              ("\t" "(\\\\F|\\\\f|\\\\C|\\\\H|\\\\T|\\\\Q|\\\\W|\\\\A)(.[^;]*);")
  37.              ("\t" "(\\\\L|\\\\O|\\\\l|\\\\o)")
  38.              ("\t" "\\\\~")
  39.              ("\t" "\\\\P")
  40.              ("\t" "\n")
  41.              ("\t" "\r")
  42.              ("\t" "({|})")
  43.              ("\\" "\\x01")
  44.              ("{" "\\x02")
  45.              ("}" "\\x03")
  46.            )
  47.         )
  48.       )
  49.       (while (setq a (vl-string-search "\t" str))
  50.         (if
  51.           (and (> a 0)
  52.             (/= "" (vl-string-right-trim " " (setq text1 (substr str 1 a))))
  53.           )
  54.           (setq l2 (cons text1 l2))
  55.         )
  56.         (setq str (substr str (+ 2 a)))
  57.       )
  58.       (if (> (strlen str) 1) (setq l2 (cons str l2)))
  59.       (reverse l2)
  60.     )
  61.     ;获取各行单行正文文本及在母文本的位置信息
  62.     ;(CZmstr2stri mstr(CZmstr2text mstr))
  63.     (defun CZmstr2stri (mstr strs / dd flag2 hp hstr i k m n n1 ns ps ps1 str str1)
  64.       (setq i    0
  65.         k    0
  66.         hstr ""
  67.         m    0
  68.       )
  69.       (foreach str strs
  70.         (if (listp str)
  71.           (setq ps  (cadr str)
  72.             str (car str)
  73.           )
  74.         )
  75.         ;str为lst特殊用法-炸取的子串可获取自然换行
  76.         (setq dd (strlen str)
  77.           n1 0
  78.           m  (1+ m)
  79.         )
  80.         (while (setq n1 (vl-string-search str mstr n1))
  81.           (if
  82.             (wcmatch (substr mstr 1 n1) ",*[};{],*\\P,*\t,*\r,*\n,*\\L,*\\O,*\\o,*\\~")
  83.             (setq n  n1
  84.               n1 (strlen mstr)
  85.             )
  86.             (setq n1 (+ dd n1))
  87.           )
  88.         )
  89.         (if n
  90.           (progn
  91.             (setq str1 (substr mstr 1 n))
  92.             (setq mstr (substr mstr (+ 1 dd n)))
  93.             (setq i (+ n k i)) ;括号内-k上一次单行长i上次单行位置
  94.             (setq k dd)
  95.             (if
  96.               (or (vl-string-search "\\P" str1)
  97.                 (vl-string-search "\n" str1)
  98.                 ;下面2项是判断自然换行
  99.                 (and hp (= i (+ (caar hp) (cadar hp))) (setq flag2 t))
  100.                 (and ps
  101.                   ps1
  102.                   (>
  103.                     (abs
  104.                       (car
  105.                         (trans (mapcar '- (car ps) (car ps1))
  106.                           0
  107.                           (mapcar '- (cadr ps1) (car ps1))
  108.                         )
  109.                       )
  110.                     )
  111.                     (* 1.2 (caddr ps))
  112.                   )
  113.                   (setq flag2 t)
  114.                 )
  115.               ) ;行首判断
  116.               (setq ns (if hp (cons (cons hstr (reverse hp)) ns))
  117.                 hp (cond
  118.                      ((not ps) (list (list i dd)))
  119.                      (t
  120.                        (if flag2
  121.                          (list (list i dd (car ps) "\n"))
  122.                          (list (list i dd (car ps)))
  123.                        )
  124.                      )
  125.                    ) ;自然换行标记"\n"另用
  126.                 flag2 nil
  127.                 hstr  str
  128.               )
  129.               (setq hp
  130.                 (if (and ps (= 1 m))
  131.                   (cons (list i dd (car ps)) hp)
  132.                   (cons (list i dd) hp)
  133.                 )
  134.                 hstr (strcat hstr str)
  135.               )
  136.             )
  137.             (setq ps1 ps)
  138.           )
  139.         )
  140.       )
  141.       (reverse (cons (cons hstr (reverse hp)) ns))
  142.     )
  143.     ;炸取MTEXT字串数据
  144.     (defun explodedata (e / ang e0 el es h l1 p str)
  145.       (setq el (entlast) es (entget e))
  146.       (setq ang (cdr (assoc 50 es)))
  147.       (vla-Copy (vlax-ename->vla-object e))
  148.       ((if command-s command-s vl-cmdf) "_explode" (entlast))
  149.       (while (setq el (entnext el))
  150.         (setq es (entget el))
  151.         (setq e0 (cdr (assoc 0 es)))
  152.         (if
  153.           (and
  154.             (= e0 "TEXT")
  155.             (/= "" (vl-string-right-trim " " (setq str (cdr (assoc 1 es)))))
  156.           )
  157.           (setq
  158.             p  (cdr (assoc 10 es))
  159.             h  (cdr (assoc 40 es))
  160.             l1 (cons (list str (list p (polar p ang (* 10 h)) h)) l1)
  161.           )
  162.         )
  163.         (entdel el)
  164.       )
  165.       (reverse l1)
  166.     )
  167.     (defun getMtextbox (e / a es l l1 p1 p2 w w1 z)
  168.       (setq
  169.         es (entget e)
  170.         a  (cdr (assoc 50 es))
  171.         l  (cdr (assoc 42 es))
  172.         w  (cdr (assoc 43 es))
  173.         z  (cdr (assoc 71 es))
  174.         w1 (if (member z '(4 5 6)) (* 0.5 w) (if (member z '(7 8 9)) 0 w))
  175.         l1 (if (member z '(2 5 8)) (* 0.5 l) (if (member z '(1 4 7)) 0 l))
  176.         p1 (polar (polar (verRot2D (cdr (assoc 10 es)) (- 0 a)) pi l1)
  177.              (* 1.5 pi)
  178.              w1
  179.            )
  180.         p1 (verRot2D p1 a)
  181.         p2 (polar p1 a l)
  182.         a  (+ a (* 0.5 pi))
  183.       )
  184.       (list p1 p2 (polar p2 a w) (polar p1 a w))
  185.     )
  186.     (defun verRot2D (v a / c s x y)
  187.       (setq
  188.         c (cos a)
  189.         s (sin a)
  190.         x (car v)
  191.         y (cadr v)
  192.       )
  193.       (list (- (* x c) (* y s)) (+ (* x s) (* y c)))
  194.     );;; 旋转向量到指定角度 by高飞
  195.     (defun polarps (ps ang d)
  196.       (mapcar (function (lambda (p) (polar p ang d))) ps)
  197.     ) ;点集按向移位
  198.     (defun putstr2getbox (e str)
  199.       (Vlax-Put (vlax-ename->vla-object e) 'TextString str)
  200.       (entupd e)
  201.       (setq ps (getMtextbox e))
  202.     )
  203.   )
  204.   (setq ob (vlax-ename->vla-object e))
  205.   (setq es (entget e))
  206.   (setq pos (cdr (assoc 71 es)))
  207.   (setq mstr (Vlax-Get ob 'TextString))
  208.   (setq ps (getMtextbox e))
  209.   (setq p01 (car ps)
  210.     p02 (cadr ps)
  211.     p03 (caddr ps)
  212.     p04 (cadddr ps)
  213.   )
  214.   (setq d0 (cdr (assoc 41 es)))
  215.   (setq h (* 1.35 (cdr (assoc 40 es))))
  216.   (if
  217.     (and
  218.       (or (= 0 d0) (> d0 (+ h (distance p01 p02))))
  219.       ;+h是确保无自然换行
  220.       (not (wcmatch mstr "*\\pxi#*,*\\pxi-#*,*\\pi#*,*\\pi-#*")) ;无缩进
  221.     )
  222.     (setq hids (reverse (CZmstr2stri mstr (CZmstr2text mstr))))
  223.     ;可以不炸取的情况
  224.     (setq hids (reverse (CZmstr2stri mstr (explodedata e))))
  225.     ;有自然换行或缩进,炸取单行文本也是高效的
  226.   )
  227.   (setq d0 (distance p01 p04))
  228.   (setq ang0 (cdr (assoc 50 es))
  229.     ang  (+ (* 0.5 pi) ang0)
  230.   )
  231.   (setq hids1 hids)
  232.   (foreach id hids
  233.     (vla-Copy (vlax-ename->vla-object e))
  234.     (setq e1 (entlast))
  235.     ;复制可减少最后一次(entupd e)效率近乎倍增
  236.     (setq str1 mstr)
  237.     (setq str1 (substr str1 1 (+ (car (last id)) (cadr (last id)))))
  238.     ;删除该行以后--不影响格式
  239.     (if (cadddr (cadr id))
  240.       (setq str1 (strcat
  241.                    (substr str1 1 (caadr id))
  242.                    "\n"
  243.                    (substr str1 (1+ (caadr id)))
  244.                  )
  245.       )
  246.     ) ;炸取数据有自然换行l临时加入换行符-取包围框
  247.     (if (setq p1 (caddr (cadr id)))
  248.       (setq sjd (car (trans (mapcar '- p1 p04) 0 (mapcar '- p01 p04))))
  249.       (setq sjd 0)
  250.     ) ;炸取数据取得的行首基点-计算缩进
  251.     (setq ps (putstr2getbox e1 str1))
  252.     (if (member pos '(7 8 9))
  253.       (setq p1 (cadddr ps)
  254.         p2 (caddr ps)
  255.       )
  256.       (setq p1 (car ps)
  257.         p2 (cadr ps)
  258.         d1 (distance (car ps) (cadddr ps))
  259.       )
  260.     ) ;比对基线点
  261.     (foreach subid (setq hids1 (cdr hids1))
  262.       (foreach a (reverse (cdr subid))
  263.         (setq str1 (strcat
  264.                      (substr str1 1 (car a))
  265.                      (substr str1 (+ 1 (car a) (cadr a)))
  266.                    )
  267.         )
  268.       ) ;改行以前有效字符全换为""
  269.     )
  270.     (setq ps (putstr2getbox e1 str1))
  271.     (entdel e1)
  272.     (setq p11 (car ps)
  273.       p12 (cadr ps)
  274.     ) ;比对基线点
  275.     (setq exp1 '(list p11 p12 (polar p12 ang h) (polar p11 ang h)))
  276.     (if (member pos '(7 8 9))
  277.       (setq ps (eval exp1)
  278.         d  (car (trans (mapcar '- (caddr ps) p1) 0 (mapcar '- p2 p1)))
  279.         ps (polarps ps ang (+ d d0 (- 0 h)))
  280.       )
  281.       (setq d   (car (trans (mapcar '- p11 p2) 0 (mapcar '- p1 p2)))
  282.         p11 (polar p11 ang d)
  283.         p12 (polar p12 ang d)
  284.         ps  (eval exp1)
  285.         ps  (if (member pos '(1 2 3))
  286.               ps
  287.               (polarps ps ang (* 0.5 (- d0 d1)))
  288.             )
  289.       )
  290.     )
  291.     (setq ps (polarps ps ang0 sjd))
  292.     (setq boxs (cons (list (caadr id) (strlen (car id)) ps) boxs))
  293.     ;(setq boxs(cons ps boxs))
  294.   )
  295.   boxs
  296. )
  297. ;测试
  298. (defun c:tt66 (/ e)
  299.   (if (setq e (ssget ":s:e" '((0 . "mtext"))))
  300.     (foreach ps (mapcar 'caddr (Mtextsubboxs (ssname e 0)))
  301.       (command "pline")
  302.       (foreach p ps (command "none" p))
  303.       (command "none" (car ps))
  304.       (command "")
  305.     )
  306.   )
  307. )



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 9 小时前 来自手机 | 显示全部楼层
fangmin723 发表于 2025-4-25 14:06
在中望CAD2014中,旋转角度后,右中对齐



我没用中望,CAD包围框中望不支持
回复 支持 反对

使用道具 举报

发表于 9 小时前 | 显示全部楼层
本帖最后由 fangmin723 于 2025-4-25 14:19 编辑
wzg356 发表于 2025-4-25 14:12
我没用中望,CAD包围框中望不支持

后面的数字都忽略了吗,还有,试着更改多行文子的行高或行高比例,你那边可以测试下看看,有没有问题

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 9 小时前 来自手机 | 显示全部楼层
本帖最后由 wzg356 于 2025-4-25 14:34 编辑
fangmin723 发表于 2025-4-25 14:14
后面的数字都忽略了吗,还有,试着更改多行文子的行高或行高比例,你那边可以测试下看看,有没有问题


有效文字没问题的,包围框首尾也没问题——/与字高行高无关——是CAD系统的包围框数据几何比对计算获取。
炸开仅仅是为了快速确定自然换行的字符位置(不是坐标)
回复 支持 反对

使用道具 举报

 楼主| 发表于 9 小时前 | 显示全部楼层
fangmin723 发表于 2025-4-25 14:14
后面的数字都忽略了吗,还有,试着更改多行文子的行高或行高比例,你那边可以测试下看看,有没有问题

取得各单行/段落内容和位置索引hids
mstr是完整的带格式的多行文本字符串
(setq hids(reverse(CZmstr2stri mstr(CZmstr2text mstr))))
回复 支持 反对

使用道具 举报

发表于 9 小时前 | 显示全部楼层
wzg356 发表于 2025-4-25 14:34
取得各单行/段落内容和位置索引hids
mstr是完整的带格式的多行文本字符串
(setq hids(reverse(CZmstr2s ...

等有时间了,我研究下,看看中望哪里出了问题
回复 支持 反对

使用道具 举报

发表于 7 小时前 | 显示全部楼层
刚刚还在想代码,准备看有没有现成的,马上这就有了,及时雨啊
回复 支持 反对

使用道具 举报

发表于 7 小时前 | 显示全部楼层
支持,感谢分享
回复 支持 反对

使用道具 举报

发表于 7 小时前 | 显示全部楼层

适合简单的Mtext格式

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-4-25 23:49 , Processed in 0.207307 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表