TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: XXL1966 on May 04, 2013, 01:12:33 PM

Title: Projecting points on polylines and determining side
Post by: XXL1966 on May 04, 2013, 01:12:33 PM
Hello,

i need a function that projects points on a polyline within a certain distance and determine the side of the points on the polyline.

The first step is easy by using the vlax-curve-getClosestPointTo, next compute the distance between point and projection and compare with given distance. As for the side. Is there a ready to use function in (v)lisp to do this ? For a straight segmented polyline i could determine the segment the point is projected on (but how ?) and then compute the area of the triangle between segment and projection point (area will be + or -).

Just curious if anyone else already solved this problem or maybe knows an easy way to do this...

thanks !

 
Title: Re: Projecting points on polylines and determining side
Post by: jvillarreal on May 04, 2013, 01:17:00 PM
Maybe this will help?
http://www.theswamp.org/index.php?topic=40416.0 (http://www.theswamp.org/index.php?topic=40416.0)
Title: Re: Projecting points on polylines and determining side
Post by: Lee Mac on May 04, 2013, 01:26:17 PM
For straight segments you can also test the whether the sine of the angle between the segment and given point is positive or negative:

Code - Auto/Visual Lisp: [Select]
  1. (sin (- (angle <segment-start> <given-point>) (angle <segment-start> <segment-end>)))

If the above is positive, the point lies to the left of the segment; if negative, to the right.
Title: Re: Projecting points on polylines and determining side
Post by: XXL1966 on May 04, 2013, 01:32:37 PM
thx for the fast replies. But i still need the segment the point is projected on, this doesn't result from vlax-curve-getClosestPointTo. Is there a VLISP function that results the segment with a given point (result of vlax-curve-getClosestPointTo) on the curve ?
Title: Re: Projecting points on polylines and determining side
Post by: Lee Mac on May 04, 2013, 01:43:19 PM
But i still need the segment the point is projected on, this doesn't result from vlax-curve-getClosestPointTo. Is there a VLISP function that results the segment with a given point (result of vlax-curve-getClosestPointTo) on the curve ?

Retrieving the segment is relatively easy:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / en pa pt )
  2.     (if
  3.         (and
  4.             (setq pt (getpoint "\nPoint: "))
  5.             (setq en (car (entsel "\nPolyline: ")))
  6.             (= "LWPOLYLINE" (cdr (assoc 0 (entget en))))
  7.         )
  8.         (progn
  9.             (setq pt (vlax-curve-getclosestpointto en (trans pt 1 0))
  10.                   pa (vlax-curve-getparamatpoint en pt)
  11.             )
  12.             (entmake (list '(0 . "POINT") (cons 10 (vlax-curve-getpointatparam en (fix pa)))))
  13.             (entmake (list '(0 . "POINT") (cons 10 (vlax-curve-getpointatparam en (1+ (fix pa))))))
  14.         )
  15.     )
  16.     (princ)
  17. )
Title: Re: Projecting points on polylines and determining side
Post by: XXL1966 on May 04, 2013, 01:59:27 PM
thx !

will have a look into this VLAX functions.
Title: Re: Projecting points on polylines and determining side
Post by: Lee Mac on May 04, 2013, 03:45:36 PM
Here is a quick draft of a possible program for this task:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:sidetest( / en p1 p2 pa pt )
  2.     (if
  3.         (and
  4.             (setq pt (getpoint "\nPoint to test: "))
  5.             (setq en (car (entsel "\nLWPolyline: ")))
  6.             (= "LWPOLYLINE" (cdr (assoc 0 (entget en))))
  7.         )
  8.         (progn
  9.             (setq p1 (vlax-curve-getclosestpointto en (trans pt 1 0))
  10.                   pa (vlax-curve-getparamatpoint en p1)
  11.             )
  12.             (if (equal '(0.0 0.0 0.0) (vlax-curve-getsecondderiv en pa) 1e-8)
  13.                 (setq p1 (vlax-curve-getpointatparam en (fix pa))
  14.                       p2 (vlax-curve-getpointatparam en (1+ (fix pa)))
  15.                 )
  16.                 (setq p2 (mapcar '+ p1 (vlax-curve-getfirstderiv en pa)))
  17.             )
  18.             (alert (strcat "\nPoint is on " (whichside? pt p1 p2) " of polyline."))
  19.         )
  20.     )
  21.     (princ)
  22. )
  23.  
  24. (defun whichside? ( givenpoint point1 point2 )
  25.     (if (minusp (sin (- (angle point1 givenpoint) (angle point1 point2))))
  26.         "RIGHT"
  27.         "LEFT"
  28.     )
  29. )
Title: Re: Projecting points on polylines and determining side
Post by: owenwengerd on May 04, 2013, 04:01:41 PM
            (entmake (list '(0 . "POINT") (cons 10 (vlax-curve-getpointatparam en (fix pa)))))
            (entmake (list '(0 . "POINT") (cons 10 (vlax-curve-getpointatparam en (1+ (fix pa))))))

Bad programmer, bad (http://otb.manusoft.com/2013/01/quirkypolyline-exposing-foolish-programmers.htm).
Title: Re: Projecting points on polylines and determining side
Post by: XXL1966 on May 05, 2013, 05:18:39 AM
ah, the master pops up everywhere ;-)

with quirky polylines you mean like having identical vertices etc ?
Title: Re: Projecting points on polylines and determining side
Post by: owenwengerd on May 05, 2013, 09:09:21 AM
with quirky polylines you mean like having identical vertices etc ?

Lee's code assumes that vertex parameters are (consecutive) integers, which is not guaranteed.
Title: Re: Projecting points on polylines and determining side
Post by: TheMaster on May 09, 2013, 10:26:34 PM
Actually, I think that code may have a more significant problem with edge-cases involving polyines that are not parallel to the UCS XY plane.

Code: [Select]
(vlax-curve-getParamAtPoint (vlax-curve-getClosestPointTo (cadr (entsel "\nPick polyline: "))))

will not necessarily give the correct result if the polyline is not in the XY plane of the current UCS.

The pick point returned by (entsel) is always in the UCS XY plane, making it view-dependent, which means that it may only appear to be closer to the desired vertex in the current view projection, but can actually be closer to another vertex.

AFAIK, the correct and only completely-reliable way to acquire a vertex is via (ssget ":S") and (ssnamex)