Announcements
Autodesk Community will be read-only between April 26 and April 27 as we complete essential maintenance. We will remove this banner once completed. Thanks for your understanding

how to make two circle follow path in autocad?

darryl_sumirana.da2
Explorer

how to make two circle follow path in autocad?

darryl_sumirana.da2
Explorer
Explorer

Hi everyone, 

 

i'm having problem when i try to make two circle to follow path using path array function.

the problem is, the first circle follow my path correctly but the second one isn't.

i have snap the picture to make it clear.

 

if anyone can help me resolve this it would be appreciated.

Thank you.

 

0 Likes
Reply
Accepted solutions (4)
2,114 Views
18 Replies
Replies (18)

edwin.prakoso
Advisor
Advisor

I think you tried to create an array path from a block. The block array base point is the first circle center point. When AutoCAD creates the array, it places the block on the base point, then rotates the block aligned to the path. That is why the 1st circle is always on the path, but the 2nd circle is not.

You need to think about how it works, then move the base point to achieve what you want.

Cheers,
Edwin Prakoso
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

0 Likes

darryl_sumirana.da2
Explorer
Explorer

Yes, i use block on the model.

i have tried to explode it but it still wont come up as i wanted.

is there any way that block have 2 base point?

 

thank you for your help

0 Likes

edwin.prakoso
Advisor
Advisor

I haven't used the array path for a long time. Please forget what I said about the block basepoint. Apparently you can change the array base point without altering the block.

See the difference between these two arrays.

basepoint changes.png

The 2nd one was created by moving the array base point to the center of the block.

array base point tool.png

array base point.png

Check if this works for you. Remember that now the center of the block will be coincident with the path, but both of the circles' centers maybe not.

Cheers,
Edwin Prakoso
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

j.palmeL29YX
Mentor
Mentor

@darryl_sumirana.da2 wrote:

 

if anyone can help me resolve this it would be appreciated.

 

 


 

This can not be done in AutoCAD. 

I'm afraid you have to rotate the items manually. 

The video shows how I would do that:  

 

 

The result is of course not an assoziataive array, but you get precisely adjusted items along the path (all centerpoints are placed correct). 

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

tramber
Advisor
Advisor
Accepted solution

Or you can use constraints but only if the path is within a block it self overwise it will warp. And the path inside that block can not be a spline. If it would be the case then it would need a FLATEN command....

My solution is nice but may put you far from the point that the division gave !

tramber_0-1690371157937.png

 

neaton
Advisor
Advisor

For the items in the array that don't align use the subselect option by holding down the CTRL key to select individual items in the array to move and rotate them. See more information here: Modify individual array items  

~Nancy 

darryl_sumirana.da2
Explorer
Explorer

thank you for your video.

i did this the whole time, but it's kinda repetitive that's why i wonder is there any other way to make it faster.

appreciate it tho

0 Likes

darryl_sumirana.da2
Explorer
Explorer

Hi,

thank you for your advice, i did what you've suggest, but it still won't follow the path 

darryl_sumiranada2_0-1690507833302.png

 and also when should i use FLATEN command?

 

thank you.

0 Likes

j.palmeL29YX
Mentor
Mentor
Accepted solution

@darryl_sumirana.da2 wrote:

.. is there any other way to make it faster.

 


 

You can use the attached LISP which defines a new command TEST. 

To rotate the items (after prepairing as said above: draw an additional Circle in the block definition, create the array with not aligned items, explode the array) start the Lisp. Now pick the item at the second circle, drag the item to the intersection with the path and pick again. Repeat the command with an ENTER or SPACE and again pick twice (at the small circle of the block and at the intersection). 

 

 

 

For each item you need only two Pick's. 

Is that fast enough? 

 

Here the (quick and dirty) LISP. Of course you can refine it as you need. 

 

 

 

 

 

 

(defun c:test (/)
  (setq osold (getvar "osmode"))
  (setvar "osmode" 36)
  (setq item (entsel "\nSelect item: "))
  (setq obj (car item))
  (setq ppoint (cdr item))
  (setq bpoint (cdr (assoc 10 (entget obj))))
  (command "_rotate" obj "" bpoint "_r" 0 pause)
  (setvar osmode (getvar osold))
)

 

 

 

 

[EDIT]: 

As an additional small impovement you can run the MULTIPLE command before you start the Lisp the first time. So you avoid the ENTER or SPACE  to repeat the command and you need only repeatedly

- pick the (small right) circle

- pick the intersection. 

The same effect you can achieve if you add a while or repeat loop in the LISP. A lot of possibilities ...

 

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

tramber
Advisor
Advisor

To answer you @darryl_sumirana.da2,

My solution is more convenient with an array that has been exploded. It is only a second manipulation.

In such a case, i was meaning that tangency constraint can only apply to a polyline and not to a spline. Flatten easily turn a spline to a polyline...

nrz13
Advisor
Advisor

If I understand what you're wanting correctly, I think you need to ensure the center point of your block is snapped to the starting point of the path. A similar issue came up recently in another thread.


Work:  AutoCAD 2022.1.3, Windows 10 Pro v22H2 64-bit, Intel Core i7-8700K, 32GB RAM, Samsung 960 Pro SSD, AMD Radeon Pro WX 5100, 3 Dell Monitors (3840x2160)
Home: AutoCAD 2022.1.3, Windows 10 Pro v22H2 64-bit, Intel Core i7-11700, 64GB RAM, Samsung 980 Pro SSD, NVIDIA Quadro P2200, Dell Monitor (3840x2160)
0 Likes

darryl_sumirana.da2
Explorer
Explorer

Thank you very much, this is my first time use LISP, and it turns out to be exciting.

appreciate it 👍

0 Likes

leeminardi
Mentor
Mentor
Accepted solution

EDIT 8/9/2023  Please see improved code in post #19.  LRM

 

The following program will "usually" position an array of blocks along a spline with rotations determined by the block's base point and a point on the block's x axis a distance "L"  .  The bisection numerical method is used to find the location of the point on the spline a distance L from the block's base point.  If the spline is well behaved (no radical tight curves) a satisfactory solution can be determined.

leeminardi_0-1690899809155.png

leeminardi_1-1690899832913.png

For very irregular shaped splines a satisfactory solution may not be determined.  For example, note how the first block (bottom left) could be at a steeper angle.

leeminardi_2-1690899980319.png

I've only done limited testing.  I used the attached drawing to test the program which assumes a value of 1.3 for L.  I used A = 1 for the spacing in this example.

 

(defun C:test (/ L A path pt smax dmax n s1 p1 L1 sm s0 s1 dm pt ang j)
;  Adds blocks along a spline.  The block's origin is placed on the spline.
;  The angle of the block is determined by a second point a distance L in the X
; direction of the spline.  The block's have a spacing of A. 
; L. Minardi 8/1/2023  v4
  (command "ucs" "w")
  (setvar 'osmode 0)
  (setq L (getreal "\nEnter distance between the block's base point and a point on the block's x axis: "))
  (setq A (getreal "\nEnter distance to next block: "))
(setq blockname (getstring "\nEnter block name: "))
;(setq L 1.3 A 1 blockname "block1") ; used for debugging
  (setq
    path (car (entsel "\nSelect Path."))
    pt	 (vlax-curve-getStartPoint path)
    smax  (vlax-curve-getEndParam path)
    dmax (vlax-curve-getDistAtParam path smax)
    n (+ (/ dmax (+ L A)) 1)
    s1 smax
    p1 (vlax-curve-getPointAtParam path s1)
    L1 (distance pt p1)
    sm 0.
  )
(setq j 1)
(while (< j n)
  (if (equal sm 0)
    (setq s0 0)
    (progn
      (setq dm (vlax-curve-getDistAtParam path sm))
      (setq pt (vlax-curve-getPointAtDist path (+ dm A)))
      (setq s0 (vlax-curve-getParamAtPoint path pt))
    )
  )
  (SplinePtAtDist path pt L s0 s1)
  (setq ang (/ (* (angle pt pm) 180.) pi))
  (command "-insert" blockname pt 1 1 ang)
  (setq j (+ j 1))
)					; end j while
(princ)  
)

(defun SplinePtAtDist (path pt L s0 s1 / i  )
; find the point on the spline that is a distance L from the point pt
; in the parametric interval s0 to s1 using bisection method. 
(setq i 0)
(while (< i 20) ; sets maximum interations
(setq sm (/ (+ s0 s1) 2)) ; midpoint between s0 and s1
(setq pm   (vlax-curve-getPointAtParam path sm)) ; point at sm
  (if (< (distance pt pm) L) ; determine if soln between so and sm, or sm and s1
    (setq s0 sm
	  p0 (vlax-curve-getPointAtParam path s0)
    )
    (setq s1 sm
	  p1 (vlax-curve-getPointAtParam path s1)
    )
  )
;;;(command "point" pm)  ; used for debugging
(setq i (+ i 1))
(setq err (/ (abs (- (distance pt pm) L)) L))
(if (<  err 0.001)
  (setq i 100)
  )
) ; end while
)  

 

 

 

 

 

 

 

lee.minardi

j.palmeL29YX
Mentor
Mentor

@darryl_sumirana.da2 

 

I'd suggest in Line 35 of the LISP a small correction:   

 

(command "-insert" blockname pt 1 1 ang) ;;; "block1" substituted by blockname 

 

@leeminardi 

A nice work, thanks. This answer should be accepted as solution. I've had a similar intention, but was not able to write such a LISP. 

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

0 Likes

leeminardi
Mentor
Mentor

@j.palmeL29YX thanks for the compliment and catching the error on line 35. I had hard wired the block name during the debugging process and forget to change it back to a variable before posting.  I have corrected the code in my post.

lee.minardi
0 Likes

darryl_sumirana.da2
Explorer
Explorer

wow, this is perfect, but to be honest i'm still learning how this whole things work.

but it gets interesting, any hint where to start to learn about this LISP?

Thank you. 

0 Likes

j.palmeL29YX
Mentor
Mentor

@darryl_sumirana.da2 wrote:

any hint where to start to learn about this LISP?

 


 

The bible 🙂 for each (german) AutoLISP beginner you find >>here<<

(In the meantime it is also pulished as book [in german language])

 

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

0 Likes

leeminardi
Mentor
Mentor
Accepted solution

I was not satisfied with the version of the program I posted in post #14. The numerical algorithm I created to find a point (p) on a spline a specified distance (L) from a known point (pt) used a point midway along the spline for the first guess. It then used the bisection numerical method to find p. In some cases, this would not find the closest solution point to pt.

leeminardi_1-1691605799609.png

 

I rewrote the program to assume that the first guess for P was at a distance L, measured along the spline. This will always yield a point too close to pt to be the solution (except if the spline is straight) but not so far away either. From there the algorithm "walks" along the spline at a step size 1/3*L until it passes the solution and then backs up one half the step size until that's too much then goes forward 1/4 the step size. The process is repeated until a location for p within acceptable limits is found.

 

I think this approach yields much better results for very wavy spline but I am sure there are cases that will yield unacceptable results.

 

Compare the following solutions via the first method and the new approach.

First method example results:

leeminardi_2-1691605998356.png

 

Improved version:

leeminardi_3-1691606032312.png

 

To get a feel for how the algorithm converges to a solution here is a sample with points placed at the successive guesses made by the program. Note how some solutions are found in as little as 3 guesses.

leeminardi_4-1691606075365.png

Points showing successive guesses.

leeminardi_5-1691606151650.png

 

As a side note, I recently posted a tutorial for 3ds Max users on using a similar method to find the point on a cable that is a fixed distance from a trolley with an overhead boom. I think it provides a good explanation how a numerical solution (i.e., a solver) works.

3ds Max Tutorial - creating your own solver

 

(defun C:ArraySpline (/ L A blockname path pt smax smax dmax sL more p ang sp dpt )
;  Adds a series of blocks along a spline.  The block's origin is placed on the spline.
;  The angle of the block is determined by a second point of the block a distance L in the X
; direction of the block.  The block's have a user defined  spacing of A. 
; L. Minardi 8/9/2023 
  (command "ucs" "w")
  (setvar 'osmode 0)
(setq L (getreal
	  "\nEnter distance between the block's base point and a point on the block's x axis: "
		)
      A		(getreal "\nEnter distance to next block: ")
      blockname	(getstring "\nEnter block name: ")
)
;(setq L 1.3 A 1 blockname "block1") ; used for debugging
  (setq
    path (car (entsel "\nSelect Path."))
    pt	 (vlax-curve-getStartPoint path)
    smax (vlax-curve-getEndParam path)
    dmax (vlax-curve-getDistAtParam path smax)
    sL	 (vlax-curve-getParamAtDist path L)
    more T				; flag for loop  
  )
  (while more				; loop for adding blocks until end of spline is reached
    (setq p   (SplinePtAtDist path pt L) ; location on spline for block's second point
	  ang (/ (* (angle pt p) 180.) pi)
    )
    (command "-insert" blockname pt 1 1 ang)
    (setq dp  (vlax-curve-getDistAtPoint path p) ; distance to p
	  sp  (vlax-curve-getParamAtPoint path p) ; parameter at p
	  pt  (vlax-curve-getPointAtDist path (+ dp A)) ; next block location
	  p   (vlax-curve-getPointAtDist path (+ dp A L)) ; initial guess for second point on spline 
	  dpt (vlax-curve-getDistAtPoint path pt) ; distance along spline to pt
    )
    (if	(< (- sMax sp) sL)		; test if another block will fit on spline
      (setq more nil)
    )
  )					; end  while
  (princ)
)

(defun SplinePtAtDist (path pt  L  / disPt p s spt sDelta i sgn err)
; find the point on a spline that is a distance L from the point pt, 
; path - spline object name
; pt - known point on the spline that is closer to the beinning of the spline
;      than the desired point p that is a straingt line distance L away.  
; L - distance between the block's base point and a point on its x axis.

(setq disPt  (vlax-curve-getDistAtPoint path pt)
      p	     (vlax-curve-getPointAtDist path (+ disPt L))
      s	     (vlax-curve-getParamAtPoint path p)
      spt    (vlax-curve-getParamAtPoint path pt)
      sDelta (/ (- s spt) 3)
      i	     0
      sgn 1
)
(while (< i 20) ; sets maximum interations for solution
(if (> L (distance pt p)) 
  (progn ; true, L > distance
    (if	(> (* sgn -1) 0)
      (setq sgn	   (* sgn -1)  ; reverse search diection 
	    sDelta (/ sDelta 2); halve the interval search size
      )
    )
  )
  (progn ; false L not > distance
    (if	(< (* sgn -1) 0)
      (setq sgn	   (* sgn -1)
	    sDelta (/ sDelta 2)
      )
    )
  )
)
(setq s	(+ s (* sgn sDelta))
      p	(vlax-curve-getPointAtParam path s)
)
;;;(command "point" p)  ; used for debugging
(setq i (+ i 1))
(setq err (/ (abs (- (distance pt p) L)) L))
(if (< err 0.001) (setq i 100)) ; exit loop if error acceptable
) ; end while
  (setq p p)
) ; end defun   
lee.minardi