Author Topic: Draw a circle dynamically  (Read 4121 times)

0 Members and 1 Guest are viewing this topic.

Robert_s

  • Guest
Draw a circle dynamically
« on: June 17, 2009, 08:46:36 AM »
Hello,

I am trying to find and learn from code that will allow me to draw a circle dynamically.

Before placing the circle I would like to use  the keyboard's  "+" key to increase the
size/diameter or the "-" to decrease the size/diameter dynamically.

I've seen one here but it was too complicated from me. Any help would be appreciated.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10339
Re: Draw a circle dynamically
« Reply #1 on: June 17, 2009, 08:58:20 AM »
How would you place and size the first circle?
What increments would you assign to the + - keys?
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Robert_s

  • Guest
Re: Draw a circle dynamically
« Reply #2 on: June 17, 2009, 09:04:00 AM »
Hi Cab,

For initial size..24"
Increments..4"

Thank you.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10339
Re: Draw a circle dynamically
« Reply #3 on: June 17, 2009, 09:46:11 AM »
The way a routine / procedure is created is to establish rules & steps with sequence.

Rules:
Starting Size:  0.24  ? diameter or Radius ?
Increment Size:    ? diameter or Radius ?
Minimum Size? nn  ? diameter or Radius ?
Maximum Size? nn  ? diameter or Radius ?
Allowable keyboard entries + - Enter Esc
Action for each Allowable Key?
Action for disallowed keys?
Layer to use:  Current Layer

Steps: [ Pseudo Code ]
User picks center point
Draw the Starting circle
Get user input [ + or - or EnterKey ]
  Action for + Key: Draw a larger circle
  Action for - Key: Draw a smaller circle
  Action for Enter Key: End Program


How would you change these & answer any that are incomplete.
« Last Edit: June 17, 2009, 09:52:57 AM by CAB »
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Robert_s

  • Guest
Re: Draw a circle dynamically
« Reply #4 on: June 17, 2009, 10:14:06 AM »
How about this?


Rules:
Starting Size:  0.24  ? diameter or Radius ?     24" Diameter.
Increment Size:    ? diameter or Radius ?        2" Diameter.
Minimum Size? nn  ? diameter or Radius ?        none...Action for Enter Key: End Program.   
Maximum Size? nn  ? diameter or Radius ?       none...Action for Enter Key: End Program.   
Allowable keyboard entries + - Enter Esc        please add "D" for Diameter. So user can keyin a desired diameter instead. 
Action for each Allowable Key?                     see "Steps". 
Action for disallowed keys?                          prompt "Invalid selection".

Steps: [ Pseudo Code ]
User picks center point
Draw the Starting circle
Get user input [ + or - or EnterKey ]
  Action for + Key: Draw a larger circle
  Action for - Key: Draw a smaller circle
  Action for Enter Key: End Program......(Draw the circle)

Additions
  Action for Esc: Cancel the program
  Action for letter "D": user is allow to key-in a desired diameter instead.
  Action for "Space Bar": Same as Action for enter (End program).
 

Lee Mac

  • Seagull
  • Posts: 12227
  • London, England
Re: Draw a circle dynamically
« Reply #5 on: June 17, 2009, 10:33:17 AM »
You could look into the GRREAD and GRVECS functions.

For example, to get you started, to draw a simple circle using a combination of GRREAD and GRVECS, look at the example below:

Code: [Select]
(defun c:test (/ gr lst i)
  (while (not (eq 3 (car (setq gr (grread t 7 0)))))
    (redraw)
    (setq lst nil i 0)
    (repeat 300
      (setq lst
        (cons
          (polar (cadr gr)
                 (* i (/ pi 150))
                 (/ (getvar "VIEWSIZE") 20))
          lst))
      (setq i (1+ i)))
    (grvecs (append '(3) (reverse lst))))
  (princ))

In Pseudo code:

WHILE the user doesn't click a point
Set the variables to nil
Construct a list of points forming a "circle" (constructed from 300 segments)
Append the list with the colour (3 in this case), and display it with GRVECS.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10339
Re: Draw a circle dynamically
« Reply #6 on: June 17, 2009, 11:10:37 AM »
Robert,
There must be a minimum circle size & the layer must be addressed.

Here is a routine but I left out the D for user input. I expect you to complete that section.

Code: [Select]
(defun c:MyCircle (/ CIRCLEDIAM CIRCLEENT CPT GRR KEY MAXDIAM MINDIAM
                   MSG STEPSIZE CircleLay)
  ;;  sub to make a circle & return the ename
  (defun MakeCircle (cen rad lay)
    (entmakex
      (list
        (cons 0 "CIRCLE")
        (cons 6 "BYLAYER")
        (cons 8 lay)          ; layer
        (cons 10 cen)
        (cons 39 0.0)
        (cons 40 rad)         ; radius
        (cons 62 256)
        (cons 210 (list 0.0 0.0 1.0))
      )
    )
  )


  (setq CircleDiam 24.0       ; this is the starting size for the circle
        StepSize   4.0
        MinDiam    4.0
        MaxDiam    0
        CircleLay  (getvar "clayer")  
        CircleEnt  nil         ; this is the ename for the circle
  )
  (setq cpt (getpoint "\nPick the center point for circle."))
  (setq msg "\nUse + - keys to change size. D to enter. Enter to quit. :")
  (if cpt                     ; draw the first circle
    (progn
      ;;  Loop reading keyboard using grread
      (while                  ; get the string from user, exit only for ENTER
        (progn
          (if (or (null CircleEnt) (null (entget CircleEnt)))
            (progn
              (setq CircleEnt (makeCircle cpt (/ CircleDiam 2.0) CircleLay))
              (princ (strcat "\nCircle diameter is " (rtos CircleDiam 2 2)))
              (princ msg)
            )
          )
          (cond
            ((eq 2 (car (setq grr (grread t 7 0)))) ; keyboard input
             (setq key (cadr grr))
             (cond
               ((= key 43)    ; + key
                (if (or (zerop MaxDiam) (<= (+ CircleDiam StepSize) MaxDiam))
                  (progn      ;  increase circle size
                    (setq CircleDiam (+ CircleDiam StepSize))
                    (entdel CircleEnt) ; remove old circle
                  )
                  (princ "\nCircle has reached Maximum size.")
                )
                t             ;stay in loop
               )

               ((= key 45)    ; - key
                (if (>= (- CircleDiam StepSize) MinDiam)
                  (progn      ;  decrease circle size
                    (setq CircleDiam (- CircleDiam StepSize))
                    (entdel CircleEnt) ; remove old circle
                  )
                  (princ "\nCircle has reached Minimum size.")
                )
                t             ;stay in loop
               )

               ((member key '(68 100)) ; D or d for user entry of Diameter
                (princ "\nThis function is under construction. :)\n")

               )

               ((or (= key 13) (= key 32)) ; ENTER or Spacebar - where done here
                (princ "\nUser Quit.")
                nil           ; exit loop
               )

               ((princ "\nInvalid Keypress.") (princ msg))

             )                ; end cond
            )
            (t t) ; no valid input, stay in loop
          )
        )
      )                       ; while
    )
  )
  (princ)                     ; exit quietly
)
(prompt "\nMy Circle Lisp loaded. Enter MyCircle to run.")
(princ)                       ; kill echo to command line from last function
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12227
  • London, England
Re: Draw a circle dynamically
« Reply #7 on: June 17, 2009, 11:12:11 AM »
Alan, you might want to allow for key 61 (=), as that can be counted as "+".

Robert_s

  • Guest
Re: Draw a circle dynamically
« Reply #8 on: June 17, 2009, 11:23:23 AM »
Thanks Cad & Lee

..Actually I was kinda thinking of a combination of both of your routines.
Wherein I change the circle's diameter dynamically on the screen "before"
I place it. I'm sorry if I did'nt explain it well.


CAB

  • Global Moderator
  • Seagull
  • Posts: 10339
Re: Draw a circle dynamically
« Reply #9 on: June 17, 2009, 11:49:10 AM »
Robert,
You can combine the two routines in this thread to acheave your goal.
I've reached the age where the happy hour is a nap. ()
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12227
  • London, England
Re: Draw a circle dynamically
« Reply #10 on: June 17, 2009, 12:09:43 PM »
Not as elegant as Alan's, but I'm not as experienced as him  :oops:

Code: [Select]
(defun c:mycircle (/ *error* inc msg gr lst i flag tmp)
  (vl-load-com)

  (defun *error* (msg)
    (redraw)
    (if (not (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*"))
      (princ (strcat "\n<< Error: " msg " >>"))
      (princ "\n*Cancel*"))
    (princ))
 
  (or *Cir$Dia* (setq *Cir$Dia* 24.)) ; Initial Diameter
  (setq Inc 2.)  ; Increment
 
  (princ (setq msg "\n<< Position Circle [+] or [-] to Change [D]iameter >>"))
  (while
    (or
      (and (setq gr (grread t 15 0))
           (eq 5 (car gr)) (not flag))
      (and (eq 2 (car gr))
           (vl-position (cadr gr)
             '(68 100 43 45 61 13 32)) (not flag)))
    (redraw)
    (cond ((and (eq 5 (car gr)) (listp (cadr gr)))
           (setq lst nil i 0)
           (repeat 300
             (setq lst
               (cons
                 (polar (cadr gr)
                        (* i (/ pi 150.))
                        (/ *Cir$Dia* 2.)) lst) i (1+ i)))
           (grvecs (append '(6) lst (cdr lst) (list (car lst)))))
          ((eq 2 (car gr)) ; Keyboard input
           (cond ((vl-position (cadr gr) '(61 43)) ; +
                  (setq *Cir$Dia* (+ Inc *Cir$Dia*)))
                 ((eq 45 (cadr gr)) ; -
                  (if (> *Cir$Dia* Inc)
                    (setq *Cir$Dia* (- *Cir$Dia* Inc))
                    (progn
                      (princ "\n<< Minimum Circle Diameter Reached >>")
                      (princ msg))))
                 ((vl-position (cadr gr) '(13 32))
                  (setq flag T)
                  (princ "\n<< User Quit >>"))
                 ((vl-position (cadr gr) '(68 100)) ; D/d
                  (initget 6)
                  (if (setq tmp (getreal "\nSpecify Diameter: "))
                    (setq *Cir$Dia* tmp)))))))
  (if (and (not flag) (listp (cadr gr)))
    (entmakex
      (list
        (cons 0 "CIRCLE")
        (cons 8 (getvar "CLAYER"))
        (cons 10 (cadr gr))
        (cons 40 (/ *Cir$Dia* 2.))
        (cons 62 6))))
  (redraw)
  (princ))
« Last Edit: June 18, 2009, 06:02:34 AM by Lee Mac »

Robert_s

  • Guest
Re: Draw a circle dynamically
« Reply #11 on: June 17, 2009, 12:19:25 PM »
Thank you Lee!!!..Thank you Cab!!!

ronjonp

  • Needs a day job
  • Posts: 6938
Re: Draw a circle dynamically
« Reply #12 on: June 17, 2009, 07:18:39 PM »
Lee,

FWIW...

If you use this for your vector list it will make it solid rather than dashed  :-)

(grvecs (append '(3) lst (cdr lst) (list (car lst))))

Ron

Windows 10 x64 - AutoCAD /C3D 2020

Custom Build PC

Lee Mac

  • Seagull
  • Posts: 12227
  • London, England
Re: Draw a circle dynamically
« Reply #13 on: June 17, 2009, 09:28:25 PM »
Thanks Ron.

Am I right in thinking that that "shift" using (cdr) and attaching the (car) covers up the "gaps" in the circle?

ronjonp

  • Needs a day job
  • Posts: 6938
Re: Draw a circle dynamically
« Reply #14 on: June 17, 2009, 10:38:04 PM »
Thanks Ron.

Am I right in thinking that that "shift" using (cdr) and attaching the (car) covers up the "gaps" in the circle?

Exactly  :-)

Windows 10 x64 - AutoCAD /C3D 2020

Custom Build PC