Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

get vertices number

21 REPLIES 21
SOLVED
Reply
Message 1 of 22
Anonymous
3238 Views, 21 Replies

get vertices number

My goal is to select the block (test_block), select the cyan polyline, and return the angle and distance (s) to the vertices ahead.
example: if I select the block with attribute 01 it returns me (128.75 42.0185)
attribute block 05 (308.75 42.0185 276.103 12.6343)
attribute block 02 (96.103 12.6343 132.667 23.556) [...]

The function I am creating works but I depend on the verticie ID as I get the correct ID or is there another way to get the result ??

 

(defun c:ang2dist nil
  (setq obj (vlax-ename->vla-object (setq ent (car (entsel ))))) ;;select block/vla
  (setq baseblk (vlax-get obj 'insertionpoint)) ;; base point
  (setq sspline (ssget "_C" (mapcar '+ baseblk '(5 5)) (mapcar '- baseblk '(10 10)) '((0 . "LWPOLYLINE")(8 . "pline")))) ; select pline
  (setq entpline (ssname sspline 0))
  (setq vert (vlax-curve-getendparam entpline)) ;get total verticie
  (setq id 0) ; number verticie id
  (setq dist (- (vlax-curve-getdistatparam entpline (1+ id)) (vlax-curve-getdistatparam entpline id))) ;get dist  verticie id
  (setq ang (angle '(0.0 0.0 0.0) (vlax-curve-getfirstderiv entpline id))) ;get angle verticie -> radian
  (setq lst (list (list (r2d ang) dist))) ; creat list
)
r2d link here >> https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/bearing-and-distance-lisp-modification/td-p/9373785

(defun r2d (r) (if (>= (* 180.0 (/ r pi)) 360) (- (* 180.0 (/ r pi)) 360) (* 180.0 (/ r pi))))

 

21 REPLIES 21
Message 2 of 22
Sea-Haven
in reply to: Anonymous

Removed should have looked at dwg 1st.

 

Is pline Clockwise or anticlock wise ? Needs an answer.

 

The vertices as a list is easy so make a list of Blk ins to vert point, distance and angle,  find closest one ie smallest distance. Then just loop through the list again vertice dist ang outputting.

 

(setq plent (entsel "\nPick pline"))
(if plent (setq co-ord (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (car plent))))))

  

Message 3 of 22
pbejse
in reply to: Anonymous


@Anonymous wrote:
example: if I select the block with attribute 01 it returns me (128.75 42.0185)
attribute block 05 (308.75 42.0185 276.103 12.6343)
attribute block 02 (96.103 12.6343 132.667 23.556) [...]

Are those the expected results based on your sample drawing? or is it something else?

 

 

Message 4 of 22
Anonymous
in reply to: pbejse

@Sea-Haven I didn't understand what you're getting at.

 

@pbejse  Yes, this is the result I hope for.

Message 5 of 22
dlanorh
in reply to: Anonymous

Are you trying to get the angle and distance from the insertion point of each block to the nearest vertex of the polyline?

 

Or are you trying to get the angle and distance of each polyline segment?

 

When I run your code on your drawing it always returns (128.75 42.0185). This is the angle (not the bearing)  and distance of the first segment of the polyline, irrespective of which block I select. This is because you are always checking the angle and distance of the polyline from (id) to (+ id 1) (vertex 0 to vertex 1) no matter which block you select

I am not one of the robots you're looking for

Message 6 of 22
Anonymous
in reply to: dlanorh


Or are you trying to get the angle and distance of each polyline segment?


Exact angle and distance !!!

 


When I run your code on your drawing it always returns (128.75 42.0185). This is the angle (not the bearing)  and distance of the first segment of the polyline, irrespective of which block I select. This is because you are always checking the angle and distance of the polyline from (id) to (+ id 1) (vertex 0 to vertex 1) no matter which block you select


 

I realized this, I wanted to understand how to get the ID of the vertices in front of each block. generating the result that I showed in the example.

Message 7 of 22
pbejse
in reply to: Anonymous


@Anonymous wrote:

@pbejse  Yes, this is the result I hope for.


I can bring you up to the point where you get the vertices number and you can continue from there, You good with that? 

 

Message 8 of 22
Anonymous
in reply to: pbejse

I'm not very good, (I'm still learning), but it already helps me.

Message 9 of 22
ВeekeeCZ
in reply to: Anonymous

@Anonymous 

 

I can see that you use the term vertex ID. Do you know how's that related to the curve's "parameter"?

(vlax-curve-GetParamAtPoint...) Do you understand what the value of "param" (parameter) represents? Is the value of a parameter different for different curve types? Line vs. polyline...

 

If someone knows where is some nice (possibly graphical) explanation what param represents, please share the link here. I don't know and don't want to draw it... thx

Message 10 of 22
Anonymous
in reply to: ВeekeeCZ

@ВeekeeCZ Yes I know!! I will only deal with polylines.

Message 11 of 22
ВeekeeCZ
in reply to: Anonymous

So where is the issue?

Get the list of all vertices (coordinates), sort them by a distance to your ins-point, then get the param of the closest one. 

 

Message 12 of 22
dlanorh
in reply to: Anonymous

This should sort it.

 

 

(defun c:ang2dist ( / obj baseblk sspline ent ep cpt cp fp pp np ang dist lst)
  (setq obj (vlax-ename->vla-object (setq ent (car (entsel ))))) ;;select block/vla
  (setq baseblk (vlax-get obj 'insertionpoint)) ;; base point
  (setq sspline (ssget "_C" (mapcar '+ baseblk '(5 5)) (mapcar '- baseblk '(10 10)) '((0 . "LWPOLYLINE")(8 . "pline")))) ; select pline
  (setq ent (ssname sspline 0))

  (setq ep (vlax-curve-getendparam ent)
        cpt (vlax-curve-getclosestpointto ent baseblk)
        cp (vlax-curve-getparamatpoint ent cpt)
        fp (rem cp 1.0)
        cp (fix cp)
  )

  (if (> fp 0.49999) 
    (setq cp (1+ cp) pp (if (> cp 0) (1- cp) nil) np (if (< cp ep) (1+ cp) nil))
    (setq pp (if (> cp 0) (1- cp) nil) np (if (< cp ep) (1+ cp) nil))
  )

  (cond ( (and cp np)
          (setq ang (angle (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent np))
                dist (distance (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent np))
                lst (cons (list (r2d ang) dist) lst)
          )
        )
  )
  (cond ( (and cp pp)
          (setq ang (angle (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent pp))
                dist (distance (vlax-curve-getpointatparam ent cp) (vlax-curve-getpointatparam ent pp))
                lst (cons (list (r2d ang) dist) lst)
          )
        )
  )
  (setq lst (apply 'append lst))
)

 

 

You will still need to insert (defun r2d)

 

(Edited to correct code)

I am not one of the robots you're looking for

Message 13 of 22
Kent1Cooper
in reply to: Anonymous

Here's my approach:

 

(defun c:ang2dist (/ ent baseblk sspline entpline neapt idpar idpt predata postdata)
  (setq
    ent (car (entsel "\nSelect Block: "))
    baseblk (cdr (assoc 10 (entget ent))) ; base point
    sspline (ssget "_C" (mapcar '+ baseblk '(5 5)) (mapcar '- baseblk '(5 5)) '((0 . "LWPOLYLINE") (8 . "pline"))) ; find pline
    entpline (ssname sspline 0)
    neapt (vlax-curve-getClosestPointTo entpline baseblk) ; closest point to Block insertion
    idpar (fix (+ (vlax-curve-getParamAtPoint entpline neapt) 0.5)); nearest whole parameter value
    idpt (vlax-curve-getPointAtParam entpline idpar); vertex location there
    predata
      (if (setq prept (vlax-curve-getPointAtParam entpline (1- idpar)))
        (list
          (read (angtos (angle idpt prept) 0 4)) ; angle to previous vertex [degrees]
          (distance idpt prept); distance to there
        ); list
      ); if & predata
    postdata
      (if (setq postpt (vlax-curve-getPointAtParam entpline (1+ idpar)))
        (list
          (read (angtos (angle idpt postpt) 0 4)) ; angle to following vertex [degrees]
          (distance idpt postpt); distance to there
        ); list
      ); if & postdata
    lst (append predata postdata) ; create list
  ); setq
); defun

 

It doesn't require a radians-to-degrees conversion function, and it doesn't require converting the Block to a VLA object, and it doesn't require determining the number of vertices, nor sorting them in any way, and it uses a simpler way to find the closest vertex to a Block's insertion point.

 

I kept most of your variable names, but adjusted some for clarity [and added some].  I left 'lst' out of the localized variables list, so it will survive after the end of the routine.

 

For a Block closest to an end vertex, the data about the direction from there that doesn't exist will simply be nil, so the final list will include only the information about the direction that does exist.

 

[The singular is vertex; the plural is vertices.]

Kent Cooper, AIA
Message 14 of 22
pbejse
in reply to: Kent1Cooper


@Kent1Cooper wrote:

Here's my approach:

 

(defun c:ang2dist (/ ent baseblk sspline entpline neapt idpar idpt predata postdata)
... predata
      (if (setq prept (vlax-curve-getPointAtParam entpline (1- idpar)))
        (list
          (read (angtos (angle idpt prept) 0 4)) 
          (distance idpt prept)
        )
      )
    postdata
      (if (setq postpt (vlax-curve-getPointAtParam entpline (1+ idpar)))
        (list
          (read (angtos (angle idpt postpt) 0 4))
          (distance idpt postpt)
        )
      )
    lst (append predata postdata)
  )
)

Nice @Kent1Cooper , I only got to the point postdata and left it at that 😊

👍 

Message 15 of 22
pbejse
in reply to: dlanorh


@dlanorh wrote:

This should sort it.

(setq ang  (angle (vlax-curve-getpointatparam ent cp)
		  (vlax-curve-getpointatparam ent np)
	   )
      dist (distance (vlax-curve-getpointatparam ent cp)
		     (vlax-curve-getpointatparam ent np)	   )
      lst  (cons (list (r2d ang) dist) lst)
)
...

 

I used a similar approach to get the data, then i run out of gas 😊 

(mapcar '(lambda (f)
  	(f (vlax-curve-getpointatparam e pr)
	   		(vlax-curve-getpointatparam e pr+)
    	)
	   )
	(list angle distance))

 

Message 16 of 22
Sea-Haven
in reply to: Anonymous

For me like the others find the closest pline. then just get its vertices ((x y) (x y) (x y)...) then make a distance function

This is distance from insert point to the (nth of the co-ords, save as a list ((ang dist)...) once smallest is found you know the starting position in your vertice list so can proceed till end of this list with angle and distance.

Message 17 of 22
john.uhden
in reply to: ВeekeeCZ

You know, MJ, that Owen Wengerd advised us not to rely on parameters.  But I think that's only because he can create polylines with "quirky" parameters.  He's a genius in my book.  The way I see it, parameters are the indices for vertices, starting at zero.  Like @Kent1Cooper, I have never had a problem using parameters within polylines.  There are plenty of Visual Lisp functions that can convert a parameter to a point or distance, and vice versa.  I really can't do without them.  I think my favorite is getfirstderiv which returns the angle as a vector of the tangent at any point.

God bless Peter Petrov!

John F. Uhden

Message 18 of 22
john.uhden
in reply to: Kent1Cooper

@Kent1Cooper  wrote "[The singular is vertex; the plural is vertices.]"

I am impressed with your progress with grammar.

Test, which is correct?

A.  A group of men see the sunset.

or

B.  A group of men sees the sunset.

John F. Uhden

Message 19 of 22
pbejse
in reply to: pbejse

Another... 

(defun c:ang2dist (/	rtd  Ll&Ur _PointsAndParam blocks i sspline
		     e	point	 pts atv  v prv nxt data  )
  (defun rtd (a) (/ (* a 180.0) pi))
  (defun _PointsAndParam (e / p l)
    (if	(eq (setq p (vlax-curve-getEndParam e)) (fix p))
      (repeat (setq p (1+ (fix p)))
	(setq l	(cons (list
			(setq p (1- p))
			(vlax-curve-getPointAtParam e p)
		      )
		      l
		)
	)
      )
    )
  )

  (defun Ll&Ur (p f)
    (setq fz 10.00);<--- size of the box
    (polar p (* pi f) (* fz (sqrt 2)))
  )

  (if (setq blocks (ssget '((0 . "INSERT") (66 . 1))))
    (repeat (setq i (sslength blocks))
      (setq e (ssname blocks (setq i (1- i))))
      (setq ipoint (cdr (assoc 10 (entget e))))
      (setq atv (getpropertyvalue e "NUMBER")) ;<--- Hard coded TAG name
      (if
	(setq sspline
	       (ssget "C"
		      (Ll&Ur ipoint 0.25)
		      (Ll&Ur ipoint 1.25)
		      '((0 . "LWPOLYLINE") (8 . "pline"))
	       )
	)

	 (progn
	   (setq pts (_PointsAndParam (setq pl (ssname sspline 0))))
	   (setq v (vl-sort pts
			    '(lambda (a b)
			       (< (distance ipoint (Cadr a))
				  (distance ipoint (Cadr b))
			       )
			     )
		   )
	   )
	   (setq DAta (cons (list atv
			      (append
				(if
				  (setq prv (assoc (1- (Caar v)) pts))
				   (list
				     (rtd (angle (cadar v) (cadr prv)))
				     (distance (cadar v) (cadr prv))
				   )
				)
				(if
				  (setq nxt (assoc (1+ (Caar v)) pts))
				   (list
				     (rtd (angle (cadar v) (cadr nxt)))
				     (distance (cadar v) (cadr nxt))
				   )
				)
			      )
			)
			Data
		  )
	   )
	 )
      )
    )
  )
  Data
)

Select objects: (("05" (308.75 42.0185 276.103 12.6343)) ("01" (128.75 42.0185)) ("02" (96.103 12.6343 132.667 23.556)) ("03" (312.667 23.556 136.959 53.9246)))

 

This version uses the selected polylines coordinates in line with @Sea-Haven suggestion instead of closestpointto approach.

 

HTH

 

 

Message 20 of 22
ВeekeeCZ
in reply to: john.uhden

So did I, never had problems. thx

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


AutoCAD Beta