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

0 Members and 1 Guest are viewing this topic.

qwrtz

  • Newt
  • Posts: 22
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?

JohnK

  • Administrator
  • Seagull
  • Posts: 10604
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.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

PKENEWELL

  • Bull Frog
  • Posts: 309
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

  • Water Moccasin
  • Posts: 1626
  • 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

  • Newt
  • Posts: 22
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

  • Gator
  • Posts: 3225
  • 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_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2121
  • 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
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.


Grrr1337

  • Swamp Rat
  • Posts: 812
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)
  )
)
vevo.bg

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2121
  • 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
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

qwrtz

  • Newt
  • Posts: 22
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 »