用齐次坐标绘制正12面体
本帖最后由 ashleytgg 于 2018-3-14 16:33 编辑参照《计算机图形学原理教程》编著 ——李建平 , 电子科技大学出版社, 中其次坐标的图形变换原理,写了几个lisp 函数。
绘制了正12面体, 觉得非常有趣,在此和大家飞享下。 其中也也引用了 high_fly_bird 的一个小函数矢量叉积。
;; 定义一个三维镜像的函数
;; group 为一个四维点集合 , point_A point_Bpoint_C 为镜像平面的三个点
(defun mirror_3d (group point_A point_Bpoint_C /
Cen Axis x_Ceny_Cen z_Cen
x_Axis y_Axis z_AxisP_1 P_2
cos_a sin_a cos_bsin_b P1->P2
Cen->Axis T_ry T_rxT_XY_mirror
T_ry-1 T_rx-1 T_m-1T_综合 Vector_0
Vector_1
)
;; 求平面 ABC 的 法向量
(setqVector_0 (mapcar '- point_B point_A)
Vector_1 (mapcar '- point_C point_A)
)
;; 求向量Vector_0 Vector_1 的叉积,为平面法向量normal_vector
(setqnormal_vector
(G:CrossProductor Vector_0 Vector_1)
)
;; 定义新的原点, 和新的 Z轴
(setqCenpoint_A
Axis (mapcar '+ Cen normal_vector)
)
;; 把原点移动到Cen ,Z轴向量转变为 Cen->Axis
(setqT_m (list
(list 1 0 0 (* (car Cen) -1))
(list 0 1 0 (* (cadr Cen) -1))
(list 0 0 1 (* (caddr Cen) -1))
(list 0 0 0 1)
)
)
;; 设置point_A point_B 的坐标 x_A y_A z_A ,x_B y_B z_B
(mapcar 'set
'(x_Cen y_Cen z_Cen x_Axis y_Axis z_Axis)
(append Cen Axis)
)
(setqP_1 (list y_Cen Z_Cen)
P_2 (list y_Axis Z_Axis)
P1->P2 (distance p_1 P_2)
)
(if (> P1->P2 1e-8)
(setq
cos_a (/ (- z_Axis z_Cen) P1->P2)
sin_a (/ (- y_Axis y_Cen) P1->P2)
)
(setq cos_a1
sin_a0
)
)
(setqT_rx (list
(list 1 0 0 0)
(list 0 cos_a (* -1 sin_a) 0)
(list 0 sin_a cos_a 0)
(list 0 0 0 1)
)
)
(setq
Cen->Axis (distance Cen Axis)
cos_b (/ P1->P2 Cen->Axis)
sin_b (/ (- x_Axis x_Cen) Cen->Axis)
)
(setqT_ry (list
(list cos_b 0 (* -1 sin_b) 0)
(list 0 1 0 0)
(list sin_b 0 cos_b 0)
(list 0 0 0 1)
)
)
;; 对XY平面 进行镜像
(setqT_XY_mirror
(list
(list 1 0 0 0)
(list 0 1 0 0)
(list 0 0 -1 0)
(list 0 0 0 1)
)
)
(setqT_ry-1 (list
(list cos_b 0 sin_b 0)
(list 0 1 0 0)
(list (* -1 sin_b) 0 cos_b 0)
(list 0 0 0 1)
)
)
(setqT_rx-1 (list
(list 1 0 0 0)
(list 0 cos_a sin_a 0)
(list 0 (* -1 sin_a) cos_a 0)
(list 0 0 0 1)
)
)
(setqT_m-1 (list
(list 1 0 0 (car Cen))
(list 0 1 0 (cadr Cen))
(list 0 0 1 (caddr Cen))
(list 0 0 0 1)
)
)
(setqT_综合
(mapcar '(lambda(lst)
(setqlst (mxv T_m lst)
lst (mxv T_rx lst)
lst (mxv T_ry lst)
lst (mxv T_XY_mirror lst)
lst (mxv T_ry-1 lst)
lst (mxv T_rx-1 lst)
lst (mxv T_m-1 lst)
)
)
(list
'(1 0 0 0)
'(0 1 0 0)
'(0 0 1 0)
'(0 0 0 1)
)
)
;; 对T_综合 进行装置
T_综合 (list (mapcar 'car T_综合)
(mapcar 'cadr T_综合)
(mapcar 'caddr T_综合)
(mapcar 'cadddr T_综合)
)
)
(mapcar '(lambda (u)
(mxv T_综合 U)
)
group
)
)
;;(mirror_3d group point_A point_B point_C)
;;定义一个坐标系重置函数,把一个已知坐标系,原点重置为point_A ,Z轴设置方向point_A->point_B
(defun reset_coordinate_system (grouppoint_Apoint_B/x_A
y_Az_Ax_By_Bz_B
P_1P_2cos_asin_acos_b
sin_bP1->P2A->BT_ryT_rx
T_综合
)
(setqT_m (list
(list 1 0 0 (* (car point_A) -1))
(list 0 1 0 (* (cadr point_A) -1))
(list 0 0 1 (* (caddr point_A) -1))
(list 0 0 0 1)
)
)
(mapcar 'set
'(x_A y_A z_A x_B y_B z_B)
(append point_A point_B)
)
(setqP_1 (list y_A Z_A)
P_2 (list y_B Z_B)
P1->P2 (distance p_1 P_2)
)
(if (> P1->P2 1e-8)
(setq
cos_a (/ (- z_B z_A) P1->P2)
sin_a (/ (- y_B y_A) P1->P2)
)
(setq cos_a1
sin_a0
)
)
(setqT_rx (list
(list 1 0 0 0)
(list 0 cos_a (* -1 sin_a) 0)
(list 0 sin_a cos_a 0)
(list 0 0 0 1)
)
)
(setq
A->B(distance point_A point_B)
cos_b (/ P1->P2 A->B)
sin_b (/ (- x_B x_A) A->B)
)
(setqT_ry (list
(list cos_b 0 (* -1 sin_b) 0)
(list 0 1 0 0)
(list sin_b 0 cos_b 0)
(list 0 0 0 1)
)
)
(setqT_综合
(mapcar '(lambda(lst)
(setqlst (mxv T_m lst)
lst (mxv T_rx lst)
lst (mxv T_ry lst)
)
)
(list
'(1 0 0 0)
'(0 1 0 0)
'(0 0 1 0)
'(0 0 0 1)
)
)
;; 对T_综合 进行装置
T_综合 (list (mapcar 'car T_综合)
(mapcar 'cadr T_综合)
(mapcar 'caddr T_综合)
(mapcar 'cadddr T_综合)
)
)
(mapcar '(lambda (u)
(mxv T_综合 U)
)
group
)
)
;;(reset_coordinate_systemgrouppoint_Apoint_B );;定义一个三维对齐函数,既把一个三维向量P_A->P_B P_A->P_C , 经过一系列平移、旋转操作,和另外一个
;;已经知道的向量target_A->target_B target_A->target_C , 重合
(defun align_3d(group point_A point_B
point_C target_A target_B
target_C / normal_vector
normal_vector_target axis_rotation_0
axis_rotation_1 T_m U_offset
Vector_0 Vector_1
)
;; 求平面 ABC 的 平面法向量 normal_vector
(setqVector_0 (mapcar '- point_B point_A)
Vector_1 (mapcar '- point_C point_A)
)
(setqnormal_vector
(G:CrossProductor Vector_0 Vector_1)
)
;; 求平面target_A target_B target_C 的 平面法向量 normal_vector_target
(setqVector_0 (mapcar '- target_B target_A)
Vector_1 (mapcar '- target_C target_A)
)
(setqnormal_vector_target
(G:CrossProductor Vector_0 Vector_1)
)
;; 求向量 normal_vector normal_vector_target 组成平面的法向量
(setqAxis_vector
(G:CrossProductor normal_vector normal_vector_target)
)
(if (= (apply '+ Axis_vector) 0)
;; 当Axis_vector 为0 时,表示normal_vector 和normal_vector_target 共线 ,则
;; 平面target_A target_B target_C和 平面 ABC 共面
(setq ang 0)
;; 建立以 '(0 0 0)normal_vector normal_vector_target 位XY平面,'(0 0 0)->Axis_vector Z轴的坐标系
(setq lst (reset_coordinate_system
(list normal_vector normal_vector_target)
'(0 0 0)
Axis_vector
)
ang_0 (angle '(0 0)
(mapcar '+ '(0 0) (car lst))
)
ang_1 (angle '(0 0)
(mapcar '+ '(0 0) (cadr lst))
)
;; ang为 由平面 ABC 旋转到平面target_A target_B target_C 的旋转角度,
;;也是向量O->normal_vector 和O->normal_vector_target 之间的夹角
ang (- ang_1 ang_0)
;; 求 由平面 ABC 旋转到平面target_A target_B target_C 的旋转轴
axis_rotation_0 point_A
axis_rotation_1 (mapcar '+ point_A Axis_vector)
)
)
(if (/= ang 0)
;; 图像group 绕着旋转轴axis_rotation_0 axis_rotation_1 旋转ang度
(setq group(rotate_3d (append (list (append point_A (list 1))
(append point_B (list 1))
)
group
)
axis_rotation_0
axis_rotation_1
ang
)
)
)
(setqU_offset (mapcar '- target_A point_A)
T_m (list
(list 1 0 0 (car U_offset))
(list 0 1 0 (cadr U_offset))
(list 0 0 1 (caddr U_offset))
(list 0 0 0 1)
)
)
(setqgroup (mapcar '(lambda (u)
(mxv T_m U)
)
group
)
)
;; 把point_A->point_B target_A->target_B 变成四维点
(setq
lst_四维 (mapcar
'(lambda(x)
(append x (list 1))
)
(list (car group) (cadr group) target_A target_B)
)
)
(setq
lst (reset_coordinate_system
lst_四维
target_A
(mapcar '+ target_A normal_vector_target)
)
;; 计算向量 point_A->point_B的象限角
ang_0 (angle (mapcar '+ '(0 0) (car lst))
(mapcar '+ '(0 0) (cadr lst))
)
;;计算向量target_A->target_B 的象限角
ang_1 (angle (mapcar '+ '(0 0) (caddr lst))
(mapcar '+ '(0 0) (cadddr lst))
)
;; 向量 point_A->point_Btarget_A->target_B 在同一个平面内时的旋转角度 Δ
Δ (- ang_1 ang_0)
)
;; 让图像group 绕着 point_A->normal_vector 旋转Δ ,再绕着绕着旋转轴axis_rotation_0 axis_rotation_1 旋转ang度
;; 最后 坐标原点 移动到target_A
(rotate_3d (cddr group)
target_A
(mapcar '+ target_A normal_vector_target)
Δ
)
)
;; group 为一个四维点集合 , point_A point_B 为旋转轴的两个点,φ 为旋转角度,单位弧度
;; 旋转轴point_A point_B 的距离必须大于0 ,本程序不考虑 point_A point_B 重合的情形
(defun rotate_3d (group point_A point_B φ / x_A
y_A z_A x_B y_B z_B P_1
P_2 cos_a sin_a cos_b sin_b P1->P2
A->B T_ry T_rx T_rZ T_ry-1T_rx-1
T_m-1 T_综合
)
(setqT_m (list
(list 1 0 0 (* (car point_A) -1))
(list 0 1 0 (* (cadr point_A) -1))
(list 0 0 1 (* (caddr point_A) -1))
(list 0 0 0 1)
)
)
;; 设置point_A point_B 的坐标 x_A y_A z_A ,x_B y_B z_B
(mapcar 'set
'(x_A y_A z_A x_B y_B z_B)
(append point_A point_B)
)
(setqP_1 (list y_A Z_A)
P_2 (list y_B Z_B)
P1->P2 (distance p_1 P_2)
)
(if (> P1->P2 1e-8)
;; 当向量A->B 不平行于X 轴时
(setq
cos_a (/ (- z_B z_A) P1->P2)
sin_a (/ (- y_B y_A) P1->P2)
)
;; 当向量A->B 平行于X 轴时 ,既垂直于 YZ平面,此时A->B与X轴的夹角为0度
(setq cos_a1
sin_a0
)
)
(setqT_rx (list
(list 1 0 0 0)
(list 0 cos_a (* -1 sin_a) 0)
(list 0 sin_a cos_a 0)
(list 0 0 0 1)
)
)
(setq
A->B(distance point_A point_B)
cos_b (/ P1->P2 A->B)
sin_b (/ (- x_B x_A) A->B)
)
(setqT_ry (list
(list cos_b 0 (* -1 sin_b) 0)
(list 0 1 0 0)
(list sin_b 0 cos_b 0)
(list 0 0 0 1)
)
)
;; 绕AB顺时针旋转 φ 角度,就变成绕新的Z 轴逆时针旋转φ 角度
(setqT_rZ (list
(list (cos φ) (* -1 (sin φ)) 0 0)
(list (sin φ) (cos φ) 0 0)
(list 0 0 1 0)
(list 0 0 0 1)
)
)
(setqT_ry-1 (list
(list cos_b 0 sin_b 0)
(list 0 1 0 0)
(list (* -1 sin_b) 0 cos_b 0)
(list 0 0 0 1)
)
)
(setqT_rx-1 (list
(list 1 0 0 0)
(list 0 cos_a sin_a 0)
(list 0 (* -1 sin_a) cos_a 0)
(list 0 0 0 1)
)
)
(setqT_m-1 (list
(list 1 0 0 (car point_A))
(list 0 1 0 (cadr point_A))
(list 0 0 1 (caddr point_A))
(list 0 0 0 1)
)
)
(setqT_综合
(mapcar '(lambda(lst)
(setqlst (mxv T_m lst)
lst (mxv T_rx lst)
lst (mxv T_ry lst)
lst (mxv T_rz lst)
lst (mxv T_ry-1 lst)
lst (mxv T_rx-1 lst)
lst (mxv T_m-1 lst)
)
)
(list
'(1 0 0 0)
'(0 1 0 0)
'(0 0 1 0)
'(0 0 0 1)
)
)
;; 对T_综合 进行装置
T_综合 (list (mapcar 'car T_综合)
(mapcar 'cadr T_综合)
(mapcar 'caddr T_综合)
(mapcar 'cadddr T_综合)
)
)
(mapcar '(lambda (u)
(mxv T_综合 U)
)
group
)
)
;;( rotate_3dgroup point_A point_B φ) 高手太多,我等惭愧跪拜 都是书本上抄来的,我只是翻译下而已。 确实好用。学习了。
页:
[1]