To Find Self Intersection of LWPOLYLINE

To Find Self Intersection of LWPOLYLINE

MehtaRajesh
Advocate Advocate
12,112 Views
123 Replies
Message 1 of 124

To Find Self Intersection of LWPOLYLINE

MehtaRajesh
Advocate
Advocate

Hi,

I am posting useful function to find Self Intersection for selected LWPOLYLINE.
You might be having other options, but I find this one as a quickest and Simple


(defun IsSelfIntersect (l / vcnt vcnt1 crossresult pt1 pt2 pt3 pt4)
(setq vcnt 0)
(setq crossresult F)
(repeat (1- (length l))
 (setq pt1 (nth vcnt l))
   (setq pt2 (nth (1+ vcnt) l))
   (setq vcnt1 vcnt)
 (setq isdone "T")
 (while isdone
  (if (and (nth (+ 2 vcnt) l) (nth (+ 3 vcnt) l))
  (progn
   (setq pt3 (nth (+ 2 vcnt) l))
   (setq pt4 (nth (+ 3 vcnt) l))
       (if (inters pt1 pt2 pt3 pt4)
   (progn
      (setq crossresult T)
   );progn
   );if
  );progn
  (progn
   (setq isdone nil)
  );progn
  );if
    (setq vcnt (1+ vcnt))
 );while
   (setq vcnt (1+ vcnt1)) 
);repeat
crossresult
);defun

Below Function to get the Coordinate list of LWPOLYLINE

(defun lwptslw (lst / pair rtn)
  (while (setq pair (assoc 10 lst))
    (setq rtn (cons (cdr pair) rtn)
   lst (cdr (member pair lst))
    )
  )
  (reverse rtn)
)

USAGE:
Command: (IsSelfIntersect (LWPTSLW (ENTGET (CAR (ENTSEL "\nSelect Lwpolyline to find Self Intersectioni")))))

Regards,
Rajesh

0 Likes
12,113 Views
123 Replies
Replies (123)
Message 61 of 124

АлексЮстасу
Advisor
Advisor

@marko_ribar 

We have now chosen lisp to have little or no dependence on AutoCAD versions. We have a frustrating experience where excellent, necessary applications on ObjectArx can't be used because of versions.
I'm not sure if the problem with million coordinates is because of ‘intersectwith. This problem shows up in programs that don't use ‘intersectwith. And it may not show up when ‘intersectwith is used. I meant the general logic of codes.


The code with ‘while etc. can probably be sped up?


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes
Message 62 of 124

marko_ribar
Advisor
Advisor

@АлексЮстасу 

Here, try this version... But it also uses (while) loops and also intersectwith method... That's all I can think of...

(defun c:self-inters-overls ( / *error* unique selfintlst ent obj1 el obj2 sl lst )

  (or
    (not
      (vl-catch-all-error-p
        (vl-catch-all-apply
          (function vlax-get-acad-object) nil
        )
      )
    )
    (vl-load-com)
  )

  (defun *error* ( m )
    (if (and m (wcmatch (strcase m) "*EXIT*"))
      (princ)
      (if m
        (progn
          (prompt m)
          (princ)
        )
        (if lst
          (progn
            (prompt "\n")
            (read (vl-princ-to-string (unique lst 1e-6)))
          )
        )
      )
    )
  )

  (defun unique ( lst fuzz / a ll )
    (while (setq a (car lst))
      (if (vl-some (function (lambda ( x ) (equal x a fuzz))) (cdr lst))
        (setq ll (cons a ll) lst (vl-remove-if (function (lambda ( x ) (equal x a fuzz))) (cdr lst)))
        (setq ll (cons a ll) lst (cdr lst))
      )
    )
    (reverse ll)
  )

  (defun selfintlst ( obj1 obj2 / lst rtn )
    (setq lst
      (vlax-invoke
        (if (= (type obj1) (quote ename))
          (vlax-ename->vla-object obj1)
          obj1
        )
        (quote intersectwith)
        (if (= (type obj2) (quote ename))
          (vlax-ename->vla-object obj2)
          obj2
        )
        acextendnone
      )
    )
    (repeat (/ (length lst) 3)
      (setq rtn
        (cons
          (list (car lst) (cadr lst) (caddr lst))
          rtn
        )
      )
      (setq lst (cdddr lst))
    )
    (reverse rtn)
  )

  (if
    (and
      (setq ent (car (entsel "\nPick POLYLINE entity to get its self-intersecting-overlapping points...")))
      (wcmatch (cdr (assoc 0 (entget ent))) "*POLYLINE")
    )
    (if
      (not
        (vl-catch-all-error-p
          (vl-catch-all-apply
            (function vlax-curve-getstartpoint)
            (list ent)
          )
        )
      )
      (progn
        (setq obj1 (vlax-ename->vla-object ent))
        (setq el (entlast))
        (vla-explode obj1)
        (while (setq el (entnext el))
          (setq obj2 (vlax-ename->vla-object el))
          (setq sl (selfintlst obj1 obj2))
          (setq sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getstartpoint el) 1e-6))) sl)
                sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getendpoint el) 1e-6))) sl)
          )
          (if sl
            (setq lst (append sl lst))
          )
          (setq sl nil)
          (vl-catch-all-apply (function vla-delete) (list obj2))
        )
      )
      (progn
        (prompt "\nInvalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
        (exit)
      )
    )
    (prompt "\nMissed or Invalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
  )
  (*error* nil)
)

 

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 63 of 124

АлексЮстасу
Advisor
Advisor

@marko_ribar,

Oh! 🙂
First, really fast.
Second, finds almost all self-intersections.

 

In mill_pl.dwg, false result on the smaller polyline, many or almost all vertices are considered self-intersections.
In start_test_100-100_mr.dwg, I've circled in yellow what's not found.

 


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes
Message 64 of 124

bergerF5EFQ
Participant
Participant

@АлексЮстасу wrote:

The code with ‘while etc. can probably be sped up?


OK, performance of any code is always a good question. But WHILE is definitely not the problem. Probably you can modify the code to use MAPCAR and a LAMBDA instead, which should be a little faster, but the main performance problem is that Lisp is an interpreter language. As a rule of thumb Lisp code runs 10 times slower than C++/C# code, but the Lisp code can be developed 10 times faster than C++/C# code. Therefore still today Lisp is used as a prototype language.

 

But interestingly the Lisp interpreter in BricsCAD is much, much faster than that in AutoCAD. At least 10 times faster or more. I programmed CADCAL, a clone of the GeomCAL application in AutoCAD, and I wrote it only in Lisp. In BricsCAD CADCAL runs almost as fast as GeomCAL does in AutoCAD.

 

So if speed performance of Lisp applications is the question, BricsCAD is the solution. Cheers to Thorsten Moses, who made that!

 

Regards, Tom

 

 

 

Message 65 of 124

daniel_cadext
Advisor
Advisor

Here’s a C++ version for AutoCAD 2025 if you want to compare performance

https://www.theswamp.org/index.php?topic=59892.0

takes about 4 seconds to chomp though 800 or so of the mill_pl sample (altered the green so it’s not overlapping)

 

A new python version here

https://www.theswamp.org/index.php?topic=59870.msg622866#msg622866

python takes 20 seconds for the same test.  Python is almost as fast on a per case bases, but there’s a thread lock which is a bummer

 

interz.png

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 66 of 124

АлексЮстасу
Advisor
Advisor

@bergerF5EFQ,

I am a technologist, and the most important thing for me is to provide users and problem solving with reliable, efficient, productive tools.
If Autodesk bought B..., and made ObjectArx, C# programs independent of AutoCAD versions, I would be the staunchest supporter of both. 🙂


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes
Message 67 of 124

bergerF5EFQ
Participant
Participant

@АлексЮстасу wrote:

@bergerF5EFQ,

If Autodesk bought B...,

 I hope very much that this will never happen. If so, I am out of that business. Better the other way around and Br.... buys AutoCAD, this could be good for all of us.

 

As ever before you can today buy AutoCAD, and add all the Lisp and ARX applications which are on the market for AutoCAD.

And since BricsCAD is available, you can buy that and add all the Lisp and BRX applications which are on the market.

And if you are an application developer like me, you can write Lisp, C++ and C# programs and publish these for both markets.

 

What are you missing?

0 Likes
Message 68 of 124

АлексЮстасу
Advisor
Advisor

@daniel_cadext,

Your speed and solution are impressive!
... We don't have C programmers at the moment. And I don't know if we will have them in 3 years, in 5 years to adapt C codes for new versions.
We're using 2018 now, because the C programs we need only work in that version...

 

The maximum allowable time to solve a problem can be defined as a time comparable to the time of the AutoCAD commands themselves. For example, if AutoCAD creates a region from a polyline with 5000 vertices in 9-10 seconds, a program that finds self-intersections in 12-15 seconds in such a polyline is quite fast. (Others do it in 25 or 125 seconds, but they don't find all of them).
Now the latest version from @marko_ribar is very fast relative to other lisp, and does almost everything as it should.

 


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes
Message 69 of 124

marko_ribar
Advisor
Advisor

@АлексЮстасу 

I am sorry to bother you again, but it seems that my latest version fails to find intersection at example shown at picture...

 

self-inters-overls.png

So, to make it work in all situations, I am afraid that it must be much slower... Here is my latest code that passes this final test, but unfortunately it is very much slow... I don't know if Dan has something new, but like I said if striving for speed, then Python or ObjectARX, or .NET could be an answer... If you have BricsCAD, then maybe, this my code could be all that is needed...

(defun c:self-inters-overls ( / *error* unique isoobjs unisoobjs *lst* vertlst selfintlst ent cad vl obj1 el ss i e obj2 sl lst )

  (or
    (not
      (vl-catch-all-error-p
        (vl-catch-all-apply
          (function vlax-get-acad-object) nil
        )
      )
    )
    (vl-load-com)
  )

  (defun *error* ( m )
    (if (and m (wcmatch (strcase m) "*EXIT*"))
      (princ)
      (if m
        (progn
          (prompt m)
          (princ)
        )
        (if lst
          (progn
            (prompt "\nSelf-intersecting-overlapping points in WCS are : ")
            (prompt "\n")
            (read (vl-princ-to-string (unique lst 1e-6)))
          )
          (princ)
        )
      )
    )
  )

  (defun unique ( lst fuzz / a ll )
    (while (setq a (car lst))
      (if (vl-some (function (lambda ( x ) (equal x a fuzz))) (cdr lst))
        (setq ll (cons a ll) lst (vl-remove-if (function (lambda ( x ) (equal x a fuzz))) (cdr lst)))
        (setq ll (cons a ll) lst (cdr lst))
      )
    )
    (reverse ll)
  )

  (defun isoobjs ( s / ss i e enx )
    (setq ss (ssget "_X"))
    (repeat (setq i (sslength ss))
      (setq e (ssname ss (setq i (1- i))))
      (if (and (not (ssmemb e s)) (not (vl-position (cons 60 1) (setq enx (entget e)))))
        (progn
          (entupd (cdr (assoc -1 (entmod (append enx (list (cons 60 1)))))))
          (setq *lst* (cons e *lst*))
        )
      )
    )
  )

  (defun unisoobjs nil
    (if *lst*
      (foreach e *lst*
        (entupd (cdr (assoc -1 (entmod (subst (cons 60 0) (cons 60 1) (entget e))))))
      )
    )
  )

  (defun vertlst ( obj / e ent enx lst )
    (if (= (type obj) (quote vla-object))
      (setq ent (vlax-vla-object->ename obj))
      (setq ent obj)
    )
    (setq e ent)
    (cond
      ( (= (cdr (assoc 0 (setq enx (entget ent)))) "LWPOLYLINE")
        (mapcar
          (function
            (lambda ( p )
              (trans
                (append
                  (mapcar (function +) (list 0.0 0.0) p)
                  (list (cdr (assoc 38 enx)))
                )
                e
                0
              )
            )
          )
          (mapcar (function cdr)
            (vl-remove-if
              (function
                (lambda ( x )
                  (/= (car x) 10)
                )
              )
              enx
            )
          )
        )
      )
      ( (and (= (cdr (assoc 0 enx)) "POLYLINE") (or (= 8 (cdr (assoc 70 enx))) (= 9 (cdr (assoc 70 enx)))))
        (while (setq ent (entnext ent))
          (if (= (cdr (assoc 0 (setq enx (entget ent)))) "VERTEX")
            (setq lst
              (cons
                (cdr (assoc 10 enx))
                lst
              )
            )
          )
        )
        (reverse lst)
      )
      ( (= (cdr (assoc 0 enx)) "POLYLINE")
        (while (setq ent (entnext ent))
          (if (= (cdr (assoc 0 (setq enx (entget ent)))) "VERTEX")
            (setq lst
              (cons
                (cdr (assoc 10 enx))
                lst
              )
            )
          )
        )
        (mapcar
          (function
            (lambda ( p )
              (trans p e 0)
            )
          )
          (reverse lst)
        )
      )
    )
  )

  (defun selfintlst ( obj1 obj2 / lst rtn )
    (setq lst
      (vlax-invoke
        (if (= (type obj1) (quote ename))
          (vlax-ename->vla-object obj1)
          obj1
        )
        (quote intersectwith)
        (if (= (type obj2) (quote ename))
          (vlax-ename->vla-object obj2)
          obj2
        )
        acextendnone
      )
    )
    (repeat (/ (length lst) 3)
      (setq rtn
        (cons
          (list (car lst) (cadr lst) (caddr lst))
          rtn
        )
      )
      (setq lst (cdddr lst))
    )
    (reverse rtn)
  )

  (if
    (and
      (setq ent (car (entsel "\nPick POLYLINE entity to get its self-intersecting-overlapping points...")))
      (wcmatch (cdr (assoc 0 (entget ent))) "*POLYLINE")
    )
    (if
      (not
        (vl-catch-all-error-p
          (vl-catch-all-apply
            (function vlax-curve-getstartpoint)
            (list ent)
          )
        )
      )
      (progn
        (isoobjs (ssadd ent))
        (vla-zoomextents (setq cad (vlax-get-acad-object)))
        (setq vl (vertlst ent))
        (setq obj1 (vlax-ename->vla-object ent))
        (setq el (entlast))
        (vla-explode obj1)
        (foreach v vl
          (if (setq ss (ssget "_C" (trans v 0 1) (trans v 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
              )
            )
          )
          (if (and ss (> (sslength ss) 3))
            (setq lst (cons v lst))
          )
        )
        (while (wcmatch (cdr (assoc 0 (entget (entnext el)))) "VERTEX,SEQEND")
          (setq el (entnext el))
        )
        (while (setq el (entnext el))
          (setq obj2 (vlax-ename->vla-object el))
          (setq sl (vl-catch-all-apply (function selfintlst) (list obj1 obj2)))
          (if (and sl (not (vl-catch-all-error-p sl)))
            (progn
              (setq sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getstartpoint el) 1e-6))) sl)
                    sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getendpoint el) 1e-6))) sl)
              )
              (if sl
                (setq lst (append sl lst))
              )
              (setq sl nil)
            )
          )
          (vl-catch-all-apply (function vla-delete) (list obj2))
          (vlax-release-object obj2)
        )
        (if (and ent (vlax-erased-p ent))
          (entdel ent)
        )
        (vla-zoomprevious cad)
        (unisoobjs)
      )
      (progn
        (prompt "\nInvalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
        (exit)
      )
    )
    (prompt "\nMissed or Invalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
  )
  (*error* nil)
)

 

HTH.

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 70 of 124

Sea-Haven
Mentor
Mentor

My $0.05 is 2 minutes fast enough ? The task was to convert a dwg to company standards, when done manually can take 3 hours, I got 35 minutes 1st go down to 2, all done in lisp. There are 5 functions used involving thousands of objects. 

 

Are people asking to much ? Why does it take a minute ? Hey just do it manually. It also leads onto those who are prepared to pay and can see the value in your work in how much money they are saving per project.

Message 71 of 124

АлексЮстасу
Advisor
Advisor

@marko_ribar,

 

Maybe you didn't notice my message to you - #63?

 


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes
Message 72 of 124

marko_ribar
Advisor
Advisor

Just to inform... I changed my last code slightly - it should work well on all POLYLINE types including 3DPOLYLINE...

Regards, M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 73 of 124

marko_ribar
Advisor
Advisor

Hi there...

I think I finished with my latest code updates... There were several interventions since I informed that I changed code slightly, but now I can't figure at what situation it will fail... This means that that code is finally revisioned (lastly posted)... I had to add (vla-zoomextends cad) just after (isoobjs (ssadd ent)) and at end just before (unisoobjs), (vla-zoomprevious cad)... All this with zooming is because I used (ssget "_C" (trans v 0 1) (trans v 0 1)) - this needs much better precision when picking points with crossing... Still, I don't know if this will be enough with polylines with very dense vertices distributions, so please check zoomings with those polylines like 4000-5000 vertices, and if it fails, change (vla-zoomextends cad) to (vla-zoomcenter cad (vlax-3d-point v) scf)... (not sure with this last syntax, but I suppose that it'll be something like that...)

Regards, and stay well,

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 74 of 124

komondormrex
Mentor
Mentor

finds none for each of plines

komondormrex_0-1733858911611.png

 

0 Likes
Message 75 of 124

marko_ribar
Advisor
Advisor

I've totally removed (vertlst) sub function as there is no need for it after (vla-explode obj1)... All that's needed is to check selections around (vlax-curve-getstartpoint el) and (vlax-curve-getendpoint el)... Here is the code and I hope that that's all from me... Please, retest examples you have and they failed with my previous posted code...

(defun c:self-inters-overls ( / *error* unique isoobjs unisoobjs *lst1* *lst2* selfintlst ape ent cad obj1 el ss i e obj2 ellst ell sl lst )

  (or
    (not
      (vl-catch-all-error-p
        (vl-catch-all-apply
          (function vlax-get-acad-object) nil
        )
      )
    )
    (vl-load-com)
  )

  (defun *error* ( m )
    (if ape
      (setvar (quote aperture) ape)
    )
    (if (and m (wcmatch (strcase m) "*EXIT*"))
      (princ)
      (if m
        (progn
          (prompt m)
          (princ)
        )
        (if lst
          (progn
            (prompt "\nSelf-intersecting-overlapping points in WCS are : ")
            (prompt "\n")
            (read (vl-princ-to-string (unique lst 1e-6)))
          )
          (princ)
        )
      )
    )
  )

  (defun unique ( lst fuzz / a ll )
    (while (setq a (car lst))
      (if (vl-some (function (lambda ( x ) (equal x a fuzz))) (cdr lst))
        (setq ll (cons a ll) lst (vl-remove-if (function (lambda ( x ) (equal x a fuzz))) (cdr lst)))
        (setq ll (cons a ll) lst (cdr lst))
      )
    )
    (reverse ll)
  )

  (defun isoobjs ( s / ss i e enx rtn )
    (setq ss (ssget "_X"))
    (repeat (setq i (sslength ss))
      (setq e (ssname ss (setq i (1- i))))
      (if (and (not (ssmemb e s)) (not (vl-position (cons 60 1) (setq enx (entget e)))))
        (progn
          (entupd (cdr (assoc -1 (entmod (append enx (list (cons 60 1)))))))
          (setq rtn (cons e rtn))
        )
      )
    )
    rtn
  )

  (defun unisoobjs ( *lst* )
    (if *lst*
      (foreach e *lst*
        (entupd (cdr (assoc -1 (entmod (subst (cons 60 0) (cons 60 1) (entget e))))))
      )
    )
  )

  (defun selfintlst ( obj1 obj2 / lst rtn )
    (setq lst
      (vlax-invoke
        (if (= (type obj1) (quote ename))
          (vlax-ename->vla-object obj1)
          obj1
        )
        (quote intersectwith)
        (if (= (type obj2) (quote ename))
          (vlax-ename->vla-object obj2)
          obj2
        )
        acextendnone
      )
    )
    (repeat (/ (length lst) 3)
      (setq rtn
        (cons
          (list (car lst) (cadr lst) (caddr lst))
          rtn
        )
      )
      (setq lst (cdddr lst))
    )
    (reverse rtn)
  )

  (setq ape (getvar (quote aperture)))
  (setvar (quote aperture) 1)
  (if
    (and
      (setq ent (car (entsel "\nPick POLYLINE entity to get its self-intersecting-overlapping points...")))
      (wcmatch (cdr (assoc 0 (entget ent))) "*POLYLINE")
    )
    (if
      (not
        (vl-catch-all-error-p
          (vl-catch-all-apply
            (function vlax-curve-getstartpoint)
            (list ent)
          )
        )
      )
      (progn
        (setq *lst1* (isoobjs (ssadd ent)))
        (vla-zoomextents (setq cad (vlax-get-acad-object)))
        (setq obj1 (vlax-ename->vla-object ent))
        (setq el (entlast))
        (vla-explode obj1)
        (while (wcmatch (cdr (assoc 0 (entget (entnext el)))) "VERTEX,SEQEND")
          (setq el (entnext el))
        )
        (while (setq el (entnext el))
          (setq *lst2* (isoobjs (ssadd el)))
          (vla-zoomextents cad)
          (unisoobjs *lst2*)
          (if (setq ss (ssget "_C" (trans (vlax-curve-getstartpoint el) 0 1) (trans (vlax-curve-getstartpoint el) 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
                (if (not (eq e (vlax-vla-object->ename obj1)))
                  (setq ell (cons e ell))
                )
              )
            )
          )
          (if
            (and
              ss
              (or
                (> (sslength ss) 3)
                (and
                  (= (sslength ss) 3)
                  (vl-some
                    (function
                      (lambda ( x )
                        (and
                          (not (equal (vlax-curve-getstartpoint x) (vlax-curve-getstartpoint el) 1e-6))
                          (not (equal (vlax-curve-getendpoint x) (vlax-curve-getstartpoint el) 1e-6))
                        )
                      )
                    )
                    ell
                  )
                )
              )
            )
            (setq lst (cons (vlax-curve-getstartpoint el) lst))
          )
          (setq ell nil)
          (if (setq ss (ssget "_C" (trans (vlax-curve-getendpoint el) 0 1) (trans (vlax-curve-getendpoint el) 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
                (if (not (eq e (vlax-vla-object->ename obj1)))
                  (setq ell (cons e ell))
                )
              )
            )
          )
          (if
            (and
              ss
              (or
                (> (sslength ss) 3)
                (and
                  (= (sslength ss) 3)
                  (vl-some
                    (function
                      (lambda ( x )
                        (and
                          (not (equal (vlax-curve-getstartpoint x) (vlax-curve-getendpoint el) 1e-6))
                          (not (equal (vlax-curve-getendpoint x) (vlax-curve-getendpoint el) 1e-6))
                        )
                      )
                    )
                    ell
                  )
                )
              )
            )
            (setq lst (cons (vlax-curve-getendpoint el) lst))
          )
          (setq ell nil)
          (setq obj2 (vlax-ename->vla-object el))
          (setq sl (vl-catch-all-apply (function selfintlst) (list obj1 obj2)))
          (if (and sl (not (vl-catch-all-error-p sl)))
            (progn
              (setq sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getstartpoint el) 1e-6))) sl)
                    sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getendpoint el) 1e-6))) sl)
              )
              (if sl
                (setq lst (append sl lst))
              )
              (setq sl nil)
            )
          )
          (setq ellst (cons el ellst))
          (vla-zoomprevious cad)
        )
        (foreach el ellst
          (if (and el (not (vlax-erased-p el)))
            (entdel el)
          )
        )
        (vla-zoomprevious cad)
        (unisoobjs *lst1*)
      )
      (progn
        (prompt "\nInvalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
        (exit)
      )
    )
    (prompt "\nMissed... or invalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
  )
  (*error* nil)
)

 

HTH.

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 76 of 124

marko_ribar
Advisor
Advisor

I've changed my lastly posted code once again... I hope that now it'll find overlapping point like @komondormrex explained...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 77 of 124

АлексЮстасу
Advisor
Advisor

@marko_ribar,

 

Maybe it is enough to zooming for ssget only 1 time?

You are using the method already tried by Lee Mac - break the polyline into lines. His lisp on a polyline with 4600 vertices ran for over 7 minutes and I aborted the run.
Whereas your version in #62 ran for 12-14 seconds, and found almost everything, the last lisp I aborted at 14 minutes.


... We have come to where we started:
1. there is no lisp that finds all self-intersections and self-overlaps,
2. works fast - a few seconds even for polylines with thousands of vertices,

3. both closed and non-closed polylines,
4. it works without false results.
Including in coordinates in millions.
I.e. there was not and is not a full-fledged lisp solution ...


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes
Message 78 of 124

marko_ribar
Advisor
Advisor

@АлексЮстасу 

For correct results in coordinates in millions, I suggest that you temporarilly scale whole DWG from base WCS point 0,0 using scale factor 1e-8... Then when you get point(s), just multiply each point(s) coordinates with 1e+8 with using this syntax :

(mapcar (function (lambda ( x ) (mapcar (function (lambda ( y ) (* y 1e+8))) x))) pts), where pts is list of point(s) obtained from routine result... To make routine work faster, I removed all those zooms for which you stated as unneccessary, but I can't for sure guarantee that picking selection sets would perform correct - catching precisely only things crossing those start/end points of exploded entities, without selecting nearby other exploded things... So, here is my code - with just removed (zooms)...

(defun c:self-inters-overls ( / *error* unique isoobjs unisoobjs *lst* selfintlst ape ent cad obj1 el ss i e obj2 ellst ell sl lst )

  (or
    (not
      (vl-catch-all-error-p
        (vl-catch-all-apply
          (function vlax-get-acad-object) nil
        )
      )
    )
    (vl-load-com)
  )

  (defun *error* ( m )
    (if ape
      (setvar (quote aperture) ape)
    )
    (if (and m (wcmatch (strcase m) "*EXIT*"))
      (princ)
      (if m
        (progn
          (prompt m)
          (princ)
        )
        (if lst
          (progn
            (prompt "\nSelf-intersecting-overlapping points in WCS are : ")
            (prompt "\n")
            (read (vl-princ-to-string (unique lst 1e-6)))
          )
          (princ)
        )
      )
    )
  )

  (defun unique ( lst fuzz / a ll )
    (while (setq a (car lst))
      (if (vl-some (function (lambda ( x ) (equal x a fuzz))) (cdr lst))
        (setq ll (cons a ll) lst (vl-remove-if (function (lambda ( x ) (equal x a fuzz))) (cdr lst)))
        (setq ll (cons a ll) lst (cdr lst))
      )
    )
    (reverse ll)
  )

  (defun isoobjs ( s / ss i e enx rtn )
    (setq ss (ssget "_X"))
    (repeat (setq i (sslength ss))
      (setq e (ssname ss (setq i (1- i))))
      (if (and (not (ssmemb e s)) (not (vl-position (cons 60 1) (setq enx (entget e)))))
        (progn
          (entupd (cdr (assoc -1 (entmod (append enx (list (cons 60 1)))))))
          (setq rtn (cons e rtn))
        )
      )
    )
    rtn
  )

  (defun unisoobjs ( *lst* )
    (if *lst*
      (foreach e *lst*
        (entupd (cdr (assoc -1 (entmod (subst (cons 60 0) (cons 60 1) (entget e))))))
      )
    )
  )

  (defun selfintlst ( obj1 obj2 / lst rtn )
    (setq lst
      (vlax-invoke
        (if (= (type obj1) (quote ename))
          (vlax-ename->vla-object obj1)
          obj1
        )
        (quote intersectwith)
        (if (= (type obj2) (quote ename))
          (vlax-ename->vla-object obj2)
          obj2
        )
        acextendnone
      )
    )
    (repeat (/ (length lst) 3)
      (setq rtn
        (cons
          (list (car lst) (cadr lst) (caddr lst))
          rtn
        )
      )
      (setq lst (cdddr lst))
    )
    (reverse rtn)
  )

  (setq ape (getvar (quote aperture)))
  (setvar (quote aperture) 1)
  (if
    (and
      (setq ent (car (entsel "\nPick POLYLINE entity to get its self-intersecting-overlapping points...")))
      (wcmatch (cdr (assoc 0 (entget ent))) "*POLYLINE")
    )
    (if
      (not
        (vl-catch-all-error-p
          (vl-catch-all-apply
            (function vlax-curve-getstartpoint)
            (list ent)
          )
        )
      )
      (progn
        (setq *lst* (isoobjs (ssadd ent)))
        (vla-zoomextents (setq cad (vlax-get-acad-object)))
        (setq obj1 (vlax-ename->vla-object ent))
        (setq el (entlast))
        (vla-explode obj1)
        (while (wcmatch (cdr (assoc 0 (entget (entnext el)))) "VERTEX,SEQEND")
          (setq el (entnext el))
        )
        (while (setq el (entnext el))
          (if (setq ss (ssget "_C" (trans (vlax-curve-getstartpoint el) 0 1) (trans (vlax-curve-getstartpoint el) 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
                (if (not (eq e (vlax-vla-object->ename obj1)))
                  (setq ell (cons e ell))
                )
              )
            )
          )
          (if
            (and
              ss
              (or
                (> (sslength ss) 3)
                (and
                  (= (sslength ss) 3)
                  (vl-some
                    (function
                      (lambda ( x )
                        (and
                          (not (equal (vlax-curve-getstartpoint x) (vlax-curve-getstartpoint el) 1e-6))
                          (not (equal (vlax-curve-getendpoint x) (vlax-curve-getstartpoint el) 1e-6))
                        )
                      )
                    )
                    ell
                  )
                )
              )
            )
            (setq lst (cons (vlax-curve-getstartpoint el) lst))
          )
          (setq ell nil)
          (if (setq ss (ssget "_C" (trans (vlax-curve-getendpoint el) 0 1) (trans (vlax-curve-getendpoint el) 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
                (if (not (eq e (vlax-vla-object->ename obj1)))
                  (setq ell (cons e ell))
                )
              )
            )
          )
          (if
            (and
              ss
              (or
                (> (sslength ss) 3)
                (and
                  (= (sslength ss) 3)
                  (vl-some
                    (function
                      (lambda ( x )
                        (and
                          (not (equal (vlax-curve-getstartpoint x) (vlax-curve-getendpoint el) 1e-6))
                          (not (equal (vlax-curve-getendpoint x) (vlax-curve-getendpoint el) 1e-6))
                        )
                      )
                    )
                    ell
                  )
                )
              )
            )
            (setq lst (cons (vlax-curve-getendpoint el) lst))
          )
          (setq ell nil)
          (setq obj2 (vlax-ename->vla-object el))
          (setq sl (vl-catch-all-apply (function selfintlst) (list obj1 obj2)))
          (if (and sl (not (vl-catch-all-error-p sl)))
            (progn
              (setq sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getstartpoint el) 1e-6))) sl)
                    sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getendpoint el) 1e-6))) sl)
              )
              (if sl
                (setq lst (append sl lst))
              )
              (setq sl nil)
            )
          )
          (setq ellst (cons el ellst))
        )
        (foreach el ellst
          (if (and el (not (vlax-erased-p el)))
            (entdel el)
          )
        )
        (vla-zoomprevious cad)
        (unisoobjs *lst*)
      )
      (progn
        (prompt "\nInvalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
        (exit)
      )
    )
    (prompt "\nMissed... or invalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
  )
  (*error* nil)
)

 

HTH.

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 79 of 124

marko_ribar
Advisor
Advisor

@АлексЮстасу 

Can you report, if this quick fix works for far away polylines that are with coordinates in millions units... Here is my code for you to test...

(defun c:self-inters-overls-millions ( / *error* unique isoobjs unisoobjs *lst* selfintlst cmd ape ucsf ent cad obj1 el ss i e obj2 ellst ell sl lst sp ti )

  (or
    (not
      (vl-catch-all-error-p
        (vl-catch-all-apply
          (function vlax-get-acad-object) nil
        )
      )
    )
    (vl-load-com)
  )

  (defun *error* ( m )
    (if ucsf
      (if command-s
        (command-s "_.ucs" "_p")
        (vl-cmdf "_.ucs" "_p")
      )
    )
    (if ape
      (setvar (quote aperture) ape)
    )
    (if cmd
      (setvar (quote cmdecho) cmd)
    )
    (if (and m (wcmatch (strcase m) "*EXIT*"))
      (princ)
      (progn
        (prompt "\nElapsed time : ") (princ (rtos (- (car (_vl-times)) ti) 2 16)) (prompt " milliseconds...")
        (if m
          (progn
            (if lst
              (progn
                (prompt "\nSelf-intersecting-overlapping points in WCS are : ")
                (prompt "\n")
                (setq lst (mapcar (function (lambda ( x ) (mapcar (function +) sp x))) (unique lst 1e-6)))
                (setq lst (mapcar (function (lambda ( x ) (mapcar (function (lambda ( y ) (* y 1e+6))) x))) lst))
                (read (vl-princ-to-string lst))
              )
            )
            (prompt m)
            (princ)
          )
          (if lst
            (progn
              (prompt "\nSelf-intersecting-overlapping points in WCS are : ")
              (prompt "\n")
              (setq lst (mapcar (function (lambda ( x ) (mapcar (function +) sp x))) (unique lst 1e-6)))
              (setq lst (mapcar (function (lambda ( x ) (mapcar (function (lambda ( y ) (* y 1e+6))) x))) lst))
              (read (vl-princ-to-string lst))
            )
            (princ)
          )
        )
      )
    )
  )

  (defun unique ( lst fuzz / a ll )
    (while (setq a (car lst))
      (if (vl-some (function (lambda ( x ) (equal x a fuzz))) (cdr lst))
        (setq ll (cons a ll) lst (vl-remove-if (function (lambda ( x ) (equal x a fuzz))) (cdr lst)))
        (setq ll (cons a ll) lst (cdr lst))
      )
    )
    (reverse ll)
  )

  (defun isoobjs ( s / ss i e enx rtn )
    (setq ss (ssget "_X"))
    (repeat (setq i (sslength ss))
      (setq e (ssname ss (setq i (1- i))))
      (if (and (not (ssmemb e s)) (not (vl-position (cons 60 1) (setq enx (entget e)))))
        (progn
          (entupd (cdr (assoc -1 (entmod (append enx (list (cons 60 1)))))))
          (setq rtn (cons e rtn))
        )
      )
    )
    rtn
  )

  (defun unisoobjs ( *lst* )
    (if *lst*
      (foreach e *lst*
        (entupd (cdr (assoc -1 (entmod (subst (cons 60 0) (cons 60 1) (entget e))))))
      )
    )
  )

  (defun selfintlst ( obj1 obj2 / lst rtn )
    (setq lst
      (vlax-invoke
        (if (= (type obj1) (quote ename))
          (vlax-ename->vla-object obj1)
          obj1
        )
        (quote intersectwith)
        (if (= (type obj2) (quote ename))
          (vlax-ename->vla-object obj2)
          obj2
        )
        acextendnone
      )
    )
    (repeat (/ (length lst) 3)
      (setq rtn
        (cons
          (list (car lst) (cadr lst) (caddr lst))
          rtn
        )
      )
      (setq lst (cdddr lst))
    )
    (reverse rtn)
  )

  (setq cmd (getvar (quote cmdecho)))
  (setvar (quote cmdecho) 0)
  (setq ape (getvar (quote aperture)))
  (setvar (quote aperture) 1)
  (if (= 0 (getvar (quote worlducs)))
    (progn
      (vl-cmdf "_.ucs" "_w")
      (setq ucsf t)
    )
  )
  (if
    (and
      (setq ent (car (entsel "\nPick POLYLINE entity to get its self-intersecting-overlapping points...")))
      (wcmatch (cdr (assoc 0 (entget ent))) "*POLYLINE")
    )
    (if
      (not
        (vl-catch-all-error-p
          (vl-catch-all-apply
            (function vlax-curve-getstartpoint)
            (list ent)
          )
        )
      )
      (progn
        (setq ti (car (_vl-times)))
        (vl-cmdf "_.scale" ent "" "_non" (list 0.0 0.0 0.0) 1e-6)
        (vl-cmdf "_.move" ent "" "_non" (setq sp (vlax-curve-getstartpoint ent)) "_non" (list 0.0 0.0 0.0))
        (setq *lst* (isoobjs (ssadd ent)))
        (vla-zoomextents (setq cad (vlax-get-acad-object)))
        (setq obj1 (vlax-ename->vla-object ent))
        (setq el (entlast))
        (vla-explode obj1)
        (while (wcmatch (cdr (assoc 0 (entget (entnext el)))) "VERTEX,SEQEND")
          (setq el (entnext el))
        )
        (while (setq el (entnext el))
          (if (setq ss (ssget "_C" (trans (vlax-curve-getstartpoint el) 0 1) (trans (vlax-curve-getstartpoint el) 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
                (if (not (eq e (vlax-vla-object->ename obj1)))
                  (setq ell (cons e ell))
                )
              )
            )
          )
          (if
            (and
              ss
              (or
                (> (sslength ss) 3)
                (and
                  (= (sslength ss) 3)
                  (vl-some
                    (function
                      (lambda ( x )
                        (and
                          (not (equal (vlax-curve-getstartpoint x) (vlax-curve-getstartpoint el) 1e-6))
                          (not (equal (vlax-curve-getendpoint x) (vlax-curve-getstartpoint el) 1e-6))
                        )
                      )
                    )
                    ell
                  )
                )
              )
            )
            (setq lst (cons (vlax-curve-getstartpoint el) lst))
          )
          (setq ell nil)
          (if (setq ss (ssget "_C" (trans (vlax-curve-getendpoint el) 0 1) (trans (vlax-curve-getendpoint el) 0 1)))
            (repeat (setq i (sslength ss))
              (setq e (ssname ss (setq i (1- i))))
              (if (= (cdr (assoc 0 (entget e))) "VERTEX")
                (ssdel e ss)
                (if (not (eq e (vlax-vla-object->ename obj1)))
                  (setq ell (cons e ell))
                )
              )
            )
          )
          (if
            (and
              ss
              (or
                (> (sslength ss) 3)
                (and
                  (= (sslength ss) 3)
                  (vl-some
                    (function
                      (lambda ( x )
                        (and
                          (not (equal (vlax-curve-getstartpoint x) (vlax-curve-getendpoint el) 1e-6))
                          (not (equal (vlax-curve-getendpoint x) (vlax-curve-getendpoint el) 1e-6))
                        )
                      )
                    )
                    ell
                  )
                )
              )
            )
            (setq lst (cons (vlax-curve-getendpoint el) lst))
          )
          (setq ell nil)
          (setq obj2 (vlax-ename->vla-object el))
          (setq sl (vl-catch-all-apply (function selfintlst) (list obj1 obj2)))
          (if (and sl (not (vl-catch-all-error-p sl)))
            (progn
              (setq sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getstartpoint el) 1e-6))) sl)
                    sl (vl-remove-if (function (lambda ( x ) (equal x (vlax-curve-getendpoint el) 1e-6))) sl)
              )
              (if sl
                (setq lst (append sl lst))
              )
              (setq sl nil)
            )
          )
          (setq ellst (cons el ellst))
        )
        (foreach el ellst
          (if (and el (not (vlax-erased-p el)))
            (entdel el)
          )
        )
        (vla-zoomprevious cad)
        (vl-cmdf "_.move" ent "" "_non" (list 0.0 0.0 0.0) "_non" sp)
        (vl-cmdf "_.scale" ent "" "_non" (list 0.0 0.0 0.0) 1e+6)
        (unisoobjs *lst*)
      )
      (progn
        (prompt "\nInvalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
        (exit)
      )
    )
    (prompt "\nMissed... or invalid entity pick... Picked entity must be POLYLINE... Better luck next time...")
  )
  (*error* nil)
)

 

HTH.

M.R.

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 80 of 124

АлексЮстасу
Advisor
Advisor

@marko_ribar,

Yeah, it's working. But instead of two intersection points, it gives one. And it doesn't find overlaps.
Like the previous one, it checks for about 1 minute.
Why did you use Scale? And not Move?

Both this option and the previous ones for many cases of self-overlapping and touching do not give any messages.

no_messages.png

I have attached an example with million coordinates earlier. I am attaching it here as well.


-- Alexander, private person, pacifist, english only with translator 🙂 --

Object-modeling _ odclass-odedit.com _ Help

0 Likes