Aligning the rotating object along a path

Aligning the rotating object along a path

Anonymous
Not applicable
6,283 Views
19 Replies
Message 1 of 20

Aligning the rotating object along a path

Anonymous
Not applicable

I want to align a line or block that rotates at any angle along a path(curve or spline).

the array on path command doesn't allow for rotating.

Please let me know if you have any good ideas or autoLISPs

img1.png

 

ref.

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/is-there-a-way-to-array-with-rotatio...

https://forums.autodesk.com/t5/autocad-forum/copy-or-array-block-along-path-while-also-rotating-path...

0 Likes
Accepted solutions (4)
6,284 Views
19 Replies
Replies (19)
Message 2 of 20

CodeDing
Advisor
Advisor

@Anonymous,

 

I have a couple questions...

1) is the Rotate Object (RO) a block? series of lines? PLINEs?

2) Is the Path, when spline, at a uniform radius? or at a variable radius?

 

Posting a dwg of the objects in the image you provided would greatly help also.

 

Best,

~DD

0 Likes
Message 3 of 20

john.uhden
Mentor
Mentor

You can use the vlax-curve-getfirstderiv function to obtain the tangent angle at any point along any curve.

Well, actually a sharp vertex leaves you with decisions... tangent to just before or just after the vertex, or maybe some kind of average.  But not a literal average if the angles hover around 0 (= (* 2 pi)).

John F. Uhden

0 Likes
Message 4 of 20

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

I want to align a line or block that rotates at any angle along a path(curve or spline).

 

…. 

ref.

....

https://forums.autodesk.com/t5/autocad-forum/copy-or-array-block-along-path-while-also-rotating-path/m-p/6877733


 

If you can hang in there a little, and if no one else posts something else first, I am working on a modification of DivideMeasurePlus.lsp [linked to in your second link] to add an incremented-rotation option.  Assuming it works out, it would have all the other enhancements over regular Divide and Measure, and it would give you the option of whether to place, at incremented rotations, Blocks, or Lines [of User-specified length, and without needing to have one drawn already], or any  User-selected object(s).  [It will be omitting the Points option from the incremented-rotation choice, since rotation doesn't mean anything for a Point.]

Kent Cooper, AIA
Message 5 of 20

Anonymous
Not applicable

attach a sample drawing...

 

Thanks.

0 Likes
Message 6 of 20

Anonymous
Not applicable

I tried DivideMeasurePlus.lsp.
However, it rotates an angle about the tangent direction of the path,
Or they all have the same angle.

0 Likes
Message 7 of 20

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

I tried DivideMeasurePlus.lsp.
However, it rotates an angle about the tangent direction of the path,
Or they all have the same angle.


 

Yes, you have both those choices.  It's the incremented  rotation option that I'm working on including in it.  I put some time into it when I can....

Kent Cooper, AIA
0 Likes
Message 8 of 20

CADaSchtroumpf
Advisor
Advisor

Hi,

 

Perhaps this?

(defun c:exp2 ( / js dxf_obj obj_vlax pt_start pt_end total_dist partial_dist ori_dist lst_pt increment_dist increment_ang ang)
  (princ "\nSelect an object to measure: ")
  (while
    (not
      (setq js
        (ssget "_+.:E:S"
          (list
            (cons -4 "<OR")
              (cons 0 "*POLYLINE,LINE,ARC,CIRCLE,ELLIPSE")
              (cons -4 "<NOT")
                (cons -4 "&") (cons 70 112)
              (cons -4 "NOT>")
              (cons 0 "SPLINE")
            (cons -4 "OR>")
            (cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
            (cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
          )
        )
      )
    )
    (princ "\nIsn't an avalaibled object for this function!")
  )
  (vl-load-com)
  (setq
    dxf_obj (entget (ssname js 0))
    obj_vlax (vlax-ename->vla-object (ssname js 0))
    pt_start (vlax-curve-getStartPoint obj_vlax)
    pt_end (vlax-curve-getEndPoint obj_vlax)
    total_dist (vlax-curve-getDistAtParam obj_vlax (vlax-curve-getEndParam obj_vlax))
    partial_dist (getreal "\nSet steep to ? <1.0>: ")
    ori_dist partial_dist
  )
  (if (not partial_dist) (setq partial_dist 1.0 ori_dist partial_dist))
  (cond
    ((> total_dist partial_dist)
      (setq
        increment_dist partial_dist
        increment_ang pi
      )
      (while (< increment_dist total_dist)
        (setq
          lst_pt (cons (vlax-curve-getClosestPointTo obj_vlax (vlax-curve-getPointAtDist obj_vlax increment_dist)) lst_pt)
          increment_dist (+ increment_dist partial_dist)
        )
      )
      (foreach n lst_pt
        (setq
          ang (angle '(0.0 0.0 0.0) (vlax-curve-getFirstDeriv obj_vlax (vlax-curve-getParamAtPoint obj_vlax n)))
        )
        (entmake
          (list
            (cons 0 "LINE")
            (cons 100 "AcDbEntity")
            (assoc 67 dxf_obj)
            (assoc 410 dxf_obj)
            (cons 8 (getvar "CLAYER"))
            (cons 100 "AcDbLine")
            (cons 10
              (polar
                (trans n 0 (cdr (assoc 210 dxf_obj)))
                (+ ang (setq increment_ang (+ increment_ang (angtof "5.0" 0))))
                partial_dist
              )
            )
            (cons 11
              (polar
                (trans n 0 (cdr (assoc 210 dxf_obj)))
                (+ ang increment_ang pi)
                partial_dist
              )
            )
            (assoc 210 dxf_obj)
          )
        )
      )
    )
    (T (princ "\nThe lenght as too big for object!"))
  )
  (prin1)
)
Message 9 of 20

Anonymous
Not applicable

Yes!! that’s right.
Can I change the default angle and line length?

0 Likes
Message 10 of 20

CADaSchtroumpf
Advisor
Advisor

@Anonymous  a écrit :

Yes!! that’s right.
Can I change the default angle and line length?


Yes, in (cons 10) and (cons 11) , I have put (angtof "5.0" 0) for 5° angle increment and partial_dist ("Set step to") for half-length.

You can put for exemple (angtos "15.0" 0) for 15° and substitute partial_dist by a real value; 2.5 for exemple for obtain line length at 5.0

 

0 Likes
Message 11 of 20

Anonymous
Not applicable

It doesn't work well.
I want the form of inputting angle and line length in the command.
Can you modify it?

0 Likes
Message 12 of 20

CADaSchtroumpf
Advisor
Advisor
Accepted solution

I re-post it

(defun c:exp2 ( / js dxf_obj obj_vlax pt_start pt_end total_dist partial_dist ori_dist inc_ang l_line lst_pt increment_dist increment_ang ang)
  (princ "\nSelect an object to measure: ")
  (while
    (not
      (setq js
        (ssget "_+.:E:S"
          (list
            (cons -4 "<OR")
              (cons 0 "*POLYLINE,LINE,ARC,CIRCLE,ELLIPSE")
              (cons -4 "<NOT")
                (cons -4 "&") (cons 70 112)
              (cons -4 "NOT>")
              (cons 0 "SPLINE")
            (cons -4 "OR>")
            (cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
            (cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
          )
        )
      )
    )
    (princ "\nIsn't an avalaibled object for this function!")
  )
  (vl-load-com)
  (initget 7)
  (setq
    dxf_obj (entget (ssname js 0))
    obj_vlax (vlax-ename->vla-object (ssname js 0))
    pt_start (vlax-curve-getStartPoint obj_vlax)
    pt_end (vlax-curve-getEndPoint obj_vlax)
    total_dist (vlax-curve-getDistAtParam obj_vlax (vlax-curve-getEndParam obj_vlax))
    partial_dist (getdist (trans pt_start 0 1) "\nSet step to?: ")
    ori_dist partial_dist
  )
  (initget 1)
  (setq inc_ang (getangle (trans pt_start 0 1) "\nIncrement of angle?: "))
  (initget 7)
  (setq l_line (getdist (trans pt_start 0 1) "\nLength of line?: "))
  (cond
    ((> total_dist partial_dist)
      (setq
        increment_dist partial_dist
        increment_ang pi
      )
      (while (< increment_dist total_dist)
        (setq
          lst_pt (cons (vlax-curve-getClosestPointTo obj_vlax (vlax-curve-getPointAtDist obj_vlax increment_dist)) lst_pt)
          increment_dist (+ increment_dist partial_dist)
        )
      )
      (foreach n lst_pt
        (setq
          ang (angle '(0.0 0.0 0.0) (vlax-curve-getFirstDeriv obj_vlax (vlax-curve-getParamAtPoint obj_vlax n)))
        )
        (entmake
          (list
            (cons 0 "LINE")
            (cons 100 "AcDbEntity")
            (assoc 67 dxf_obj)
            (assoc 410 dxf_obj)
            (cons 8 (getvar "CLAYER"))
            (cons 100 "AcDbLine")
            (cons 10
              (polar
                (trans n 0 (cdr (assoc 210 dxf_obj)))
                (+ ang (setq increment_ang (+ increment_ang inc_ang)))
                (* l_line 0.5)
              )
            )
            (cons 11
              (polar
                (trans n 0 (cdr (assoc 210 dxf_obj)))
                (+ ang increment_ang pi)
                (* l_line 0.5)
              )
            )
            (assoc 210 dxf_obj)
          )
        )
      )
    )
    (T (princ "\nThe lenght as too big for the object!"))
  )
  (prin1)
)
Message 13 of 20

john.uhden
Mentor
Mentor

Instead of all that filtering, how about...

(vlax-method-applicable-p object 'vlax-curve-getfirstderiv))

?

I think Land Desktop contours qualified.  Don't know about Civil 3D thingies, though with my recent coronation I can get C3D and find out.

Maybe plants have roots or stems or branches or fronds that are technically curves.

Maybe even electrical circuits, or Frank Gehry walls.

Or HVAC piping, or colonoscopy tubing, or ...

BTW, colonoscopies don't hurt one bit.  It's just drinking that Suprep is what will turn you into a simpering milksop.

John F. Uhden

0 Likes
Message 14 of 20

CADaSchtroumpf
Advisor
Advisor

Hi John,

 

I think that the 'vlax-curve-getfirstdriv is not a method and  have not a property

So I can't check it, or I don't know how make it...

(vlax-method-applicable-p object 'vlax-curve-getfirstderiv))

For me this return alway nil

0 Likes
Message 15 of 20

Anonymous
Not applicable

I want to use it as a block instead of a line.
Can you change it?

0 Likes
Message 16 of 20

CADaSchtroumpf
Advisor
Advisor

I have it with block... But you must adapt with your block, I'm not guessing!

(defun make_blk_measure ( / )
     (if (not (tblsearch "STYLE" "$BLK_MEAS"))
       (entmake	'((0 . "STYLE")
		  (5 . "40")
		  (100 . "AcDbSymbolTableRecord")
		  (100 . "AcDbTextStyleTableRecord")
		  (2 . "$BLK_MEAS")
		  (70 . 0)
		  (40 . 0.0)
		  (41 . 1.0)
		  (50 . 0.0)
		  (71 . 0)
		  (42 . 0.1)
		  (3 . "simplex.shx")
		  (4 . "")
		 )
       )
     )
     (if (not (tblsearch "BLOCK" "BLK_MEASURE_CURVE"))
       (progn
	 (entmake
	   '((0 . "BLOCK") (8 . "0") (2 . "BLK_MEASURE_CURVE") (70 . 2) (4 . "") (8 . "0") (62 . 0) (6 . "ByBlock") (370 . -2) (10 0.0 0.0 0.0))
	 )
	 (entmake
	   '((0 . "POINT") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPoint") (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (50 . 0.0))
	 )
	 (entmake
	  '(
	(0 . "ATTDEF")
	(100 . "AcDbEntity")
	(67 . 0)
	(410 . "Model")
	(8 . "0")
	(100 . "AcDbText")
	(10 0.05 0.1 0.0)
	(40 . 0.1)
	(1 . "0.0")
	(50 . 1.570796326794896)
	(41 . 1.0)
	(51 . 0.0)
	(7 . "$BLK_MEAS")
	(71 . 0)
	(72 . 0)
	(11 0.0 0.1 0.0)
	(210 0.0 0.0 1.0)
	(100 . "AcDbAttributeDefinition")
	(3 . "measure")
	(2 . "VALUE_MEASURE")
	(70 . 0)
	(73 . 2)
	(74 . 2)
	  )
	 )
	 (entmake '((0 . "ENDBLK") (8 . "0") (62 . 0) (6 . "ByBlock") (370 . -2)))
       )
    )
)
(defun z_dir (p1 p2 / )
	(trans
		'(0.0 1.0 0.0)
		(mapcar
			'(lambda (k)
				(/ k
					(sqrt
						(apply '+
							(mapcar
								'(lambda (x) (* x x))
								(mapcar '- p2 p1)
							)
						)
					)
				)
			)
			(mapcar '- p2 p1)
		)
		0
	)
)
(defun c:blk-att_measure ( / js dxf_obj obj_vlax pt_start pt_end total_dist partial_dist lst_pt increment_dist sv_luprec sv_dzin ang dxf_210)
	(princ "\nSélectionner un objet curviligne à mesurer/diviser: ")
	(while
		(not
			(setq js
				(ssget "_+.:E:S"
					(list
						(cons 0 "*POLYLINE,LINE,ARC,CIRCLE,ELLIPSE,SPLINE")
						(cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
						(cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
						(cons -4 "<NOT")
						(cons -4 "&") (cons 70 112)
						(cons -4 "NOT>")
					)
				)
			)
		)
		(princ "\nCe n'est pas un objet curviligne valable pour cette fonction!")
	)
	(vl-load-com)
	(setq
		dxf_obj (entget (ssname js 0))
		obj_vlax (vlax-ename->vla-object (ssname js 0))
		pt_start (vlax-curve-getStartPoint obj_vlax)
		pt_end (vlax-curve-getEndPoint obj_vlax)
		total_dist (vlax-curve-getDistAtParam obj_vlax (vlax-curve-getEndParam obj_vlax))
	)
	(initget "Mesurer Diviser _Measure Divide")
	(if (eq (getkword (strcat "\n[Mesurer/Diviser] l'objet d'une longueur de " (rtos total_dist) "? <M>: ")) "Divide")
		(progn
			(initget 7)
			(setq
				partial_dist (getint "\nEntrez le nombre de segments: ")
				partial_dist (/ total_dist partial_dist)
			)
		)
		(progn
			(initget 7)
			(setq partial_dist (getdist "\nSpécifiez la longueur du segment: "))
		)
	)
	(cond
		((> total_dist partial_dist)
			(make_blk_measure)
			(setq
				lst_pt (list pt_start)
				increment_dist partial_dist
				sv_luprec (getvar "LUPREC")
				sv_dzin (getvar "DIMZIN")
			)
			(setvar "CMDECHO" 1)
			(setvar "DIMZIN" 0)
			(command "_.luprec" pause)
			(while (< increment_dist total_dist)
				(setq
					lst_pt (cons (vlax-curve-getPointAtDist obj_vlax increment_dist) lst_pt)
					increment_dist (+ increment_dist partial_dist)
				)
			)
			(setq lst_pt (reverse (cons pt_end lst_pt)))
			(foreach n lst_pt
				(setq
					ang (angle '(0.0 0.0 0.0) (vlax-curve-getFirstDeriv obj_vlax (vlax-curve-getParamAtPoint obj_vlax n)))
					dxf_210 (z_dir n (polar n ang (* 0.1 partial_dist)))
				)
				(entmake
					(list
						(cons 0 "INSERT")
						(cons 100 "AcDbEntity")
						(assoc 67 dxf_obj)
						(assoc 410 dxf_obj)
						(cons 8 (getvar "CLAYER"))
						(cons 100 "AcDbBlockReference")
						(cons 66 1)
						(cons 2 "BLK_MEASURE_CURVE")
						(cons 10 (trans n 0 dxf_210))
						(cons 41 (* 0.1 partial_dist))
						(cons 42 (* 0.1 partial_dist))
						(cons 43 (* 0.1 partial_dist))
						(cons 50 ang)
						(cons 210 dxf_210)
					)
				)
				(entmake
					(list
						(cons 0 "ATTRIB")
						(cons 100 "AcDbEntity")
						(assoc 67 dxf_obj)
						(assoc 410 dxf_obj)
						(cons 8 (getvar "CLAYER"))
						(cons 100 "AcDbText")
						(cons 10
							(polar
								(polar (trans n 0 dxf_210) (+ (/ pi 2) ang) (* 0.1 partial_dist))
								ang
								(* 0.05 partial_dist)
							)
						)
						(cons 40 (* 0.1 partial_dist))
						(cons 1 (rtos (vlax-curve-getDistAtPoint obj_vlax n)))
						(cons 50 (+ (/ pi 2) ang))
						(cons 41 1.0)
						(cons 51 0.0)
						(cons 7 "$BLK_MEAS")
						(cons 71 0)
						(cons 72 0)
						(cons 11 (polar (trans n 0 dxf_210) (+ (/ pi 2) ang) (* 0.1 partial_dist)))
						(cons 210 dxf_210)
						(cons 100 "AcDbAttribute")
						(cons 2 "VALUE_MEASURE")
						(cons 70 0)
						(cons 73 2)
						(cons 74 2)
					)
				)
				(entmake (list (cons 0 "SEQEND") (cons 8 (getvar "CLAYER")) (cons 62 0) (cons 6 "ByBlock") (cons 370 -2)))
			)
			(setvar "LUPREC" sv_luprec)
			(setvar "DIMZIN" sv_dzin)
		)
		(T (princ "\nLa longueur est trop grande pour l'objet!"))
	)
	(prin1)
)
0 Likes
Message 17 of 20

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

I want to use it as a block instead of a line.
Can you change it?


 

I had "promised" something back in Message 4, and had worked on it some at the time, but it had drifted from my consciousness, and now you've reminded me.  It could maybe use more extensive testing, but I'm posting it -- the attached DivideMeasurePlus-IR.lsp is the version with Incremented-Rotation option added.  You can do it with Points [for which Rotation, whether incremented or not, is not relevant nor asked for], or Lines, or Blocks, or any selected already-drawn object(s) -- all the choices in the original DIV+ and MEA+ commands [I did not change the command names], with all their other enhancements over ordinary Divide and Measure.

Kent Cooper, AIA
0 Likes
Message 18 of 20

Anonymous
Not applicable

The contents are strange.
I think there are other content.

 

What I want is to modify / add the last command line,
- Select objects (path):
- Set step to ?:
- Increment of angle ?:
- Length of line ?: → select block (enter block name), set center point

0 Likes
Message 19 of 20

CADaSchtroumpf
Advisor
Advisor
Accepted solution

As I said before, I'm not a reader of thoughts ...
I gave an example of using block with attributes.

Without more precision on your part, I will consider the use of a simple block with an insertion scale of 1.

(defun c:exp2-blk ( / js dxf_obj obj_vlax pt_start pt_end total_dist partial_dist ori_dist inc_ang nam_blk lst_pt increment_dist increment_ang ang)
  (princ "\nSelect an object to measure: ")
  (while
    (not
      (setq js
        (ssget "_+.:E:S"
          (list
            (cons -4 "<OR")
              (cons 0 "*POLYLINE,LINE,ARC,CIRCLE,ELLIPSE")
              (cons -4 "<NOT")
                (cons -4 "&") (cons 70 112)
              (cons -4 "NOT>")
              (cons 0 "SPLINE")
            (cons -4 "OR>")
            (cons 67 (if (eq (getvar "CVPORT") 2) 0 1))
            (cons 410 (if (eq (getvar "CVPORT") 2) "Model" (getvar "CTAB")))
          )
        )
      )
    )
    (princ "\nIsn't an avalaibled object for this function!")
  )
  (vl-load-com)
  (initget 7)
  (setq
    dxf_obj (entget (ssname js 0))
    obj_vlax (vlax-ename->vla-object (ssname js 0))
    pt_start (vlax-curve-getStartPoint obj_vlax)
    pt_end (vlax-curve-getEndPoint obj_vlax)
    total_dist (vlax-curve-getDistAtParam obj_vlax (vlax-curve-getEndParam obj_vlax))
    partial_dist (getdist (trans pt_start 0 1) "\nSet step to?: ")
    ori_dist partial_dist
    nam_blk ""
  )
  (initget 1)
  (setq inc_ang (getangle (trans pt_start 0 1) "\nIncrement of angle?: "))
  (while (not (tblsearch "BLOCK" nam_blk))
    (setq nam_blk (getstring "\nName of block?: "))
  )
  (cond
    ((> total_dist partial_dist)
      (setq
        increment_dist partial_dist
        increment_ang pi
      )
      (while (< increment_dist total_dist)
        (setq
          lst_pt (cons (vlax-curve-getClosestPointTo obj_vlax (vlax-curve-getPointAtDist obj_vlax increment_dist)) lst_pt)
          increment_dist (+ increment_dist partial_dist)
        )
      )
      (foreach n lst_pt
        (setq
          ang (angle '(0.0 0.0 0.0) (vlax-curve-getFirstDeriv obj_vlax (vlax-curve-getParamAtPoint obj_vlax n)))
        )
        (entmake
          (list
            (cons 0 "INSERT")
            (cons 100 "AcDbEntity")
            (assoc 67 dxf_obj)
            (assoc 410 dxf_obj)
            (cons 8 (getvar "CLAYER"))
            (cons 100 "AcDbBlockReference")
            (cons 66 0)
            (cons 2 nam_blk)
            (cons 10 (trans n 0 (cdr (assoc 210 dxf_obj))))
            (cons 41 1.0)
            (cons 42 1.0)
            (cons 43 1.0)
            (cons 50 (+ ang (setq increment_ang (+ increment_ang inc_ang))))
            (assoc 210 dxf_obj)
          )
        )
      )
    )
    (T (princ "\nThe lenght as too big for the object!"))
  )
  (prin1)
)
0 Likes
Message 20 of 20

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

What I want is to modify / add the last command line,
- Select objects (path):
- Set step to ?:
- Increment of angle ?:
- Length of line ?: → select block (enter block name), set center point


 

Have you tried the routine attached to Message 17?  It does all that and more, except for having the selection of the path [or any number of paths] at the end.  You can choose to have it draw Lines of whatever length you choose [which will be centered on the path without your needing to specify a center point], or give it a Block name [the insertion point will go on the path without your needing to specify], or select any existing object(s), which can be an already-drawn Line, or an already-Inserted Block, or anything else including multiple  objects.  [In the case of user-Selected object(s), you do need to specify the reference point relative to it/them that will be placed on the path(s).]  You also get the choice of not only the increment  of angle, but the angle of the first one  from which that increment proceeds.  And you can do it in MEASURE-like operation or DIVIDE-like operation, with other choices that those commands don't give you.

Kent Cooper, AIA
0 Likes