filter selection with entsel

Discussion in 'AutoCAD' started by p.bassetto, Aug 18, 2004.

  1. p.bassetto

    p.bassetto Guest

    I created a lisp that count a number of block entities (by block name) in a selection set. It works if I select a block, but it results in an error if the selection is empty or not a block.
    What can I add to make the lisp accept the correct selection?
    be patient, please, I'm a real beginner!
    thanks
    Paolo

    (setq bl (assoc 2 (entget (car (entsel "\n Select the block entity you want to count:")))))
     
    p.bassetto, Aug 18, 2004
    #1
  2. p.bassetto

    Tom Smith Guest

    If no selection is made, entsel returns nil, and your version will crash on
    (entget (car nil)). Any time you do an entsel you need to check for no
    selection being made. Something along the lines of:

    (if (setq ent (entsel "\n Select the block entity you want to count:"))
    (progn
    (setq bl (assoc 2 (entget (car ent))))
    <do whatever else here>
    )
    )

    Note that all the rest of the program execution needs to be made contingent
    on this, because if ent isn't picked, then bl has no value.
     
    Tom Smith, Aug 18, 2004
    #2
  3. p.bassetto

    p.bassetto Guest

    I added your part and if I select nothing it exits the lisp quietly without errors, but if I select a line or circle... it gives me a mistake (error: bad SSGET list) because he aspects later in the routine a block name (setq ss (ssget (list bl))) , bl should be something like:(2 . "45park").
    so how can I introduce this second condition (select block only)?
    thank you
     
    p.bassetto, Aug 18, 2004
    #3
  4. p.bassetto

    Jim Claypool Guest

    This will make certain first that an object was selected, then that is is a
    block.
    (setq not_ok 1)
    (while not_ok
    (while (not (setq ename (entsel "\nSelect the bllock entity you want to
    count"))))
    (setq ename (car ename))
    (if (= (cdr (assoc 0 (entget ename))) "INSERT")
    (setq
    bl (cdr (assoc 2 (entget ename)))
    not_ok nil
    )
    (alert "Object selected is not a block")
    )
    )

    Or, rather than using entsel, you could do this.

    (while (not (setq ss (ssget ":S" '((0 . "INSERT"))))))
    (setq bl (cdr (assoc 2 (entget (ssname ss 0)))))


    a selection set. It works if I select a block, but it results in an error if
    the selection is empty or not a block.
    want to count:")))))
     
    Jim Claypool, Aug 18, 2004
    #4
  5. p.bassetto

    Tim Badger Guest

    Try this.

    (setq ed nil)
    (while(= ed nil)
    (if (setq ed(entsel "\nSelect Block: "))(progn
    (setq ed(entget(car ed)))
    (if(equal (cdr(assoc 0 ed)) "INSERT")
    (progn

    PLACE WHAT YOU WANT TO DO WITH THE BLOCK HERE

    );-end progn
    (setq ed nil)
    );-end if
    ));-end progn and if
    );-end while


    TimB


    without errors, but if I select a line or circle... it gives me a mistake
    (error: bad SSGET list) because he aspects later in the routine a block name
    (setq ss (ssget (list bl))) , bl should be something like:(2 . "45park").
     
    Tim Badger, Aug 18, 2004
    #5
  6. p.bassetto

    autocart Guest

    do you mean how to create the dotted pair (2 . "45park")?
    (cons 2 bl) ;bl must be an atom to create a dotted pair
     
    autocart, Aug 18, 2004
    #6
  7. Here is how I like to set up filters with entsel. This will loop
    until all filters are met.

    (while (not (and
    (setq ent (entsel "\nSelect Block: "))
    (setq ent_data (entget (car ent)))
    (setq bl (assoc 2 ent_data))
    (= (cdr bl) "45park")
    ;;;add more filters if needed
    )
    )
    )

    --
    Ken Alexander
    Acad2004
    Windows XP

    "We can't solve problems by using the same kind
    of thinking we used when we created them."
    --Albert Einstein

    without errors, but if I select a line or circle... it gives me a
    mistake (error: bad SSGET list) because he aspects later in the
    routine a block name (setq ss (ssget (list bl))) , bl should be
    something like:(2 . "45park").
     
    Ken Alexander, Aug 18, 2004
    #7
  8. p.bassetto

    Tom Smith Guest

    (while(= ed nil)

    Sorry to be picky, but I keep seeing this in lisps, and its a pet peeve. The
    proper test for a thing being nil is the function null. The = function
    should be reserved for numerical comparison. It's shorter and clearer to
    use:

    (while (null ed) ...
     
    Tom Smith, Aug 18, 2004
    #8
  9. p.bassetto

    MP Guest

    instead of putting it all in one line, divide the steps and check for errors
    along the way
    (setq selection(car (entsel "\n Select the block entity you want to
    count:")))
    (if selection
    (progn
    (setq entlist(entget selection))
    (if(= "INSERT"(cdr(assoc 0 entlist)));it's a block
    (setq blkName (assoc 2 entlist))
    (princ"\nNot a block")
    );if a block
    );progn
    (princ"\nNothing selected")
    );if selection

    if you don't want the error reports you can also put the logic flow into an
    'and' clause
    (and
    (setq selection(car (entsel "\n Select the block entity you want to
    count:")))
    (setq entlist(entget selection))
    (= "INSERT"(cdr(assoc 0 entlist)))
    (setq blkName (assoc 2 entlist))
    );and

    if at the end of that 'and' clause blkName is still nil, you know something
    went wrong, but you don't necessarily know if it was no selection or a
    non-insert selection

    so depends on how you want to structure your code in a given instance

    hth
    mark

    a selection set. It works if I select a block, but it results in an error if
    the selection is empty or not a block.
    want to count:")))))
     
    MP, Aug 18, 2004
    #9
  10. p.bassetto

    p.bassetto Guest

    thank you to everybody, I learned something new. now my lisp works and it doesn't stop on wrong inputs.
    paolo
     
    p.bassetto, Aug 18, 2004
    #10
  11. p.bassetto

    Tom Smith Guest

    As the others mentioned, you need to test for every necessary condition --
    if your program requires a block name, then you need to test for that too.

    You should try each of the solutions offered. A side effect of the while
    loop constructions is that they will keep on prompting you forever until you
    pick the right object, or cancel the function. That may or may not be what
    you want. To me, it depends on the nature of the function. Often I don't
    want relentless repeating prompts, but would prefer that the function just
    quietly exit if I don't pick anything.

    Another way to approach this kind of thing is with a cond:

    (cond
    ((null (setq ent (entsel "\n Select the block entity you want to
    count:")))
    (princ "\nNothing selected.")
    )
    ((/= "INSERT" (cdr (assoc 0 (setq edata (entget (car ent))))))
    (princ "\nNot a block.")
    )
    <more tests here if necessary>
    (t
    (setq bl (cdr (assoc 2 edata)))
    <the rest of your code goes here>
    )
    )

    The cond lets you test for each necessary condition in a given order, in a
    clear way, and optionally report what's wrong. The trick is to set up each
    test so that if it fails to do the expected thing, the cond is exited. The
    last test t will always trigger whatever follows it, if your program
    execution gets that far.

    Over time, you'll notice that when you have multiple conditions to test, it
    can get very confusing to use a series of nested if's. In those cases, a
    cond construction can be a clearer way of doing the same thing.
     
    Tom Smith, Aug 18, 2004
    #11
  12. p.bassetto

    Tim Badger Guest

    Does your pet peeve do the job? If so, it's correct. That could be why you
    keep seeing it in lisps. You use null - and that's fine, and many of us use
    nil - and that's fine. B.T.W. I count 14 characters either way.
     
    Tim Badger, Aug 18, 2004
    #12
  13. p.bassetto

    Jürg Menzi Guest

    Hi Paolo

    This function works for most 'entsel' purposes:
    Code:
    (defun MeExtEntsel (Pmt Lst Err / CurEnt ExLoop)
    (while (not ExLoop)
    (initget " ")
    (setq CurEnt (entsel Pmt))
    (cond
    ((eq CurEnt "") (setq ExLoop T CurEnt nil))
    (CurEnt
    (if (apply 'and
    (mapcar '(lambda (l) (member l (entget (car CurEnt)))) Lst)
    )
    (setq ExLoop T)
    (princ (strcat " the selected object is not a " Err "!"))
    )
    )
    ((princ " 1 selected, 0 found. "))
    )
    )
    CurEnt
    )
    
    Returns:
    - User select a correct entity: '(<Ename> '(x y z))
    - User select a wrong entity: remains in loop, print error message
    - User pick nothing: remains in loop, print message '1 selected, 0 found.'
    - User press Enter, Space or right mouse click: nil
    Use:
    Code:
    (MeExtEntsel
    "\nSelect block: "
    '((0 . "INSERT")(2 . "MyBlock"))
    "not a block named MyBlock"
    )
    
    Cheers
     
    Jürg Menzi, Aug 18, 2004
    #13
  14. Trying to stay with the same practices as most Acad commands, are
    there any that when asked to select an object will exit the command on
    a missed pick? I agree that the nature of the function and personal
    preference come into play. But I wouldn't call the while loop's
    "loop" a side effect, it fulfills its purpose..... to loop until
    desired conditions are met.

    --
    Ken Alexander
    Acad2004
    Windows XP

    "We can't solve problems by using the same kind
    of thinking we used when we created them."
    --Albert Einstein
     
    Ken Alexander, Aug 18, 2004
    #14
  15. p.bassetto

    Doug Broad Guest

    Tim,
    We all come here to share. It is expected that
    our code will be critiqued. It does no good to
    be offended by such criticism. The real tragedy
    is when the criticism ceases. To offer a comparison,
    there is more than the number of characters to consider.

    Consider these timing tests:

    (defun one ()(= a nil))
    (defun two ()(equal a nil))
    (defun three ()(null a))
    (defun four ()(not a))
    (load "bench")

    (bench '(one two three four) nil '(1000))

    ONE
    Elapsed: 100
    Average: 0.1000

    TWO
    Elapsed: 110
    Average: 0.1100

    THREE
    Elapsed: 80
    Average: 0.0800

    FOUR
    Elapsed: 110
    Average: 0.1100
     
    Doug Broad, Aug 18, 2004
    #15
  16. p.bassetto

    Tom Smith Guest

    Well, strictly speaking there's one less character in (null <thing>) than in
    (= nil <thing>). But I didn't mean shorter in character count, I meant it's
    shorter in terms of (<operator> <operand>) versus (<operator> <operand>
    <operand>).

    One version uses a direct test -- does this symbol evaluate to nil? The
    other uses a roundabout test requiring another symbol -- is the evaluation
    of this symbol numerically equal to the evaluation of the predefined symbol
    nil. "Is it nil?" versus "does it represent the same number as the thing we
    call nil."

    Yes, both "do the job." Just as (1+ <n>) returns the same thing as (+ 1 <n>)
    and (zerop <n>) returns the same thing as (= 0 <n>) and (minusp <n>) returns
    the same thing as (> 0 <n>). In each case, there's a direct operation that
    can be performed on the single symbol in question, versus an alternate
    version that requires another symbol to be brought in.

    Do whatever you want. In each of these cases, I prefer the more succint
    version, not because of counting characters or any difference in execution
    speed, but because to my mind it's simply more direct and conceptually
    clear. I apologize if I upset or offended you.
     
    Tom Smith, Aug 18, 2004
    #16
  17. Hi Ken,

    Two that come to mind.

    Command: divide
    Select object to divide: *Invalid*

    Command: measure
    Select object to measure: *Invalid*

    Never have liked those messages!
     
    Jason Piercey, Aug 18, 2004
    #17
  18. Thanks Jason.

    Hanging my head.....I made a divide function before I realized there
    already was one. Mine loops until selected or esc'd out.

    --
    Ken Alexander
    Acad2004
    Windows XP

    "We can't solve problems by using the same kind
    of thinking we used when we created them."
    --Albert Einstein
     
    Ken Alexander, Aug 18, 2004
    #18
  19. p.bassetto

    Tim Badger Guest

    I welcome critique... always have and always will. Might be the lack of
    sleep and to much coffee, but I did not see where Tom's post was being
    constructive in this case. Sorry, but it just struck me as coming across
    more as a fixation. Could be I need more sleep and less coffee ;)

    TimB


    snip:
     
    Tim Badger, Aug 18, 2004
    #19
  20. I don't know why those two commands act the
    way they do. Perhaps they just haven't been
    updated behave like most other commands.
     
    Jason Piercey, Aug 18, 2004
    #20
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.