Find vertices of a selected line LISP

Find vertices of a selected line LISP

Anonymous
Not applicable
3,141 Views
7 Replies
Message 1 of 8

Find vertices of a selected line LISP

Anonymous
Not applicable

I have drawn four parallel lines with LISP and I am trying to make a function where the user can select 2 lines, the program finds the vertices of these lines and draw a circle with center point in each vertex. On the circle that should be drawn I know I can use (command "_circle" radius coordinates) but I do not know how to select the line and get the vertices.

 

(Defun test ()
(command "_.pline" '(130 200) '(200 200) "")
(command "_.pline" '(130 150) '(200 150) "")
(command "_.pline" '(130 100) '(200 100) "")
(command "_.pline" '(130 50) '(200 50) "") ")
)

 

0 Likes
Accepted solutions (1)
3,142 Views
7 Replies
Replies (7)
Message 2 of 8

Kent1Cooper
Consultant
Consultant
Accepted solution

There are several ways you can do that.  Here's one:

 

(Defun test (/ p1 p2)
  (command
"_.pline" (setq p1 '(130 200)) (setq p2 '(200 200)) ""
"_.circle" p1 YourRadius
"_.circle" p2 YourRadius
    "_.pline" (setq p1 '(130 150)) (setq p2 '(200 150)) ""
    "_.circle" p1 YourRadius
    "_.circle" p2 YourRadius
    "_.pline" (setq p1 '(130 100)) (setq p2 '(200 100)) ""
    "_.circle" p1 YourRadius
    "_.circle" p2 YourRadius
    "_.pline" (setq p1 '(130 50)) (setq p2 '(200 50)) ""
    "_.circle" p1 YourRadius
    "_.circle" p2 YourRadius
); command ); defun

 

Is there some reason they need to be Plines, or would just Lines do?

 

That assumes you have no running object snap modes in effect.

 

EDIT:  Here's another abbreviated version:

 

(Defun test (/ p1 p2)
(foreach Y '(200 150 100 50) (command "_.pline" (setq p1 (list 130 Y)) (setq p2 (list 200 Y)) "" "_.circle" p1 YourRadius "_.circle" p2 YourRadius ); command
); foreach ); defun

 

If you really need it done somehow by selecting each (p)line and getting its vertices/endpoints after drawing it, rather than by saving the points while drawing the (p)lines and using those saved points for the Circle centers:

 

(vl-load-com)
(Defun test () (foreach Y '(200 150 100 50) (command "_.pline" (list 130 Y) (list 200 Y) "" "_.circle" (vlax-curve-getStartPoint (entlast)) YourRadius       "_.circle" (vlax-curve-getEndPoint (entlast)) YourRadius
); command ); foreach ); defun

Also, should that be (defun C:test ... ?  If you add the C:, you can type just test at the Command line; if not, you have to type (test) with the parentheses.

 

Kent Cooper, AIA
Message 3 of 8

Anonymous
Not applicable

Thanks, but the third code you wrote was so I could select the lines, right? Maybe I'm doing something wrong but it did not work here. The four parallel lines only appear.

 
0 Likes
Message 4 of 8

ВeekeeCZ
Consultant
Consultant

Select a line:

 

(if (setq en (car (entsel "\nSelect line: ")))
  (setq p1 (cdr (assoc 10 (entget en)))
        p2 (cdr (assoc 11 (entget en))))
Message 5 of 8

dbroad
Mentor
Mentor

A command approach would be as follows (An activeX approach would execute much faster):

;;;Michael Puckett
(defun cdrs (key lst / pair rtn)
   (while (setq pair (assoc key lst))
      (setq rtn (cons (cdr pair) rtn)
         lst (cdr (member pair lst))
      )
   )
   (reverse rtn)
)
;;D.C. Broad - Basic demo draw circles at each selected polyline vertex.
(defun c:circlline ( / dia ss e ei)
  (setq dia (getdist "\nCircle diameter: "))
  (princ "\nSelect 2 polylines: ")
  (if (setq ss (ssget '((0 . "lwpolyline"))))
    (progn
      (command "._undo" "_begin")
      (repeat (min 2 (sslength ss))
	(setq e (ssname ss 0))
	(ssdel e ss)
	(setq ei (entget e))
	(mapcar	'(lambda (p)
		   (command "._circle" p "_d" dia)
		 )
		(cdrs 10 ei)
	)
      )
    )
  )
  (command "._undo" "_end")
  (princ)
)
Architect, Registered NC, VA, SC, & GA.
Message 6 of 8

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Thanks, but the third code you wrote was so I could select the lines, right? Maybe I'm doing something wrong but it did not work here. The four parallel lines only appear.


I did make an error there, in calling for the endpoint of the last entity as the center of the 2nd Circle, since at that point the last entity is the first Circle.  It should have been more like this:

(vl-load-com)
(Defun test (/ pl)
  (foreach Y '(200 150 100 50)
    (command
      "_.pline" (list 130 Y) (list 200 Y) ""
      "_.circle" (vlax-curve-getStartPoint (setq pl (entlast))) YourRadius
      "_.circle" (vlax-curve-getEndPoint pl) YourRadius
    ); command
  ); foreach
); defun

 

That does work for me, with the YourRadius replaced with a numerical radius value [that's why I colored/italicized it, to call attention to it -- you need to do something with that to use the code -- it could be an explicit number or a variable holding one].

 

I apparently misread something about the original Post, thinking you wanted to expand on your code that draws the lines, to add the Circles at their ends.  Maybe I shouldn't have used the word "select" -- I didn't mean User selection, since the routine draws the lines, and they're not there for the User to select when the routine starts.  I meant that the routine "selects" the lines after they're drawn, to get the start and end points from them for drawing the Circles, as opposed to [the other routines] putting them in variables in the process of drawing the lines, and getting them from the variables for drawing the Circles, rather than getting them from the lines themselves.

 

If you want to select already-drawn lines, the code in Post 1 is really irrelevant.  You could restrict it to two of them, but there's no need, nor even a need to restrict it to Lines or Polylines.  Back later with a generic routine to draw Circles at both ends of any kind of object....

Kent Cooper, AIA
Message 7 of 8

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....  Back later with a generic routine to draw Circles at both ends of any kind of object....


Here's one that does that [lightly tested], on any Line, Polyline, Arc, Circle, Ellipse, Spline or Ray, as long as you continue to pick things:

 

(defun C:CatE (/ rad ss ent); = Circle(s) at End(s)
  (initget (if *CatErad* 0 1)); no Enter on first use
  (setq *CatErad*
    (cond
      ( (getdist
          (strcat
            "\nRadius of Circle(s) to draw at End(s)"
            (if *CatErad* (strcat " <" (rtos *CatErad*) ">") "")
            ": "
          ); strcat
        ); getdist
      ); User-input condition
      (*CatErad*); on Enter with prior value
    ); cond
  ); setq
  (while (setq ss (ssget "_+.:S" '((0 . "*LINE,ARC,CIRCLE,ELLIPSE,RAY"))))
    (command "_.circle" "_none" (vlax-curve-getStartPoint (setq ent (ssname ss 0))) *CatErad*)
    (if (not (or (vlax-curve-isClosed ent) (member '(0 . "RAY") (entget ent))))
      (command "_.circle" "_none" (vlax-curve-getEndPoint (setq ent (ssname ss 0))) *CatErad*)
    ); if
  ); while
  (princ)
); defun

 

On closed things and Rays, it puts just one, at the start/end point of closed things.  It could be made to disallow closed things if preferred, to draw Circles only on open ends.  It could be made to either disallow or work differently with MLINEs if you might ever have those [currently it would allow selection of one, but couldn't draw the Circles with this method].

 

It ends if you hit Enter/space/ESCape, or pick an inappropriate object type, or just miss, but it could be made to account for the latter two conditions and ask again.  It draws the Circles on the current Layer, but could be made to set a built-in Layer, or ask the User, or use the Layer of the selected object.  And of course it could have *error* handling added, command-echo suppression, Undo begin/end wrapping, etc.

Kent Cooper, AIA
Message 8 of 8

Anonymous
Not applicable

Thanks a lot for the help, guys! You guys are amazing and I'm learning a lot in this forum !!

0 Likes