how to filter polylines with ssget & dxf group code

how to filter polylines with ssget & dxf group code

Anonymous
Not applicable
8,216 Views
20 Replies
Message 1 of 21

how to filter polylines with ssget & dxf group code

Anonymous
Not applicable

Hello 

Does anyone know how to filter polylines with an AutoLisp Program. Im trying save some time cleaning drawings. i`m new with Lisp. im triying something like this (ssget "X" '((0 . "LWPOLYLINE")(-4 . "=")(70 . 1))) but i don`t know how to add a range . i`ve already use qselect and filter but those are not enough. 

 

i would really appreciate any help

0 Likes
8,217 Views
20 Replies
Replies (20)
Message 2 of 21

cadffm
Consultant
Consultant
Look at Help[F1]
AND
<
=
>

Or bitwise AND
For closed lwpolylines try this
(ssget "_X"
'(
(0 . "LWPOLYLINE")
(-4 . "&")
(70 . 1)
)
)

Sebastian

0 Likes
Message 3 of 21

Anonymous
Not applicable

and how can I add the range to the selection im trying this but it doesn work

(ssget "_X"
'(
(0 . "LWPOLYLINE")
(-4 . "&")
(70 . 1)

(-4 . ">=") i pretend add a selection range between 2.5 and 5

(70 . 2.5)

(-4 . "<=")

(70 . 5)
)
)

0 Likes
Message 4 of 21

_gile
Consultant
Consultant

Hi,

 

You have to clarify what you mean with: "a selection range between 2.5 and 5".

The 70 group code for LWPOLYLINE is a flag which can only have 4 values:

0 => opened polyline, disabled line type generation

1 => closed polyline, disabled line type generation

128 => opened polyline, enabled line type generation

129 (1 + 128) => closed polyline, enabled line type generation



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 21

Anonymous
Not applicable

i apologize if i wasn´t enough clear,  what i meant with "a selection range between 2.5 and 5" i wanted to say that the program should ask for a minimn and maximum length and this will look for all the polylines that have a length that are between this range e.g. 2.6, 3, 4.7. 

 

 

 

0 Likes
Message 6 of 21

_gile
Consultant
Consultant

You cannot filter polylines by length with ssegt and a selection filter.

You have to iterate through the selection to check for each polyline length.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 21

Anonymous
Not applicable

i thoght it was going to be easier, do you have a little program that i could use as an example??

0 Likes
Message 8 of 21

Jonathan.Trostad
Advocate
Advocate

I don't have code as such, but I feel it helps to put what you want into a format with steps. so for this task:

1)  use SSGET to grab the lw polylines in the drawing

2) convert your selection set to a list of entities for processing <- you might not need this step, but selection sets confuse me...

3) FOREACH entity, get the length of the polyline (possibly by grabbing the DXF 10 out of the entity and doing math)

3a)  IF the length is too small, delete the entity (possibly use ENTDEL), else move on

 

0 Likes
Message 9 of 21

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... . i`ve already use qselect and filter but those are not enough.

....

the program should ask for a minimn and maximum length and this will look for all the polylines that have a length that are between this range e.g. 2.6, 3, 4.7.


 

QSELECT is enough, without the need to define a routine -- you just need to do it in 2 stages:

PLlengthrange1.PNG  and then  PLlengthrange2.PNG

Kent Cooper, AIA
Message 10 of 21

_gile
Consultant
Consultant

Here's a little function to 'post-filter' a selection set. It works with all entities that have a Length property.

 

(defun filterByLength (selectionSet minLength maxLength / i e l)
  (repeat (setq i (sslength selectionSet))
    (setq e (ssname selectionSet (setq i (1- i)))
          l (vl-catch-all-apply 'getpropertyvalue (list e "Length"))
    )
    (if
      (or
        (vl-catch-all-error-p l)
        (and minLength (< l minLength))
        (and maxLength (< maxLength l))
      )
       (ssdel e selectionSet)
    )
  )
  selectionSet
)

To filter LWPOLYLINE entities in the 2.5-5.0 range:

(filterByLength (ssget "_X" '((0 . "LWPOLYLINE"))) 2.5 5.)

To filter LINE entities greater than 2.5

(filterByLength (ssget "_X" '((0 . "LINE"))) 2.5 nil)

To filter lines and any type of polylines lower than 2.5

(filterByLength (ssget "_X" '((0 . "LINE,*POLYLINE"))) nil, 2.5)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 21

roland.r71
Collaborator
Collaborator

@Jonathan.Trostad wrote:

I don't have code as such, but I feel it helps to put what you want into a format with steps. so for this task:

1)  use SSGET to grab the lw polylines in the drawing

2) convert your selection set to a list of entities for processing <- you might not need this step, but selection sets confuse me...

3) FOREACH entity, get the length of the polyline (possibly by grabbing the DXF 10 out of the entity and doing math)

3a)  IF the length is too small, delete the entity (possibly use ENTDEL), else move on

 


As for your point 2) : You do indeed not need that step.

A selectionset IS a list of entities (for processing), so no need for conversion.

You should keep in mind that such a set only contains a reference to the entities, not the entities data (DXF groupcodes & values). To get to the data, its better to combine it with the FOREACH of point 3)

 

To explain:

(setq ss (ssget "X" (list '(0 . "LWPOLYLINE"))))

This will create a list (selection set) containing ALL lwpolyline entities found within the entire database of acad (that's what the "X" is for) and store it with the variable "ss"

 

Since acad handles selection sets as different from lists (although they are basically the same) you can not use functions for lists on selection sets.

 

So,

(foreach ent ss

   ; do stuff

)

Works only if ss where a list, but not when its a selection set.

 

Instead you need to step thru the selection set by 'entry id' (the nth entry of the set)

(setq i 0)

(while (< i (sslength ss)) ; keep going as long as "i" is smaller as the number of selected items.

   (setq ent (entget (ssname ss i))) ; retrieve entity data for entry "i" (0 is first, 1 is second !!!)

 

The ssname function will retrieve the entities name from the selectionset.

entget retrieves the data (for a given entity name)

 

Now you have the entities data stored inside "ent", as a list! (a dotted pair / association list)

From here you can retrieve the values for each DXF groupcode, or change them (using entmod)

This includes retrieving the length.

   (setq entLength (cdr (assoc 10 ent))) ; this will retrieve the value for DXF group code 10. (as each entry is a dotted pair list (key . value), you need cdr to retrieve the value.

 

   (setq i (1+ i)) ; up the counter, for next entry

) ; end while

 

Check the links for more info on each function and how it works. For a complete list of selectionset functions, check the: Selection Set Manipulation Functions Reference.

 

Hope this helps (if even a little) to understand how to work with selection sets, as its realy one of the most powerfull (& most used) parts of AutoLISP.

Message 12 of 21

Kent1Cooper
Consultant
Consultant

@roland.r71 wrote:

@Jonathan.Trostad wrote:

....

3) FOREACH entity, get the length of the polyline (possibly by grabbing the DXF 10 out of the entity and doing math)

....


....

   (setq ent (entget (ssname ss i))) ; retrieve entity data for entry "i" (0 is first, 1 is second !!!)

.... 

From here you can retrieve the values for each DXF groupcode....

This includes retrieving the length.

   (setq entLength (cdr (assoc 10 ent))) ; this will retrieve the value for DXF group code 10. ....


 

Watch out!  @Jonathan.Trostad should have talked about getting all  the DXF 10 entries [plural] out of the entity data list and doing math [which, if they're thinking about adding up distances between vertices, wouldn't give an accurate result if there are arc segments involved], but @roland.r71 seems to have been misled by the actual wording into thinking that DXF 10 holds the length of a LWPolyline.  It does not, any more than DXF 70 was apparently assumed to, back in Message 3!  Getting the content from DXF 10 [or, in AutoLisp extracting-information format, (cdr (assoc 10 ent)) ] will get you only the coordinates of the location of the first vertex.  If any  DXF entry in entity data stored the length, the OP's task would be considerably easier [it could be filtered for in (ssget)], but none does.

 

You don't need to extract the entity data list from the entities in the selection set for what the OP wants to do.  You do need to step through the set, but you can get the length of each without pulling its entity data list.  Carrying on from parts of @roland.r71's sequence of events:

 

(setq

  ename (ssname ss i); just the entity, not the entity data list

  elength (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename))

)

 

Then elength can be compared to the desired range, and something done with ename depending on the result [removed from the selection set, or put into a different one, or deleted, or moved to a special Layer, or whatever].

Kent Cooper, AIA
Message 13 of 21

roland.r71
Collaborator
Collaborator

Yeah, good point.

Although I'm actually fully aware that you can't retrieve the total length for a lwpolyline that easily, my goal was to explain the basics of working with a selection set using the forementioned DXF code, and failed to adress the fact that for the given case, getting to the lwpolyline length, this wouldn't actually work.

 

So I kinda misled everyone, including myself, by focussing on the 'how to work with selection sets', neglecting the actual issue from the OP. Smiley Embarassed

Message 14 of 21

john.uhden
Mentor
Mentor

Oh, cut it out.  Your message was clear, and I'm sure the OP learned a lot from it.

Kent just tends to be "the closer."  God bless him.

Though it strikes me that he must be independently wealthy to have such free time.

Even though I cooked dinner and it's keeping warm in the oven, I am being yelled at right now.  😕

They tell me I should have a hobby.  Umm, er, I thought this was.  But I think the hobby is supposed to be weeding the gardens <yech>.

John F. Uhden

0 Likes
Message 15 of 21

Anonymous
Not applicable

I really aprecciate this explaination since im starting with autolisp this is very helpful im going to try to build the code in this way

0 Likes
Message 16 of 21

Anonymous
Not applicable

I really apreciate this example but I can`t make it work, should I run the funtion from the command prompt ?

and after place the selection set (filterByLength (ssget "_X" '((0 . "LINE,*POLYLINE"))) nil, 2.5).

 

I think i need more experience with this

0 Likes
Message 17 of 21

Anonymous
Not applicable

Cooper

you are right it works, i`m going to test this way in some of drawings that i have. the problem that i had with q select is that some times i put the length but it doesn select anything. and always is with polylines with lines I don,t have any problem.

0 Likes
Message 18 of 21

_gile
Consultant
Consultant

In the OP, you said: "im triying something like this (ssget "X" '((0 . "LWPOLYLINE")(-4 . "=")(70 . 1)))"

So while the 'filterByLength' routine is loaded, in your code you replace

(ssget "X" '((0 . "LWPOLYLINE")))

with something like this

(filterByLength (ssget "_X" '((0 . "LWPOLYLINE"))) 2.5 5.0)

If you want to simply highlight the selection, always after having loaded filterByLength routine, paste the following expression in the command line:

(sssetfirst nil (filterByLength (ssget "_X" '((0 . "LWPOLYLINE"))) 2.5 5.0))

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 19 of 21

Jonathan.Trostad
Advocate
Advocate

@roland.r71 I would argue that your explanation of why I don't need step 2 is actually how I would accomplish step 2. You did convert the selection set to a list.

@Kent1Cooper You are right. My thought was to measure point to point distances. I had not considered curves. As per typical you seem to think these things out a bit better than most.

 

Cheers,

0 Likes
Message 20 of 21

john.uhden
Mentor
Mentor
IMHO, converting a selection set to a list is handy for sorting or using
mapcar.

John F. Uhden

0 Likes