Jump to content

Sorting mixed order points on a polyline object


nkeseci

Recommended Posts

Hi,

 

Can anyone help me to write a lisp function to sort the points (assume the intersection points) on a polyline?

 

With my code, I have a polyline object and a set of intersection points on it. I need to calculate the cumulative distance between those points and vertex points consecutively.

 

Thanks,

Link to comment
Share on other sites

The following function will sort the points based on their position along the polyline:

 

(defun sortpoints ( ent lst )
   (vl-sort lst
       (function
           (lambda ( a b )
               (<  (vlax-curve-getparamatpoint ent a)
                   (vlax-curve-getparamatpoint ent b)
               )
           )
       )
   )
)

Or, if the points do not necessarily lie on the object:

 

(defun sortpoints ( ent lst )
   (vl-sort lst
       (function
           (lambda ( a b )
               (<  (vlax-curve-getparamatpoint ent (vlax-curve-getclosestpointto ent a))
                   (vlax-curve-getparamatpoint ent (vlax-curve-getclosestpointto ent b))
               )
           )
       )
   )
)

The above functions should be called with the entity name of the polyline in question, and the list of WCS points, e.g.:

 

(sortpoints <entity-name> <point-list>)

 

You will also need to ensure (vl-load-com) is called before using the above functions.

Link to comment
Share on other sites

  • 2 weeks later...

Thank you for your answer. But the sortpoints function seems to not working. I tried the function in my code with sample data.

Sample data are vertex points of polyline. I mixed the order of vertex points and I expect your function (sortpoints) sorts those points. But it gave me the same order of points. Maybe it could be my fault.

 

Here is the sample points (vertices of a polyline)

(370961.248 310947.465) ;1

(371118.717 311119.493) ;2

(371016.444 311267.177) ;3

(371083.002 311526.843) ;4

(371232.353 311705.362) ;5

(370930.404 311919.585) ;6

 

Here is the entire code:

 

(vl-load-com)

;*
;* NK_FINT : Find intersection points 
;*           (intersections points of selected polyline with lines)
;*
(defun C:nk_fint (/ plObj line_ss int_ss intP inc ent verts ptList)
 (setq
   plObj (vlax-ename->vla-object (car (entsel "\nSelect Polyline: "))); = Polyline OBJect
   line_ss (ssget "_X" '((0 . "LINE"))); = Line Selection Set
   int_ss (ssadd); = things that intersect -- start empty
   inc -1
 ); setq
 (setq ptList '(
   ;(370961.248 310947.465) ;1
   (371118.717 311119.493) ;2
   (371016.444 311267.177) ;3
   (370961.248 310947.465) ;1
   (371083.002 311526.843) ;4
   (371232.353 311705.362) ;5
   (370930.404 311919.585) ;6
   )
 )
 (princ "\n\Before: \n")
 (writepoints ptList) ;for testing purpose
 (repeat (sslength line_ss)
   (setq ent (ssname line_ss (setq inc (1+ inc)))); = line ENTity
   (if
     (setq intP  ; intersection point
     (vlax-invoke plObj 'intersectWith (vlax-ename->vla-object ent) acExtendNone); vlax-invoke
   ); setq
   (progn
     (setq verts (getverts plObj intP))
     (princ "\nVerts:\n")  (writepoints verts)  ;for testing purpose
     (ssadd ent int_ss)
   ) ; progn
   ); if
 ); repeat

 (sortpoints plObj ptList)
 (princ "\n\nAfter: \n")
 (writepoints ptList)  ;for testing purpose

 (princ)
); defun

;*
;* WRITEPOINTS: write points (test-purpose)
;*
(defun writepoints ( plst / x1 y1 ptmp)
 (while (setq ptmp (car plst))
   (princ (rtos (car ptmp) 2 3))(princ " ")(princ (rtos (cadr ptmp) 2 3))(princ "\n")
   (setq plst (cdr plst))
 )
 (princ)

)

;*
;* SORTPOINTS: sorts given points along with selected polyline
;*
(defun sortpoints ( ent lst )
 (vl-sort lst
   (function
     (lambda ( a b )
       (<  (vlax-curve-getparamatpoint ent a)
           (vlax-curve-getparamatpoint ent b)
      )
     )
   )
 )
)

;*
;* GETVERTS: Gives vertex points of selected Polyline.
;*
(defun getverts (pObj iPt / PtOnObj DistPick DistV1 PtV1 VNum distFlag DistV2 PtV2)
 (setq PtOnObj (vlax-curve-getClosestPointTo pObj iPt))
 (setq DistPick (vlax-curve-getDistatPoint pObj PtOnObj))
 (setq DistV1 0.0)
 (setq PtV1 (vlax-curve-getPointatparam pObj 0));;Pl start point
 (setq VNum 1.0)
 (setq distFlag T)
 (while distFlag
   (setq DistV2 (vlax-curve-getDistatParam pObj Vnum))
   (setq PtV2 (vlax-curve-getPointatParam pObj Vnum))
   (if (> DistV2 DistPick)
     (setq DistFlag nil)
     (setq Vnum (+ 1 Vnum) PtV1 PtV2)
   )
 )
 (list PtV1 PtV2);;returns list of 2 vertices bounding pick point
)

 

Thanks,

Link to comment
Share on other sites

Since your list of coordinate values are expressed as literals and only given to 3 d.p. precision, there is the possibility that the vlax-curve-getparamatpoint function may not recognise that the point lies on the given polyline entity; did you try my second suggested function which uses the vlax-curve-getclosestpointto function to 'snap' the coordinates to the polyline?

 

Also, note that I have stated that the above functions require an entity-name argument, not a VLA-Object; the vlax-curve-* functions will perform correctly with both types of argument (ename / vla-object), however, the functions will be faster when supplied with an entity-name over a VLA-Object (furthermore, there is no need for the conversion usig vlax-ename->vla-object).

 

EDIT: On closer inspection of your code, you are not updating the value of the ptList variable following the call to my sortpoints function:

(sortpoints plObj ptList)

You will need to assign the ptList variable the value returned by the sorting function:

(setq ptList (sortpoints plObj ptList))

This reasoning applies since we are passing the sorting function with the value held by the ptList variable, not a 'pointer' to the variable itself (as you might by passing a quoted symbol).

Link to comment
Share on other sites

Yes, I was just doing a very simple error. I forgot the assignment:

(setq ptList (sortpoints plObj ptList))

 

But it gave the expected result with vlax-curve-getclosestpointto function, as you explained:

(defun sortpoints ( ent lst )
 (vl-sort lst
   (function
     (lambda ( a b )
       (<  (vlax-curve-getparamatpoint ent (vlax-curve-getclosestpointto ent a))
           (vlax-curve-getparamatpoint ent (vlax-curve-getclosestpointto ent b))
       )
     )
   )
 )
)

 

Thank you very much :)

Link to comment
Share on other sites

  • 4 years later...

Sir,

 

I need this lisp program for my urgent work badly. I had also tried this program but this showing error as below:

 

Command: NK_FINT

 

Select Polyline:

Before:

371118.717 311119.493

371016.444 311267.177

370961.248 310947.465

371083.002 311526.843

371232.353 311705.362

370930.404 311919.585

; error: bad argument type: lselsetp nil

 

 

This is my humble request to you guys if you have some time please upload corrected this program for me in txt format.

 

Thanks in advance.

Best regards,

Rajan Nautiyal

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...