TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: crowellsr on March 26, 2007, 05:05:17 PM
-
Is there a way to calculate the angle that corresponds to a calculated sine value in LISP. I have yet to see a function for it and would rather not reinvent the wheel if there is already a way to do it.
Thanks
Steve
-
you mean like arcsin?
asin(real)
-
Yeah I think thats what it is called. It is the function that gives you the angle from a sine value.
-
Trig functions posted to the Adesk newsgroups by Jon Fleming c.1997:
;;; the trigonometric functions not included with autolisp.
;;; jon fleming, may 20 1997.
;;; note that some of the functions (arcsecant and arccosecant)
;;; use other functions defined in this file.
;;; note that none of these functions check for valid
;;; arguments. passing valid arguments is the responsibility
;;; of the calling program.
;;; 9.7e307 was determined experimentally to be the largest
;;; number that can be generated in autolisp (in r14).
;;;--------------------------------------------------------
;;; tangent accepts any angle in radians, and returns the
;;; tangent in the range -9.7e307+epsilon to 9.7e307 inclusive
(defun tan (z / cosz)
(if (zerop (setq cosz (cos z)))
9.7e307
(/ (sin z) cosz)
)
)
;;; secant accepts any angle in radians, and returns the
;;; secant in the ranges -9.7e307+epsilon to -1.0 inclusive
;;; and 1.0 to 9.7e307 inclusive
(defun sec (z / cosz)
(if (zerop (setq cosz (cos z)))
9.7e307
(/ 1.0 cosz)
) ;_ end if
)
;;; cosecant accepts any angle in radians, and returns the
;;; cosecant in the ranges -9.7e307+epsilon to -1.0 inclusive
;;; and 1.0 to 9.7e307 inclusive
(defun csc (z / sinz)
(if (zerop (setq sinz (sin z)))
9.7e307
(/ 1.0 sinz)
)
)
;;; arcsine (inverse sine) accepts an argument in the range
;;; -1.0 to 1.0 inclusive, and returns an angle in radians in
;;; the range (-pi/2) to (pi/2) inclusive.
(defun asin (z /)
(atan z (sqrt (- 1.0 (* z z))))
)
;;; arccosine (inverse cosine) accepts an argument in the
;;; range -1.0 to 1.0 inclusive, and returns an angle in
;;; radians in the range pi to 0 inclusive
(defun acos (z /)
(atan (sqrt (- 1.0 (* z z))) z)
)
;;; arcsecant (inverse secant) accepts an argument in
;;; one of two ranges: minus infinity to -1 inclusive or
;;; 1 to infinity inclusive, and returns an angle in
;;; radians in the range pi to 0 inclusive (except
;;; exactly pi/2 will never be returned on a computer
;;; with finite numerical precision)
(defun asec (z /)
(acos (/ 1.0 z))
)
;;; arccosecant (inverse cosecant) accepts an argument
;;; in one of two ranges: minus infinity to -1 inclusive or
;;; 1 to infinity inclusive, and returns an angle in
;;; radians in the range -pi/2 to pi/2 inclusive (except
;;; exactly 0.0 will never be returned on a computer
;;; with finite numerical precision)
(defun acsc (z /)
(asin (/ 1.0 z))
)
;;; arccotangent (inverse cotangent) accepts an argument
;;; in the range minus infinity to plus infinity
;;; inclusive and returns an angle in radians in the;;; range pi to 0 inclusive.
(defun acot (z /)
(- (/ pi 2.0) (atan z))
)
-
There are a couple of values that will crash asin, so ...
(defun asin (num)
(cond ((> (abs num) 1.0)
(alert (strcat " Arc-sine error in (CTAU:asin ." "\n Spitting the dummy"))
(exit)
)
((zerop num) 0.0)
((= num 1.0) *pi/2*)
((= num -1.0) (- *pi/2*))
(t (atan num (sqrt (- 1.0 (* num num)))))
)
)
*pi/2* is a constant I use.
-
Hi,
Here's my way.
Because, on 3D working acad can loose some precision (i.e. here (http://www.theswamp.org/index.php?topic=14649.0)), I use a "fuzz" for num values very closed but upper to 1 or lower to -1.
(defun ASIN (num)
(cond
((equal num 1 1e-9) (/ pi 2))
((equal num -1 1e-9) (/ pi -2))
((< -1 num 1)
(atan num (sqrt (- 1 (expt num 2))))
)
)
)
(defun ACOS (num)
(cond
((equal num 1 1e-9) 0.0)
((equal num -1 1e-9) pi)
((< -1 num 1)
(atan (sqrt (- 1 (expt num 2))) num)
)
)
)
-
you mean like arcsin?
asin(real)
i was looking in general autocad help... that's for use with 'cal
sorry
-
Is there a way to calculate the angle that corresponds to a calculated sine value in LISP. I have yet to see a function for it and would rather not reinvent the wheel if there is already a way to do it.
Thanks Steve
Dear Steve,
(defun $geomcal()
(if (null cal)
(if (> (atoi (substr (getvar "ACADVER") 1 2)) 13)
(arxload "geomcal") (xload "geomcal")))
)
(defun asind_CAL(x);in degrees
($geomcal)
(setq x (c:cal "ASIN (x)"))
)
(defun asin_CAL(x) ;in radians
($geomcal)
(setq x (c:cal "D2R (ASIN (x))"))
)
HofCAD CSI
-
Here is a TRI function that I wrote last year for calculating the sides and angles of right and oblique triangles. The function is fairly easy to use. It has six arguments: Side s1, Side s2, Side s3, Angle a, Angle b, and Angle c. Angles are in radians. It returns a 1 based list so you can use the ‘nth’ function to retrieve your results. To display the text help information, just type (tri ? ? ? ? ? ?) on the command line as follows:
Note: This displays better using a courier or mono-spaced font.
Command: (tri ? ? ? ? ? ?)
tri error: (tri nil nil nil nil nil nil)
Only 2 or 3 valid arguments can be passed to tri function.
tri - Calculates the sides and angles of a triangle
Arguments: 6 |\ /\
s1 = Side s1 |a\ /a \
s2 = Side s2 | \ / \
s3 = Side s3 s2 | \ s3 s2 / \ s3
a = Angle a radians | \ / \
b = Angle b radians |c___b\ /c________b\
c = Angle c radians s1 s1
Syntax example: (tri 3 ? ? 0.643501 ? ?);where ? = nil
Returns: (list nil 3.0 4.0 5.0 0.643501 0.927295 1.5708)
Note: For right triangles only supply the argument values for 2 sides,
or 1 side and 1 angle. Use ? or nil for the Angle c argument value.
For oblique triangles only supply argument values for 3 sides,
or 2 sides and 1 angle, or 1 side and 2 angles.
;-------------------------------------------------------------------------------
; tri - Calculates the sides and angles of a triangle
; Arguments: 6 | /\
; s1 = Side s1 |\ /a \
; s2 = Side s2 |a\ / \
; s3 = Side s3 s2 | \ s3 s2 / \ s3
; a = Angle a radians | \ / \
; b = Angle b radians |c__b\ /c________b\
; c = Angle c radians s1 s1
; Syntax example: (tri 3 ? ? 0.643501 ? ?);where ? = nil
; Returns: (list nil 3.0 4.0 5.0 0.643501 0.927295 1.5708);nth 1 based list
; Note: For right triangles only supply the argument values for 2 sides, or
; 1 side and 1 angle. Use ? or nil for the Angle c argument value. For oblique
; triangles only supply argument values for 3 sides, or 2 sides and 1 angle,
; or 1 side and 2 angles.
; Programming example usages:
; (setq Side2 (nth 2 (tri 3 ? ? 0.643501 ? ?))) = 4.0
; (setq AngleB (nth 5 (tri 3 ? ? 0.643501 ? ?))) = 0.927295
;-------------------------------------------------------------------------------
(defun tri (s1 s2 s3 a b c / acos asin e1 e2 e3 e4 e5 e6 j k negative passed tan)
;-----------------------------------------------------------------------------
; acos
; Arguments: 1
; x = real number between 0 and 1. May be passed as the sum of dividing two
; sides of a right triangle.
; Returns: acos of x, the radian degrees between sides of a right triangle
;-----------------------------------------------------------------------------
(defun acos (x)
(atan (/ (sqrt (- 1 (* x x))) x))
);defun acos
;-----------------------------------------------------------------------------
; asin
; Arguments: 1
; sine = real number between -1 to 1
; Returns: arcsin of sine
;-----------------------------------------------------------------------------
(defun asin (sine / cosine)
(setq cosine (sqrt (- 1.0 (expt sine 2))))
(if (zerop cosine)
(setq cosine 0.000000000000000000000000000001)
);if
(atan (/ sine cosine))
);defun asin
;-----------------------------------------------------------------------------
; tan
; Arguments: 1
; radians = Radian degrees
; Returns: Tangent of radian degrees
;-----------------------------------------------------------------------------
(defun tan (radians)
(/ (sin radians) (cos radians))
);defun tan
;-----------------------------------------------------------------------------
; Start of main function
;-----------------------------------------------------------------------------
(if (= (type s1)'INT)(setq s1 (float s1))) (if (<= s1 0)(setq s1 nil))
(if (= (type s2)'INT)(setq s2 (float s2))) (if (<= s2 0)(setq s2 nil))
(if (= (type s3)'INT)(setq s3 (float s3))) (if (<= s3 0)(setq s3 nil))
(if (= (type a)'INT)(setq a (float a))) (if (<= a 0)(setq a nil))
(if (= (type b)'INT)(setq b (float b))) (if (<= b 0)(setq b nil))
(if (= (type c)'INT)(setq c (float c))) (if (<= c 0)(setq c nil))
(setq e1 s1 e2 s2 e3 s3 e4 a e5 b e6 c passed t)
(cond
((and (= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq a (atan (/ s1 s2)) c (* pi 0.5) b (- c a) s3 (/ s1 (sin a)))
);case s1 s2
((and (/= (type s1)'REAL)(= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq a (acos (/ s2 s3)) c (* pi 0.5) b (- c a) s1 (* s2 (tan a)))
);case s2 s3
((and (= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq b (acos (/ s1 s3)) c (* pi 0.5) a (- c b) s2 (* s3 (sin b)))
);case s1 s3
((and (= (type s1)'REAL)(/= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq c (* pi 0.5) b (- c a) s2 (/ s1 (tan a)) s3 (/ s1 (sin a)))
);case s1 a
((and (= (type s1)'REAL)(/= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (* pi 0.5) a (- c b) s2 (* s1 (tan b)) s3 (/ s1 (cos b)))
);case s1 b
((and (/= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq c (* pi 0.5) b (- c a) s1 (* s2 (tan a)) s3 (/ s2 (cos a)))
);case s2 a
((and (/= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (* pi 0.5) a (- c b) s1 (/ s2 (tan b)) s3 (/ s2 (sin b)))
);case s2 b
((and (/= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq c (* pi 0.5) b (- c a) s1 (* s3 (sin a)) s2 (* s3 (cos a)))
);case s3 a
((and (/= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (* pi 0.5) a (- c b) s1 (* s3 (cos b)) s2 (* s3 (sin b)))
);case s3 b
((and (= (type s1)'REAL)(= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq j (/ (+ s1 s2 s3) 2.0) k (sqrt (/ (* (- j s1)(- j s2)(- j s3)) j)) a (* 2 (atan (/ k (- j s1)))) b (* 2 (atan (/ k (- j s2)))) c (- pi (+ a b)))
);case s1 s2 s3
((and (= (type s1)'REAL)(/= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (- pi (+ a b)) s2 (/ (* s1 (sin b)) (sin a)) s3 (/ (* s1 (sin c)) (sin a)))
);case s1 a b
((and (/= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(= (type c)'REAL))
(setq a (- pi (+ b c)) s1 (/ (* s2 (sin a)) (sin b)) s3 (/ (* s2 (sin c)) (sin b)))
);case s2 b c
((and (/= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(= (type c)'REAL))
(setq b (- pi (+ a c)) s1 (/ (* s3 (sin a)) (sin c)) s2 (/ (* s3 (sin b)) (sin c)))
);case s3 a c
((and (= (type s1)'REAL)(/= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(= (type c)'REAL))
(setq b (- pi (+ a c)) s2 (/ (* s1 (sin b)) (sin a)) s3 (/ (* s1 (sin c)) (sin a)))
);case s1 a c
((and (/= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (- pi (+ a b)) s1 (/ (* s2 (sin a)) (sin b)) s3 (/ (* s2 (sin c)) (sin b)))
);case s2 a b
((and (/= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(= (type c)'REAL))
(setq a (- pi (+ b c)) s1 (/ (* s3 (sin a)) (sin c)) s2 (/ (* s3 (sin b)) (sin c)))
);case s3 b c
((and (= (type s1)'REAL)(/= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(= (type c)'REAL))
(setq a (- pi (+ b c)) s2 (/ (* s1 (sin b)) (sin a)) s3 (/ (* s1 (sin c)) (sin a)))
);case s1 b c
((and (/= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(= (type c)'REAL))
(setq b (- pi (+ a c)) s1 (/ (* s2 (sin a)) (sin b)) s3 (/ (* s2 (sin c)) (sin b)))
);case s2 a c
((and (/= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (- pi (+ a b)) s1 (/ (* s3 (sin a)) (sin c)) s2 (/ (* s3 (sin b)) (sin c)))
);case s3 a b
((and (= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(= (type c)'REAL))
(setq a (atan (/ (* s1 (sin c)) (- s2 (* s1 (cos c))))) b (- pi (+ a c)) s3 (/ (* s1 (sin c)) (sin a)))
);case s1 s2 c
((and (/= (type s1)'REAL)(= (type s2)'REAL)(= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq b (atan (/ (* s2 (sin a)) (- s3 (* s2 (cos a))))) c (- pi (+ a b)) s1 (/ (* s2 (sin a)) (sin b)))
);case s2 s3 a
((and (= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (atan (/ (* s3 (sin b)) (- s1 (* s3 (cos b))))) a (- pi (+ b c)) s2 (/ (* s3 (sin b)) (sin c)))
);case s1 s3 b
((and (= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq b (asin (/ (* s2 (sin a)) s1)) c (- pi (+ a b)) s3 (/ (* s1 (sin c)) (sin a)))
);case s1 s2 a
((and (/= (type s1)'REAL)(= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq c (asin (/ (* s3 (sin b)) s2)) a (- pi (+ b c)) s1 (/ (* s2 (sin a)) (sin b)))
);case s2 s3 b
((and (= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(= (type c)'REAL))
(setq a (asin (/ (* s1 (sin c)) s3)) b (- pi (+ a c)) s2 (/ (* s3 (sin b)) (sin c)))
);case s1 s3 c
((and (= (type s1)'REAL)(= (type s2)'REAL)(/= (type s3)'REAL)(/= (type a)'REAL)(= (type b)'REAL)(/= (type c)'REAL))
(setq a (asin (/ (* s1 (sin b)) s2)) c (- pi (+ a b)) s3 (/ (* s2 (sin c)) (sin b)))
);case s1 s2 b
((and (/= (type s1)'REAL)(= (type s2)'REAL)(= (type s3)'REAL)(/= (type a)'REAL)(/= (type b)'REAL)(= (type c)'REAL))
(setq b (asin (/ (* s2 (sin c)) s3)) a (- pi (+ b c)) s1 (/ (* s3 (sin a)) (sin c)))
);case s2 s3 c
((and (= (type s1)'REAL)(/= (type s2)'REAL)(= (type s3)'REAL)(= (type a)'REAL)(/= (type b)'REAL)(/= (type c)'REAL))
(setq c (asin (/ (* s3 (sin a)) s1)) b (- pi (+ a c)) s2 (/ (* s1 (sin b)) (sin a)))
);case s1 s3 a
(t (setq passed nil)
);case errors
);cond
(foreach item (list s1 s2 s3 a b c)
(if (= (type item)'REAL) (if (<= Item 0)(setq negative t)))
);foreach
(if (or (not passed) negative)
(progn
(textscr)(princ "\ntri error: (tri ")(princ e1)(princ " ")(princ e2)(princ " ")(princ e3)(princ " ")(princ e4)(princ " ")(princ e5)(princ " ")(princ e6)(princ ")")
(if negative (progn (princ "\nResults: s1 = ")(princ s1)(princ ", s2 = ")(princ s2)(princ ", s3 = ")(princ s3)(princ "\n a = ")(princ a)(princ ", b = ")(princ b)(princ ", c = ")(princ c)))
(princ "\nOnly 2 or 3 valid arguments can be passed to tri function.\n")
(princ "\ntri - Calculates the sides and angles of a triangle")
(princ "\nArguments: 6 |\\ /\\ ");Text display depends on users font
(princ "\n s1 = Side s1 |a\\ /a \\ ")
(princ "\n s2 = Side s2 | \\ / \\ ")
(princ "\n s3 = Side s3 s2 | \\ s3 s2 / \\ s3")
(princ "\n a = Angle a radians | \\ / \\ ")
(princ "\n b = Angle b radians |c___b\\ /c________b\\ ")
(princ "\n c = Angle c radians s1 s1")
(princ "\nSyntax example: (tri 3 ? ? 0.643501 ? ?);where ? = nil")
(princ "\nReturns: (list nil 3.0 4.0 5.0 0.643501 0.927295 1.5708)")
(princ "\nNote: For right triangles only supply the argument values for 2 sides,")
(princ "\nor 1 side and 1 angle. Use ? or nil for the Angle c argument value.")
(princ "\nFor oblique triangles only supply argument values for 3 sides,")
(princ "\nor 2 sides and 1 angle, or 1 side and 2 angles.")
(exit)
);progn
);if
(list nil s1 s2 s3 a b c);nth 1 based list
);defun tri
I think I've included everything. If not let me know.