・ 2つの線分やベクトルのなす角度を取得
関数 (angle) で取得できる角度は、現在の作図平面の X軸から反時計回りに計測し、ラジアンで表わされます。 与えられた点が 3D
点の場合には、これらの点を現在の作図平面に投影して角度を取得します。
つまり、実際の線分やベクトルのなす角度ではないということです。
現在の作図平面上での角度を取得
これは、関数 (angle) を利用すすればOKですね
;***********************************************************************; ;2つの線分のなす角度を求める ; ;Z値が違って実際には交わらない場合でも現在の作図平面に投影した角度を返す; ;***********************************************************************; (defun Jo_2line_ang( / ang1 ang2 ang) (defun Jof_line_ang (;線分の現在作図平面上の角度を返す; / ed ang) (while (not ed) (setq ed (entget (car (entsel "\n線分を選択")))) (if (= "LINE" (cdr (assoc 0 ed))) (setq ang (angle (trans (cdr (assoc 10 ed)) 0 1) (trans (cdr (assoc 11 ed)) 0 1))) (progn (setq ed nil) (princ "\n選択したオブジェクトは線分ではありません")) ) ) ang ) (defun Jof_dis_ang (;2角の差異を返す; ang1 ang2 / ang ) (cond ((< ang1 ang2) (- ang2 ang1)) (T (+ (- (* 2 pi) ang1) ang2)) ) ) (setq ang1 (Jof_line_ang)) (setq ang2 (Jof_line_ang)) (setq ang (Jof_dis_ang ang1 ang2)) (setq ang (* (/ ang pi) 180)) (princ (strcat "\n" (rtos ang) "°です")) (princ) )
3次元での実際の角度を取得
AベクトルとBベクトルのなす角Θの間には、次の公式が成り立っています
そして、Lispには acos(アークコサイン) がないので、cosからtanを求め、atan(アークタンジェント)により角度を求めなければなりません。
;**********************************************************; ;2つの3次元ベクトルのなす角度を求める ; ;**********************************************************; (defun Jo_v_ang( / ed pt sp ep vb v ang) (defun Jof_v_inp (;ベクトルの内積(inner product)を返す; v1;ベクトル; v2;ベクトル; ) (apply '+ (mapcar '* v1 v2 )) ) (defun Jof_v_len (;ベクトルの長さを返す; v;ベクトル; ) (sqrt (apply '+ (mapcar '(lambda(x) (expt x 2)) v))) ) (defun Jof_v_ang (;ベクトル v1 v2 のなす角を返す; v1 v2 / fuz cos_v) (setq cos_v (/ (Jof_v_inp v1 v2) (* (Jof_v_len v1) (Jof_v_len v2)))) (setq fuz 1e-6) (if (equal cos_v 0 fuz) (/ pi 2) (if (minusp cos_v) (+ (atan (/ (sqrt (- 1.0 (expt cos_v 2))) cos_v)) pi) (atan (/ (sqrt (- 1.0 (expt cos_v 2))) cos_v)) ) ) ) (setq ed (entget (car (entsel "\n線分を選択")))) (setq pt (getpoint "\n点を指示")) (setq sp (cdr (assoc 10 ed))) (setq ep (cdr (assoc 11 ed))) (setq vb (mapcar '- ep sp)) (setq v (mapcar '- (trans pt 1 0) sp)) (setq ang (Jof_v_ang vb v)) (setq ang (* (/ ang pi) 180)) (princ (strcat "\n" (rtos ang) "°です")) (princ) )