AutoLISP error: Bad Point Argument with SSGET "_W"

AutoLISP error: Bad Point Argument with SSGET "_W"

betsy.kirtland
Enthusiast Enthusiast
4,618 Views
18 Replies
Message 1 of 19

AutoLISP error: Bad Point Argument with SSGET "_W"

betsy.kirtland
Enthusiast
Enthusiast

Hi friends,

 

I'm having trouble using ssget to select a region on which I need to run MASSPROP.  My code is below:

 

;Assign name of .mpr files to be created
(setq FileName (strcat "SectionNumber" (itoa counter)))
  
;Select the region 
(setq Region (ssget "W" '(-50 50) '(50 -50)))
;(setq Region (entsel))

;Pull the centroid coordinates out of the region's properties
(setq centroid (vlax-safearray->list (vlax-variant-value (vlax-get-property (vlax-ename->vla-object (car Region)) "Centroid"))))

;Pull the Principal Directions out of the region's properties
;Note that the resulting list is in the form (x1 x2 y1 y2)
;Therefore, the user should chose the first and third inputs, or the second and fourth
(setq PrDir (vlax-safearray->list (vlax-variant-value (vlax-get-property (vlax-ename->vla-object (car Region)) "PrincipalDirections"))))

;Selects the first and third values from the extracted Principal Directions
(setq PrDirx (list (nth 0 PrDir) (nth 2 PrDir)))

;Set the USC such that the origin is at the centroid of the region,
;and the X-axis is along one of the Principal Directions
(command "ucs" "_NON" centroid "_NON" PrDirx "")

;Run MASSPROP on the region and save the output to a file
(command "_MASSPROP" Region "" "_Y" FileName)

You'll notice that I have the line "(setq Region (entsel)" commented out right now.  When I un-comment that line, and comment out the  "(setq Region (ssget "W" '(-50 50) '(50 -50)))" line instead, it does exactly what I want.  For some reason, it doesn't like my use of ssget.  I sometimes get "error: bad argument type: consp <Select set: ###>" or "error: bad point argument", and I can't figure out what's causing either of them.

 

I have tried adding Z coordinates to the points, adding two other points such that it reads (ssget "W" '(-50 -50) '(-50 50) '(50 50) '(50 -50)), adding "_NONE" between all of the points... nothing has worked so far.  Any insight that anyone might have would be greatly appreciated!  I have 183 regions to run MassPROP on... I don't really want to have to select each one individually using entsel!

 

PS. I am using Civil3D 2017, in case that matters!

 

0 Likes
Accepted solutions (1)
4,619 Views
18 Replies
Replies (18)
Message 2 of 19

betsy.kirtland
Enthusiast
Enthusiast

Hi again, thought I would provide some more information.

I've attached an image of one of the regions that I'm trying to run Massprop on.  There are 183 similar regions above this one that are each 1 unit above the next.  After running Massprop on one of the sections, it moves the UCS up 1 unit and then runs massprop on the next sections.  My full code is here:

(defun c:MP-2D (/ FileName counter)
(setq counter 1)

;Ensure that the program starts at the bottom
(command "ucs" "Named" "Restore" "2d")

;ENTER NUMBER OF SECTION CUTS. Enter as counter max value below:
(while (<= counter 3)
	;Assign name of .mpr files to be created
  	(setq FileName (strcat "SectionNumber" (itoa counter)))
  
  	;Select the region 
  	(setq Region (ssget "W" '(-50 50) '(50 -50) '((0 . "REGION"))))
	;(setq Region (entsel))

  	;Pull the centroid coordinates out of the region's properties
  	(setq centroid (vlax-safearray->list (vlax-variant-value (vlax-get-property (vlax-ename->vla-object (car Region)) "Centroid"))))

  	;Pull the Principal Directions out of the region's properties
  	;Note that the resulting list is in the form (x1 x2 y1 y2)
  	;Therefore, the user should chose the first and third inputs, or the second and fourth
  	(setq PrDir (vlax-safearray->list (vlax-variant-value (vlax-get-property (vlax-ename->vla-object (car Region)) "PrincipalDirections"))))

  	;Selects the first and third values from the extracted Principal Directions
  	(setq PrDirx (list (nth 0 PrDir) (nth 2 PrDir)))

  	;Set the USC such that the origin is at the centroid of the region,
  	;and the X-axis is along one of the Principal Directions
  	(command "ucs" "_NON" centroid "_NON" PrDirx "")

	;Run MASSPROP on the region and save the output to a file
  	(command "_MASSPROP" Region "" "_Y" FileName)

  	;Add one to the counter
  	(setq counter (+ counter 1))
  	
  	;Return to original USC before moving the UCS to the next section height
  	(command "ucs" "previous")
  
  	;MOVE THE UCS UP TO THE HEIGHT OF THE NEXT SECTION CUT
  	;Change z-coordinate in all three points below to be
  	;equal to the height between sections
  	;i.e., '(0 0 deltaz) '(1 0 deltaz) '(0 1 deltaz)
    	(command "ucs" "_3p" "_NON" '(0 0 1) "_NON" '(1 0 1) "_NON" '(0 1 1))
))

As I said in my previous post, if I use "entsel" to select the region, then the code runs perfectly.  If I try to use "ssget", it doesn't like it.  Because there are 184 regions to run massprop on, though, I need this code to be fully automated (i.e. I don't want to have to select each region individually as the code runs).

 

Now, I've done some more thinking since my original post, and I have realized that the type of variable that "Region" is differs between using ssget and entsel.  If I put a breakpoint at the "(setq centroid....)" line of code, run it using ssget for Region, and then use the "type" function in the Visual Lisp Console, it returns 

_1_$ type Region
#<SUBR @000000004bcfea20 TYPE>
<Selection set: 73>

However, if I do the same using entsel instead of ssget, the "type" function returns

_1_$ type Region
#<SUBR @000000004bcfea20 TYPE>
(<Entity name: 55e26e80> (5.14935 1.4122 0.0))

So, it seems that using entsel results in Region being an entity, while ssget results in Region being a selection set?  Am I understanding that correctly?

It seems that then the code stops running and displays an error when it tries to run the next line and gets to (vlax-ename->vla-object (car Region)) when Region is a selection set instead of an entity.


How can I use ssget to select my region and store it as an entity?

Thanks in advance for any and all help!

0 Likes
Message 3 of 19

roland.r71
Collaborator
Collaborator

Note: SSGET returns a selection set, ENTSEL does NOT.

So, they are not interchangeable.

 

Where SSGET will return a selection set with entity names, ENTSEL combines 1 entity name with the selection point. Retrieve that name first, then use ENTGET to get to the DXF group code info.

 

(entget (ssname (nth # ss))) ; this returns the entity data from a selection set (setq ss (ssget ...)).

(entget (car es)) ; this returns the data for a selected entity (setq es (entsel)).

 

Disclaimer: I wrote this from memory, and didn't test it.

0 Likes
Message 4 of 19

betsy.kirtland
Enthusiast
Enthusiast

Hi Roland,

 

Thanks for the reply!  I am pretty new to using lisp, so my apologies if my questions are a little foolish.

I changed the ssget portion of my code my code to be 

;Select the region 
  	(setq ss (ssget "W" '(-50 0.5) '(50 -0.5)))
  	(setq Region (entget (ssname (nth 0 ss))))

When I run "type" on the new variable "ss", I get 

_1_$ type ss
#<SUBR @0000000041bdea20 TYPE>
<Selection set: 21>

But the code doesn't like the next line (setq Region (entget.....).  I think it's having trouble with the (nth 0 ss) portion, but to be honest, I don't really understand how the functions ssname or entget work, so I might just be doing something wrong there.

I also tried to check the value of ss before it tries to do the next line, and I get

_1_$ !ss
nil

which obviously implies that ss is empty, and is probably why doing (nth 0 ss) won't work.  That confuses me though, because there is definitely a region in the selection window of (-50 0.5) to (50 -0.5)...

 

Any more thoughts?  Thanks again for the help!

0 Likes
Message 5 of 19

john.uhden
Mentor
Mentor
Accepted solution

SS is a selection set, not a list.

To retrieve the first entity in the selection set, count from zero...

(setq e (ssname ss 0))

(setq ent (entget e))

 

But it strikes me that if you want to process all the regions in the drawing, then create a selection set of all of them and then process each one...

(setq ss (ssget "X" '((0 . "REGION"))))

(setq i 0)

(while (< i (sslength ss))

  (setq e (ssname ss I))

 (setq i (1+ i))

  etc.

)

John F. Uhden

Message 6 of 19

roland.r71
Collaborator
Collaborator

Yep. My Bad memory...

Should be as @john.uhden wrote it:

(entget (ssname ss #)) ; where ss is the selection set and # is the index number ( 0 = first)

 

The (nth # ss) is for lists. So i made a little mixup there.

 

The SSNAME function retrieves the name of the entity from the selection set.

ENTGET uses that name to retrieve the entities data.

However, that will still result in errors, if the selection set is empty...

Message 7 of 19

betsy.kirtland
Enthusiast
Enthusiast

John,

Thanks, that does make a lot of sense.  For some reason, my use of (ssget "W"..) is resulting in an empty selection set, which is confusing to me, but I like your solution much more anyway.  How would the regions be numbered when selecting all of the regions using your method?  Would 0 be the bottom-most or top-most region or a random region in the middle?  Ideally, I'd like for the first selection to be the bottom-most region and the last selection to be the top-most region.  All of the sections in elevation are shown in the attached image.

 

Thank you to you and Roland for all of the help thus far!

0 Likes
Message 8 of 19

devitg
Advisor
Advisor

The Selection Set  [SSGET] comes in the order they were done, or in inverse, I do not know , ACAD use the HANDLE  to sort it. As Handle is unique for a entity . 

And for any other way to SSGET, like W C CP WP FENCE and so on , points SHALL be at the  screen . 

 

And last but not least , a PNG can not be edited in ACAD, so , please upload a sample.DWG 

 

 

0 Likes
Message 9 of 19

roland.r71
Collaborator
Collaborator

@betsy.kirtland wrote:

John,

Thanks, that does make a lot of sense.  For some reason, my use of (ssget "W"..) is resulting in an empty selection set, which is confusing to me, but I like your solution much more anyway.  How would the regions be numbered when selecting all of the regions using your method?  Would 0 be the bottom-most or top-most region or a random region in the middle?  Ideally, I'd like for the first selection to be the bottom-most region and the last selection to be the top-most region.  All of the sections in elevation are shown in the attached image.

 

Thank you to you and Roland for all of the help thus far!


I fear not. Unless the regions where created top to bottom. As they are selected from the database in the order of creation.

 

So, you would need to process the selection set first, to determine the correct order of regions, based on their y coordinate.

 

There are a few ways to accomplish that, but right now i don't have an example ready. (& no time to create one, atm)

Message 10 of 19

john.uhden
Mentor
Mentor

Yes, you must sort the selection set by any criteria you want.

If it's by location, you could sort by its centroid or by any corner of its boundingbox.

What to do is convert the selection set into a list of enames, and to each one prefix it with the coordinate of interest, then sort the list in any order (say descending Y value), then remove the prefixes.

We're just about to eat dinner now.  If you need example code, I can provide it on my next visit.

John F. Uhden

Message 11 of 19

john.uhden
Mentor
Mentor

Here's one method:

(defun RegionsInDescendingYOrder ( / ss i e centroid sslist)
  (and
    (setq ss (ssget "x" '((0 . "REGION")(410 . "Model"))))
    (repeat (setq i (sslength ss))
      (setq e (ssname ss (setq i (1- i))))
      (setq centroid (vlax-get (vlax-ename->vla-object e) 'centroid))
      (setq sslist (cons (list centroid e) sslist))
    )
    (setq sslist (mapcar 'cdr (vl-sort sslist '(lambda (a b)(> (cadar a)(cadar b))))))
  )
  sslist
)

I love that kind of crap.

BTW, dinner was excellent... boneless chicken breasts sauteed with garlic and herbs, and sliced red potatoes and veggies and herbs grilled in a foil packet, and my wife's 5 star coleslaw.  We grow the herbs (rosemary and thyme), so they are fresh.  Eating at home is usually better than going out (which we can't afford anyway).

Anybody want my recipe for easy linguini with white clam sauce?

John F. Uhden

Message 12 of 19

Sea-Haven
Mentor
Mentor

When you use the x=-50 can you see that on the screen there is a bug at times if you do stuff off screen the lisp can error. I tried "w" '( x y) etc and worked fine.

0 Likes
Message 13 of 19

roland.r71
Collaborator
Collaborator

@Sea-Haven wrote:

When you use the x=-50 can you see that on the screen there is a bug at times if you do stuff off screen the lisp can error. I tried "w" '( x y) etc and worked fine.


 

As @devitg already pointed out "any other way to SSGET, like W C CP WP FENCE and so on , points SHALL be at the  screen . "

 

As long as your x -50 is visible on screen, no problem. But your "window" selection can not select anything off-screen.

 

In such case it's best to zoom in on the area or zoom extent first. Making sure the region you wish to select is fully visible on screen.

Message 14 of 19

betsy.kirtland
Enthusiast
Enthusiast

Roland et al ,

That makes sense.  I did notice with an earlier version of my code that being too far zoomed in or out would cause it to error or crash.  It didn't occur to me that the selection window would have to be entirely on the screen... silly me.  And I am hesitant to provide the .dwg that I am working on as I am not sure of the confidentiality of the project.  If I were still struggling to get this to work, I would create a similar sample one, but at this point, I have it working enough for the purposes of my project.

 

John,

Your dinner sounded wonderful and I am always interested in any recipe that includes the word "easy"!  I added a "c:" the in first line of your code so that I could call it in AutoCAD's command window, and when I tried to execute it, I got the error "AutoCAD.application: Region is not in the UCS plane"

However, the regions were created in ascending order, so I think that I am OK without that portion of code anyway, using your original idea of creating a selection set of all of them and then processing them one by one.

 

Thank you so much, everyone for all of your help!  I hope everyone had a great 4th of July (if you're in the states.. if not, then I hope you had a great Wednesday!)

0 Likes
Message 15 of 19

john.uhden
Mentor
Mentor
I am not aware of the error you mentioned.  All I provided you is a means to sort all the regions in descending Y order.  I don't understand why a vlax-get would cause an error.
 
I'll have to work on typing up that linguini recipe.  It will be tough, but I will try to minimize the setqs, getpoints, and mapcars.  🙂

John F. Uhden

0 Likes
Message 16 of 19

roland.r71
Collaborator
Collaborator

@john.uhden wrote:
I am not aware of the error you mentioned.  All I provided you is a means to sort all the regions in descending Y order.  I don't understand why a vlax-get would cause an error.
 
I'll have to work on typing up that linguini recipe.  It will be tough, but I will try to minimize the setqs, getpoints, and mapcars.  🙂

 

Could it be as simple as (vl-load-com) ???

0 Likes
Message 17 of 19

john.uhden
Mentor
Mentor

@roland.r71asked, "Could it be as simple as (vl-load-com) ???"

 

Not the linguini recipe, but without vl-load-com the error would have been about no vla-object.

John F. Uhden

0 Likes
Message 18 of 19

roland.r71
Collaborator
Collaborator

Correct.

I missed the "Region is not in the UCS plane" part i guess.

 

Good to know your linguini doesn't require any ActiveX too Smiley Wink

0 Likes
Message 19 of 19

john.uhden
Mentor
Mentor

But my omelets require ActiveEggs.

John F. Uhden

0 Likes