立即注册 登录
晓东CAD家园-论坛 返回首页

eachy的个人空间 http://bbs.xdcad.net/?14 [收藏] [复制] [分享] [RSS]

日志

选择集曲线断开程序详解

已有 154 次阅读2013-5-6 17:44 |个人分类:Lisp

 

选择集曲线断开程序详解  

目的:对所选择的曲线实体在交点处均断开。

与此相关帖子
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命令断开曲线了



这里曲线要用点对的形式。

对单个曲线用上面的基本方法,现在是一些不确定的点的集合,而且在一个点处可能有数个曲线通过。如何将点和曲线对应起来呢?
这里可以用一个以点为中心的最小框再次选择曲线,然后调用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

路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-13 15:36 , Processed in 0.219237 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

返回顶部