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

How to Return entityname largest polyline of a selection set?

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
mid-awe
795 Views, 9 Replies

How to Return entityname largest polyline of a selection set?

Hi all,

 

I need to return the entity name of the largest (longest closed) polyline in a selection set. At this point I have no trouble creating the selection set and even getting the area of the boundingbox, which is not the most acurate way to find the true size, but it's a start. The part that has me stumped is: if I iterate through the selection set, then how can I compare one to the other when I have access to the current entity. I've been staring at examples of lambdas but it seems to me that iterating through the selection set is going about it wrong in the first place. 

 

Below is my current code with a remaining issue. I can return the largest area of the polylines (no good for more than two entities in selection set), but I do not know how to return the entityname:

 

(IF (> (SETQ SS (SSGET "x" '((0 . "*POLYLINE") (8 . "POOL") (-4 . "<OR") (62 . 5) (62 . 256) (-4 . "OR>"))))
       1
    )
  (PROGN
    (SETQ a   (1- a)
	  ent (CDR (CAR (SSNAME ss a)))
	  en2 (CDR (CAR (SSNAME ss (1- a))))
	  ar1 (APPLY '*
		     (LIST (LAMBDA (ent)
			     (VLAX-INVOKE-METHOD (VLAX-ENAME->VLA-OBJECT ent) 'getboundingbox 'minpt 'maxpt)
			     (SETQ pt1 (TRANS (VLAX-SAFEARRAY->LIST minpt) 0 ent)
				   pt2 (TRANS (VLAX-SAFEARRAY->LIST maxpt) 0 ent)
			     )
			     (VL-REMOVE 0.0 (MAPCAR '- pt2 pt1))
			   )
		     )
	      )
	  ar2 (APPLY '*
		     (LIST (LAMBDA (en2)
			     (VLAX-INVOKE-METHOD (VLAX-ENAME->VLA-OBJECT en2) 'getboundingbox 'minpt 'maxpt)
			     (SETQ pt1 (TRANS (VLAX-SAFEARRAY->LIST minpt) 0 en2)
				   pt2 (TRANS (VLAX-SAFEARRAY->LIST maxpt) 0 en2)
			     )
			     (VL-REMOVE 0.0 (MAPCAR '- pt2 pt1))
			   )
		     )
	      )
	  big (MAX ar1 ar2)
    )
  )
)

 There is no doubt that this code is rough. I'm trying to hammer out how, then I'll see if I can simplify it.

 

Thank you for any help/advice.

 

9 REPLIES 9
Message 2 of 10
mid-awe
in reply to: mid-awe

Ok, I've tried building it out in a way that makes sense to me:

(IF (> (SETQ SS (SSGET "x" '((0 . "*POLYLINE") (8 . "POOL") (-4 . "<OR") (62 . 5) (62 . 256) (-4 . "OR>")))) 1)
    (PROGN
      (SETQ a	(1- a)
	    ent	(CDR (CAR (SSNAME ss a)))
	    en2	(CDR (CAR (SSNAME ss (1- a))))
	    ar1	(CONS ENT
		      (APPLY '*
			     (LIST (LAMBDA (ent)
				     (VLAX-INVOKE-METHOD (VLAX-ENAME->VLA-OBJECT ent) 'getboundingbox 'minpt 'maxpt)
				     (SETQ pt1 (TRANS (VLAX-SAFEARRAY->LIST minpt) 0 ent)
					   pt2 (TRANS (VLAX-SAFEARRAY->LIST maxpt) 0 ent)
				     )
				     (VL-REMOVE 0.0 (MAPCAR '- pt2 pt1))
				   )
			     )
		      )
		)
	    ar2	(CONS EN2
		      (APPLY '*
			     (LIST (LAMBDA (en2)
				     (VLAX-INVOKE-METHOD (VLAX-ENAME->VLA-OBJECT en2) 'getboundingbox 'minpt 'maxpt)
				     (SETQ pt1 (TRANS (VLAX-SAFEARRAY->LIST minpt) 0 en2)
					   pt2 (TRANS (VLAX-SAFEARRAY->LIST maxpt) 0 en2)
				     )
				     (VL-REMOVE 0.0 (MAPCAR '- pt2 pt1))
				   )
			     )
		      )
		)
	    big	(MAX (cdr ar1) (cdr ar2))
	    bigr (if (= big (cdr ar1)) (car ar1) (car ar2))
	    *poolENT* bigr
      )
    )
  )

 And, i get this error:

error: bad argument type for compare: <Selection set: 238> 1

 I'm not sure what is wrong other than I'm just handling it wrong.

Message 3 of 10
Lee_Mac
in reply to: mid-awe

Hi mid-awe,

 

Consider the following quick example:

 

(defun c:bigpoly ( / ar1 ar2 ent idx rtn sel )
    (if
        (setq sel
            (ssget "_X"
               '(
                    (0 . "*POLYLINE")
                    (8 . "POOL")
                    (-4 . "<OR")
                        (62 . 5)
                        (62 . 256)
                    (-4 . "OR>")
                    (-4 . "&=")
                    (70 . 1)
                )
            )
        )
        (progn
            (repeat (setq idx (sslength sel))
                (setq ent (ssname sel (setq idx (1- idx))))
                (if (< ar1 (setq ar2 (vla-get-area (vlax-ename->vla-object ent))))
                    (setq ar1 ar2
                          rtn ent
                    )
                )
            )
            (redraw rtn 3)
        )
    )
    (princ)
)
(vl-load-com) (princ)
Message 4 of 10
mid-awe
in reply to: Lee_Mac

Lee,

Thank you. Works great. I still bang my head at some of these "tricks". But, I will be hanging on to (-4 . "&=") (70 . 1)
Does that filter closed polylines? Also, I've not seen the "&=" before. I'm sure that will be very helpful going forward.

Again, Thank you.
Message 5 of 10
Lee_Mac
in reply to: mid-awe


@mid-awe wrote:
Lee,

Thank you. Works great. I still bang my head at some of these "tricks". But, I will be hanging on to (-4 . "&=") (70 . 1)
Does that filter closed polylines? Also, I've not seen the "&=" before. I'm sure that will be very helpful going forward.

Again, Thank you.

You're most welcome mid-awe -

I hope my code was clear to understand, but if not, feel free to ask about anything you are unsure of. Smiley Happy

 

Regarding the relational operator "&=": this is the bitwise masked equals operator, and its use in the ssget filter list in conjunction with the DXF group 70 code is equivalent to:

 

(= 1 (logand 1 (cdr (assoc 70 <DXF data>))))

I have put together a more complete ssget function reference on my site which includes additional examples.

 

Lee

Message 6 of 10
Kent1Cooper
in reply to: Lee_Mac

Since the original question specifically mentions finding the longest closed Polyline, consider that the greatest area doesn't necessarily indicate the longest perimeter.  [A 6x6 square has a smaller perimeter length, but a greater area, than a 10x3 rectangle.]  It may be that you should change this in Lee's routine:

 

  (if (< ar1 (setq ar2 (vla-get-area (vlax-ename->vla-object ent))))

    (setq ar1 ar2
             rtn ent

 

to something like this, to get the length rather than the area:

 

  (if (< len1 (setq len2 (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent))))

    (setq len1 len2

             rtn ent

Kent Cooper, AIA
Message 7 of 10
Lee_Mac
in reply to: Kent1Cooper


@Kent1Cooper wrote:

to something like this, to get the length rather than the area:

 

  (if (< len1 (setq len2 (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent))))

    (setq len1 len2

             rtn ent


Or alternatively retrieve the ActiveX Length property:

 

(vla-get-length (vlax-ename->vla-object ent))

 

Message 8 of 10
Kent1Cooper
in reply to: Lee_Mac


@Lee_Mac wrote:
....

Or alternatively retrieve the ActiveX Length property:

 

(vla-get-length (vlax-ename->vla-object ent))

 


Yes.  My brain defaults to the distance-at-End-Parameter approach because I use it in many routines that may need to find lengths of various entity types.  Not all entity types have a Length property [Arcs and Circles don't].  But Polylines do, so in a case that's limited to them like this, that works -- and it's shorter!.  [The distance-at-End-Point approach is also unreliable, returning 0 for closed entities.  But distance-at-End-Parameter gets it right for any entity type, open or closed.]

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


@Kent1Cooper wrote:

Since the original question specifically mentions finding the longest closed Polyline, consider that the greatest area doesn't necessarily indicate the longest perimeter.  [A 6x6 square has a smaller perimeter length, but a greater area, than a 10x3 rectangle.]

 


Good point Kent. 

Message 10 of 10
mid-awe
in reply to: mid-awe

Many great things have arisen here. 🙂 Thank you all.

 

I'm sure Lee was interpreting my example code in which I did my best to find the area of the bounding box (length * width). So, for my needs, the area is perfectly acceptable, although, I have a use for both the area and length.

 

At this point in the larger program either area or length will do.

 

Thank you all.

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

Post to forums  

Autodesk Design & Make Report

”Boost