I think I'm missing something that ought to be obvious - again...

Discussion in 'AutoCAD' started by David Kozina, Apr 21, 2004.

  1. David Kozina

    David Kozina Guest

    OK, the following code section is part of my get* routine arsenal such as it
    may be.

    Anyway, basically, one of 3 things ought to happen -

    If there is a Start_pt supplied, (getpoint..) should be called with the
    Start point option.

    If no Start_pt, then without.

    Upon failure of either (getpoint..) function, a default 'Current_pt' value
    should be returned.

    My question is if the (if..) statement below could be contained in a single
    3 condition cond statement, with the default 'T' case being to just return
    Current_pt? Whenever I see code duplication, I start to wonder...

    (if Start_pt
    ; then
    (cond
    ; case
    ((getpoint Start_pt CLMsg_str)
    );_end case
    ; default case
    (T
    Current_pt
    );_end case
    );_end cond
    ; else
    (cond
    ; case
    ((getpoint CLMsg_str)
    );_end case
    ; default case
    (T
    Current_pt
    );_end case
    );_end cond
    );_end if

    So maybe...

    (cond
    ; case Start_pt provided
    (Start_pt
    (getpoint Start_pt CLMsg_str)
    );_end case
    ; case no Start_pt
    ((getpoint CLMsg_str)
    );_end case
    ; default case
    (T
    Current_pt
    );_end case
    );_end cond

    But, now... something seems wrong here, too, because if Start_pt exists, I
    DON'T want to run (getpoint..) AGAIN should the first one fail, which it
    would, no?

    Does this make sense to anyone?
    Any suggestions on how to improve/streamline the above?

    Appreciatively,
    David Kozina
     
    David Kozina, Apr 21, 2004
    #1
  2. David Kozina

    Rudy Tovar Guest

    (while (setq p1 (getpoint))
    (do_this_or_that)
    )
     
    Rudy Tovar, Apr 21, 2004
    #2
  3. David Kozina

    David Kozina Guest

    Um, perhaps I need to clarify that the *context* of the code portion I
    posted was part of a library/toolbox routine for getting user input, with
    message, default, and current value argument options, amongst others.

    My question itself deals with how I might simplify the code logic. But
    perhaps I'm just not understanding your kind reply?

    Best regards,
    David Kozina
     
    David Kozina, Apr 21, 2004
    #3
  4. David Kozina

    Tom Smith Guest

    It seems to works as you describe. If Start-Pt is supplied, the first
    condition fires, and you exit the cond. If not, the second getpoint runs,
    and if it returns a point, you exit the cond. If the second getpoint gets a
    null response, then the third condition returns the fallback Current_pt.

    The test for the first condition is Start_pt -- if supplied, that triggers
    the getpoint result. If the return value of the getpoint is nil, it doesn't
    matter, you've already left the cond by firing the test.

    In the second condition, the getpoint is both test and the result. If it
    gets a null response, then the test wasn't passed, and you move on to the
    third condition.
     
    Tom Smith, Apr 21, 2004
    #4
  5. David Kozina

    David Kozina Guest

    Tom,
    Thanks very much for the explanation... but... (see below)


    OK, then this is what I DON'T want to happen...
    See - basically, if the first condition- with Start_pt returns nil, then
    what I want returned is Current_pt (IOW, the default). Does this make
    sense? This is what happens with the first (if..) statement - but I was
    hoping to 'reduce' it, if possible.
     
    David Kozina, Apr 21, 2004
    #5
  6. David Kozina

    Tom Smith Guest

    Then change the first condition to require both Start_pt and a return from
    getpoint. That way it will work as both test and result like your second
    condition:

    ((and
    Start_pt
    (getpoint Start_pt CLMsg_str)))
     
    Tom Smith, Apr 21, 2004
    #6
  7. David Kozina

    David Bethel Guest

    I think I understand......

    (setq start_pt nil current_pt nil)

    (while (cond ((not start_pt)
    (setq start_pt (getpoint "\nStart Point: ")
    current_pt start_pt))
    ((setq start_pt (getpoint start_pt "\nNext Point: "))
    (setq current_pt start_pt))))

    (prin1 current_pt)


    -David
     
    David Bethel, Apr 21, 2004
    #7
  8. David Kozina

    David Kozina Guest

    But then that SECOND getpoint condition might run, no?
     
    David Kozina, Apr 21, 2004
    #8
  9. David Kozina

    David Kozina Guest

    Luis, there seems to be some problems with the 'download'... sorry to say.
     
    David Kozina, Apr 21, 2004
    #9
  10. David Kozina

    Tom Smith Guest

    But then that SECOND getpoint condition might run, no?

    Hmmm. How about:

    (or
    (and
    Start_pt
    (setq Return_pt (getpoint Start_pt CLMsg_str)))
    (setq Return_pt (getpoint CLMsg_str))
    (setq Return_pt Current_pt))
     
    Tom Smith, Apr 21, 2004
    #10
  11. David Kozina

    David Kozina Guest

    David,

    Thanks for your reply, too...

    I guess I need to clarify things a bit more as to what I'm trying to
    accomplish here...

    Below is the toolbox routine as it stands now. If I've copied someone
    else's code, I'm not aware of it and besides, I've probably mangled it
    beyond recognition anyway... ;)

    ; Input Point
    (defun djkIGetPoint
    (Init_bit ; Initget bit value
    Init_str ; Initget keyword string / nil
    Message_str ; Message Prompt to User
    Default_pt
    Current_pt ; nil -> Default_pt
    Start_pt ; [Base Point / nil] - Rubberbanding base point / No base
    point
    /
    CLMsg_str ; Constructed Command Line Message String
    )
    ; begin
    (if (not Current_pt)
    ; then
    (setq Current_pt Default_pt)
    ; else
    ;
    )
    (setq CLMsg_str
    (strcat
    "\n"
    Message_str
    " < "
    (vl-princ-to-string Current_pt)
    " >: "
    )
    );_end setq
    (if Init_str
    ; then
    (initget Init_bit Init_str)
    ; else
    (initget Init_bit)
    )
    (if Start_pt
    ; then
    (cond
    ; case
    ((getpoint Start_pt CLMsg_str)
    );_end case
    ; default case
    (T
    Current_pt
    );_end case
    );_end cond
    ; else
    (cond
    ; case
    ((getpoint CLMsg_str)
    );_end case
    ; default case
    (T
    Current_pt
    );_end case
    );_end cond
    );_end if
    ; end
    );_end defun


    I might call it like so in another program:
    ....
    (setq First_pt
    (djkIGetPoint
    0
    nil
    "Pick the first point"
    '(0 0 0)
    First_pt
    '(1 1 0)
    )
    )
    ....


    My question deals with the "3-way" logic of the utility routine, which I
    felt could be improved upon.

    Best regards,
    David Kozina
     
    David Kozina, Apr 21, 2004
    #11
  12. David Kozina

    David Kozina Guest

    Same thing, no?

    Sheesh, I guess it isn't as obvious as I first believed.

    I like your (and..) test suggestion, but it's 'failure' will provoke the
    unwanted second (getpoint..) run here as well?

    The only thing I can figure here is to include another local test1 variable,
    that gets cleared in the first test, and if it doesn't exist, the second
    won't run? But this seems just as complicated (or more) than the original
    (if...) statement.

    I do appreciate everyone's comments on this.

    Best regards,
    David Kozina
     
    David Kozina, Apr 21, 2004
    #12
  13. David Kozina

    David Kozina Guest

    Luis,

    Thanks for the routine - it uses grdraw which I need to review in more
    depth, it appears...

    Appreciatively,
    David Kozina
     
    David Kozina, Apr 21, 2004
    #13
  14. David Kozina

    Jeff Mishler Guest

    How about:

    (or
    (and
    Start_pt
    (setq Return_pt (getpoint Start_pt CLMsg_str))
    )
    (and
    (not Start_pt)
    (setq Return_pt (getpoint CLMsg_str))
    )
    (setq Return_pt Current_pt)
    )

    Jeff
     
    Jeff Mishler, Apr 21, 2004
    #14
  15. David Kozina

    David Kozina Guest

    Now - at first glance - this looks about right.
    Thanks very much!

    Best regards,
    David Kozina
     
    David Kozina, Apr 21, 2004
    #15
  16. David Kozina

    Tom Smith Guest

    (cond
    ((if Start_pt
    (getpoint Start_pt CLMsg_str)
    (getpoint CLMsg_str)))
    (Current_pt))
     
    Tom Smith, Apr 22, 2004
    #16
  17. David Kozina

    David Kozina Guest

    I'd say that does pretty good in the streamlined category :)
    Thanks, Tom!

    Best regards,
    David Kozina
     
    David Kozina, Apr 22, 2004
    #17
  18. Da:Marc'Antonio Alessi
    Soggetto:R: Transparent Lisp Command (OSNAP)
    Newsgroups:autodesk.autocad.customization
    Data:2001-09-03 14:40:11 PST

    I wrote this many years ago, when initget bit 128 was introduced.
    You can nest more than one function using upoint rather than getpoint.
    The transparent functions can be nested in a command or upoint response
    in any sequence and number.
    I do not remember why I used (ALONG """""""ACTIVE""""""") with many "
    but I still use these functions in all my routines, maybe now if I have
    time I want to revise something.


    ; from Inside Autolisp - New Riders Publishing (modified)

    ;* BIT (1 no null, 0 no one) e KWD key word ("" no one) see INITGET
    ;* MSG prompt string with default <DEF> added (nil no one),
    ;* ":" will be added
    ;* BPT base point (nil per nessuno)
    ;
    (defun upoint (bit kwd msg def bpt / inp pts ptZ)
    (if def
    (setq
    ptZ (caddr def)
    pts (strcat
    (rtos (car def)) "," (rtos (cadr def))
    "," (if ptZ (rtos ptZ) "0")
    )
    msg (strcat "\n" msg " <" pts ">: ")
    bit (* 2 (fix (/ bit 2)))
    )
    (setq msg (strcat "\n" msg ": "))
    )
    (setq inp "NOTVALIDSTRING" bit (+ bit 128))
    (while
    (not
    (or
    (= 'LIST (type inp))
    (null inp)
    (if (= 'STR (type inp))
    (or
    (= 'LIST (type (read inp)))
    (wcmatch kwd (strcat "*" inp "*"))
    )
    )
    ) )
    (initget bit kwd)
    (setq inp (if bpt (getpoint msg bpt) (getpoint msg)))
    )
    (if inp
    (if (or (/= 'STR (type inp)) (atom (read inp)))
    inp
    (eval
    (if (= "ACTIVE" (cadr (read inp)))
    (subst nil "ACTIVE" (read inp))
    (read inp)
    )
    )
    )
    def
    )
    )
    ;
    (defun MEDIO (cmdact / pts pt2 cblip corto)
    (graphscr)
    (setq cblip (getvar "BLIPMODE") corto (getvar "ORTHOMODE"))
    (setvar "BLIPMODE" 1) (setvar "ORTHOMODE" 0)
    (setq
    pts (upoint
    40 "" ">>First point <Lastpoint>"
    (getvar "LASTPOINT") (getvar "LASTPOINT")
    )
    pt2 (upoint 41 "" ">>Second point" nil pts)
    )
    (setq pts (polar pts (angle pts pt2) (/ (distance pts pt2) 2.0)))
    (setvar "BLIPMODE" cblip) (setvar "ORTHOMODE" corto)
    (cond
    ( (and pts cmdact) (command "_NONE" pts) )
    ( pts )
    ( T (ai_alert "Mid point not found.") (princ) )
    )
    )
    ;
    (defun ALONG (cmdact / pts e1 ende1 corto cosnp)
    (graphscr)
    (setq corto (getvar "ORTHOMODE") cosnp (getvar "OSMODE"))
    (setvar "ORTHOMODE" 0) (setvar "OSMODE" 0)
    (while (not e1)
    (setq e1 (entsel "\n>>Pick near an endpoint: "))
    (if e1
    (if (setq ende1 (osnap (cadr e1) "_END"))
    nil
    (progn
    (ai_alert "Entity not valid for the function.")
    (setq e1 nil)
    ) ) )
    )
    (setq
    #mdist (udist 46 "" ">>Distance from endpoint" #mdist ende1)
    pts (polar ende1 (angle ende1 (osnap (cadr e1) "_MID")) #mdist)
    )
    (setvar "ORTHOMODE" corto) (setvar "OSMODE" cosnp)
    (cond
    ( (and pts cmdact) (command "_NONE" pts) (princ) )
    ( pts )
    ( T (ai_alert "Point not found.") (princ) )
    )
    )
    ;
    (defun BISETTR (cmdact / pts corm)
    (graphscr)
    (setq corm (getvar "ORTHOMODE")) (setvar "ORTHOMODE" 0)
    (setq
    pts (upoint
    40 "" ">>Angle vertex <Lastpoint>"
    (getvar "LASTPOINT") (getvar "LASTPOINT")
    )
    #rel1 (udist 46 "" ">>Distance from vertex" #rel1 pts)
    #ang1 (uangle 40 "" ">>First reference angle" #ang1 pts)
    #ang2 (uangle 40 "" ">>Second reference angle" #ang2 pts)
    )
    (if (< #ang1 #ang2)
    (progn
    (grdraw
    pts (polar pts (+ #ang1 (/ (- #ang2 #ang1) 2.00)) #rel1) -1 1
    )
    (setq pts (polar pts (+ #ang1 (/ (- #ang2 #ang1) 2.00)) #rel1))
    )
    (progn
    (grdraw
    pts
    (polar
    pts (+ #ang1 (gar 180.0)(/ (- #ang2 #ang1) 2.00)) #rel1
    )
    -1 1
    )
    (setq pts (polar
    pts (+ #ang1 (gar 180.0)(/ (- #ang2 #ang1) 2.00)) #rel1
    ) )
    )
    )
    (setvar "ORTHOMODE" corm)
    (cond
    ( (and pts cmdact) (command "_NONE" pts) (princ) )
    ( pts )
    ( T (ai_alert "Point not found.") (princ) )
    )
    )
    ;
    (defun DISTPR (cmdact / pts pt2 inc corto cblip)
    (graphscr)
    (setq corto (getvar "ORTHOMODE") cblip (getvar "BLIPMODE" ))
    (setvar "ORTHOMODE" 1) (setvar "BLIPMODE" 1)
    (setq
    inc 0
    pts (upoint
    -88 "" ">>Reference point <Lastpoint>"
    (getvar "LASTPOINT") nil
    )
    )
    (while
    (setq pt2 (upoint -88 "" ">><Next point>/Return to stop" nil pts))
    (setq inc (+ inc (distance pts pt2)))
    (prompt
    (strcat
    "\n>>Distance: " (rtos (distance pts pt2)) " Angle: "
    (angtos (angle pts pt2))
    " Total distance: " (rtos inc) "\n "
    )
    )
    (grdraw pts pt2 -1 1) (setq pts pt2)
    )
    (setvar "ORTHOMODE" corto) (setvar "BLIPMODE" cblip)
    (cond
    ( (and pts cmdact) (command "_NONE" pts) (princ) )
    ( pts )
    ( T (ai_alert "Point not found.") (princ) )
    )
    )
    ;
    ----------------------------------------------------------------------

    this is the macro for menu:


    ^P$M=$(if,$(getvar,cmdactive),(ALONG """""""ACTIVE"""""""),(ALONG nil));
    ^P$M=$(if,$(getvar,cmdactive),(MEDIO """""""ACTIVE"""""""),(MEDIO nil));
    ^P$M=$(if,$(getvar,cmdactive),(BISETTR """""""ACTIVE"""""""),(BISETTR nil));
    ^P$M=$(if,$(getvar,cmdactive),(DISTPR """""""ACTIVE"""""""),(DISTPR nil));



    ----------------------------------------------------------------------

    Example of use in C:xxx

    (defun C:ALE_Triang3Side (/ pt1 pt2 lt2 lt3 sper tng)
    (setq
    pt1 (upoint 40 "" "First point on first side <Lastpoint>"
    (getvar "LASTPOINT") (getvar "LASTPOINT")
    )
    #mdist (udist 46 "" "Length first side" #mdist pt1)
    #ang (uangle 40 "" "Angle first side" #ang pt1)
    pt2 (polar pt1 #ang #mdist)
    )
    (grdraw pt1 pt2 -1 1)
    (setq lt2 (udist 46 "" "Length second side" #mdist pt1))
    (while (not (and (< lt3 (+ #mdist lt2 )) (> lt3 (abs (- #mdist lt2)))))
    (initget (+ 2 8 32))
    (setq lt3 (udist 46 "" "Length third side" lt2 pt2))
    (if (or (> lt3 (+ #mdist lt2 )) (< lt3 (abs (- #mdist lt2))))
    (alert "No triangle exist with this side!")
    )
    )
    (setq
    sper (/ (+ lt3 #mdist lt2) 2.0)
    tng (sqrt(/ (* (- sper #mdist ) (- sper lt2)) (* sper (- sper lt3))))
    )
    (command
    "_.PLINE" "_NONE" pt1 "_NONE" pt2
    "_NONE" (polar pt1 (+ #ang (* 2.0 (atan tng))) lt2) "_C"
    )
    (princ)
    )


    (defun udist (bit kwd msg def bpt / inp)
    (if def
    (setq
    msg (strcat "\n" msg " <" (ALE_RTOS_DZ8 def) ">: ")
    bit (* 2 (fix (/ bit 2)))
    )
    (setq msg (strcat "\n" msg ": "))
    )
    (initget bit kwd)
    (setq inp (if bpt (getdist msg bpt) (getdist msg)))
    (if inp inp def)
    );defun UDIST

    (defun uangle (bit kwd msg def bpt / inp)
    (if def
    (setq
    msg (strcat "\n" msg " <" (angtos def) ">: ")
    bit (* 2 (fix (/ bit 2)))
    )
    (setq msg (strcat "\n" msg ": "))
    )
    (initget bit kwd)
    (setq inp (if bpt (getangle msg bpt) (getangle msg)))
    (if inp inp def)
    );defun UANGLE

    --
    ________________________________________________

    Marc'Antonio Alessi
    http://xoomer.virgilio.it/alessi
    (strcat "NOT a " (substr (ver) 8 4) " guru.")

    O.S. = XP Pro 2002 Ita - Sp.1
    AutoCAD = 2004 Ita - Sp.1a
    ________________________________________________
     
    Marc'Antonio Alessi, Apr 22, 2004
    #18
  19. David Kozina

    Tom Smith Guest

    I'd say that does pretty good in the streamlined category :)

    Like you, I get bothered if I think the logic's wrong or the code's bloated.
    I tend to get suspicious when I see a long string of if's & start wondering
    if cond wouldn't clean things up.
     
    Tom Smith, Apr 22, 2004
    #19
  20. David Kozina

    David Kozina Guest

    Marc'Antonio,

    I've used a set of 'utility' user input functions cobbled together from here
    and there, and even some of my own "original" stuff, such as it is, and,
    like you, 'use them in all my routines'. Recently I've been trying to
    review these (and several other) basic functions to see if they might be
    improved upon (or trash-canned), and if so, how?

    One thing that I hadn't considered doing, until recently, was include
    Initget BIT and KEYWORD arguments to the functions. IOW, I was setting
    these 'outside' the routine. But this raises another question/issue when it
    comes to such 'utility' functions...

    Something I have a real struggle in deciding is where to 'initialize'
    settings (such as initget) - inside the function 'black box' included as an
    argument, or outside in the main body of the program.

    If a utility function has too many 'bells and whistles' (perhaps in the form
    of arguments) it seems to me that it is defeating its own purpose. But
    insufficient capability is just as bad, no?

    Can someone offer any guidance in this case?

    I notice that your very kind examples make use of said Bit and Keyword
    arguments - may I ask WHY you decided to include them, as opposed to setting
    these 'outside'?

    Any comments along these lines would no doubt prove to be extremely helpful.

    Best regards,
    David Kozina
     
    David Kozina, Apr 22, 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.