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

Polyline Vertices

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
MIKEZERBY
623 Views, 9 Replies

Polyline Vertices

Hello everyone,

 

I have a piece of code that works in AutoCAD 2009 but does not work in 2013. I pass a lwpolyline to it and it would pull out the vertices.

 

(defun log_w_pts (obj / indxx xlist ylist)
	(setq indxx 14)
	(repeat (cdr (assoc 90 obj))
		(setq xlist (cons (cadr (nth indxx obj)) xlist)
		      ylist (cons (caddr (nth indxx obj)) ylist)
		      indxx (+ 4 indxx)
		)
	)
	(setq p1 (list (apply 'min xlist) (apply 'min ylist))
	      p2 (list (apply 'max xlist) (apply 'min ylist))	
	      p3 (list (apply 'max xlist) (apply 'max ylist))
	      p4 (list (apply 'min xlist) (apply 'max ylist))
	)
)

 Now I get this error message. "Error: bad argument type: consp 0"

 

Anyone know what the problem might be. I'm assuming that Autodesk changed something.

 

Thanks,

Mike

9 REPLIES 9
Message 2 of 10
hmsilva
in reply to: MIKEZERBY

Hi Mike,

 

a new group code 91 for lwpolylines was introduced in AC2010, and it's a constraints marker per vertex.
Perhaps something like this

 

(defun log_w_pts (obj / xlist ylist)
  (foreach n obj
    (if	(= (car n) 10)
      (setq xlist (cons (cadr n) xlist)
	    ylist (cons (caddr n) ylist)
      )
    )
  )
  (setq	p1 (list (apply 'min xlist) (apply 'min ylist))
	p2 (list (apply 'max xlist) (apply 'min ylist))
	p3 (list (apply 'max xlist) (apply 'max ylist))
	p4 (list (apply 'min xlist) (apply 'max ylist))
  )
)

 

Hope that helps
Henrique

EESignature

Message 3 of 10
MIKEZERBY
in reply to: hmsilva

Hi Henrique,

 

That worked thanks!

 

Now I can move on and find out what else they changed. Smiley Happy

Message 4 of 10
hmsilva
in reply to: MIKEZERBY

You're welcome, Mike
Glad I could help

Henrique

EESignature

Message 5 of 10
Kent1Cooper
in reply to: MIKEZERBY

Just for fun, another way that it occurred to me you could get the 'xlist' and 'ylist' variables, if 'obj' is the Polyline's entity data list, without using (repeat) or (foreach):

 

(vl-load-com); [if needed]

(setq

  verts (vl-remove-if-not '(lambda (q) (= (car q) 10)) obj); vertex entries only

  xlist (mapcar 'cadr verts); X coordinates

  ylist (mapcar 'caddr verts); Y coordinates

  p1 .... ; etc.

); setq

 

 

Also, [I don't know how you're using the results, but...] if p1/p2/p3/p4 are used to define the overall extents of the Polyline, then:

1)  it won't always be correct if there are any outward-bulging arc segments, since it looks only at vertex locations;

2)  it won't always be correct if there is any non-zero width in the Polyline, since it looks only at vertex locations; and

3)  you can get the extents directly, accounting for both 1) and 2) but also appropriate if they don't apply, without having to list and compare vertex X & Y coordinates:

 

(vla-getboundingbox (vlax-ename->vla-object PolylineEntityName) 'minpt 'maxpt)
(setq
  LL (vlax-safearray->list minpt); Lower Left corner
  UR (vlax-safearray->list maxpt); Upper Right corner
)

 

and if you still need the lower right and upper left as defined locations, you can call LL p1 instead, and UR p3, and derive p2 & p4 easily enough from them.  If you're using them to draw a Polyline box around the extents, you can use the Rectangle command with LL and UR, without needing p2/p4 at all.

Kent Cooper, AIA
Message 6 of 10
MIKEZERBY
in reply to: Kent1Cooper

Hello Kent,

 

That option works well too!

 

What is the biggest advantage of one or the other?

 

Mike

Message 7 of 10
MIKEZERBY
in reply to: Kent1Cooper

Hi Kent,

 

I'm using that as a function that feeds the corner points of the polyline back into the main program that is cutting a window rough opening into a precut log wall drawing. Each of the logs in the stack are polylines. 

 

Thanks again,

Mike

Message 8 of 10
Kent1Cooper
in reply to: MIKEZERBY


@mikezerby wrote:

Hello Kent,

 

That option works well too!

 

What is the biggest advantage of one or the other?

 

Mike


I would guess [without bench-marking it] that my suggested approach would be slightly faster, though it wouldn't likely be detectable to a User unless this is part of something that does the same with a large number of Polylines at once.

The (foreach) and (repeat) versions have two (setq) functions going within each step as they plow through the entity data list -- for the right kind of entry, they first add the X coordinate to one list, and then add the Y coordinate to another, and then go on to look at the next entity data entry, and when they find the right kind again, open up both of those lists again to add another coordinate to each one with another separate (setq) operation for each.  The (mapcar) approach also steps through all the entity data entries to look for the right kind in making its vertex-only abbreviated list, but then pulls all the X coordinates out into a list in one (setq) operation for the entire list, and likewise for the Y coordinates.  That's why I suspect it might be faster, but it wouldn't surprise me if there's something about the way it goes about it that might counteract my intuition about it.

 

Certainly none of the approaches is "better" than the others if they all produce the same results, unless you consider the slight differences in the amount of code needed to be a criterion, or there is a noticeable speed difference in them under the conditions of your application.

Kent Cooper, AIA
Message 9 of 10
_gile
in reply to: Kent1Cooper

Hi,

 

Just for fun too.

As Kent said, it will only works with linear 0 width segments polylines.

 

(defun massoc (key alst)
  (if (setq alst (member (assoc key alst) alst))
    (cons (cdar alst) (massoc key (cdr alst)))
  )
)

(defun log_w_pts (pline / pts)
  (setq	pts (massoc 10 (entget pline))
	p1  (apply 'mapcar (cons 'min pts))
	p3  (apply 'mapcar (cons 'max pts))
	p2  (list (car p3) (cadr p1))
	p4  (list (car p1) (cadr p3))
  )
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 10 of 10
Lee_Mac
in reply to: _gile

Another variation:

 

(defun log_w_pts ( ent / enx pt1 pt2 vtx )
    (setq enx (entget ent))
    (while (setq vtx (assoc 10 enx))
        (setq pt1 (cond ((mapcar 'min (cdr vtx) pt1)) ((cdr vtx)))
              pt2 (cond ((mapcar 'max (cdr vtx) pt2)) ((cdr vtx)))
              enx (cdr (member vtx enx))
        )
    )
    (list pt1 (list (car pt2) (cadr pt1)) pt2 (list (car pt1) (cadr pt2)))
)

 

Returns a list of four points defining the bounding box of a straight-segmented polyline.

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

Post to forums  

Autodesk Design & Make Report

”Boost