Need help with lisp code

Need help with lisp code

Anonymous
Not applicable
2,004 Views
19 Replies
Message 1 of 20

Need help with lisp code

Anonymous
Not applicable

I need a code that will draw a series of concentric circles from a common point (maybe user selected) to points on a line (or nodes).  Anyone seen anything like this?  I would do it by hand, but there are around 700 circles to draw. Thanks.

0 Likes
Accepted solutions (1)
2,005 Views
19 Replies
Replies (19)
Message 2 of 20

j.palmeL29YX
Mentor
Mentor

Please show us an example what you want to get.

Jürgen Palme
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature

Message 3 of 20

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

I need a code that will draw a series of concentric circles from a common point (maybe user selected) to points on a line (or nodes).  ....


If the User is to select  the Points, in simplest terms, something like this [minimally tested]:

 

(defun c:CTP (/ ptss ctr)
  (prompt "\nFor Points through which to draw concentric Circles,")
  (setq
    ptss (ssget '((0 . "POINT")))
    ctr (getpoint "\nCenter of concentric Circles: ")
  )
  (repeat (setq n (sslength ptss))
    (command "_.circle"
"_none" ctr
"_none" (cdr (assoc 10 (entget (ssname ptss (setq n (1- n))))))
) ) (princ) )

The same general idea could be applied if the Points are selected by some automatic means, such as collecting them after a MEASURE or DIVIDE command, and likewise if the common center is to determined other than by the User selecting it.

 

Kent Cooper, AIA
0 Likes
Message 4 of 20

Anonymous
Not applicable

If you have say joined lines then make into a pline then just get the co-ordinates and pass each pt to the circle command, just like the previous example. Maybe use a mixture. Note if lines are joined you will get two circles if you use end and start point. Hence for lines say start only may be best. Use a selection set of point,line,lwpolyline and then check each entity and run the correct choice.

 

Provide more info.

0 Likes
Message 5 of 20

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

... concentric circles from a common point (maybe user selected) to points on a line (or nodes).  ....


Can we get a clarification about terminology?  People are interpreting this differently.  A reply to @j.palmeL29YX's request may answer it sufficiently, but to clarify why that request was made:

 

What, exactly, do you mean by "points on a line (or nodes)"?  Because NODE is the Object-Snap designator for Point entities  [or Point objects, if you prefer], such as are drawn with the POINT or MEASURE or DIVIDE commands, I assumed that was what you meant by "points" in the routine I posted [which would deal with them whether or not there is any "line" or path of any kind involved].  But maybe you are using the word "line" not in the sense that AutoCAD uses it [a Line entity  or Line object ], but rather, as some people sometimes do around here, in a looser sense that might include other kinds of "linework" such as Polylines or Arcs or Splines or....  If that's what you mean, and if "nodes" might be something like what AutoCAD would call vertices  along a Polyline, then the solution would be very different, and potentially far more complicated if different meanings for both "point" and "line" might be involved in the same operation, as @Anonymous has pointed out.

 

So what is it?

Kent Cooper, AIA
0 Likes
Message 6 of 20

Anonymous
Not applicable

This works perfectly, thank you!

 

0 Likes
Message 7 of 20

cschnarr
Enthusiast
Enthusiast

@Kent1Cooper 

Kent. I was looking for code to draw a series of concentric circles by inputting the diameter at the command line for each size (including the first circle). I want to pick the center with the mouse, then input diameters one by one. Then escape when completed. I thought there was a concentric circle routine already in AutoCAD but is seems not.

 

Layer and all other setting will be in place.

My process would be:

Initiate command

Pick center

Type (example) 12.5 <enter>

22.31 <enter>

24.06 <enter>

etc.

<escape>

 

Any assistance will be greatly appreciated. I'm not fining any results by searching, so I ask!

0 Likes
Message 8 of 20

Sea-Haven
Mentor
Mentor

Maybe something like this.

(defun c:circoffs ( / pt rad)
(setq pt (getpoint "\Please pick centre point"))
(while (setq rad (getreal "\nPlease enter radius Enter to exit"))
(command "circle" pt rad)
)
(princ)
)
(c:circoffs)

 

0 Likes
Message 9 of 20

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

....

...
(setq pt (getpoint "\Please pick centre point"))
(while (setq rad (getreal "\nPlease enter radius Enter to exit"))
  (command "circle" pt rad)
)
....

That would have been my approach, with one exception:  I suggest you use (getdist) rather than (getreal) to ask for the radii.  That way, you have options that (getreal) does not allow.  You can give it a radius by picking two points on-screen if appropriate.  And if you use Imperial Architectural units, you can type in a value in feet and inches and fractions if you want.

Kent Cooper, AIA
0 Likes
Message 10 of 20

cschnarr
Enthusiast
Enthusiast

@Sea-Haven 

@Kent1Cooper 

 

Thanks for the input. I am working off of a manufacturers spec sheet where all the sizes are listed as diameters. I don't want to have to drag out my calculator and divide all the given values by 2. I will see if I can edit this to use a diameter input at the command line (not radius). I will post back if I have success.

0 Likes
Message 11 of 20

cschnarr
Enthusiast
Enthusiast

Thanks to @Sea-Haven  and @Kent1Cooper  for their guidance.

 

I created a hybrid version that works for me.

 

;; Concentric Circles Defined by Center Point and Diameter

(defun c:concirc ( / pt rad dia)
(setq pt (getpoint "\nSELECT CENTER POINT"))
(while (setq dia (getdist "\nNEXT CIRCLE DIAMETER - Enter to exit"))
(setq rad (/ dia 2))
(command "circle" pt rad)
)
(princ)
)
(c:concirc)

 

Thanks for the fast assistance!

0 Likes
Message 12 of 20

Kent1Cooper
Consultant
Consultant

@cschnarr wrote:

....

....
(defun c:concirc ( / pt rad dia)
(setq pt (getpoint "\nSELECT CENTER POINT"))
(while (setq dia (getdist "\nNEXT CIRCLE DIAMETER - Enter to exit"))
(setq rad (/ dia 2))
(command "circle" pt rad)
)
....

....


Just a small suggestion:  Any variable that is used only once doesn't need to be saved to a variable.  You can just put whatever determines its value in at the place where that value is needed.  In this case, the rad variable is not necessary:

....
(defun c:concirc (/ pt dia)
  (setq pt (getpoint "\nSELECT CENTER POINT: "))
  (while (setq dia (getdist "\nNEXT CIRCLE DIAMETER <exit>: "))
    (command "_.circle" "_non" pt (/ dia 2))
  )
)
....

[I added the "_non" Osnap call before the pt circle center, in case there might sometimes be anything near enough to there that any running Osnap mode(s) could catch it unintended.]

Kent Cooper, AIA
0 Likes
Message 13 of 20

cschnarr
Enthusiast
Enthusiast

@Kent1Cooper Thank you for the guidance.

I thought the code might be useful to more people if it had an option to use either radius or diameter input for each time the command is invoked.

 

However: I am not able to accomplish the switching with an "if" statement.

 

Can you show me where my structure is incorrect?

(defun c:concirc ( / pt def rad dia)
(initget 1 "Diameter Radius")
	(cond
	((eq def "diameter") 2)
	((eq def "radius") 1)
(setq def (getreal  "Options: Diameter/<Radius>"))
) ; end cond
(setq pt (getpoint "\nSELECT CENTER POINT"))
(if (= def 1)
	(progn ; Radius Selected
		(while (setq rad (getdist "\nNEXT CIRCLE RADIUS - Enter to exit"))
		(command "_.circle"  "_non" pt rad)
		) ; end while
		) ; end progn
		
	(progn ; Diameter Selected
		(while (setq dia (getdist "\nNEXT CIRCLE DIAMETER - Enter to exit"))
		(setq rad (/ dia 2))
		(command "_.circle" "_non" pt rad)
		) ; end while
		) ; end progn
	) ; end if
(princ)
) ; end defun
(c:concirc)

 

Thank you!

0 Likes
Message 14 of 20

Sea-Haven
Mentor
Mentor

Simplest way would be just type a value say 12 for radius and -24 for diameter easy to check as you can not have a -ve radius.

 

I do agree with Kent the getdist would be useful for feet and inches. God bless metric. 

 

Do you have a number of preset radius that you want or are they random, I have something it will allow about up to 20 choices of fixed sizes in a dcl, pretty sure RLX can do like 40. 

 

(if (< rad 0.0)(setq rad (abs (/ rad 2.0))))
0 Likes
Message 15 of 20

Kent1Cooper
Consultant
Consultant

@cschnarr wrote:

....

Can you show me where my structure is incorrect?

(defun c:concirc ( / pt def rad dia)
(initget 1 "Diameter Radius")
	(cond
	((eq def "diameter") 2)
	((eq def "radius") 1)
(setq def (getreal  "Options: Diameter/<Radius>"))
) ; end cond
....

....


Could it have something to do with case-sensitivity?

....

  ((eq def "Diameter") 2)
  ((eq def "Radius") 1)

....

 

But beyond that, the structure is wrong.  In one place it checks for a text-string value for the def variable, in nother place for an integer value.  One variety is enough -- I don't think you need the integers.

 

Your (initget) with the 1 argument disallows Enter, so there's no way of accepting the default -- the User is required to type something in at the prompt every time.

 

I would try something like this:

 

 

(defun C:CONCIRC (/ pt dist)
  (initget 6 "Diameter Radius"); no 0, no negative [don't disallow Enter]
  (setq CCdef ; global variable
    (cond
      ( (getkword
          (strcat
            "Options [Diameter/Radius] <"
            (cond (CCdef) ("Radius"))
              ; [current value default if present, otherwise Radius]
            ">: "
          ); strcat
        ); getkword
      ); end User-input condition
      (CCdef); current value default if present on Enter
      ("Radius"); initial default [Enter on first use]
    ); cond & CCdef
    pt (getpoint "\nSELECT CENTER POINT")
  ); setq
  (while
    (setq dist
      (getdist (strcat "\nNext Circle " def " <exit>: "))
    ); setq
    (command "_.circle" "_non" pt
      (if (= CCdef "Radius") dist (/ dist 2))
    ); command
  ); while
  (princ)
)

 

 

Kent Cooper, AIA
0 Likes
Message 16 of 20

Kent1Cooper
Consultant
Consultant

Correction:

 

(getdist (strcat "\nNext Circle " CCdef " <exit>: "))

 

[The CCdef variable name is to be more distinctive and this-command-specific, to reduce the likelihood of its being overwritten by another routine that might use the same variable name if it were more generic.]

Kent Cooper, AIA
0 Likes
Message 17 of 20

cschnarr
Enthusiast
Enthusiast

@Kent1Cooper 

Thank you Kent! That works perfectly. I will post here for others benefit.

 

@Sea-Haven 

Sea Haven, I am looking at a manufactures spec sheet for pipe fittings (in this case). I'm just reading off a spreadsheet on the spec page. Diameter A = "", Diameter B= "", Diameter C="", Etc. for a given size of pipe. Using Kent's approach I can just follow the row on the spread sheet, and key in each diameter (not necessarily in consecutive order). All I need is a set of concentric circles with specified diameters. None of my vendors specify pipe, or tube or rod, or bolts, or really anything else by radius. We always get diameters. I'm not coding in to the routine any pre-set values.

 

My workflow can now be 6.25 <enter> 7.125 <enter> 8.96 <enter> 9.5 <enter> ... and <enter> to complete the set of concentric circles. This is a good time saver. Thank you for your suggestions as well.

 

This is what is working for me.

 

;; Concentric Circles Defined by Center Point and Radius or Diameter Definition
;; Created by Kent Cooper 2021
;; This routine repeats the CIRCLE command an until empty input is supplied at the command line <enter key> initiates an exit.
;; All circles are defined by keyboard entry of the next circle's diameter or radius (user's choice).
;; User's choice of circle definition (CCdef) will be used for all consecutive circles (ie. all diameters entered).
;; The next time the routine is called the user is presented with the choice of radius or diameter definitions again.

(defun C:CONCIRC (/ pt dist)
  (initget 6 "Diameter Radius"); no 0, no negative [don't disallow Enter]
  (setq CCdef ; global variable
    (cond
      ( (getkword
          (strcat
            "Options [Diameter/Radius] <"
            (cond (CCdef) ("Radius"))
              ; [current value default if present, otherwise Radius]
            ">: "
          ); strcat
        ); getkword
      ); end User-input condition
      (CCdef); current value default if present on Enter
      ("Radius"); initial default [Enter on first use]
    ); cond & CCdef
    pt (getpoint "\nSELECT CENTER POINT")
  ); setq
  (while
    (setq dist
      (getdist (strcat "\nNext Circle " CCdef " <exit>: "))
    ); setq
    (command "_.circle" "_non" pt
      (if (= CCdef "Radius") dist (/ dist 2))
    ); command
  ); while
  (princ)
)

 

Hope this helps someone else!

0 Likes
Message 18 of 20

Sea-Haven
Mentor
Mentor

If you do have preset values this may be useful its a library routine. So you could call various list of size options. It is just called from your code. Tick on as many as you want. This has a 1 line spacer so could get twice as many displayed if remove 1 line from code. Just ask if you want help.

 

 

(if (not AH:Toggs)(load "Multiple toggles.lsp"))
(ah:toggs '("Choose a diameter" "6.25" "7.125" "8.96" "9.5" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12"))

 

 

 

 

SeaHaven_0-1633664019199.png

 

0 Likes
Message 19 of 20

Kent1Cooper
Consultant
Consultant

@cschnarr wrote:

.... None of my vendors specify pipe, or tube or rod, or bolts, or really anything else by radius. We always get diameters. ....

 

....
;; All circles are defined by keyboard entry of the next circle's diameter or radius (user's choice).
;; User's choice of circle definition (CCdef) will be used for all consecutive circles (ie. all diameters entered).
;; The next time the routine is called the user is presented with the choice of radius or diameter definitions again.

....
            "Options [Diameter/Radius] <"
            (cond (CCdef) ("Radius"))
              ; [current value default if present, otherwise Radius]
            ">: "
          ); strcat
        ); getkword
      ); end User-input condition
      (CCdef); current value default if present on Enter
      ("Radius"); initial default [Enter on first use]
....

 

Hope this helps someone else!


If you usually get Diameters, you can make that the initial default option.  And a few suggested tweaks of the description, for capabilities that are there even if you don't often use them:

 

....
;; All circles are defined by keyboard entry of the next circle's diameter or radius (user's choice) or by picking two points on-screen.
;; User's choice of circle definition (CCdef) will be used for all consecutive circles (ie. all diameters or radii entered).
;; The next time the routine is called the user is presented with the choice of radius or diameter definitions again, with the previous choice offered as default.

 

....
          "Options [Diameter/Radius] <"
          (cond (CCdef) ("Diameter"))
          ; [current value default if present, otherwise Diameter]
          ">: "
        ); strcat
      ); getkword
    ); end User-input condition
    (CCdef); current value default if present on Enter
    ("Diameter"); initial default [Enter on first use]
....

Kent Cooper, AIA
0 Likes
Message 20 of 20

cschnarr
Enthusiast
Enthusiast

Thanks @Kent1Cooper 

I left the radius default to mimic OEM behavior, but I saw the possibility to do what you showed.

I will only use diameters, but someone else might need a similar tool so we gave them both options.

I am once again in awe of (and indebted to) your programming skills!

 

Thanks @Sea-Haven 

That's a cool one. I'm unfortunately not in a repetitive field. Automation would be soooo much more fun If I could ever do anything more than once.  🙂

 

I have what I needed and have shared with the community. Thanks to everyone out there for contributing!

0 Likes