Author Topic: Combo (getreal)/(getpoint)?  (Read 653 times)

0 Members and 1 Guest are viewing this topic.

qwrtz

  • Mosquito
  • Posts: 16
Combo (getreal)/(getpoint)?
« on: February 01, 2019, 02:26:36 PM »
Is there any way to prompt for a numeric input OR a point, so the user can either enter a number or pick a point? I know the (getreal) and (getpoint) functions won't allow it, but does someone have a function that combines the two?

I want to prompt for a second point, either by picking the second point or by entering X- and Y-coordinates of the offset from the first point. I know I can do that by using (getreal) and telling the user to press Enter to change to point input, but is there any way to do it without the Enter?

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9277
Re: Combo (getreal)/(getpoint)?
« Reply #1 on: February 01, 2019, 03:05:54 PM »
Code: [Select]
Command: (getpoint "\nPlease pick a point: ")

Please pick a point: 0,0
(0.0 0.0 0.0)

getpoint allows you to type or pick.
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

PKENEWELL

  • Bull Frog
  • Posts: 228
Re: Combo (getreal)/(getpoint)?
« Reply #2 on: February 01, 2019, 05:17:30 PM »
John is correct.

(getpoint) will accept all the same coordinate entry options as the commands. if you use (getpoint <pt1> "prompt: "), where <pt1> is a variable for the 1st point, you can use all the relative offset entry methods such as @x,y,x or @dist>angle, etc.
"When you are asked if you can do a job, tell 'em, 'Certainly I can!' Then get busy and find out how to do it." - Theodore Roosevelt

VovKa

  • Swamp Rat
  • Posts: 1163
  • Ukraine
Re: Combo (getreal)/(getpoint)?
« Reply #3 on: February 01, 2019, 05:39:30 PM »
Code: [Select]
(initget 128)
(if (setq p (getpoint "Point or number: "))
  (if (listp p)
    p
    (read p)
  )
)

qwrtz

  • Mosquito
  • Posts: 16
Re: Combo (getreal)/(getpoint)?
« Reply #4 on: February 02, 2019, 12:11:07 AM »
Thanks, Vovka. That was brilliant, and exactly what I needed. It took me a while to understand it.

Thanks also John and PKENEWELL for replies, but I was trying to avoid entering a point by using the @ symbol and the comma, since those are not on the numeric keypad. With Vovka's method, I can prompt for a picked point or a single number. If the user opts to enter a number, it can be done using just the numeric keypad, and then another number can be entered there as the Y-coordinate. If the user opts to pick a point, then that point is used instead of entering coordinates.

I wanted this for input of the second corner of a rectangle, either by pick point or by coordinates. Unfortunately, there's no rubber banding. But with a variation in the value of initget, the user can opt to just press Enter, and then pick the second corner with rubber banding.

Code: [Select]
(defun Waitcom () (while (> (getvar "cmdactive") 0) (command pause)) ) ; subroutine
(defun c:RR ( / p1 p2 x1 y1 inp1)
(setq p1 (getpoint "First corner of Rectangle: "))

; second input can be either a point (2nd corner) or a number (width)
(initget 129)  ; bit 7 allows arbitrary input as if it is a keyword
; if bits 7 and 0 are set and the user presses Enter, a null string is returned.
(if (setq inp2 (getcorner p1 "Second corner or width: ")) (progn
;----if there's any input in response to getpoint, continue

(if (listp inp2)
;----test whether the input is a list, i.e. a point rather than a single number

(progn  ;----start of the Then expression
(setq p2 inp2)  ; then the input is the second corner
(command "Rectang" p1 p2)  ; draw a rectangle between the two corners
)  ;----end of the Then expression

(progn  ;----start of the first Else expression
(setq x1 (read inp2))  ; else the first list or atom in the input string is the width

(if x1  ;----test whether the entered width was non-nil
(progn  ;----start of the second Then expression
(setq y1 (getreal "Height of Rectangle: ")) ;----then get the height...
(command "Rectang" "D" x1 y1 p1) (Waitcom)
;----and draw a rectangle by width/height/point
)  ;----end of the second Then expression

(progn  ; beginning of the second Else expression:
; if not non-nil, then the input was just Enter
(command "Rectang" p1)  (Waitcom) ;----else draw a rectangle from p1
)  ;----end of the second Else expression
)  ;----end of If the entered width was non-nil

)  ;----end of the first Else expression

)  ;----end (if) the input is a point
)) ;----end (if) there was any input at all and its progn
(sssetfirst nil (ssget "L"))
)  ;----end defun
edited:  second (getpoint) changed to (getcorner p1); subroutine added
« Last Edit: February 03, 2019, 08:30:43 PM by qwrtz »

ribarm

  • Water Moccasin
  • Posts: 2167
  • Marko Ribar, architect
Re: Combo (getreal)/(getpoint)?
« Reply #5 on: February 02, 2019, 02:25:56 AM »
You could use (getcorner p1 "\nSecond point - corner : ") for your second point input-specification... Its more elegant graphical solution IMHO...
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

kdub

  • Mesozoic relic
  • SuperMod
  • Swamp Rat
  • Posts: 1365
  • class keyThumper<T>:ILazy<T>
Re: Combo (getreal)/(getpoint)?
« Reply #6 on: February 02, 2019, 02:34:01 AM »
Perhaps this will serve as a start to the input function :...

Code - Auto/Visual Lisp: [Select]
  1. (defun c:doit (/ *error* P P1 P2 X Y)
  2.   (defun *error* (msg /) (kdub:on-error msg))
  3.   (vla-endundomark *:activedoc)
  4.   (vla-startundomark *:activedoc)
  5.   ;;
  6.   (if (setq P1 (getpoint "\nSelect First Point: "))
  7.     (progn (initget (+ 1 128))
  8.            (if (setq p (getpoint "\nSelect Second Point OR Enter X Offset: "))
  9.              (if (listp p)
  10.                (setq P2 p)                   ;else
  11.                (setq X (read p))
  12.              )
  13.            )
  14.     )
  15.   )
  16.   (if X
  17.     (setq Y  (getreal "\nEnter Y Offset: ")
  18.           P2 (mapcar '+ P1 (list X Y 0))
  19.     )
  20.   )
  21.   (if (and P1 P2)
  22.     (progn (princ (strcat "\nFirst Point :-> (" (kdub:ptos P1 nil 6) ")"))
  23.            (princ (strcat "\nSecond Point :-> (" (kdub:ptos P2 nil 6) ")"))
  24.     )
  25.   )
  26.   (*error* nil)
  27.   (princ)
  28. )
  29.  
  30. ;;;------------------------------------------------------------------
  31. ;;;------------------------------------------------------------------
  32. ;;;
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39. ;; LIBRARY :
  40.  
  41. ;;;; IAcadApplication Object
  42. (or *:acapp (setq *:acapp (vlax-get-acad-object)))
  43. ;;;; IAcadDocument Object
  44. (or *:activedoc (setq *:activedoc (vla-get-activedocument *:acapp)))
  45.  
  46. ;;;------------------------------------------------------------------
  47. ;;;------------------------------------------------------------------
  48. ;;;
  49. (defun kdub:on-error (msg /)
  50.   ;;----- Cancel any Active Commands -------------------------------------
  51.   (while (< 0 (getvar 'cmdactive)) (command-s nil))
  52.   (setvar 'menuecho 1)
  53.   ;;----- Display error message if applicable _---------------------------
  54.   (cond
  55.     ((not msg))
  56.     ((member (strcase msg t)
  57.              '("console break" "function cancelled" "quit / exit abort")
  58.      )
  59.      (princ "\nFunction Cancelled.")
  60.     )
  61.     (msg
  62.      (princ (strcat "\nApplication Error: " (itoa (getvar 'errno)) " :- " msg))
  63.      ;;----- Display backtrace ------------------------------------------
  64.      (vl-bt)
  65.     )
  66.   )
  67.   (setvar 'errno 0)
  68.   (vla-endundomark *:activedoc)
  69.   (princ)
  70. )
  71.  
  72. ;;;------------------------------------------------------------------
  73. ;;;------------------------------------------------------------------
  74. ;;;
  75. ;;; kwb 20021103
  76. ;;; KDUB:ptos (pt xmode xprec
  77.  
  78. ;; Return a point formatted as a string
  79. ;; Arguments :
  80. ;; pt       : point list
  81. ;; xmode  : Units to use , can be nil
  82. ;; xprec   : display precision to use , can be nil
  83.  
  84. (defun kdub:ptos (pt xmode xprec)
  85.   (or xmode (setq xmode (getvar "LUNITS")))
  86.   (or xprec (setq xprec (getvar "LUPREC")))
  87.   (if pt
  88.     (strcat (rtos (car pt) xmode xprec)
  89.             ",  "
  90.             (rtos (cadr pt) xmode xprec)
  91.             ",  "
  92.             (rtos (caddr pt) xmode xprec)
  93.     )
  94.   )
  95. )
  96.  
  97. ;;;------------------------------------------------------------------
  98. ;;;------------------------------------------------------------------
  99.  
  100.  



Command: DOIT
Select First Point:
Select Second Point OR Enter X Offset:
First Point :-> (904.682857,  3320.706092,  0.000000)
Second Point :-> (3215.383964,  4156.859104,  0.000000)
Command:
Command:
DOIT
Select First Point:
Select Second Point OR Enter X Offset: 200
Enter Y Offset: 300
First Point :-> (876.155662,  3216.186972,  0.000000)
Second Point :-> (1076.155662,  3516.186972,  0.000000)
« Last Edit: February 02, 2019, 02:46:47 AM by kdub »
called Kerry in my other life

Sometimes the question is more important than the answer.
#ridesober


Grrr1337

  • Swamp Rat
  • Posts: 708
Re: Combo (getreal)/(getpoint)?
« Reply #8 on: February 02, 2019, 07:43:35 AM »
Although I'd prefer and use VovKa's suggestion, heres an alternative (quick and dirty) :

Code: [Select]
(defun C:test ( / 3Dpt->2Dpt _drawrec L p bbox )
  (setq 3Dpt->2Dpt (lambda (p) (mapcar '(lambda (x) (nth x p)) '(0 1))))
  (setq _drawrec (lambda (L) (redraw) (apply ''((a b c d) (foreach x '((a b)(b c)(c d)(d a)) (eval (append '(grdraw) x '(1 1))))) L)))
  (and
    (setq L
      (CycleInputs
        '(
          (p1 (progn (initget "Exit") (if (and w h p2) "Exit" (eval (append (if p2 '(getcorner p2) '(getpoint)) '("\nSpecify first point [Exit] <Next Input>: "))))))
          (p2 (progn (initget "Exit") (if (and w h p1) "Exit" (eval (append (if p1 '(getcorner p1) '(getpoint)) '("\nSpecify second point [Exit] <Next Input>: "))))))
          (w (progn (initget "Exit") (if (and p1 p2) "Exit" (getreal "\nInput width [Exit] <Next Input>: "))))
          (h (progn (initget "Exit") (if (and p1 p2) "Exit" (getreal "\nInput height [Exit] <Next Input>: "))))
        )
        (lambda (sym val) (= "Exit" val) )
      ); CycleInputs
    )
    (cond
      ( (apply 'and (setq bbox (mapcar 'cdr (list (assoc 'p1 L) (assoc 'p2 L)))))
        (setq bbox (mapcar '3Dpt->2Dpt bbox))
      )
      ( (vl-some '(lambda (x) (setq p (cdr (assoc x L)))) '(p1 p2))
        (setq bbox (list (3Dpt->2Dpt p) (mapcar '+ (mapcar '(lambda (x) (cdr (assoc x L))) '(w h)) p)))
      )
    ); cond 
    (_drawrec (LM:BBox->List bbox))
  ); and
  (princ)
); defun C:test



; Grrr
; Cycles the prompts for the user's inputs
; inpL - assoc list of inputs [CAR = symbol to bound] [CADR = evaluation]
; exitf - exit function for the user
; Returns assoc list with the successful inputs, with the symbols unbounded
; NOTE: the returned input list might be partial - so length check comparsion might be required, when used
(defun CycleInputs ( inpL exitf / tmp )
  (cond  ; (87 114 105 116 116 101 110 32 98 121 32 71 114 114 114)
    ( (not inpL) inpL)
    ( (setq tmp (vl-catch-all-apply (function (lambda (a b) (set a (eval b)))) (car inpL))) ; bound the symbols in the input list
      (cond
        ( (vl-catch-all-error-p tmp) (prompt (vl-catch-all-error-message tmp)) )
        ( (and exitf (vl-catch-all-apply (function exitf) (list (caar inpL) tmp))) (set (caar inpL) nil) ) ; Exiting, unbound the last symbol
        (
          (mapcar (function (lambda (tmp) (set (car tmp) nil) tmp)) ; unbound the symbols from the input list
            (cons (cons (caar inpL) tmp) (CycleInputs (cdr inpL) exitf)) ; store the successful input and go to the next one
          )
        )
      ); cond
    )
    ( (CycleInputs (reverse (cons (car inpL) (reverse (cdr inpL)))) exitf) ) ; Else, shift to the next input and store the failed as last one
  ); cond
); defun CycleInputs


;;----------------=={ BoundingBox -> List }==-----------------;;
;;                                                            ;;
;;  Returns the coordinates of a rectangle from the           ;;
;;  coordinates of the lower-left and upper-right corners     ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2010 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  bbox - list of lower-left and upper-right coordinates     ;;
;;------------------------------------------------------------;;
;;  Returns:  coordinates of rectangle                        ;;
;;------------------------------------------------------------;;

(defun LM:BBox->List ( bbox )
  (mapcar
    (function
      (lambda ( funcs )
        (mapcar
          (function
            (lambda ( func ) ((eval func) bbox))
          )
          funcs
        )
      )
    )
    '((caar  cadar)  (caadr cadar) (caadr cadadr) (caar  cadadr))
  )
)

:)
« Last Edit: February 02, 2019, 07:49:57 AM by Grrr1337 »
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)

kdub

  • Mesozoic relic
  • SuperMod
  • Swamp Rat
  • Posts: 1365
  • class keyThumper<T>:ILazy<T>
Re: Combo (getreal)/(getpoint)?
« Reply #9 on: February 02, 2019, 02:54:24 PM »
The Original Requirement.

Is there any way to prompt for a numeric input OR a point, <<<<

I want to prompt for a second point, either by picking the second point or by entering X- and Y-coordinates of the offset from the first point. <<<<


... just a reminder.
called Kerry in my other life

Sometimes the question is more important than the answer.
#ridesober

qwrtz

  • Mosquito
  • Posts: 16
Re: Combo (getreal)/(getpoint)?
« Reply #10 on: February 02, 2019, 06:57:03 PM »
Thanks, Ribarm. That was what I needed. I replaced (getpoint) with (getcorner p1) and now the command works exactly as i wanted.

It draws a rectangle with rubber-banding, and it accepts X- and Y-coordinates instead of a second point. But in addition to the inconvenient @, syntax, the relative coordinates can be entered one at a time on the numeric keypad, each followed by Enter.

Everyone else, thanks very much for the input. I don't understand it yet but I'll try to, and that will no doubt expand my skill with lisp.
« Last Edit: February 03, 2019, 08:33:17 PM by qwrtz »