IsInside with Offset

Discussion in 'AutoCAD' started by Marc'Antonio Alessi, Sep 12, 2003.

  1. ; From a Tony Tanzillo suggestion, see
    ; John Uhden's @cv_inside function thread.
    ; minimal, dirty, etc...
    ;
    (defun ALE_IsInside (ImpPnt EntNam / NewEnt EntAre)
    (command "_.AREA" "_O" EntNam)
    (setq EntAre (getvar "AREA"))
    (command
    "_.OFFSET" (/ EntAre 10000) EntNam ImpPnt ""
    "_.AREA" "_O" (setq NewEnt (entlast))
    )
    (entdel NewEnt)
    (> EntAre (getvar "AREA"))
    )

    command: pline 0.0 100,0 100,50 0,50 c

    command: (ALE_IsInside '(-0.00000000001 -0.00000000001) (entlast))
    nil

    command: (ALE_IsInside '(0.00000000001 0.00000000001) (entlast))
    T

    --
    ________________________________________________

    Marc'Antonio Alessi (TV) Italy
    (strcat "NOT a " (substr (ver) 8 4) " guru.")

    O.S. = XP Pro 2002 - Sp.1 - Ita
    AutoCAD = 2002 Ita - Sp.1
    _VERNUM = "K.0.44"
    ACADVER = "15.06s (LMS Tech)"
    (ver) = "Visual LISP 2000 (it)"
    ________________________________________________
     
    Marc'Antonio Alessi, Sep 12, 2003
    #1
  2. Marc'Antonio Alessi

    Doug Broad Guest

    Marco,
    Thanks for the illustration. I like your improvement on Tony's
    good suggestion. With your method, you will probably not
    run into problems that may arise when the through point is inside
    the object but causes an error because the polyline can not
    be offset through the point.

    I think I understand your "dirty" comment and concur. A polyline
    can have an area without being closed so that may need checking.
    There may also still be some polylines that will not offset well
    despite the smallness of the offset distance. That is two or more
    polylines may be created some with a larger area than the original
    if the polyline has re-entrant geometry.

    Thanks for posting this solution.

    Regards,
    Doug
     
    Doug Broad, Sep 12, 2003
    #2
  3. I agree with you entirely.

    Thanks to you.

    Marco

    --
     
    Marc'Antonio Alessi, Sep 13, 2003
    #3
  4. Marc'Antonio Alessi

    Doug Broad Guest

    Marco,
    I was probably incorrect about the area of the polyline ever being
    larger when offset through a point inside a figure but in some cases
    the offset polyline becomes 2 or more separate figures. This is true
    whether the point is outside or inside and so the separate polylines
    created must be collected and the sum of the new areas should be
    smaller than the original area. Sorry for that error.

    Have a nice weekend.

    Regards,
    Doug
     
    Doug Broad, Sep 13, 2003
    #4
  5. ; new approach minimal, dirty, etc...
    ; comments are welcome
    ;
    (defun ALE_Bound_IsInside (ImpPnt EntNam / LstEnt NewEnt SnpBas RgnMod
    FuzFct)
    (setq
    FuzFct '(0.00001 0.00001)
    LstEnt (entlast)
    SnpBas (getvar "SNAPBASE")
    RgnMod (getvar "REGENMODE")
    )
    (setvar "SNAPBASE" ImpPnt) (setvar "REGENMODE" 1)
    (command
    "_.ZOOM"
    "_NONE" (mapcar '- ImpPnt FuzFct)
    "_NONE" (mapcar '+ ImpPnt FuzFct)
    "_.BOUNDARY" "_A" "_B" "_N" EntNam "" "" "_NONE" ImpPnt ""
    "_.ZOOM" "_P"
    )
    (setvar "SNAPBASE" SnpBas) (setvar "REGENMODE" RgnMod)
    (cond
    ( (eq LstEnt (setq NewEnt (entlast))) nil )
    ( (entdel NewEnt) T )
    )
    )

    command: pline 0.0 100,0 100,50 0,50 c

    command: (ALE_Bound_IsInside '(0.0000001 0.0000001) (entlast))
    T

    command: (ALE_Bound_IsInside '(-0.0000001 -0.0000001) (entlast))
    nil

    Note: I can not get more precision of about 0.0000001.
     
    Marc'Antonio Alessi, Sep 13, 2003
    #5
  6. Ok, thanks for explanation.

    Nice w.e.

    --
     
    Marc'Antonio Alessi, Sep 13, 2003
    #6
  7. Marc'Antonio Alessi

    Joe Burke Guest

    Hi Marco,

    I'm curious. Which one of these functions do you prefer, boundary or offset?

    I ran some tests. Watch out. ;-)

    I think I understand why you zoom with the boundary function, but not with the
    offset function. Boundary seems to need the zoom to attain precision, while
    offset doesn't. For that reason alone, I would tend to prefer offset. Maybe I'm
    flaky, but I tend to be suspicious of functions which need zoom to work right.
    Not to mention the screen hiccup.

    Regarding precision using your 100 x 50 unit example. Including Doug's function
    from the other thread and both functions posted here. All seem to choke
    somewhere around seven decimal places given your examples. That seems a wash and
    not a concern.

    BTW, I was not ignoring your post in the other thread about how to do this with
    plines comprised of line segments only. What wasn't clear in that thread,
    because of the way it started, was it was aimed at plines with bulges. So as
    Tony and (I think) Doug said, line segment solutions were not pertinent to the
    topic at hand.

    I expect a few more spins on this topic before it comes to conclusion.

    Regards
    Joe
     
    Joe Burke, Sep 13, 2003
    #7
  8. Hi Joe,
    offset?

    I prefear the offset approach.

    To avoid what Doug pointed out:
    figures...

    we can use a minimum offset distance (on my tests is 0.0000001 - 7 dp),
    but maybe in rare cases we can have "Doug behaviour"

    Again:
    a new function with VisualLisp can escape the use of the AREA command,
    improvements are welcome.

    (defun ALE_IsInside (ImpPnt EntNam / NewEnt EntAre)
    (command "_.AREA" "_O" EntNam)
    (setq EntAre (getvar "AREA"))
    (command
    "_.OFFSET" 0.0000001 EntNam "_NONE" ImpPnt ""
    "_.AREA" "_O" (setq NewEnt (entlast))
    )
    (cond
    ( (eq EntNam NewEnt)
    (alert "I can't compute this point inside this object!")
    )
    ( (entdel NewEnt)
    (> EntAre (getvar "AREA"))
    )
    )
    )

    now the max "precision" is 8 dp (???):
    command: pline 0.0 100,0 100,50 0,50 c
    command: (ALE_IsInside '(0.00000001 0.00000001) (entlast))
    T
    command: (ALE_IsInside '(0.000000001 0.000000001) (entlast))
    nil


    Cheers.

    Marco
     
    Marc'Antonio Alessi, Sep 13, 2003
    #8
  9. Marc'Antonio Alessi

    Guest Guest

    I had made a routine that passed the points of a polyline back to the ssget
    to select objects
    crossing the polyline, sometimes it would select the original polyline as
    well but other times it would not.
    I ended up cheating and offseting the polyline outwards by a very small
    amount. Then every thing worked fine.
    I think it had something to do with the zoom factor and screen pixel size
    that when it passed the point back to ssget
    ssget was using the current zoom factor and pixel size to determine which
    entities lay within the polyline.
    Something similar to not being able to select an entity that cannot be
    visually seen in the autocad view port.
    Does ths mean that Autocad uses its current display list to select and
    perhaps even snap to objects that is using it as some kind of primary
    filter/modeling array..

    This would seem to be a quicker more logical approuch than trying the
    calculate relalationships of objects
    back in their original WCS in relation to the current Viewport...

    Am I on the right track here or is this pure fiction?
    Any comments....?
     
    Guest, Sep 13, 2003
    #9
  10. Marc'Antonio Alessi

    Joe Burke Guest

    Marco,

    Maybe I'm reading it wrong. Seems to me the first cond is assuming the test
    against pline (EntNam) is the last drawn object before running the function.
    Otherwise EntNam would never equal NewEnt. Yes, no, maybe?

    Joe Burke
     
    Joe Burke, Sep 14, 2003
    #10
  11. Joe,

    EntNam = the entity name where we are testing if the
    point ImpPnt is inside

    NewNam = the entity name of entity created by offset command

    if, for some reasons, the offest is not possible we have not
    a new entity

    (defun ALE_IsInside (ImpPnt EntNam / NewEnt EntAre)
    (command "_.AREA" "_O" EntNam)
    (setq EntAre (getvar "AREA"))
    (command
    "_.OFFSET" 0.0000001 EntNam "_NONE" ImpPnt ""
    "_.AREA" "_O" (setq NewEnt (entlast))
    )
    (cond
    ( (eq EntNam NewEnt)
    (princ "Point is on object or is not possible to
    compute this point inside this object!"
    )
    nil
    )
    ( (entdel NewEnt)
    (> EntAre (getvar "AREA"))
    )
    )
    )

    I think it would be better to have a new cond:

    1 It is not possible to compute this point inside this object > alert
    2 Point is on object (not inside) > nil
    3 Point is outside > nil
    4 Point is inside > T

    Marco
    --
    ________________________________________________

    Marc'Antonio Alessi (TV) Italy
    (strcat "NOT a " (substr (ver) 8 4) " guru.")

    O.S. = XP Pro 2002 - Sp.1 - Ita
    AutoCAD = 2002 Ita - Sp.1
    _VERNUM = "K.0.44"
    ACADVER = "15.06s (LMS Tech)"
    (ver) = "Visual LISP 2000 (it)"
    ________________________________________________
     
    Marc'Antonio Alessi, Sep 14, 2003
    #11
  12. Marc'Antonio Alessi

    Joe Burke Guest

    Marco,

    I may be all wet but... to test whether a new entity was created, I believe you
    have to establish the last entity first.

    (defun ALE_IsInside (ImpPnt EntNam / NewEnt EntAre)
    (setq Mark (entlast))
    < code >
    (cond
    ((eq Mark NewEnt)

    Testing (eq EntNam NewEnt) is only valid if EntNam was the last drawn object.

    Joe Burke
     
    Joe Burke, Sep 15, 2003
    #12
  13. You're absolutely right!

    I made a big mistake because my testing EntNam was the
    last entity and I had not foreseen that this could be
    always not true.

    My apologies for my lapse.

    --
    I tryed with vl-catch-all-apply to test if the point
    is on object or it is an offset rejection, but OFFSET do
    not get any error in case of:

    "Point is on object" or
    "It is not possible to offset this object"

    Note: this is my translation of Offset command messages
    because I do not know the real english prompts.


    (defun ALE_IsInside (ImpPnt EntNam / LstEnt NewEnt EntAre AltStr)
    (command "_.AREA" "_O" EntNam)
    (setq
    EntAre (getvar "AREA")
    LstEnt (entlast)
    AltStr
    (vl-catch-all-apply
    '(lambda ()
    (command
    "_.OFFSET" 0.0000001 EntNam "_NONE" ImpPnt ""
    )
    )
    )
    NewEnt (entlast)
    )
    (cond
    ( (eq LstEnt NewEnt)
    (and
    (vl-catch-all-error-p AltStr)
    (princ (vl-catch-all-error-message AltStr))
    )
    nil
    )
    ( T
    (command "_.AREA" "_O" NewEnt)
    (entdel NewEnt)
    (> EntAre (getvar "AREA"))
    )
    )
    )

    Sorry again.

    Marco
     
    Marc'Antonio Alessi, Sep 15, 2003
    #13
  14. Marc'Antonio Alessi

    Joe Burke Guest

    Marco,

    No need to apologize. Just an oversight.

    To test if the point is on the pline. This is from Doug's function in the other
    thread.

    (setq Closest (vlax-curve-getclosestpointto
    (vlax-ename->vla-object EntNam) ImpPnt))
    (if (not (equal Closest ImpPnt 1e-10))
    < OK to proceed... >

    Joe Burke
     
    Joe Burke, Sep 15, 2003
    #14
  15. Thanks,

    here is my last attempt:

    ; ImpPnt: must be a 3D point
    ;
    (defun ALE_IsInside (ImpPnt EntNam / VlaObj LstEnt NewEnt EntAre)
    (vl-load-com)
    (setq VlaObj (vlax-ename->vla-object EntNam))
    (cond
    ( (not (vlax-property-available-p VlaObj 'Area))
    (not (princ "It isn't possible to compute this object!"))
    )
    ( (equal (vlax-curve-getclosestpointto VlaObj ImpPnt) ImpPnt 1e-10)
    (not (princ "Point is on object!"))
    )
    ( (and
    (setq LstEnt (entlast))
    (not (command "_.OFFSET" 0.0000001 EntNam "_NONE" ImpPnt ""))
    (eq LstEnt (setq NewEnt (entlast)))
    )
    (not
    (princ "It isn't possible to compute this point inside this
    object!")
    )
    )
    ( T
    (setq EntAre (vlax-get-property (vlax-ename->vla-object NewEnt)
    'Area))
    (entdel NewEnt)
    (> (vlax-get-property VlaObj 'Area) EntAre)
    )
    )
    )


    --
     
    Marc'Antonio Alessi, Sep 15, 2003
    #15
  16. Marc'Antonio Alessi

    Doug Broad Guest

    Marco,
    Looks good.
     
    Doug Broad, Sep 15, 2003
    #16
  17. Marc'Antonio Alessi

    Doug Broad Guest

    This technique was mentioned in the previous thread. It should
    work fine but is limited to straight line polyline segments. If you
    are speaking about drawing a point and then selecting it, then
    the technique would also depend on pdmode and pdsize. The
    select command and ssget also depend on the objects selected
    being within the display. In addition, commands that require
    zooms could be distracting to users.

    It wouldn't bother me if the program was for me only and it
    saved me a couple hours of programming. ;-)
     
    Doug Broad, Sep 15, 2003
    #17
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.