@loitientran
The following code should work in 3D.
;; Draws a spline figuring a 3d catenary curve
;;
;; Arguments
;; pt1 : start point
;; pt2 : end point
;; H : horizontal tension
;; w : unit weight
;; k : vertical exaggeration (Y scale / X scale)
;; n : number of fit points
(defun draw3dCatenary (pt1 pt2 H w k n / cosh sinh asinh fitPoints)
;; Returns the hyperbolic cosine
(defun cosh (x)
(/ (+ (exp x) (exp (- x))) 2.)
)
;; Returns the hyperbolic sine
(defun sinh (x)
(/ (- (exp x) (exp (- x))) 2.)
)
;; Returns the inverse hyperbolic sine
(defun asinh (x)
(log (+ x (sqrt (+ (* x x) 1.))))
)
;; Computes the n fit points of the spline figuring the catenary between pt1 and pt2
;; with a = H / w
(defun fitPoints (pt1 pt2 n a k / norm p1 p2 x y z lg ht stp alpha beta gamma d1 d2 pts)
(setq norm (list (- (cadr pt1) (cadr pt2)) (- (car pt2) (car pt1)) 0.)
p1 (trans pt1 0 norm)
p2 (trans pt2 0 norm)
x (car p1)
y (cadr p1)
z (caddr p1)
lg (- (car p2) x)
ht (/ (- y (cadr p2)) k)
stp (/ lg (- n 1))
alpha (/ ht (* 2. a (sinh (/ lg (* 2. a)))))
beta (+ (/ lg 2.) (* a (asinh alpha)))
gamma (* a (- (cosh (/ beta a)) 1.))
d1 (+ x beta)
d2 (- y (* k gamma))
pts (list pt1)
)
(repeat (- n 2)
(setq pts (cons
(trans
(list (setq x (+ x stp))
(+ (* k a (- (cosh (/ (- x d1) a)) 1.)) d2)
z
)
norm
0
)
pts
)
)
)
(reverse (cons pt2 pts))
)
(entmakex
(append
(list '(0 . "SPLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbSpline")
(cons 70 8)
(cons 71 3)
(cons 74 (length lst-pts))
)
(mapcar '(lambda (x) (cons 11 x))
(fitPoints pt1 pt2 n (/ H w) k)
)
)
)
)
;; Catenary settings dialog box
(defun catenarySettings (H w k n / temp file dcl_id status lst)
(setq temp (vl-filename-mktemp "Tmp.dcl")
file (open temp "w")
)
(write-line
"Catenary: dialog {
label = \"Catenary Settings\";
: edit_box {
key = \"tension\";
edit_width=12;
label = \"Horizontal Tension: \";
allow_accept = true;
}
: edit_box {
key = \"weight\";
edit_width=12;
label = \"Unit Weight: \";
allow_accept = true;
}
: edit_box {
key = \"exaggeration\";
edit_width=12;
label = \"Vertical Exaggeration: \";
allow_accept = true;
}
: edit_box {
key = \"points\";
edit_width=12;
label = \"Number of Fit Points: \";
allow_accept = true;
}
spacer;
ok_cancel;
}"
file
)
(close file)
(setq dcl_id (load_dialog temp))
(if (not (new_dialog "Catenary" dcl_id))
(exit)
)
(set_tile "tension" (rtos H))
(set_tile "weight" (rtos w))
(set_tile "exaggeration" (rtos k))
(set_tile "points" (itoa n))
(action_tile
"accept"
(vl-prin1-to-string
(quote
(if (<= (distof (get_tile "tension")) 0.)
(progn
(alert "Needs a strictly positive real number.")
(mode_tile "tension" 2)
)
(if (<= (distof (get_tile "weight")) 0.)
(progn
(alert "Needs a strictly positive real number.")
(mode_tile "weight" 2)
)
(if (<= (distof (get_tile "exaggeration")) 0.)
(progn
(alert "Needs a strictly positive real number.")
(mode_tile "exaggeration" 2)
)
(if (<= (atoi (get_tile "points")) 6)
(progn
(alert "Needs an integer greater than or equal to 7.")
(mode_tile "points" 2)
)
(progn
(setq lst (list
(distof (get_tile "tension"))
(distof (get_tile "weight"))
(distof (get_tile "exaggeration"))
(atoi (get_tile "points"))
)
)
(done_dialog)
)
)
)
)
)
)
)
)
(setq status (start_dialog))
(unload_dialog dcl_id)
(vl-file-delete temp)
lst
)
;; Command
(defun c:3DCATENARY (/ pt1 pt2 H w k n)
(mapcar '(lambda (sym key val)
(set sym
(cond
((vlax-ldata-get "catenary" key))
((vlax-ldata-put "catenary" key val))
)
)
)
'(H w k n)
'("tension" "weight" "exaggeration" "numPts")
'(3000.0 2.0 1.0 17)
)
(while
(not
(or
(initget "Settings")
(vl-consp (setq pt1
(getpoint
(strcat
"\nCurrent settings: Horizontal Tension = "
(rtos H)
" - Unit Weight = "
(rtos w)
" - Vertical Exaggeration = "
(rtos k)
" - Number of Fit Points = "
(itoa n)
"\nStart point or [Settings] <S>: "
)
)
)
)
)
)
(if (setq lst (catenarySettings H w k n))
(mapcar '(lambda (sym key val)
(set sym (vlax-ldata-put "catenary" key val))
)
'(H w k n)
'("tension" "weight" "exaggeration" "numPts")
lst
)
)
)
(while
(setq pt2 (getpoint pt1 "\nNext point (or Enter to quit): "))
(draw3dCatenary (trans pt1 1 0) (trans (setq pt1 pt2) 1 0) H w k n)
)
(princ)
)