Author Topic: easy filter  (Read 8287 times)

0 Members and 1 Guest are viewing this topic.

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
easy filter
« Reply #15 on: July 11, 2004, 12:10:34 PM »
Here's my spin on this. I collect the layer names that use the specified linetype and use those in the selection set filter, combined with the specified linetype filter for those entity types that don't use bylayer.

Returns the ss, so in the calling function to get "continuous" "line"s you'd do this:
(setq ss (get-ltype-ents "CONTINUOUS" "LINE")
or to get "dashed" "circle"s:
(setq ss (get-ltype-ents "DASHED" "CIRCLE"))

Code: [Select]

(defun  get-ltype-ents (ltype etype / doc layers laylist)
  (vl-load-com)
  (setq doc (vla-get-activedocument (vlax-get-acad-object))
layers (vla-get-layers doc))
  (vlax-for lay layers
    (if (not (wcmatch (vla-get-name lay) "*|*"));skip xref layers
      (if (= (vla-get-linetype lay) ltype)
(if (not laylist)
 (setq laylist (vla-get-name lay))
 (setq laylist (strcat laylist "," (vla-get-name lay)))
 )
)
      )
    )
  (princ "\nMake selection......")
  (setq ss (ssget (list (cons 0 etype) '(-4 . "<OR") (cons 6 ltype) (cons 8 laylist) '(-4 . "OR>"))))
  )

rude dog

  • Guest
easy filter
« Reply #16 on: July 14, 2004, 01:49:52 AM »
Jeff seen you jumped in to help thanks....I'm still pretty new to this stuff and havent messed with vlisp, objectARX...so some of your code is kinda foriegn to me but I think i get the jist of it.....Thanks for the help guys.
and CAB for getting off the ground...my huge problem area is error checking so if any one feels like chopping and dicing away...go for it...its how I'will learn...I know for a fact there is a razor sharp cleaver in denmark  :)
Code: [Select]

(defun c:gtl ()
(prompt "\nSelect continuous ltype lines to filter ")
(setq 1ss (ssget '((0 . "Line"))))
(setq Lss (sslength 1ss))
(setq ssgrp (ssadd))
(setq cntr 0)
(while (< cntr Lss) (setq entnam (entget (ssname 1ss cntr)))
(setq Ln (cdr (assoc 8 entnam)))
(setq ssnam (cdr (assoc 6 (tblsearch "Layer" (eval Ln)))))
(if (= ssnam "Continuous")
(progn
(setq entnam (cdr (assoc -1 entnam)))
(setq ssgrp (ssadd entnam ssgrp))))
(setq cntr (1+ cntr)))
(prompt " \n To access filtered selection set: <!ssgrp> ")
(princ)
)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
easy filter
« Reply #17 on: July 14, 2004, 08:15:21 AM »
Good job Rude Dog.
A few comments from me. The routine works, that is good. :)
There are many ways to accomplish the same thing so it
may be the way someone likes to write the code which is
coders preference. Also these small routines tend to have
minimal error checking, that's OK too as long as the end user
understands that. I made a few observations in the code below
indicating the way I like to do some things, although I don't
always follow my own rules.

The routine collects LINE objects that the user selects and
then returns those with the LAYER set to Continuous. It does not
return lines set to Continuous with a layer set to a line type
other than Continuous. Is that your intention?
Code: [Select]
(defun c:gtl ()
  (prompt "\nSelect continuous ltype lines to filter ")
  (setq 1ss (ssget '((0 . "Line"))))
  ;;  if the user presses enter with nothing
  ;;  selected (sslength nil) fails
  (setq lss (sslength 1ss))
  (setq ssgrp (ssadd))
  (setq cntr 0)
  (while (< cntr lss)
    ;;  next line gets the entity list not the entity name
    ;;  perhaps entlst would be better than entnam
    (setq entnam (entget (ssname 1ss cntr)))
    (setq ln (cdr (assoc 8 entnam)))
    ;;  eval is not needed and you could combine the next 2 lines
    ;;(setq ssnam (cdr (assoc 6 (tblsearch "Layer" (eval ln)))))
    ;;(if (= ssnam "Continuous")
    ;;  resulting in the line below, eleminates the var ssnam
    (if (= (cdr (assoc 6 (tblsearch "Layer" ln))) "Continuous")
      ;;  you can eleminate the progn by combining the setq's
      ;;(progn
      ;;  (setq entnam (cdr (assoc -1 entnam)))
      ;;  (setq ssgrp (ssadd entnam ssgrp))
      ;;)
      ;;  like this
      (setq entnam (cdr (assoc -1 entnam))
            ssgrp  (ssadd entnam ssgrp)
      )

    )
    (setq cntr (1+ cntr))
  )
  (prompt " \n To access filtered selection set: <!ssgrp> ")
  (princ)
)
;;  you may want to tell the user how to run the routine
(prompt " \nLine Grabber Loaded, Enter gtl to run.")
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

SMadsen

  • Guest
easy filter
« Reply #18 on: July 14, 2004, 08:17:52 AM »
Rude dog,
There isn't much to butcher in your code. If you only intend to select entities on layers with linetype "Continuous", regardless of the object linetype, then it works perfectly.

A few notes, though:
The routine crashes if the user doesn't make a valid selection. Wrapping the whole thing in a condition will avoid that situation.

There's no need to use EVAL when searching the layer table. Evaluating a string has no real meaning.

SSADD manipulates the selection set directly so you only have use for its return value when creating a new sset, not when adding entities to it. Using SETQ only adds to the heat.

Instead of creating an additional selection set, you can also remove from an existing one with SSDEL. It works the same way as SSADD does. However, it requires a sligthly different construct of the loop because you can't fiddle with the length of the selection set and keep incrementing the counter at the same time.

This is how the same routine might be written using SSDEL:

Code: [Select]
(defun c:gtl (/ cntr entnam ssnam Ln)
  (prompt "\nSelect continuous ltype lines to filter ")
  (cond ((setq ssgrp (ssget '((0 . "Line"))))
         ;; Don't go further if a selectionset isn't created
         ;; Work with one and only one selection set
         (setq cntr 0)
         (while (setq entnam (ssname ssgrp cntr))
           (setq Ln (cdr (assoc 8 (entget entnam))))
           (setq ssnam (cdr (assoc 6 (tblsearch "Layer" Ln))))
           ;; if layer ltype is not "Continuous"
           (if (/= ssnam "Continuous")
             ;; .. then remove entnam
             (ssdel entnam ssgrp)
             ;; .. else increment counter
             (setq cntr (1+ cntr))
           )
         )
         (princ "\n To access filtered selection set: <!ssgrp> ")
        )
  )
  (princ)
)


You may want to take a different approach, though. The code below collects all layers that have the linetype "Continuous" and applies them to an SSGET filter. It is shorter in the sense that a selection set is created immediately without the need to run through it afterwards.
It is divided into three functions: a layer table searcher, a selection set builder and a command to deliver a global selection set. With it you can simply call (gtl) during an editing command to get the selection, or you can use it as a command to create a global selection set. The advantage seen from a coding point of view is that the layer table searcher is reusable. Say you want to make a filter for colors; just change the condition and voilá, new tool. Or simply add additional arguments when needed.

By the way, it filters for entities with bylayer linetype, also. Just remove the '(6 . "Bylayer) if it shouldn't do that.

Code: [Select]
(defun getLtLayer (ltype / ltlayer ltfilter)
  (setq ltfilter "")
  (while (setq ltlayer (tblnext "LAYER" (not ltlayer)))
    (and (= (strcase ltype) (strcase (cdr (assoc 6 ltlayer))))
         (setq ltfilter (strcat (cdr (assoc 2 ltlayer)) "," ltfilter))
    )
  )
  ltfilter
)

(defun gtl (/ lyrfilter sset)
  (and (setq lyrfilter (getLtLayer "Continuous"))
       (princ "\nSelect continuous ltype lines to filter ")
       (setq sset (ssget
                (list '(0 . "LINE") (cons 8 lyrfilter) '(6 . "Bylayer"))
              )
       )
  )
  sset
)

(defun C:GTL ()
  (if (setq ssgrp (gtl))
    (princ "\n To access filtered selection set: <!ssgrp>")
    (princ "\n No luck this time, buddy")
  )
  (princ)
)

SMadsen

  • Guest
easy filter
« Reply #19 on: July 14, 2004, 08:18:17 AM »
Oops, didn't see you sneak in there, CAB

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
easy filter
« Reply #20 on: July 14, 2004, 08:37:11 AM »
Hey Stig,
Great examples, really like the last one, reusable code.

one question on ssadd, you said
Quote from: Stig
SSADD manipulates the selection set directly so you only have use for its
return value when creating a new sset, not when adding entities to it.
Using SETQ only adds to the heat.

Do you prefer using
Code: [Select]
setq ssgrp '()) to create a null list?

I always learn from your post, Thanks.
« Last Edit: July 05, 2010, 10:37:06 AM by CAB »
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

SMadsen

  • Guest
easy filter
« Reply #21 on: July 14, 2004, 09:00:57 AM »
Quote from: CAB
Do you prefer using
Code: [Select]
setq ssgrp '()) to create a null list?

Ummm, not sure what you mean.

(setq ssgrp (ssadd))
will create an empty selection set and assign it to ssgrp but,

(ssadd some_entity ssgrp)
will modify ssgrp without the need to grab the return value. With SSADD it doesn't really matter if you grab the return value - other than it's redundant - but with SSDEL you will risk loosing the entire selection set. E.g.:

(setq sset (ssget))
(if (setq ent (entsel "\nPick an object to remove: "))
..(setq sset (ssdel (car ent) sset))

If ent is not part of sset then SSDEL will return nil and you'll loose the selection set. So, getting into the habit of using either of the two without SETQ is a good thing.

Added: on second thought, I do think it matters with SSADD knowing that there are only so many sset slots available and using SETQ will probably create a copy? Dunno. Haven't tested it.

Anonymous

  • Guest
easy filter
« Reply #22 on: July 14, 2004, 09:16:10 AM »
fantastic comments and examples thanks :!:  :!:
Quote

The routine collects LINE objects that the user selects and
then returns those with the LAYER set to Continuous. It does not
return lines set to Continuous with a layer set to a line type
other than Continuous. Is that your intention?

Cab, I was trying not not admitt this but the whole bylayer thing kinda confuses me :oops:
I just wanted the program to filter out lines that have a continuous linetype....just like if we opened a new session of autocad and drew a line with layer "0" set current and changed nothing....these are the type of lines I was after....I never have changed a lines linetype that comes default with its color.....
way to break it down in steps stig for later use....you da man
thanks for everyones time.....!

rude dog

  • Guest
easy filter
« Reply #23 on: July 14, 2004, 09:17:53 AM »
:oops:
that be me again

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
easy filter
« Reply #24 on: July 14, 2004, 09:42:15 AM »
Quote from: SMadsen
Quote from: CAB
Do you prefer using
Code: [Select]
setq ssgrp '()) to create a null list?

Ummm, not sure what you mean.


My mistake, I thought you were refering to
Code: [Select]
(setq ssgrp (ssadd ))
but you were actuall talking about
Code: [Select]
(setq ssgrp (ssadd entnam ssgrp))

Still good info on ssdel, I'm glad I asked. Didn't know that.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
easy filter
« Reply #25 on: July 14, 2004, 10:30:38 AM »
rude dog
the ByLayer thing is a way to control line type on a layer basis. Usually the Layer
line type is set to 'Continuous' and any line you draw on that layer is continuous.
The actual line has ByLayer as a line type so the LAYER controls the line type.
Say you have a layer called 'Medium Dashed' and you set the line weight to 'Medium'
which is controlled by your plot style stb file. I have a plot style called 'Arch D'
so lines weight for 'Medium' in that plot style is 0.30 so the line will plot at 0.30
when using that plot style.
In my LAYER 'Medium Dashed' the line type is set to 'DASHED'. When the line type of the
entity is ByLayer the LAYER line type controls the line type. The object will have a
DASHED line type applied to it. I can override the DASHED line type by changing the
objects line type to 'Continuous' instead of 'ByLayer' to get a continuous line.

I use this when I have a layer like 'Ceiling Details' and the line type is set to
'Short Dash'. All my lines on that layer have a Short Dash. On occasion I need to
differentiate a detail so I'll change that line type to 'Very Short Dash' or something
else besides 'Short Dash'.

Not sure if this helped or hurt. But the bottom line, pun intended, is the line with
'Continuous' in the linetype will have a continuous line displayed AND a line with
ByLayer' in the linetype and the Layer has 'Continuous' in the linetype will also have
a continuous line displayed. So if you want a selection set that contains lines that
"Display" a continuous line on the screen, you have to filter for both.

Stigs' filter:
Code: [Select]
(ssget '((0 . "LINE")(6 . "Continuous,Bylayer")))
will get the two types of lines and all you have to do is test the ByLayer group to see if
any layers have Continuous as a line type. Stigs last code example showed us yet another
way to do this.

I'm done.  :shock:
 CAB
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.