Equal Divide without drawing a line

Equal Divide without drawing a line

pallen9JA6T
Enthusiast Enthusiast
3,512 Views
16 Replies
Message 1 of 17

Equal Divide without drawing a line

pallen9JA6T
Enthusiast
Enthusiast

I draw parts for wall panels, and I'm trying to find a lisp that will place points equally apart with a maximum distance of 12" apart. I've been drawing a line and using the divide command and then I have to delete the line. I know there has to be better way to do this. I've attached a picture of an example of the finished solution. The points that are circled on the ends are always the same. I need to equally space points between the innermost green points. If the 62-1/4" dimension were to grow by 24", I would need an additional 2 points because of the 12" maximum. Please help, and thank you.

0 Likes
Accepted solutions (1)
3,513 Views
16 Replies
Replies (16)
Message 2 of 17

john.uhden
Mentor
Mentor

That's easy enough.

I just finished something very similar at work.  Often we have to cut arcs into chords having a maximum mid-ordinate value.  Saves a lot of time compared to trial and error.

Would it be sufficient to just place AutoCAD point objects at the locations?  I don't want to get involved in your dimension styles.  Bu you could give me a layer name for the points.

 

John F. Uhden

0 Likes
Message 3 of 17

serag.hassouna
Advocate
Advocate

Try this one, [the command is "divpts"].

What you have to do is to select the green innermost points (one by one), then specify the maximum allowable spacing (here = 12), and the command will do the rest for you.

Message 4 of 17

john.uhden
Mentor
Mentor

How shortsighted of me.  If we draw a polyline through each point, you can use QDIM to dimension all the gaps in one shot.

John F. Uhden

0 Likes
Message 5 of 17

Kent1Cooper
Consultant
Consultant

Much more of that could be automated, if you like.  If your image is of one edge of a rectangle, a routine could ask for just the two opposite corners, or even just the two edge sizes, and could construct the whole thing, not just space the no-more-than-12"-apart Circles [it looks like that's what they are -- grommets? -- not Points], but draw the whole perimeter, the Chamfered corners, the hidden-line parts [hemmed edges?], the other Circles closer to the corners, even the Dimensions, and also the Layers involved.  [It would require knowing a few more dimensions that aren't shown in the image, such as the positioning of the "other" Circles, the width of the hemmed edge, etc.]

 

But if you really only need the one string of Circles, and since your 12" maximum sounds like a standard [no need to ask for the maximum spacing], it can be simpler:

 

(defun C:DIVDC12 (/ cc1 cc2 range spcs spc)
  ; = DIVide Distance [not object] using Circles max. 12" apart
  (setq
    cc1 (getpoint "\nOne end of range: ")
    cc2 (getpoint "\nOther end: ")
    range (distance cc1 cc2)
    spcs (+ (fix (/ range 12)) (if (equal (rem range 12) 0 1e-4) 0 1))
    spc (/ range spcs)
  ); setq
  (command "_.circle" "_none" cc1 0.125); assumption -- EDIT radius to your value
  (repeat spcs
    (command "_.circle" "_none" (polar (getvar 'lastpoint) (angle cc1 cc2) spc) 0.125)
  ); repeat
  (princ)
); defun
Kent Cooper, AIA
Message 6 of 17

john.uhden
Mentor
Mentor

Try this out:

I figured you might want a minimum end gap.

(defun c:Divvie ( / *error* var vals @2d end1 end2 gap endgap ang d n p pts layer)
  ;; by John Uhden for  pallen9JA6T (08-11-18)
  (vl-load-com)
  (if (not vlax-get-acad-object)(prompt "\n\nNo vlax-get-acad-object.\n"))
  (or *acad* (setq *acad* (vlax-get-acad-object)))
  (or *doc* (setq *doc* (vlax-get *acad* 'ActiveDocument)))
  (setq vars '(cmdecho)
        vals (mapcar 'getvar vars)
        mspace (vlax-get *doc* 'ModelSpace)
        layer "POINTS" ;; change this to your liking
  )
  (defun *error* (error)
    (mapcar 'setvar vars vals)
    (vla-endundomark *doc*)
    (cond
      ((not error))
      ((wcmatch (strcase error) "*QUIT*,*CANCEL*"))
      (1 (princ (strcat "\nERROR: " error)))
    )
    (princ)
  )
  (vla-endundomark *doc*)
  (vla-startundomark *doc*)
  (mapcar 'setvar vars '(0))
  (command "_.expert" (getvar "expert")) ;; dummy command
  ;;------------------------------------------------------
  ;; Function to convert a 3D point into 2D
  (defun @2d (p)(list (car p)(cadr p)))

  (and
    (setq end1 (getpoint "\n1st end point: "))
    (setq end2 (getpoint end1 "\n2nd end point: "))
    (setq end1 (@2d end1)
               end2 (@2d end2)
    )
    (not (initget 6)) ;; no zeroes or negatives
    (or (setq gap (getdist "\nRegular spacing <12>: "))
      (setq gap 12.0)
    )
    (not (initget 5)) ;; no null or negative
    (setq endgap (getdist "\nMinimum end gap: "))
    (setq ang (angle end1 end2))
    (setq d (distance end1 end2))
    (or
      (> d (* endgap 2))
      (prompt "\nEnd gaps total more than distance between ends.")
    )
    (setq n (fix (/ (- d endgap endgap) gap)))
    (setq endgap (* 0.5 (- d (* n gap))))
    (setq pts (list (setq p (polar end1 ang endgap)) end1))
    (or
      (repeat n
        (setq pts (cons (setq p (polar p ang gap)) pts))
      )
      1
    )
    (setq pts (mapcar '@2d (reverse (cons end2 pts))))
    (vlax-invoke mspace 'addlightweightpolyline (apply 'append pts))
    (foreach p pts
      (entmakex (list '(0 . "POINT")(cons 10 p)(cons 8 layer)))
    )
    (setq ok 9)
  )
  (*error* nil)
)

John F. Uhden

0 Likes
Message 7 of 17

pallen9JA6T
Enthusiast
Enthusiast

Thank you. That works great. i have another suggestion that would help my work flow a little more. Can you make it where when you repeat the command, it remembers the previously entered "max. dist", but will allow you to change if needed (similar to how the offset and the circle command works)?

0 Likes
Message 8 of 17

Kent1Cooper
Consultant
Consultant

@pallen9JA6T wrote:

... when you repeat the command, it remembers the previously entered "max. dist", but will allow you to change if needed (similar to how the offset and the circle command works)?


 

Here's how I'd do that.  I stayed with the Circles in the original image, and you can do the same kind of prompt and default for the radius of those if you want.  Or if you really want them to be Points, or Blocks if that's what those Circles are, that's an easy adjustment.

 

(defun C:DIVDCM (/ cc1 cc2 range spcs spc)
  ; = DIVide Distance [not object] using Circles, at user-specified Maximum spacing
  (initget (if *DIVDCmax* 6 7)); no zero, no negative, no Enter on first use
  (setq
    *DIVDCmax* ; global variable with routine-specific name
    (cond
      ( (getdist ; returns nil on Enter when permitted
          (strcat
            "\nMaximum Circle spacing"
            (if *DIVDCmax* (strcat " <" (rtos *DIVDCmax*) ">") "")
            ": "
          ); strcat
        ); getdist
      ); User-input condition
      (*DIVDCmax*); prior value if present, on Enter
    ); cond & *DIVDCmax*
    cc1 (getpoint "\nOne end of range: ")
    cc2 (getpoint "\nOther end: ")
    range (distance cc1 cc2)
    spcs (+ (fix (/ range *DIVDCmax*)) (if (equal (rem range *DIVDCmax*) 0 1e-4) 0 1))
    spc (/ range spcs)
  ); setq
  (command "_.circle" "_none" cc1 0.125); assumption -- EDIT radius to your value
  (repeat spcs
    (command "_.circle" "_none" (polar (getvar 'lastpoint) (angle cc1 cc2) spc) 0.125)
  ); repeat
  (princ)
); defun

The use of (getdist) [as opposed to (getreal) in @serag.hassouna' routine] means that you can also enter the distance by picking two points on-screen, or by typing in a distance involving feet, and/or fractions, none of which options are available with (getreal), which allows only an integer or decimal number.

 

The routine-specific variable name for that maximum distance is so that it's not likely to be replaced by the operation of any other AutoLisp routine.  If, for example, it was called simply 'max,' that name might also be used in something else, and if you then came back to this, the default would be wrong.  [The * before and after the name is just a convention some people use to distinguish global variable names.  Sometimes I use one only before, some people use _ instead, etc. -- completely arbitrary and expendable.]

Kent Cooper, AIA
Message 9 of 17

pallen9JA6T
Enthusiast
Enthusiast

This works, except for I need points instead of circle. The sample image looks like circle, but that is the way I have my point showing. My CNC machine recognizes the point. Also, is it possible to change from 12" maximum to 16" maximum (if needed)?

0 Likes
Message 10 of 17

Kent1Cooper
Consultant
Consultant

@pallen9JA6T wrote:

This works, except for I need points instead of circle. .... Also, is it possible to change from 12" maximum to 16" maximum (if needed)?


 

I assume you're referring to my first routine, since in the second, you can specify whatever maximum spacing you want.  But here's the Point version of the User-specificable-maximum version, remembering that as default:

(defun C:DIVDPM (/ cc1 cc2 range spcs spc)
  ; = DIVide Distance [not object] using Points, at user-specified Maximum spacing
  (initget (if *DIVDPmax* 6 7)); no zero, no negative, no Enter on first use
  (setq
    *DIVDPmax* ; global variable with routine-specific name
    (cond
      ( (getdist ; returns nil on Enter when permitted
          (strcat
            "\nMaximum Point spacing"
            (if *DIVDPmax* (strcat " <" (rtos *DIVDPmax*) ">") "")
            ": "
          ); strcat
        ); getdist
      ); User-input condition
      (*DIVDPmax*); prior value if present, on Enter
    ); cond & *DIVDPmax*
    p1 (getpoint "\nOne end of range: ")
    p2 (getpoint "\nOther end: ")
    range (distance p1 p2)
    spcs (+ (fix (/ range *DIVDPmax*)) (if (equal (rem range *DIVDPmax*) 0 1e-4) 0 1))
    spc (/ range spcs)
  ); setq
  (command "_.point" "_none" p1)
  (repeat spcs
    (command "_.point" "_none" (polar (getvar 'lastpoint) (angle p1 p2) spc))
  ); repeat
  (princ)
); defun
Kent Cooper, AIA
0 Likes
Message 11 of 17

serag.hassouna
Advocate
Advocate

Yes, I did this before using global variable[s] (the same idea stated by @Kent1Cooper).
These are 2 versions of the command "divpts" as requested, the 1st version differs slightly than Mr. Kent's version, by taking 12 as its first default value, & the 2nd version doesn't set any initial default value.
These 2 versions replaced the [getreal] function with [getdist] to accommodate with Mr. Kent's tip.

0 Likes
Message 12 of 17

pallen9JA6T
Enthusiast
Enthusiast

@Kent1CooperYour solution works great! Is it possible to revise it to omit the point on each of the "range"? Those points already exist, and if they are doubled, it gives me an error on my CNC machine. Thanks so much for your help.

0 Likes
Message 13 of 17

Kent1Cooper
Consultant
Consultant
Accepted solution

@pallen9JA6T wrote:

.... revise it to omit the point on each of the "range"....


 

Try this revision:

(defun C:DIVDPM (/ cc1 cc2 range spcs spc)
  ; = DIVide Distance [not object] using Points, at user-specified Maximum spacing
  (initget (if *DIVDPmax* 6 7)); no zero, no negative, no Enter on first use
  (setq
    *DIVDPmax* ; global variable with routine-specific name
    (cond
      ( (getdist ; returns nil on Enter when permitted
          (strcat
            "\nMaximum Point spacing"
            (if *DIVDPmax* (strcat " <" (rtos *DIVDPmax*) ">") "")
            ": "
          ); strcat
        ); getdist
      ); User-input condition
      (*DIVDPmax*); prior value if present, on Enter
    ); cond & *DIVDPmax*
    p1 (getpoint "\nOne end of range: ")
    p2 (getpoint "\nOther end: ")
    range (distance p1 p2)
    spcs (+ (fix (/ range *DIVDPmax*)) (if (equal (rem range *DIVDPmax*) 0 1e-4) 0 1))
    spc (/ range spcs)
  ); setq
  (setvar 'lastpoint p1); kind of interesting that that's allowed...
  (repeat (1- spcs)
    (command "_.point" "_none" (polar (getvar 'lastpoint) (angle p1 p2) spc))
  ); repeat
  (princ)
); defun
Kent Cooper, AIA
0 Likes
Message 14 of 17

pallen9JA6T
Enthusiast
Enthusiast

@Kent1CooperYOU'RE AWESOME! HAVE A BLESSED DAY!

0 Likes
Message 15 of 17

john.uhden
Mentor
Mentor

Perhaps you had better take another look at post #6, as I think you need a differing end gap so as to achieve a regular spacing.  But you don't want the end gaps too small, either.

John F. Uhden

0 Likes
Message 16 of 17

pallen9JA6T
Enthusiast
Enthusiast

@john.uhden

Actually, @Kent1Cooper's worked to exactly what I needed. Thanks for reply though.

0 Likes
Message 17 of 17

john.uhden
Mentor
Mentor

That's great news!  We love that kind.

John F. Uhden

0 Likes