选择集曲线断开程序详解 |
|
目的:对所选择的曲线实体在交点处均断开。
与此相关帖子 1
http://www.xdcad.net/forum/showthre...6060#post836060 2 http://www.xdcad.net/forum/showthre...3657#post833657 3 http://www.xdcad.net/forum/showthre...0472#post860472 4 http://www.xdcad.net/forum/showthre...1693#post441693 5
园断开 http://www.xdcad.net/forum/showthre...3711#post843711
下面介绍下编程思路:
第一种方法用基本的命令Break
CAD中的曲线类实体包括Line、ARC、Circle、Lwpolyline、polyline、Spline、Ellipse,程序的第一步就是要构造这些实体的选择集,自然用到
SSGET,在上面的实体中有几个实体是不能直接用Break在一个点处打断的-------闭合的周期曲线,包括
Circle、闭合的Spline、闭合的Ellipse,对这几类先行过滤掉暂不处理。
(setq filter
'((-4 . "< or")
(0 . "*polyline,arc,line") (-4 . "<and")
(0 . "spline") (-4 . "<not") (71 . 3)
(-4 . "not >") (-4 . "and >") (-4 .
"or >") ) ) (setq ss (ssget
filter))
下一步就是求出所有的交点
;;选择集交点子程序
(defun interss
(e1 e2 / pts ipts) (setq ipts (vlax-variant-value
(vla-intersectwith
e1 e2 acExtendNone
) ) ) (if
(> (vlax-safearray-get-u-bound ipts 1) 0) ;是否有交点 (progn
(setq ipts
(vlax-safearray->list ipts) ) (while (>
(length ipts) 0) (setq pts (cons (list (car ipts) (cadr ipts) (caddr ipts) )
pts ) ;此处可以在添加时判断是否有重合点 ) (setq ipts (cdddr ipts)) ) ) )
pts ;也可以在这里单独去除重合点
) ;;所有的交点表 (setq pts (interss ss))
好了下面写个程序结构
(defun c:BrkAll (/ ss pts thisdrawing filter) (setq filter '((-4 . "< or")
(0 . "*polyline,arc,line") (-4 . "< and")
(0 . "spline") (-4 . "< not") (71 . 3)
(-4 . "not >") (-4 . "and >") (-4 .
"or >") ) ) (if (setq ss (ssget filter))
(progn (setq pts (interss ss)
thisdrawing (vla-get-activedocument
(vlax-get-acad-object) ) )
(vla-startundomark thisdrawing) ......
(vla-endundomark thisdrawing) ) ) (princ)
)
|
继续,上面获得了曲线的所有交点,再看看Break命令在一个点下断开实体的方法
要将对象一分为二并且不删除某个部分,输入的第一个点和第二个点应相同。通过输入 @ 指定第二个点即可实现此过程。 -----
《CAD联机帮助》
有了交点就可以使用Break命令断开曲线了
(vl-cmdf ".break" (list curve pt) "f" pt "@")
这里曲线要用点对的形式。
对单个曲线用上面的基本方法,现在是一些不确定的点的集合,而且在一个点处可能有数个曲线通过。如何将点和曲线对应起来呢? 这里可以用一个以点为中心的最小框再次选择曲线,然后调用Break命令。这个框就选用Pickbox
(setq pick (getvar "pickbox") p1 (polar pt (* -0.75 pi) (* 2. (expt (/ pick 2) 2))) p2 (polar pt (* 0.45 pi) (* 2. (expt (/ pick 2) 2))) ) (setq s1 (ssget "_c" p1 p2 filter ))
对上面的总结
(setq pick (getvar "pickbox") p1 (polar pt (* -0.75 pi) (* 2. (expt (/ pick 2) 2))) p2 (polar pt (* 0.45 pi) (* 2. (expt (/ pick 2) 2))) ) (if (ssget "_c" p1 p2 filter) (vlax-for i (vla-get-activeselectionset
thisdrawing) (foreach pt pts (vl-cmdf ".break" (list (vlax-vla-object->ename i) x) "f" pt "@" ) ) )
)
处理点集时可以采用的方法有 repeat while mapcar
foreach 根据个人喜好选择,本人推荐使用 Foreach。
下一次介绍Break的优化提供程序运行效率。 |
再讲一讲选择集的处理问题,在Lisp下一般用repeat 或者 while
,有了ActiveX可以用更高效的方法,就是使用 ActiveSelectionSet ,可以使用的格式如下:
代码: (if (ssget) (vlax-for i (vla-get-activeselectionset thisdrawing) ..... ) )
这里可以对比下XDAPI中的
xdrx_setsstodb 和 xdrx_getentdata 函数。
需要注意的是 activeselectionset 在某些情况下会出现
Count 属性失效,可以使用下面的函数在程序运行前消除此BUG
代码: (defun ea:ClearCSet (/ cur) (if (and (not (vl-catch-all-error-p (setq cur (vl-catch-all-apply 'vla-item (list (vla-get-selectionsets (vla-get-activedocument (vlax-get-acad-object)) ) "CURRENT" ) ) ) ) ) (vl-catch-all-error-p (vl-catch-all-apply 'vla-get-count (list cur) ) ) ) (vla-delete cur) ) (princ) )
由此完整的选择处理代码如下
代码: (ea:clearcset) (if (ssget) (vlax-for i (vla-get-activeselectionset thisdrawing) ...... ) )
| |
|
最后一个问题,在处理打断实体时,有一种情况是没有必要调用Break命令的,就是当交点是曲线的Startpoint或者Endpoint时,此时的判断条件是
代码: (not (or (equal (vlax-curve-getstartpoint i) x 0.001 ) (equal (vlax-curve-getendpoint i) x 0.001 ) ) )
至此程序就全部完成了,加上其他必要的设置代码如下:
(defun xcopyright
() (princ "\n\t☆☆☆晓东家园 [www . xdcad. net] 工具,作者:
eachy☆☆☆" ) (princ) ) (defun ea:ClearCSet (/ cur) (if (and (not (vl-catch-all-error-p
(setq cur
(vl-catch-all-apply
'vla-item (list
(vla-get-selectionsets
(vla-get-activedocument (vlax-get-acad-object))
) "CURRENT" )
) ) ) )
(vl-catch-all-error-p (vl-catch-all-apply
'vla-get-count
(list cur) ) )
) (vla-delete cur) ) (princ) ) (defun interss (ss / n1 ssl aobj1 aobj2 n2
ipts pts) (setq n1 0 ssl (sslength ss) ) (while (<
n1 (1- ssl)) (setq aobj1 (ssname ss n1) aobj1 (vlax-ename->vla-object aobj1) n2 (1+ n1) ) (while (<
n2 ssl) (setq aobj2 (ssname ss n2) aobj2 (vlax-ename->vla-object aobj2) ipts (vla-intersectwith
aobj1 aobj2 0
) ipts (vlax-variant-value ipts) ) (if (>
(vlax-safearray-get-u-bound ipts 1) 0) (progn (setq ipts
(vlax-safearray->list ipts) ) (while (>
(length ipts) 0) (setq pts (cons (list (car ipts) (cadr ipts) (caddr ipts) )
pts ) )
(setq ipts (cdddr ipts)) ) ) )
(setq n2 (1+ n2)) ) (setq n1 (1+ n1)) ) pts ) (defun c:BrkAll (/ filter ss pts pick thisdrawing
oldos) (xcopyright) (setq filter '((-4 . "<or")
(0 . "*polyline,arc,line") (-4 . "<and")
(0 . "spline") (-4 . "<not") (71 . 3)
(-4 . "not>") (-4 . "and>") (-4 .
"or>") ) ) (if (setq ss (ssget filter))
(progn (setq pts (interss ss)
pick (getvar "pickbox")
thisdrawing (vla-get-activedocument
(vlax-get-acad-object) )
oldos (getvar "osmode") ) (setvar "osmode" 0)
(vla-startundomark thisdrawing) (ea:clearcset)
(foreach x pts (if (ssget "_C"
(polar x (* -0.75 pi) (* 2. (expt (/ pick 2) 2)))
(polar x (* 0.45 pi) (* 2. (expt (/ pick 2) 2)))
filter ) (vlax-for i
(vla-get-activeselectionset thisdrawing) (if (not (or
(equal (vlax-curve-getstartpoint i) x
0.001 ) (equal
(vlax-curve-getendpoint i) x 0.001
) ) )
(vl-cmdf ".break" (list
(vlax-vla-object->ename i) x) "f" x
"@" ) ) ) )
) ) (setvar "osmode" oldos) (vla-endundomark
thisdrawing) ) (princ) ) (princ "\n\t【晓东家园 [www .
xdcad.net] 交点断开工具,作者:eachy】" ) (princ)
下一部分内容将是交点断开的改进算法部分,支持
circle ellipse
|
代码:
第二种方法
第一种方法是求得一堆交点,然后再对每个交点再次选择曲线进行断开,现在换一种思考
方式,同样是求交点,不过这次是将交点与曲线对应起来,形成这样一个表 A
((曲线1 (pt11 pt12 pt13 ...)
(曲线2 (pt21 pt22 pt23 ...)
...
(曲线i (pti1 pti2 pti3 ...)
)
有了这个表我们就可以针对不同的曲线实体采取不同的处理方法。
要求得上述的表还要对求交点的函数进行改造,下面是求表的思路
while 第n个曲线
while 第n+1个曲线
intersectwith n n+1 求交点
if 交点存在
while 交点表
if 表A
progn
检索是否有 n 实体
并且 pt 表中不存在此交点
将点加入 n 实体的 pt 表
检索是否有 n+1 实体
并且 pt 表中不存在此交点
将点加入 n 实体的 pt 表
不存在 A
构造 n 和 n+1 的字表
end if
end while
end if
end while
end while