本帖最后由 林霄云 于 2014-1-6 19:08 编辑
文字基于自身中点反转——扩展对块内文字的操作
原版本文详见文字绕自身中点反转 支持UCShttp://bbs.mjtd.com/forum.php?mo ... 909&fromuid=7303580
强调更为广泛的应用,本文对文字反转进行扩展,使之对块内文字亦有效
思路:主要涉及到块内文字的操作
1,entsel选择对象,取ent和pt ,判断类型为text,直接调用反转。为insert时,取其所有text类型的子对象
2,对所有子对象,执行get-textbox,即取子对象四个角点,判断pt是否在四个角点形成的多边形内(此处比较都用默认的wcs (ocs)——即受限的UCS)。如果是,则对该对象执行反转。(默认点选文字重叠区时,重叠的文字都会反转)
流程:
1,主函数ART (Advanced Rotate Text) 进行选择对象,判断对象,当对象类型为TEXT时,调用反转函数rotate-text(en),否则继续判断,当为INSERT时,取块内类型为TEXT的ename列表。然后对每个进行判断是否单击点在其textbox中,如果是则,反转。
2,辅助函数有Rotate-text,get-textbox,inorout(判断点是否在多边形内,在代码里有感谢作者),AllEntityInBlk(取块内所有TEXT对象,在代码里有感谢原作者,我加入过滤条件)
源代码解析及测试如下- ;1,entsel选择对象,取ent和pt ,判断类型为text,直接调用反转。为insert时,取其所有text类型的子对象
- ;2,对所有子对象,执行get-textbox,取子对象四个角点,判断pt是否在四个角点形成的多边形内(此处比较都用默认的wcs (ocs))。如果是,则对该对象执行反转,退出循环。
- (defun C:ART () ;Advanced Rotate Text
- ;函数ART Advanced Rotate Text 文字绕自身中点反转,version 2.0 支持块内文字 。
- ;Desiged by 林霄云 2014年1月5日
- (princ "\n选择需要反转的文字:");提示不需要进入循环
- (while (setq enl (entsel)) ;循环操作,方便测试
- (setq en (car enl)
- en-pt (trans (cadr enl) 1 0) ;取单选的对象及其点,需要从UCS转WCS。
- ent (entget en)
- flag nil)
- (setq typ (cdr (assoc 0 ent)))
- (if (= typ "TEXT") ;如果判断是TEXT,则直接Rotate it。否则如果是块,则找到块内的文字对象列表 tn-list:text name list,对每一个text ename 进行判断。如果满足点在textbox里,则旋转之。
- (rotate-text en)
- (if (= typ "INSERT")
- (progn
- (setq tn-list (ALLENTITYINBLK en)) ;成功返回
- (foreach entn tn-list
- (setq pt-list (get-textbox entn ))
- (setq flag (inorout pt-list en-pt))
-
- (if flag
- (progn
- (rotate-text entn)
- ;更新所有块,感谢llsheng_73的思路
- ;(entupd entn)
-
- (setq i -1)
- (setq ss (ssget "X" (list (cons 2 (cdr (assoc 2 ent)) ) ) ));(entupd en) ;(entmod ent);需要更新块。但不会更新所有块。唉。
- (while (setq s1 (ssname ss (setq i (1+ i))))
- (entupd s1))
- );progn
- )
- );foreach
-
-
- );progn
- );if
- );if
-
- );while 加入循环
- (princ)
- );defun
- (princ "\nRTT 文字反转命令加载成功\nDesigned by 林霄云 2014年1月4日")
- (princ)
- ; 函数AllEntityInBlk (blk)
- (defun AllEntityInBlk (blk / bn blkdef e typ el ) ;感谢 mjtd之 jxphklibin
- (setq bn (cdr (assoc 2 (entget blk)));先找块名,bn,然后更具块找出其ename。定义的块。必然是全改的。如果不想全改,就是炸开咯。
- blkdef (tblobjname "block" bn)
- )
- (while (setq e (entnext blkdef))
- (setq typ (cdr (assoc 0 (entget e))))
-
- (if (= typ "TEXT")
- (setq el (cons e el)) ;过滤条件:只取 TEXT ,顺序不重要。
- (if (= typ "INSERT")
- (setq el (append (AllEntityInBlk e) el));list 级别的操作 el: entity list
- ;(setq el (cons e el)) ;顺序不重要。
- );if INSERT
- );if TEXT
- (setq blkdef e) ;entnext 条件
- )
- el
- )
- ;函数get-textbox(en)
- (defun get-textbox (en / ang-self ang en ent pt0-ll pt0-tr pt-ins pt-2 pt-3 pt-4 pt-list x y ) ;获取文本四角点 Get Text Box
- ;函数get-textbox(en),参数en:entity name 即ename。
- ;Desiged by 林霄云 2014年1月4日
- (setq ent (entget en))
- (setq pt-ins (cdr (assoc 10 ent))) ;第一对齐点(在 OCS 中)插入点(非UCS下坐标点);支持受限的UCS。
- (setq ang (cdr (assoc 50 ent))) ;a 文字旋转角度 弧度
-
- (setq pt-list (textbox ent)) ;取虚拟框
- (setq pt0-ll (car pt-list)) ;取左下点
- (setq pt0-tr (cadr pt-list)) ;取右上点
- (setq box-tr (mapcar '(lambda (x y) (+ x y)) pt0-ll pt0-tr)) ;取对应原点的右上点。
- (setq box-length (car box-tr))
- (setq box-height (cadr box-tr))
- (setq ang-self (atan (cadr box-tr) (car box-tr)));取转角,基点为原点。 self-ang花了作者一晚上的时间,因为polar中的角度是从坐标轴开始的。需要加自身转角。
- ;不用angle函数,angle会投影成UCS。
- (setq dis (distance '(0.0 0.0 0.0) box-tr))
- (setq pt-3 (polar pt-ins (+ ang-self ang) dis));此句+ ang-self 表示逆时针(polar正方向)转角ang-self
- (setq pt-2 (polar pt-ins ang box-length))
- (setq pt-4 (polar pt-ins (+ ang (* 0.5 pi) ) box-height)) ;此句+0.5pi 表示逆时针(polar正方向)转角90°
- ;(command "line" (trans pt-ins 0 1) (trans pt-2 0 1) (trans pt-3 0 1) (trans pt-4 0 1 ) "c") ;trans pt 0 1 wcs 转 ucs ,测试文本外框代码
- (list pt-ins pt-2 pt-3 pt-4) ;逆时针顺序,即polar函数规定的正方向
- );defun
- ;函数rotate-text(en)
- (defun rotate-text (en / ag ang-self ang en ent pt0-ll pt0-m pt0-tr pt-ins pt-list x y ) ;文字绕自身中点反转RotaTe Text
- ;函数rotate-text(en),参数en:entity name 即ename。
- ;Desiged by 林霄云 2014年1月4日
- (setq ent (entget en))
- (setq pt-ins (cdr (assoc 10 ent))) ;第一对齐点(在 OCS 中)插入点(非UCS)
- (setq ang (cdr (assoc 50 ent))) ;a 文字旋转角度 弧度(WCS)
-
- (setq pt-list (textbox ent)) ;取文本虚拟框
- (setq pt0-ll (car pt-list)) ;取左下点
- (setq pt0-tr (cadr pt-list)) ;取右上点
- (setq te-tr (mapcar '(lambda (x y) (+ x y)) pt0-ll pt0-tr)) ;取对应原点的右上点。
- (setq ang-self (atan (cadr te-tr) (car te-tr)));取转角,基点为原点。 self-ang花了作者一晚上的时间,因为polar中的角度是从坐标轴开始的。需要加自身转角。
-
- (setq pt-tr (mapcar '(lambda (x y) (+ x y)) te-tr pt-ins));取对应插入点的右上点
- ;相对pt-ins,将中点旋转角度ang
- (setq dis (* 0.5 (distance pt-ins pt-tr))) ;取长度
- (setq pt0-m (polar pt-ins (+ ang-self ang) dis))
- ;;;(command "point" pt0-m)
- (setq ag "180")
- (vla-rotate
- (vlax-ename->vla-object en)
- (vlax-3d-point pt0-m)
- (angtof ag)
- )
- );defun
- ; 函数 inorout
- ;;By Xiao_longxin 明经通道
- (defun inorout (pt_list pt / e1 n i j va va_count)
- (setq i 0
- va_count 0
- n (length pt_list)
- pt_list (append pt_list (list (car pt_list)))
- )
- (repeat n
- (setq va (- (angle pt (nth i pt_list))
- (angle pt (nth (1+ i) pt_list))
- )
- )
- (cond ((> va pi) (setq va (- va pi)))
- ((< va (* -1 pi)) (setq va (+ va pi)))
- )
- (setq va_count (+ va_count va)
- i (1+ i)
- )
- )
- (if (< (abs (- (abs va_count) pi)) 0.000001)
- 't
- 'nil
- )
- )
函数inorout作者解析:- ; 函数(inorout pt_list pt)
- ; 参数:
- ; pt_list:点表
- ; pt:所要判断的点
- ; 返回值:
- ; 如果在点表构成的多边形内,则返回T,否则返回nil。
- ; 说明:
- ; 有一不规则多边形由点a1(x1,y1)、a2(x2,y2).....an(xn,yn)依次连接而成,如何求证点p(x,y)是在多边形内还是多边形外?
- ; 将直线PAi记作ki.将ki旋转到ki+1(令kn+1=k1)的角记为βi(规定逆时针为正,顺时针为负,如果βi大于180就变成βi-360)。
- ; 从直观上看有下面的结论
- ; 若P在形内,诸β的代数和为360度;
- ; 若P在形外,诸β的代数和为0。
复制代码 结论
本代码成功反转文本进行了扩展。阐述了对块内文本进行定位的思路与实践,是对块内对象操作的一次很有益的尝试与应用。(TMA刷块内文字亦可以实现)
稍微修改,可以修正对于块镜像出现的文字问题;选择有问题的块,然后炸开实现文字反转。 |