Author Topic: Point is Inside polyline (Now with Bulges)  (Read 22808 times)

0 Members and 1 Guest are viewing this topic.

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #45 on: April 29, 2015, 11:21:43 AM »
Ronjomp,

Looks better!!, did a fast benchmark on that entity.

Quote
benchmark '((approxpoly en 0.001) (tracepline en 0.11765)))
Benchmarking .....Elapsed milliseconds / relative speed for 4 iteration(s):

    (TRACEPLINE EN 0.11765).....1466 / 1.10 <fastest>
    (APPROXPOLY EN 0.001).......1606 / 1.00 <slowest>

Only difficulty is the angular parameter.

ymg

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #46 on: April 30, 2015, 05:47:31 AM »
Here's another way to skin the cat.

          A Winding Number and Point-in-Polygon Algoritm                 
               by  David G. Alciatore and Rick Miranda                     
     http://www.engr.colostate.edu/~dga/dga/papers/point_in_polygon.pdf   

This is again the winding number algorithm.
But instead of doing the onleft cross product
test, we translate the point of the polyline
to point p as origin of the coordinate system.
We then proceed to count how many times
the y coordinates cross the positive x axis.

One interesting note about the winding number
algorithm is that the sign of the wn also gives
you the direction the polyline is drawn. Negative
wn is ccw and vice-versa.

Code - Auto/Visual Lisp: [Select]
  1. ;;                                                                            ;
  2. ;; inside_p     by   ymg                                                      ;
  3. ;;                                                                            ;
  4. ;;           A Winding umber and Point-in-Polygon Algoritm                    ;
  5. ;;              by  David G. Alciatore and Rick Miranda                       ;
  6. ;;     http://www.engr.colostate.edu/~dga/dga/papers/point_in_polygon.pdf     ;
  7. ;;                                                                            ;
  8. ;; Here instead of onleft cross product test, we translate the polyline       ;
  9. ;; to the point.  We then count the crossing of the y coordinates above       ;
  10. ;; zero.                                                                      ;
  11. ;;                                                                            ;
  12. ;;       (Under Test)                                                         ;
  13. ;;                                                                            ;
  14.  
  15. (defun inside_p (p l)
  16.    (setq w 0
  17.           xp (car p)          yp (cadr p)
  18.           x1 (- (caar l) xp)  y1 (- (cadar l) yp)
  19.    )
  20.    (foreach a (cdr l)
  21.       (setq x2 (- (car  a) xp)  y2 (- (cadr a) yp))
  22.       (cond
  23.          ((< (* y1 y2) 0)  (if (> (+ x1 (* y1 (/ (- x2 x1) (- y1 y2)))) 0)
  24.                                  (if (minusp y1) (setq w (1+ w)) (setq w (1- w)))
  25.                            ))
  26.          ((and (zerop  y1) (>  x1 0)) (if (>  y2   0) (setq w (+ w 0.5)) (setq w (- w 0.5))))
  27.          ((and (zerop  y2) (>  x2 0)) (if (minusp y1) (setq w (+ w 0.5)) (setq w (- w 0.5))))
  28.       )
  29.       (setq x1 x2  y1 y2)  
  30.    )
  31.    (not (zerop w))
  32. )
  33.  

ymg
« Last Edit: May 02, 2015, 04:47:04 PM by ymg »

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Point is Inside polyline (Now with Bulges)
« Reply #47 on: April 30, 2015, 09:43:26 AM »
Looks like inside_p does not work as well.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #48 on: April 30, 2015, 10:46:31 AM »
Ronjomp,

I'll check it, but the concept is sound.

By the way I like your illustration and poly a lot!!!

ymg

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Point is Inside polyline (Now with Bulges)
« Reply #49 on: April 30, 2015, 10:48:26 AM »
...

By the way I like your illustration and poly a lot!!!

ymg
:)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #50 on: May 02, 2015, 04:39:58 PM »
ronjomp,

Don't know what happen with your last test, but I did re-test isinside_p and my results are OK.

Maybe you were missing the last repeating point in your poly.

Don't know if you had time to read Alciatore's paper but in it
the Update Criterion for w the winding number are as follow:

Code - Auto/Visual Lisp: [Select]
  1. ;;                                                                            ;
  2. ;; inside_p     by   ymg                                                      ;
  3. ;;                                                                            ;
  4. ;;           A Winding umber and Point-in-Polygon Algoritm                    ;
  5. ;;              by  David G. Alciatore and Rick Miranda                       ;
  6. ;;     http://www.engr.colostate.edu/~dga/dga/papers/point_in_polygon.pdf     ;
  7. ;;                                                                            ;
  8. ;; Here instead of onleft cross product test, we translate the polyline       ;
  9. ;; to the point.  We then count the crossing of the y coordinates above       ;
  10. ;; zero.                                                                      ;
  11. ;;                                                                            ;
  12. ;;                                                                            ;
  13.  
  14. (defun inside_p (p l / w x1 x2 xp y1 y2 yp)
  15.    (setq w 0
  16.          xp (car p)          yp (cadr p)
  17.          x1 (- (caar l) xp)  y1 (- (cadar l) yp)
  18.    )
  19.    (foreach a (cdr l)
  20.       (setq x2 (- (car  a) xp)  y2 (- (cadr a) yp))
  21.       (cond
  22.          ((< (* y1 y2) 0)  (if (> (+ x1 (* y1 (/ (- x2 x1) (- y1 y2)))) 0)
  23.                                  (if (minusp y1) (setq w (1+ w)) (setq w (1- w)))
  24.                            ))
  25.          ((and (zerop  y1) (>  x1 0)) (if (>  y2   0) (setq w (+ w 0.5)) (setq w (- w 0.5))))
  26.          ((and (zerop  y2) (>  x2 0)) (if (minusp y1) (setq w (+ w 0.5)) (setq w (- w 0.5))))
  27.       )
  28.       (setq x1 x2  y1 y2)  
  29.    )
  30.    (not (zerop w))
  31. )
  32.  

Now the funny part is that If I remove the test when we are
smack on the poly  ((and (zerop  y1) & ((and (zerop  y2),
I still get very consistent results.

It is somewhat logical as he states in his paper that the
winding number is undefined when you are on the polyline.

ymg
« Last Edit: May 02, 2015, 04:44:36 PM by ymg »

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Point is Inside polyline (Now with Bulges)
« Reply #51 on: May 02, 2015, 11:48:20 PM »
I just used the same points for each test. Nothing fancy :)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #52 on: May 03, 2015, 10:14:55 AM »
ronjonp,

Would you mind posting your testing program and data ?

What are your thoughts on removing the two test ?

Code: [Select]
((and (zerop  y1) (>  x1 0)) (if (>  y2   0) (setq w (+ w 0.5)) (setq w (- w 0.5))))
((and (zerop  y2) (>  x2 0)) (if (minusp y1) (setq w (+ w 0.5)) (setq w (- w 0.5))))

Since we do not really care about the winding number, what we want is true or false
for inside.

If we remove them, we have a 10 % speed advantage over ptinpoly_p1

ymg


ronjonp

  • Needs a day job
  • Posts: 7529
Re: Point is Inside polyline (Now with Bulges)
« Reply #53 on: May 06, 2015, 10:05:53 AM »
Ymg.

Here's what I used to test along with the attached drawing.
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test (/ e en l l2 ss w x x1 x2 xp y1 y2 yp)
  2.   ;;                                                                            ;
  3.   ;; inside_p     by   ymg                                                      ;
  4.   ;;                                                                            ;
  5.   ;;           A Winding umber and Point-in-Polygon Algoritm                    ;
  6.   ;;              by  David G. Alciatore and Rick Miranda                       ;
  7.   ;;     http://www.engr.colostate.edu/~dga/dga/papers/point_in_polygon.pdf     ;
  8.   ;;                                                                            ;
  9.   ;; Here instead of onleft cross product test, we translate the polyline       ;
  10.   ;; to the point.  We then count the crossing of the y coordinates above       ;
  11.   ;; zero.                                                                      ;
  12.   ;;                                                                            ;
  13.   ;;       (Under Test)                                                         ;
  14.   ;;                                                                            ;
  15.   (defun inside_p (p l)
  16.     (setq w  0
  17.      xp (car p)
  18.      yp (cadr p)
  19.      x1 (- (caar l) xp)
  20.      y1 (- (cadar l) yp)
  21.     )
  22.     (foreach a (cdr l)
  23.       (setq x2 (- (car a) xp)
  24.        y2 (- (cadr a) yp)
  25.       )
  26.       (cond ((< (* y1 y2) 0)
  27.         (if (> (+ x1 (* y1 (/ (- x2 x1) (- y1 y2)))) 0)
  28.           (if (minusp y1)
  29.        (setq w (1+ w))
  30.        (setq w (1- w))
  31.           )
  32.         )
  33.        )
  34.        ((and (zerop y1) (> x1 0))
  35.         (if (> y2 0)
  36.           (setq w (+ w 0.5))
  37.           (setq w (- w 0.5))
  38.         )
  39.        )
  40.        ((and (zerop y2) (> x2 0))
  41.         (if (minusp y1)
  42.           (setq w (+ w 0.5))
  43.           (setq w (- w 0.5))
  44.         )
  45.        )
  46.       )
  47.       (setq x1 x2
  48.        y1 y2
  49.       )
  50.     )
  51.     (not (zerop w))
  52.   )
  53.   ;;=========================================================================;
  54.   ;;                                                                         ;
  55.   ;;      PtInPoly_p(): Winding number test for a point in a polygon         ;
  56.   ;;                                                                         ;
  57.   ;;      Input:    p = a point                                              ;
  58.   ;;               en = ename or vla-object of a closed polyline.            ;
  59.   ;;                                                                         ;
  60.   ;;      Return:  t, if point is in polyline. (wn is not 0)                 ;
  61.   ;;                                                                         ;
  62.   ;; Original code in C++ by Dan Sunday, Translated by ymg                   ;
  63.   ;; See: http://geomalgorithms.com/a03-_inclusion.html                      ;
  64.   ;;=========================================================================;
  65.   (defun ptinpoly_p (p l / i p1 p2 v wn y isleft)
  66.     ;; Returns t if point p is strictly to the left of v1->v2   by ymg      ;
  67.     (defun isleft (p v1 v2 / xp yp)
  68.       (setq xp (car p)
  69.        yp (cadr p)
  70.       )
  71.       (- (* (- (cadr v1) yp) (- (car v2) xp)) (* (- (car v1) xp) (- (cadr v2) yp)))
  72.     )
  73.     ;; Initialize the loop.                                                 ;
  74.     (setq p1 (car l)
  75.      y  (cadr p)
  76.      wn 0
  77.     )
  78.     ;; Loop through all edges of polygon.                                   ;
  79.     (foreach p2   (cdr l)
  80.       (if (<= (cadr p1) y)
  81.    (if (> (cadr p2) y)
  82.      (if (> (isleft p p1 p2) 0)
  83.        (setq wn (1+ wn))
  84.      )
  85.    )
  86.    (if (<= (cadr p2) y)
  87.      (if (< (isleft p p1 p2) 0)
  88.        (setq wn (1- wn))
  89.      )
  90.    )
  91.       )
  92.       (setq p1 p2)
  93.     )
  94.     (not (zerop wn))
  95.     ;; Returns t if wn not equal to zero.                  ;
  96.   )
  97.   (princ "\nSelect Points: ")
  98.   (if (setq ss (ssget '((0 . "point"))))
  99.     (progn (setq l (mapcar '(lambda (e) (cdr (assoc 10 (entget e))))
  100.             (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
  101.          )
  102.       )
  103.       (setq l2 (mapcar '(lambda (p) (list (+ 100 (car p)) (cadr p) (caddr p))) l))
  104.       (command "ERASE" ss)
  105.       (foreach p l
  106.         (if (ptinpoly_p p l)
  107.           (entmakex (list '(0 . "POINT") (cons 10 p) '(62 . 1)))
  108.           (entmakex (list '(0 . "POINT") (cons 10 p) '(62 . 7)))
  109.         )
  110.       )
  111.       (foreach p l2
  112.         (if (inside_p p l2)
  113.           (entmakex (list '(0 . "POINT") (cons 10 p) '(62 . 1)))
  114.           (entmakex (list '(0 . "POINT") (cons 10 p) '(62 . 7)))
  115.         )
  116.       )
  117.     )
  118.   )
  119.   (princ)
  120. )

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #54 on: May 06, 2015, 10:53:42 AM »
ronjomp,

Thanks, I'll take a look at it.

My other testing without the two mentionned test gives us outside
for any point on the border or directly on a point, unless the border
is into an overlapping zone.

Seems logical to me.

ymg


ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #55 on: May 07, 2015, 05:14:04 AM »
ronjomp,

In your test program, you are using the list of all points as being the polyline under Test.

You need to generate pl from the points belonging to the poly densified with either Joe Burke's tracepline
or the slower "Express Tool" equivalent.

ymg
« Last Edit: May 07, 2015, 05:33:19 AM by ymg »

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Point is Inside polyline (Now with Bulges)
« Reply #56 on: May 07, 2015, 09:37:56 AM »
Ah yes ... silly me :)
Can you give the following a test .. the cyan points are the test points and the blue points are the traced polyline. I'm getting really strange results now ( but it's probably just me ).
« Last Edit: May 07, 2015, 09:42:23 AM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #57 on: May 07, 2015, 12:48:10 PM »
Ron,

You would need at least to add that:

Code: [Select]
(setq b1 (append b1 (list (car b1))))
(setq tp1 (append b1 tp1))

Remember the last point must repeat.
As it is tp1 contains only 255 points.

But I believe that with the selection set as it is, the order of
the polyline is being scrambled.

Would be easier to detect the ename of the polyline
and call approxpoly or tracepline.

Then points could be treated as you are doing.

ymg

ronjonp

  • Needs a day job
  • Posts: 7529
Re: Point is Inside polyline (Now with Bulges)
« Reply #58 on: May 07, 2015, 12:57:27 PM »
Ahh yes ... the order of the points is what is getting hosed.  ;)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ymg

  • Guest
Re: Point is Inside polyline (Now with Bulges)
« Reply #59 on: May 10, 2015, 07:08:36 AM »
ronjomp,

I've looked into the routine you proposed to replace approxpoly, which calls "Express Tools".

To be fair, tracepoly is limited to polyline only, approxpoly can be used on any type of "vlax-curve".

I rewrote it entirely in order to optimize speed and be able to define the tolerance in terms of the maximum sagitta allowed between the segment and the curve.

Here goes the code followed by a small benchmark on a polyline composed of a single arc.
Note that I had to adjust the tolerance from angular to linear to be able to compare.

Code - Auto/Visual Lisp: [Select]
  1. ;;                                                                            ;
  2. ;; tracepline2     by ymg                                                     ;
  3. ;;                                                                            ;
  4. ;; Argument:  en,   Ename of a Polyline                                       ;
  5. ;;           tol,  Tolerance (Maximum Sagitta Allowed on Bulges)              ;
  6. ;;                                                                            ;
  7. ;; Return:  An Ordered Points List Approximating the Polyline                 ;
  8. ;;       (Requires ceil function)                                             ;
  9.  
  10. (defun tracepline2 (en tol / b d i j obj pl)
  11.    ;(if (= (type en) 'vla-object) ;
  12.    ;   (setq obj en   en (vlax-vla-object->ename  obj))
  13.        (setq obj (vlax-ename->vla-object en))
  14.    ;)  
  15.          
  16.    (repeat (fix i)
  17.       (if (not (zerop (setq b (abs (vlax-invoke obj 'getbulge (setq i (1- i)))))))
  18.          (progn
  19.             (setq j (ceil (sqrt (/ (* 0.5 (distance (car pl) (vlax-curve-getpointatparam en i)) b) tol)))
  20.                   d (/ 1.0 j)
  21.                   i (1+ i)
  22.             )
  23.             (repeat j
  24.                 (setq pl (cons (vlax-curve-getpointatparam en (setq i (- i d))) pl))
  25.             )
  26.          )
  27.          (setq pl (cons (vlax-curve-getPointAtParam en i) pl))
  28.       )
  29.    )
  30.    pl
  31. )
  32.  
  33. ;; Ceiling function, Returns the smallest integer not less than x.            ;
  34. (defun ceil  (x) (if (> (rem x 1) 0)    (+ (fix x) 1) (fix x)))
  35.  
  36.  


Quote
(benchmark '((tracepline en 0.667)(tracepline2 en 0.001) (acet-list-remove-adjacent-dups (acet-geom-object-point-list en 0.001))))
Benchmarking ...............Elapsed milliseconds / relative speed for 4096 iteration(s):

    (TRACEPLINE2 EN 0.001)........................1966 / 6.96 <fastest>
    (ACET-LIST-REMOVE-ADJACENT-DUPS (ACE...)......3416 / 4.01
    (TRACEPLINE EN 0.667)........................13682 / 1.00 <slowest>
_$ (length (TRACEPLINE2 EN 0.001))
127
_$ (length (acet-list-remove-adjacent-dups (acet-geom-object-point-list en 0.001)))
130
_$ (length (TRACEPLINE EN 0.667))
127
« Last Edit: May 10, 2015, 07:23:29 AM by ymg »