ysq101 发表于 2017-10-19 23:08:04

求大师帮忙看一下 关于PL线 "凹位"的判断

本帖最后由 ysq101 于 2017-10-19 23:24 编辑



如上图...帮忙写个可以判断有这类多线段的LISP    找到后将它们全部改为红色只要有一处凹位就直接改成红色

谢谢大师


yshf 发表于 2017-10-20 10:09:48

本帖最后由 Gu_xl 于 2017-10-20 11:14 编辑

;请试用以下程序(未判断多段线是否是闭合多边形)
(defun c:test()
    (vl-load-com)
    (setq cm (getvar "cmdecho"))
    (setvar"cmdecho" 0)
    (command "_undo" "be")

    (if (setq ssa (ssget '((0 . "*POLYLINE"))))
      (progn
             (setq m (sslength ssa) j 0)
             (repeat m
                  (setq obj(vlax-ename->vla-object (ssname ssa j))
                        pts(vlax-get obj "Coordinates")
                        name (vlax-get obj "ObjectName")
                        ptbnil
                  )
            
                  (while pts
                      (if (= name "AcDb3dPolyline")
                        (setq ptb (cons (list (car pts) (cadr pts) (caddr pts)) ptb)
                              pts (cdr (cdr (cdr pts)))
                        )
                        (setq ptb (cons (list (car pts) (cadr pts)) ptb)
                              pts (cdr (cdr pts))
                        )
                      )
                  )
               
                  (if (equal (car ptb) (last ptb) 1e-3)
                      (setq ptb (cdr ptb))
                  )
                  (setq n (1- (length ptb)) i 0slcj nil)

                  (while (<= i n)
                     (if (= i 0)
                           (setq p1 (last ptb))
                           (setq p1 (nth (1- i) ptb))
                     )
                     (setq p2 (nth i ptb))
                     (if (= i n)
                           (setq p3 (car ptb))
                           (setq p3 (nth (1+ i) ptb))
                     )
                     (setq cj (car (trans (mapcar '- p1 p2) 1 (mapcar '- p3 p2)))
                           slcj (cons cj slcj)
                     )
                     
                     (if (not (or (vl-every '(lambda(x)(> x 0.0)) slcj)
                                    (vl-every '(lambda(x)(< x 0.0)) slcj)
                              )
                           )
                           (progn
                               (vlax-put obj "color" "1")
                               (setq i n)
                           )
                      )
                      (setq i (1+ i))
                   )
                  

                  (setq j (1+ j))
             )
      )
    )

    (command "_undo" "e")
    (setvar "cmdecho" cm)
    (princ)
)

llsheng_73 发表于 2017-10-20 11:14:43

本帖最后由 llsheng_73 于 2017-10-20 15:04 编辑

对于封闭多段线,只要是凹点,那么该点及相邻两点组成的三角形的方向必然与该多段线整体方向相反
(defun plxyz(e fuz / i p pt);多段线节点三维坐标,连续重合点只取一个,根据fuz阀值过滤接近点
(setq i(-(vlax-curve-getendparam e)(logand(cdr(assoc 70(entget e)))1)-1))
(while(setq i(1- i)p(vlax-curve-getpointatparam e i))
    (setq pt(if(equal(car pt)p fuz)pt(cons p pt))))
)
(defun 2area(pt)
(apply'+(mapcar'(lambda(x y)(-(*(car x)(cadr y))(*(car y)(cadr x))))(cons(last pt)pt)pt)))
(defun pldir(e / p p1 p2);;e多段线图元或者对象
(vla-GetBoundingBox(if(=(type e)'ename)(vlax-ename->vla-object e)e)'p1'p2)
(mapcar'set'(p1 p2)(mapcar'vlax-safearray->list(list p1 p2)))
(2area(Mapcar'cdr(vl-sort(mapcar'(lambda(x)(setq p(vlax-curve-getclosestpointto e x))
                                          (cons(vlax-curve-getparamatpoint e p)p))
                                       (list(list(car p1)(cadr p2))p1(list(car p2)(cadr p1))p2))
                                  '(lambda(x y)(<(car x)(car y)))))))
(defun Pitpl(e / a p)
(setq p(plxyz e 0)
      a(pldir e))
(vl-some'(lambda(x y z)(<(*(2area(list x y z))a)0))(cons(last p)p)p(cdr(append p(list(car p)))))
)
(defun c:tt(/ s)
(if(setq s(ssget'((0 . "lwpolyline")(-4 . "&")(70 . 1))))
    (foreach x(vl-remove'nil(mapcar'(lambda(x)(if(=(type(cadr x))'ename)(cadr x)))(ssnamex s)))
      (if(Pitpl x)
      (entmod(setq x(entget x)x(if(assoc 62 x)(subst'(62 . 1)(assoc 62 x)x)(append x'((62 . 1))))))))))

其实还有更简单的办法,凹点内角大于必定大于180,如果用angle来计算两条相邻边的角度后相减来得到内角,实际上是比较烦的。好在(n-1),n,(n+1)这样连续三点的内角可以把(n+1)转换到到n(n-1)直线,根据得到的坐标的来判断是否大于180,当然,这个判断的条件实际上也会因为点的方向不一样而完全相反,
(defun plinexy(e)
(mapcar'cdr(vl-remove-if'(lambda(x)(/=(car x)10))(entget e))))
(defun 2area(pt / a)
(setq a(apply'+(mapcar'(lambda(x y)(-(*(car x)(cadr y))(*(car y)(cadr x))))(cons(last pt)pt)pt))a(/ a(abs a))))
(defun pitang(p p1 p2 a);;角p2 p1 p不大于180,a为给定方向
(<(*(car(trans(mapcar'- p1 p) 0 (mapcar'- p1 p2)))a)0))
(defun pitpl(e / p a)
(setq p(plinexy e)
a(2area p)
p(vl-some'(lambda(x y z)(pitang x y z a))(cons(last p)p)p(cdr(append p(list(car p)))))))
(defun c:tt(/ s)
(if(setq s(ssget'((0 . "lwpolyline")(-4 . "&")(70 . 1))))
    (foreach x(vl-remove'nil(mapcar'(lambda(x)(if(=(type(cadr x))'ename)(cadr x)))(ssnamex s)))
      (if(Pitpl x)
(entmod(setq x(entget x)x(if(assoc 62 x)(subst'(62 . 1)(assoc 62 x)x)(append x'((62 . 1))))))))))

lijiao 发表于 2017-10-20 10:42:50

本帖最后由 lijiao 于 2017-10-20 15:23 编辑

(defun c:aopl (/ I SS)
(if (setq ss (ssget '((0 . "LWPOLYLINE") (70 . 1))))
    (progn
      (setq i -1)
      (repeat (sslength ss)
      (ao-p (ssname ss (setq i (1+ i))))
      )
    )
)
(princ)
)
(defun ao-p (pl / DATA PTS PTS1 PTS2 Y ZXS ZX)
(setq data (entget pl))
(setq pts (VL-REMOVE-IF-NOT '(lambda (y) (= (car y) 10)) data))
(setq pts (mapcar 'cdr pts))
(setq pts1 (cdr (append pts (list (car pts)))))
(setq pts2 (cdr (append pts1 (list (car pts1)))))
(setq pts (mapcar 'list pts pts1 pts2))
(setq      pts (mapcar '(lambda (y)
                     (cons 'z y)
                     )
                  pts
            )
)
(setq zxs (mapcar 'shiliang pts))(setq zx (car zxs))
(setq zxs (VL-REMOVE-IF-NOT '(lambda (y) (= y zx)) zxs))
(if zxs
    (progn
      (if (assoc 62 data)
      (setq data (subst '(62 . 1) (assoc 62 data) data))
      (setq data (append data '((62 . 1))))
      )
      (entmod data)
      t
    )
)
)
(defun shiliang      (lst / CJ X1 X2 Y1 Y2)
(cond
    ((member (car lst) '(+ -))
   (apply 'mapcar lst)
    )
    ((= (car lst) 'x)
   (mapcar 'set '(x1 y1) (cadr lst))
   (mapcar 'set '(x2 y2) (caddr lst))
   (- (* x1 y2) (* x2 y1))
    )
    ((= (car lst) 'z)
   (setq cj (shiliang
                (list 'x
                      (shiliang (list '- (caddr lst) (cadr lst)))
                      (shiliang (list '- (cadddr lst) (cadr lst)))
                )
            )
   )
   (cond
       ((equal cj 0.0 0.0001) 0)
       ((> cj 0.0) 1)
       ((< cj 0.0) -1)
   )
    )
)
)

水吉空 发表于 2017-10-19 23:15:21

定制开发请去定制区。提问题起码要给个悬赏吧,什么都没有谁给你写?

ysq101 发表于 2017-10-19 23:22:49

本帖最后由 ysq101 于 2017-10-19 23:27 编辑

水吉空 发表于 2017-10-19 23:15
定制开发请去定制区。提问题起码要给个悬赏吧,什么都没有谁给你写?
我错了............其实我一开始忘了点悬赏   明经币我还是有很多的太久没写LISP...
现在都像个大傻瓜一样...连LISP不读不懂了

ysq101 发表于 2017-10-20 11:13:23

yshf 发表于 2017-10-20 10:09


这算法。。。好像是用点来   “硬算”

ysq101 发表于 2017-10-20 11:17:06

lijiao 发表于 2017-10-20 10:42




实测程序出错了。。。左下角一个没有凹位

自贡黄明儒 发表于 2017-10-20 12:02:22

llsheng_73 发表于 2017-10-20 11:14
对于封闭多段线,只要是凹点,那么该点及相邻两点组成的三角形的方向必然与该多段线整体方向相反

旋向有正有反就可以判断了吧,是不是不用判断整个旋向?

llsheng_73 发表于 2017-10-20 13:45:34

本帖最后由 llsheng_73 于 2017-10-20 15:21 编辑

自贡黄明儒 发表于 2017-10-20 12:02
旋向有正有反就可以判断了吧,是不是不用判断整个旋向?
整个多段线方向并不需要这条多段的所有点参与计算,实际上只需要取出四个点(其外接正矩形的四个角点到该多段线的最近点)按param排序就行
跟依次取三角形来计算旋向,直到乘积小于0或者所有三角形计算完再看乘积来判断有无凹点,应该区别不大
直接找出大于180的内角更简单也容易理解。。
(defun plinexy(e)
(mapcar'cdr(vl-remove-if'(lambda(x)(/=(car x)10))(entget e))))
(defun ptdir(pt / a);;
(if(zerop(setq a(apply'+(mapcar'(lambda(x y)(-(*(car x)(cadr y))(*(car y)(cadr x))))(cons(last pt)pt)pt))))
    0(/ a(abs a))))
(defun pitang(p p1 p2 a);;角p2 p1 p不大于180,a为给定方向
(<(*(car(trans(mapcar'- p1 p) 0 (mapcar'- p1 p2)))a)0))
(defun pitpl(e / p a);;e是否有凹点
(setq p(plinexy e)
a(ptdir p)
p(vl-some'(lambda(x y z)(pitang x y z a))(cons(last p)p)p(cdr(append p(list(car p)))))))
(defun pits(e / p a);;e的所有凹点
(setq p(plinexy e)
a(ptdir p)
p(vl-remove'nil(mapcar'(lambda(x y z)(if(pitang x y z a)y))(cons(last p)p)p(cdr(append p(list(car p))))))))
(defun c:tt(/ s);;有凹点的多段线变红
(if(setq s(ssget'((0 . "lwpolyline")(-4 . "&")(70 . 1))))
    (foreach x(vl-remove'nil(mapcar'(lambda(x)(if(=(type(cadr x))'ename)(cadr x)))(ssnamex s)))
      (if(Pitpl x)
(entmod(setq x(entget x)x(if(assoc 62 x)(subst'(62 . 1)(assoc 62 x)x)(append x'((62 . 1))))))))))
(defun c:t1(/ s p);;凹点处画圆
(if(setq s(ssget'((0 . "lwpolyline")(-4 . "&")(70 . 1))))
    (foreach x(vl-remove'nil(mapcar'(lambda(x)(if(=(type(cadr x))'ename)(cadr x)))(ssnamex s)))
      (foreach i(pits x)
(entmakex(mapcar'cons'(0 10 40 62)(list"circle"i 1 2)))))))

页: [1] 2
查看完整版本: 求大师帮忙看一下 关于PL线 "凹位"的判断