Filtering using entity name / handle

Discussion in 'AutoCAD' started by RaghuMN, Dec 29, 2004.

  1. RaghuMN

    RaghuMN Guest

    Hi all,

    I have 2 entities (point / block / text) at same point.
    I know 1 of them and want to select the other leaving out the known one. How can I do that?

    This does not work for me.

    ;get the details of 1 entity (block)
    (Setq a (car (entsel))) ;get the 1st entity
    (setq det (entget a)) ; details of a
    (setq e (cdr (assoc -1 det))) ; entity name
    (setq h (cdr (assoc 5 det))) ; handle
    (setq i (cdr (assoc 10 det))) ;insertion point

    ;now try to select the other feature

    ;tried using handle
    (setq oth (ssget "x" (list (cons 0 "insert")(cons 10 i)(cons -4 "<NOT")(cons 5 h)(cons -4 "NOT>"))))

    ;tried using entity name
    (setq oth (ssget "x" (list (cons 0 "insert")(cons 10 i)(cons -4 "<NOT")(cons -1 e)(cons -4 "NOT>"))))

    Thanks for any advice.

    MNRaghu
     
    RaghuMN, Dec 29, 2004
    #1
  2. RaghuMN

    Joe Burke Guest

    RaghuMN,

    I'm confused. Are you trying to make a selection set containing only a text object
    which shares the same insertion point as a block insert?

    Joe Burke
     
    Joe Burke, Dec 29, 2004
    #2
  3. RaghuMN

    RaghuMN Guest

    Joe,
    I mean It's of the same entity type.
    If there are 2 entities at the same insertion point, both are of same type, i.e., block and block, text and text, etc.

    So, I know the handle/entity name of one block at the point where another block resides. I want to catch that another block, leaving the known block.

    Hope I have clarified the doubt to some extent.

    Thanks,

    MNRaghu
     
    RaghuMN, Dec 29, 2004
    #3
  4. RaghuMN

    Joe Burke Guest

    RaghuMN,

    Yes, that helps to clarify the issue.

    Let's assume what I suspect is the most difficult case. You have two text objects
    which share a common insertion point. The IP of one of the two (call it TEXT1) is
    known. You want the other text object (call it TEXT2) to be added to a selection set,
    which excludes TEXT1.

    There's a fundamental problem with the idea you might be able to use the TEXT1 IP, to
    select TEXT2. It will only work if the pickbox covers some part of the TEXT2 object.
    And that will be zoom dependant.

    IOW, I don't see a way to reliably ssget the TEXT2 object by passing a point, while
    excluding the TEXT1 object.

    Consider the possibility, the TEXT2 object might also include leading spaces. Which
    would in turn make selecting it by point, all the more problematic.

    Similar ideas apply to blocks, where the block IP might not be on an object within
    the block.

    Joe Burke
     
    Joe Burke, Dec 29, 2004
    #4
  5. You can step though the selection set comparing the handles of all the
    objects, and then (ssdel) the object that matches the handle of your
    original object. You may want to use a crossing window selection set based
    upon a certain distance from the insertion point of the original text to
    ensure that it finds the other objects. Sort of what Joe Burke was
    concerned about.
     
    Allen Johnson, Dec 29, 2004
    #5
  6. RaghuMN

    RaghuMN Guest

    Thanks for the clarifications Joe and Allen.

    Gentlemen, hope I have got you correctly, that, using handle and entity name in the ssget function (directly) does not work. Hoping for any shorter solutions in future,

    Thanks,

    MNRaghu
     
    RaghuMN, Dec 30, 2004
    #6
  7. RaghuMN

    James Allen Guest

    From help file:
    "The ssget function recognizes all group codes except entity names
    (group -1), handles (group 5), and xdata codes (groups greater than 1000)."
    Sorry. What is your application? Are you deleting duplicate objects?
    --
    James Allen, EIT
    Malicoat-Winslow Engineers, P.C.
    Columbia, MO


    name in the ssget function (directly) does not work. Hoping for any shorter
    solutions in future,
     
    James Allen, Dec 31, 2004
    #7
  8. RaghuMN

    RaghuMN Guest

    James, thanks for making the issue more clear.

    Yes, my intention was to delete the duplicate objects. I now get the selection set and find the other object if it is not same as the known object using conditional statement.

    Thanks,

    MNRaghu
     
    RaghuMN, Jan 3, 2005
    #8
  9. RaghuMN

    James Allen Guest

    You're welcome.

    Along the lines of what Allen suggested, would this work for you?

    (Setq a (car (entsel))) ;get the 1st entity
    (setq det (entget a)) ; details of a
    (setq flt det) ; initialize filter
    ;; remove invalid group codes
    (foreach code '(-1 5 330)
    (setq flt (vl-remove (assoc code flt) flt))
    )
    (setq oth (ssget "x" flt)) ; ssget all identical-to-a
    (ssdel (ssname oth 0) oth) ; remove one entity

    If the entities are truly identical then it doesn't matter which one you
    keep, right?

    James


    selection set and find the other object if it is not same as the known
    object using conditional statement.
     
    James Allen, Jan 3, 2005
    #9
  10. RaghuMN

    RaghuMN Guest

    Thanks for the idea James.
    I had never thought in the way you showed me to tackle this situation.
    A good learning experience.

    Thanks,

    MNRaghu
     
    RaghuMN, Jan 4, 2005
    #10
  11. RaghuMN

    Joe Burke Guest

    Hi James,

    Using 2004 on a Dell 3GHz machine. I think both functions do the same thing.

    Just for fun... Though the bounding box method involves more code, I always get
    Timer: 0.00000000 seconds, regardless of number of objects in the drawing. My test
    file has about 10k objects in model space.

    With the filter method, elapsed time seems to depends on the number of objects in the
    drawing. With as few as 2k objects, timer returns something on the order of 0.015
    seconds. With 10k objects, 0.078 seconds.

    In both cases the functions are deleting 7 of 8 duplicate text objects.

    Granted, the difference between too fast to measure and 0.08 is meaningless within
    context. But it might not be so if a calling function was using one of these as a
    sub-function to do what Overkill does.

    BTW, you might suspect the (command ".erase" ss "") thing in the filter function
    slows it down. Not so in my testing. Commented out returns essentially the same speed
    result.

    And the bounding box function counts deleted items within the timer, unlike the
    filter function.

    Regards
    Joe Burke

    ;; delete duplicate objects within bounding box
    (defun c:BBDeleteDup ( / ename obj ss minpt maxpt minpt* maxpt* idx cnt)
    (setq ename (car (entsel "\nSelect object: ")))
    (starttimer)
    (setq obj (vlax-ename->vla-object ename))
    (vla-getboundingbox obj 'minpt 'maxpt)
    (setq minpt (vlax-safearray->list minpt))
    (setq maxpt (vlax-safearray->list maxpt))
    (setq ss (ssget "W" minpt maxpt))
    (ssdel ename ss)
    (setq idx 0)
    (setq cnt 0)
    (repeat (sslength ss)
    (setq obj (vlax-ename->vla-object (ssname ss idx)))
    (vla-getboundingbox obj 'minpt* 'maxpt*)
    (setq minpt* (vlax-safearray->list minpt*))
    (setq maxpt* (vlax-safearray->list maxpt*))
    (if (and (equal minpt minpt*) (equal maxpt maxpt*))
    (progn
    (vla-delete obj)
    (setq cnt (1+ cnt))
    )
    )
    (setq idx (1+ idx))
    )
    (endtimer)
    (princ (strcat "\nNumber of objects deleted: " (itoa cnt)))
    (princ)
    )

    ;; delete duplicate objects with filtered selection
    (defun c:FilterDeleteDup ( / ent flt ss)
    (setq ent (car (entsel)))
    (starttimer)
    (setq flt (entget ent))
    (foreach code '(-1 5 330)
    (setq flt (vl-remove (assoc code flt) flt))
    )
    (setq ss (ssget "x" flt))
    (ssdel ent ss)
    (command ".erase" ss "")
    (endtimer)
    (princ (strcat "\nNumber of objects deleted: " (itoa (sslength ss))))
    (princ)
    )

    ;---------------------------------------------------------
    (defun StartTimer ()
    (setq *start* (getvar "date")))
    (defun EndTimer (/ end)
    (setq end (* 86400 (- (getvar "date") *start*)))
    (princ (strcat "\nTimer: " (rtos end 2 8) " seconds\n")))
    ;---------------------------------------------------------
     
    Joe Burke, Jan 4, 2005
    #11
  12. RaghuMN

    James Allen Guest

    You're welcome. Check out Joe's version too.

    James
     
    James Allen, Jan 4, 2005
    #12
  13. RaghuMN

    James Allen Guest

    Hi Joe,

    Interesting, I never thought about just comparing bounding boxes. But it
    looks like the speed difference has more to do with "x" vs. "w" than
    filtering. Consider the following code, which in my test was also too fast
    to measure.

    ;; delete duplicate objects with filtered selection
    (defun c:FilterDeleteDup2 ( / cnt enm flt minpt maxpt obj ss)
    (setq enm (car (entsel)))
    (starttimer)
    (setq obj (vlax-ename->vla-object enm))
    (vla-getboundingbox obj 'minpt 'maxpt)
    (setq minpt (vlax-safearray->list minpt))
    (setq maxpt (vlax-safearray->list maxpt))
    (setq flt (entget enm))
    (foreach code '(-1 5 330)
    (setq flt (vl-remove (assoc code flt) flt))
    )
    (setq ss (ssget "w" minpt maxpt flt))
    (ssdel enm ss)
    (command ".erase" ss "")
    (setq cnt (sslength ss))
    (endtimer)
    (princ (strcat "\nNumber of objects deleted: " (itoa cnt)))
    (princ)
    )

    In reality, I think the bounding box method would still need filtering as
    well. I'd be worried about catching non-like entities with identical
    bounding boxes; even totally different geometry, like a circle in a square
    for example. And of course there's the possibility of identical geometry
    with different properties. But I think by virtue of the windowed selection,
    yours would still blaze through with some post-filtering added to it.

    Personally, I wouldn't use mine as-is either though because mine, while
    short, makes no allowance for roundoff error. In fact in my own test, mine
    did not erase one piece of text that by all rights was identical. I would
    do more work on the filter (making use of the -4 relational tests to filter
    reals) whether using "x" or "w". It sure would be nice if they offered a
    built in "equal" operator with a fuz factor in the -4 relational tests...
    Oh well.

    The mention of a sub-function brings up another point. Windowed selection
    is of course view dependent. So is it faster overall to ssget "x", or zoom
    around selecting windows? I wonder if carefully crafted filters (allowing
    for tolerances) with ssget "x" wouldn't end up being faster in the end (I've
    noticed overkill does not zoom around). But then if you also want to handle
    merging/welding of overlapping geometry I think the filters would get yet
    more complex. And so on...

    Did you have good holidays?

    James
     
    James Allen, Jan 4, 2005
    #13
  14. RaghuMN

    Joe Burke Guest

    Hi James,

    Rereading my post, apparently I got lost in my own thought stream. :)

    The reason I played with it in the first place was to see what difference speedwise
    there might be between ssget "x" and "w". You know, why search the entire drawing, if
    there's a *reliable* way to limit the selection/search area. I emphasize reliable
    because I'm not sure a bounding box, without some tinkering, would be so. Tinkering:
    scale a point list representing all four points about its center to make it a bit
    larger. Then use "wp" rather than "w".

    The other idea, comparing bounding boxes, was simply to offer an alternative. It
    would work OK if you know the duplicates in question are exact copies on the same
    layer etc. Then again, as you said, a filtered selection in a limited area is equally
    as fast. So why bother with something which doesn't offer the flexibility of your
    method.

    I hadn't thought about the fact window selection is view dependent. Good point.

    As usual I figure we're just kicking it around. My last post reads like I'm
    suggesting this way is better than that. In fact, that was not my intention at all.
    Sorry if I gave the wrong impression.

    Regards
    Joe
     
    Joe Burke, Jan 5, 2005
    #14
  15. RaghuMN

    James Allen Guest

    Joe Burke _originally_ wrote: "Just for fun... " ;) Don't worry, that's
    how I took it. But it did get me thinking.

    Believe it or not, I don't think it had even occured to me to use the
    bounding box to generate a selection window. I think my existing routine
    uses a somewhat arbitrary crossing window (yeah, it's the zoom around kind).
    But for merging/welding, the crossing window may still be needed for this
    approach. For non-crossing windows, I agree about making the window a bit
    larger, especially with the potential loss of precision through graphic
    selection.

    I appreciate the thoughts.

    James
     
    James Allen, Jan 5, 2005
    #15
  16. RaghuMN

    Joe Burke Guest

    James,

    Total tangent as follows.

    The reason the bounding box approach came to mind is I've been playing with them
    recently when selecting an object in an xref.

    Example:
    (setq elst (nenselp "\nSelect object in xref: "))

    How do I indicate to the user an object in an xref was selected, assuming I don't
    want to copy the object into the active file? Which would let me highlight it. One
    solution, draw the object's bounding box using grdraw. I know you know this can be
    complicated stuff given an object which may be nested in blocks x levels deep within
    the xref block.

    I've worked all that stuff out recently based on the same ObjMartix and
    InverseObjMatrix functions I posted previously. What I didn't have before was a
    reliable transpose point function based on those functions. I'll post if you are
    interested. BTW, I took your advice. The TransPt function asks for a point, a list of
    blocks (don't ask until you see it) and "from" and "to" arguments like the trans
    function. It works for me very nicely that way.

    Thanks for the idea based on code you posted elsewhere.

    Joe Burke
     
    Joe Burke, Jan 5, 2005
    #16
  17. RaghuMN

    James Allen Guest

    I like tangents. Interesting! And kinda scary. Among other things, I am
    basically messing with the same thing right now (xref-nested
    "highlighting"), but took the copy-the-object route. I started with a very
    careful re-evaluation of my error handling, and so far I haven't ended up
    with left over copied objects... Here's hoping. I am interested in seeing
    your work, though it may be a bit before I can give it a worthwhile look
    over (pretty erratic workload right now). And you're quite welcome.

    James
     
    James Allen, Jan 6, 2005
    #17
  18. RaghuMN

    Joe Burke Guest

    James,

    Here's the matrix functions again. They are not changed, other than comments, from
    what I posted last.

    I don't recall if I posted the TransPt function before. If I did, it didn't deal with
    deep nested blocks correctly. After beating on this version hard, I'm confident it
    does what it should.

    Agreed, when a program specifically prompts for select something in an xref, it
    should provide some visual feedback when the selection is successful. Copying the
    object so it can be highlighted is one way to do it. But as you know, doing that
    right is a bit involved code-wise. That's why I was playing with the other
    possibility, simply draw the object's bounding box. Of course for that I need all the
    following functions. So doing the bounding box right isn't exactly easy either.

    BTW, I don't have a clue on how to modify the matrix functions so they return the
    same matrix as nentselp when the block ref passed had a normal other than (0 0 1).
    Any help on that point would be much appreciated.

    Regards
    Joe

    ;; Apply a transformation matrix to a vector by Vladimir Nesterovsky
    (defun mxv (m v)
    (mapcar '(lambda (row) (apply '+ (mapcar '* row v))) m)
    ) ;end

    ;; Multiply two matrices by Vladimir Nesterovsky
    (defun mxm (m q / qt)
    (setq qt (apply 'mapcar (cons 'list q)))
    (mapcar '(lambda (mrow) (mxv qt mrow)) m)
    ) ;end

    ;; By Joe Burke with thanks to Larry Leuallen and John Uhden.
    ;; Returns the same block transformation matrix as nentselp,
    ;; except when the normal is something other than (0 0 1).
    ;; Haven't figured that one out yet.
    ;; argument vobj: a block reference ename or vla-object
    (defun ObjMatrix ( vobj / ang inspt xsf ysf zxf
    sclmatrix rotmatrix movmatrix resmatrix )
    (if (= (type vobj) 'ENAME)
    (setq vobj (vlax-ename->vla-object vobj))
    )
    (and
    (= "AcDbBlockReference" (vlax-get vobj 'ObjectName))
    (setq ang (vlax-get vobj 'Rotation))
    (setq inspt (vlax-get vobj 'InsertionPoint))
    (setq xsf (vlax-get vobj 'XScaleFactor))
    (setq ysf (vlax-get vobj 'YScaleFactor))
    (setq zsf (vlax-get vobj 'ZScaleFactor))
    ;test for non-uniformly scaled block
    (equal (abs xsf) (abs ysf) 1e-8)
    (equal (abs ysf) (abs zsf) 1e-8)
    (setq sclmatrix
    (list
    (list xsf 0 0 0)
    (list 0 ysf 0 0)
    (list 0 0 zsf 0)
    (list 0 0 0 1)
    )
    )
    ;; if block is mirrored only X, Y or Z
    ;; else, all other mirrored combinations including none
    (if
    (or
    (and (minusp xsf) (not (minusp ysf)) (not (minusp zsf)))
    (and (not (minusp xsf)) (minusp ysf) (not (minusp zsf)))
    (and (not (minusp xsf)) (not (minusp ysf)) (minusp zsf))
    )
    (setq rotmatrix
    (list
    (list (cos ang) (sin ang) 0 0)
    (list (- (sin ang)) (cos ang) 0 0)
    (list 0 0 1 0)
    (list 0 0 0 1)
    )
    )
    (setq rotmatrix
    (list
    (list (cos ang) (- (sin ang)) 0 0)
    (list (sin ang) (cos ang) 0 0)
    (list 0 0 1 0)
    (list 0 0 0 1)
    )
    )
    )
    (setq movmatrix
    (list
    (list 1 0 0 (car inspt))
    (list 0 1 0 (cadr inspt))
    (list 0 0 1 (caddr inspt))
    (list 0 0 0 1)
    )
    )
    (setq resmatrix (mxm movmatrix (mxm sclmatrix rotmatrix)))
    ) ;and
    resmatrix
    ) ;end

    ;-------------------------------------------------------------------
    ;; returns an inverse matrix
    ;; argument vobj: a block reference ename or vla-object
    (defun InverseObjMatrix ( vobj / ang inspt xsf ysf zxf
    sclmatrix rotmatrix movmatrix resmatrix )
    (if (= (type vobj) 'ENAME)
    (setq vobj (vlax-ename->vla-object vobj))
    )
    (and
    (= "AcDbBlockReference" (vlax-get vobj 'ObjectName))
    (setq ang (- (vlax-get vobj 'Rotation)))
    (setq inspt (mapcar '- (vlax-get vobj 'InsertionPoint)))
    (setq xsf (/ 1.0 (vlax-get vobj 'XScaleFactor)))
    (setq ysf (/ 1.0 (vlax-get vobj 'YScaleFactor)))
    (setq zsf (/ 1.0 (vlax-get vobj 'ZScaleFactor)))
    (equal (abs xsf) (abs ysf) 1e-8)
    (equal (abs ysf) (abs zsf) 1e-8)
    (setq sclmatrix
    (list
    (list xsf 0 0 0)
    (list 0 ysf 0 0)
    (list 0 0 zsf 0)
    (list 0 0 0 1)
    )
    )
    (if
    (or
    (and (minusp xsf) (not (minusp ysf)) (not (minusp zsf)))
    (and (not (minusp xsf)) (minusp ysf) (not (minusp zsf)))
    (and (not (minusp xsf)) (not (minusp ysf)) (minusp zsf))
    )
    (setq rotmatrix
    (list
    (list (cos ang) (sin ang) 0 0)
    (list (- (sin ang)) (cos ang) 0 0)
    (list 0 0 1 0)
    (list 0 0 0 1)
    )
    )
    (setq rotmatrix
    (list
    (list (cos ang) (- (sin ang)) 0 0)
    (list (sin ang) (cos ang) 0 0)
    (list 0 0 1 0)
    (list 0 0 0 1)
    )
    )
    )
    (setq movmatrix
    (list
    (list 1 0 0 (car inspt))
    (list 0 1 0 (cadr inspt))
    (list 0 0 1 (caddr inspt))
    (list 0 0 0 1)
    )
    )
    (setq resmatrix (mxm rotmatrix (mxm sclmatrix movmatrix)))
    ) ;and
    resmatrix
    ) ;end

    ;-------------------------------------------------------------------
    ;; supports blocks nested at any level
    ;; returns a transformed point
    ;; arguments:
    ;; pt - point to transform
    ;; blklst - typically a list of enames as returned
    ;; by the last list from nentsel or nentselp
    ;; FROM and TO similar to trans: WCS = 0, UCS = 1 and OCS = 2
    ;; examples: (TransPt point blocklist 1 2) UCS > OCS
    ;; (TransPt point blocklist 2 0) OCS > WCS
    (defun TransPt ( pt blklst from to / ptmatrix matrix matrixlst res )
    (and
    (or
    (= 3 (length pt))
    (setq pt (append pt '(0.0)))
    )
    (or
    (or (= from 0) (= from 2))
    (setq pt (trans pt 1 0))
    )
    (if (or (= to 0) (= to 1))
    (setq matrixlst (mapcar 'ObjMatrix blklst)) ;to WCS or UCS
    (setq matrixlst (reverse (mapcar 'InverseObjMatrix blklst))) ;to OCS
    )
    ;test for any nil matrix caused by a non-uniformly scaled block
    (apply 'and matrixlst)
    (setq matrix (car matrixlst))
    (if (> (length matrixlst) 1)
    (repeat (1- (length matrixlst))
    (setq matrix (mxm (cadr matrixlst) matrix))
    (setq matrixlst (cdr matrixlst))
    )
    T
    )
    (setq ptmatrix
    (list
    (list 1 0 0 (car pt))
    (list 0 1 0 (cadr pt))
    (list 0 0 1 (caddr pt))
    (list 0 0 0 1)
    )
    )
    (setq matrix (mxm matrix ptmatrix))
    (setq res
    (list
    (last (car matrix))
    (last (cadr matrix))
    (last (caddr matrix))
    )
    )
    (or
    (or (= to 0) (= to 2))
    (setq res (trans res 0 1))
    )
    ) ;and
    res
    ) ;end
     
    Joe Burke, Jan 6, 2005
    #18
  19. RaghuMN

    James Allen Guest

    Joe, I'd love to help. Will look over your functions as soon as I have a
    chance.

    In the meantime, reviewing the GetNMatrix and GetOMatrix functions that I
    posted in BlockSwap.lsp before ( ) may give you a
    head start on me. If I remember right, the GetBlockTMatrix function (which
    uses the others) returns exactly the same matrix as nentselp, given the
    right bit code.

    Fundamentally, a normal transform is the same as a rotation transform. A
    general orientation matrix consists of projection of your unit direction
    vector onto the various axes. In the AutoCAD world, "rotation" is generally
    assumed to be about the z-axis so projection of this unit direction vector
    onto the z-axis is zero.

    As well as general transformation issues, I would be interested in
    specifically discussing the nested highlighting more. It seems to me that
    the difference in amount of code would be negligible, as most of the
    overhead involves transformations which are required in either case. I will
    be out of town for a few days starting tomorrow though. Should we start a
    new thread?

    James
     
    James Allen, Jan 6, 2005
    #19
  20. RaghuMN

    Joe Burke Guest

    James,

    Yes, start a new thread when you have some time. I'll keep an eye out.

    Regarding BlockSwap, I don't think I've seen it before. Will study and thanks. I did
    save and study the code you posted in the move block insertion point thread.

    I tried a couple months ago to fix the matrix functions so they would handle a
    non-standard normal vector. Gave up, frustrated. Assuming the solution is just
    another matrix multiplication, the part I couldn't figure out is where to put a
    normal matrix in the multiplication sequence.

    I agree regarding the amount of code needed to copy an object from an xref vs.
    drawing its bounding box. And hey, who cares how much it takes if you have reliable
    code in hand. But then there is an issue, in my mind anyway, about not altering a
    drawing if you don't have to, in order to accomplish a certain task. For instance, if
    the object isn't copied, there's no concern about the baggage it might bring along. A
    copied block might add... well, you know.

    Not forgetting the fact, the bounding box idea isn't as cosmetically pleasing as copy
    and highlight.

    Have a good trip.

    Joe
     
    Joe Burke, Jan 6, 2005
    #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.