Starting in December, we will archive content from the community that is 10 years and older. This FAQ provides more information.
I feel the sweep command does not give the user much control in twist so I've written a couple of LISP programs to help a user position cross sections along the spline. The sections are defined as blocks which after positioning and rotating can be exploded to be used with the LOFT command.
The first program "BlocksOnSpline" let's the user position multiple blocks that define the section along a spline. The orientation of the sections are controlled by the first and second derivative functions. The user may also specify the start and end twist angles. I am satisfied with this program.
The second program "twist" lets the user select a block which is then rotated about its local z axis such that the block's x direction is parallel to the XY plane. Nentsel is used to extract the needed block data. Later in the program I want to use rotate3d to rotate the block about the block's z axis. I've tried using "last" and "p" and even the block's entity name to select the block for rotation but could not get the block to rotate. I finally resorted to using the block's base point location (p0). This usually works well but if the viewing angle is such that another object is visually in line with the select point it may get selected instead of the block that was orignally selected via nentsel.
What is the best way to reference the block orginally selected via netsel for use in the rotate3d command?
The attached drawing has a block named "section5x1". It's base point is at the center point. The other point is used to distinguish rotation of an additional 180°. Here are the results of using "blocksonspline"
In the following image the first section has been succesfully rotated. However, if the third section is picked the rotate3d will be done to the second section since part of its geometry is in line with the pick point (the base point) of the third section resulting in the wrong blocck being rotated.
(defun C:BlocksOnSpline (/ nsec blockname twist tottwist path inc n osm par der1
der2 p p1 p2 vy vz vx p3)
; Adds blocks along a spline. The user specifies the number of blocks and
; the total amount of twist over the length of the spline. The Z axis of the block
; is tangent to the spline.
; LRM 5/1/2023 revised 10/17/2024
(command "ucs" "w")
(setvar 'osmode 0)
(setq nsec (getint "\nEnter number of sections: "))
(setq nsec (- nsec 1))
(setq blockname (getstring "\nEnter block name: "))
(setq twist (getreal "\nEnter start twist angle: "))
(setq tottwist (getreal "\nENter total twist start to end: "))
(setq
path (car (entsel))
inc (/ (vlax-curve-getEndParam path) nsec)
n 0
osm (getvar 'osmode)
)
(setvar "cmdecho" 0)
(repeat (+ nsec 1)
(setq par (* inc n))
(setq der1 (vlax-curve-getfirstDeriv path par)
der2 (vlax-curve-getSecondDeriv path par)
p (vlax-curve-getPointAtParam path par)
)
(if (> (distance '(0 0 0) der2) 1e-10)
(setq vx (cross (cross der1 der2) der1))
(setq vx (cross '(0 0 1) der1))
)
(setq vz der1)
(setq p1 (mapcar '+ p vx))
(setq p2 (mapcar '+ p vz))
(command "-insert" blockname '(0 0 0) 1 1 0)
(command "_align" "last" "" '(0 0 0) p '(-1 0 0) p1 '(0 0 -1) p2 "n")
; (command "_align" "last" "" '(0 0 0) '(1 0 0) '(0 0 l) p p1 p2 "n")
(if (>
(abs twist) 0.00001)
(command "rotate3d" "last" "" "2" p p2 twist)
)
(setq twist (- twist (/ tottwist nsec)))
(setq n (1+ n))
) ; end repeat
(setvar 'osmode osm)
(setvar "cmdecho" 1)
(princ)
)
;;; Compute the cross product of 2 vectors a and b
(defun cross (a b / crs)
(setq crs (list
(- (* (nth 1 a) (nth 2 b))
(* (nth 1 b) (nth 2 a))
)
(- (* (nth 0 b) (nth 2 a))
(* (nth 0 a) (nth 2 b))
)
(- (* (nth 0 a) (nth 1 b))
(* (nth 0 b) (nth 1 a))
)
) ;end list
) ;end setq c
) ;end cross
(defun unitV (v / d)
(setq d (distance '(0 0 0) v)
d (mapcar '/ v (list d d d))
)
)
(defun c:twist (/ blockdata entName blockmatrix blockx blockz p0 p1 alpha alphadeg h d theta thetadeg)
; calculates the angle to rotate a block about its z axis to make the block's x axis
; parallel to the XY plane. It then rotates the block about its z axis.
; L. Minardi 10/6/2024
(setq blockdata (nentsel "\nSelect block:")
blockmatrix (nth 2 blockdata)
blockx (nth 0 blockmatrix) ; block x axis vector
blockz (nth 2 blockmatrix) ; block z axis vector
p0 (nth 3 blockmatrix) ; block position
p1 (mapcar '+ p0 (nth 2 blockmatrix)) ; point on block z axis
alpha (acos (dot '(0 0 1) blockz))
alphadeg (- 90 (/ (* alpha 180.) pi)) ; angle between world z and block z
h (sin alpha)
d (caddr blockx)
theta (* -1 (asin (/ d h))) ; rotation angle about z (radians)
thetadeg (/ (* theta 180.) pi)
)
(princ "\nTwist angle is: ")
(princ thetadeg)
(if (equal theta 0.0 0.001)
(princ
"\nX axis of block is already parallel to the XY plane!"
)
(progn
(command "_rotate3d" "_non" p0 "" "2" "_non" p0 "_non" p1 thetadeg)
(princ "\nDone!")
)
)
(princ)
)
(defun unitV (v / d)
(setq d (distance '(0 0 0) v)
d (mapcar '/ v (list d d d))
)
)
;; ArcCosine - Lee Mac
;; Args: -1 <= x <= 1
(defun acos ( x )
(if (<= -1.0 x 1.0)
(atan (sqrt (- 1.0 (* x x))) x)
)
)
; dot product of vectors a and b
(defun dot (a b / dd)
(setq dd (mapcar '* a b))
(setq dd (+ (nth 0 dd) (nth 1 dd) (nth 2 dd)))
) ;end of dot
;; ArcSine - Lee Mac
;; Args: -1 <= x <= 1
(defun asin ( x )
(if (<= -1.0 x 1.0)
(atan x (sqrt (- 1.0 (* x x))))
)
)
Can't find what you're looking for? Ask the community or share your knowledge.