明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 932|回复: 3

[源码] 用齐次坐标绘制正12面体

  [复制链接]
发表于 2018-3-14 16:33 | 显示全部楼层 |阅读模式
本帖最后由 ashleytgg 于 2018-3-14 16:33 编辑

参照《计算机图形学原理教程》编著 ——李建平 , 电子科技大学出版社, 中其次坐标的图形变换原理,写了几个lisp 函数。
    绘制了正12面体, 觉得非常有趣,在此和大家飞享下。 其中也也引用了 high_fly_bird 的一个小函数矢量叉积。


  1. ;; 定义一个三维镜像的函数
  2. ;; group 为一个四维点集合 , point_A point_B  point_C   为镜像平面的三个点
  3. (defun mirror_3d (group      point_A   point_B  point_C    /
  4.       Cen      Axis      x_Cen  y_Cen    z_Cen
  5.       x_Axis    y_Axis    z_Axis  P_1    P_2
  6.       cos_a      sin_a     cos_b  sin_b    P1->P2
  7.       Cen->Axis T_ry      T_rx  T_XY_mirror
  8.       T_ry-1    T_rx-1    T_m-1  T_综合    Vector_0
  9.       Vector_1
  10.      )

  11.   ;; 求平面 ABC 的 法向量  
  12.   (setq  Vector_0 (mapcar '- point_B point_A)
  13.   Vector_1 (mapcar '- point_C point_A)
  14.   )
  15.   ;; 求向量Vector_0 Vector_1 的叉积,为平面法向量normal_vector
  16.   (setq  normal_vector
  17.    (G:CrossProductor Vector_0 Vector_1)
  18.   )
  19.   ;; 定义新的原点, 和新的 Z轴  
  20.   (setq  Cen  point_A
  21.   Axis (mapcar '+ Cen normal_vector)
  22.   )
  23.   ;; 把原点移动到Cen ,Z轴向量转变为 Cen->Axis
  24.   (setq  T_m (list
  25.         (list 1 0 0 (* (car Cen) -1))
  26.         (list 0 1 0 (* (cadr Cen) -1))
  27.         (list 0 0 1 (* (caddr Cen) -1))
  28.         (list 0 0 0 1)
  29.       )
  30.   )

  31.   ;; 设置point_A point_B 的坐标 x_A y_A z_A ,x_B y_B z_B  
  32.   (mapcar 'set
  33.     '(x_Cen y_Cen z_Cen x_Axis y_Axis z_Axis)
  34.     (append Cen Axis)
  35.   )
  36.   (setq  P_1    (list y_Cen Z_Cen)
  37.   P_2    (list y_Axis Z_Axis)
  38.   P1->P2 (distance p_1 P_2)
  39.   )
  40.   (if (> P1->P2 1e-8)
  41.     (setq
  42.       cos_a (/ (- z_Axis z_Cen) P1->P2)
  43.       sin_a (/ (- y_Axis y_Cen) P1->P2)
  44.     )
  45.     (setq cos_a  1
  46.     sin_a  0
  47.     )
  48.   )
  49.   (setq  T_rx (list
  50.          (list 1 0 0 0)
  51.          (list 0 cos_a (* -1 sin_a) 0)
  52.          (list 0 sin_a cos_a 0)
  53.          (list 0 0 0 1)
  54.        )
  55.   )
  56.   (setq
  57.     Cen->Axis (distance Cen Axis)
  58.     cos_b     (/ P1->P2 Cen->Axis)
  59.     sin_b     (/ (- x_Axis x_Cen) Cen->Axis)
  60.   )
  61.   (setq  T_ry (list
  62.          (list cos_b 0 (* -1 sin_b) 0)
  63.          (list 0 1 0 0)
  64.          (list sin_b 0 cos_b 0)
  65.          (list 0 0 0 1)
  66.        )
  67.   )
  68.   ;; 对XY平面 进行镜像  
  69.   (setq  T_XY_mirror
  70.    (list
  71.      (list 1 0 0 0)
  72.      (list 0 1 0 0)
  73.      (list 0 0 -1 0)
  74.      (list 0 0 0 1)
  75.    )
  76.   )
  77.   (setq  T_ry-1 (list
  78.      (list cos_b 0 sin_b 0)
  79.      (list 0 1 0 0)
  80.      (list (* -1 sin_b) 0 cos_b 0)
  81.      (list 0 0 0 1)
  82.          )
  83.   )
  84.   (setq  T_rx-1 (list
  85.      (list 1 0 0 0)
  86.      (list 0 cos_a sin_a 0)
  87.      (list 0 (* -1 sin_a) cos_a 0)
  88.      (list 0 0 0 1)
  89.          )
  90.   )
  91.   (setq  T_m-1 (list
  92.     (list 1 0 0 (car Cen))
  93.     (list 0 1 0 (cadr Cen))
  94.     (list 0 0 1 (caddr Cen))
  95.     (list 0 0 0 1)
  96.         )
  97.   )
  98.   (setq  T_综合
  99.          (mapcar '(lambda  (lst)
  100.         (setq  lst (mxv T_m lst)
  101.         lst (mxv T_rx lst)
  102.         lst (mxv T_ry lst)
  103.         lst (mxv T_XY_mirror lst)
  104.         lst (mxv T_ry-1 lst)
  105.         lst (mxv T_rx-1 lst)
  106.         lst (mxv T_m-1 lst)
  107.         )
  108.       )
  109.            (list
  110.        '(1 0 0 0)
  111.        '(0 1 0 0)
  112.        '(0 0 1 0)
  113.        '(0 0 0 1)
  114.            )
  115.          )
  116.   ;; 对T_综合 进行装置
  117.   T_综合 (list (mapcar 'car T_综合)
  118.          (mapcar 'cadr T_综合)
  119.          (mapcar 'caddr T_综合)
  120.          (mapcar 'cadddr T_综合)
  121.          )
  122.   )
  123.   (mapcar '(lambda (u)
  124.        (mxv T_综合 U)
  125.      )
  126.     group
  127.   )
  128. )
  129. ;;  (mirror_3d   group    point_A point_B point_C  )
  1. ;;定义一个坐标系重置函数,把一个已知坐标系,原点重置为point_A ,Z轴设置方向point_A->point_B
  2. (defun reset_coordinate_system (group  point_A  point_B  /  x_A
  3.         y_A  z_A  x_B  y_B  z_B
  4.         P_1  P_2  cos_a  sin_a  cos_b
  5.         sin_b  P1->P2  A->B  T_ry  T_rx
  6.         T_综合
  7.              )
  8.   (setq  T_m (list
  9.         (list 1 0 0 (* (car point_A) -1))
  10.         (list 0 1 0 (* (cadr point_A) -1))
  11.         (list 0 0 1 (* (caddr point_A) -1))
  12.         (list 0 0 0 1)
  13.       )
  14.   )
  15.   (mapcar 'set
  16.     '(x_A y_A z_A x_B y_B z_B)
  17.     (append point_A point_B)
  18.   )
  19.   (setq  P_1    (list y_A Z_A)
  20.   P_2    (list y_B Z_B)
  21.   P1->P2 (distance p_1 P_2)
  22.   )
  23.   (if (> P1->P2 1e-8)
  24.     (setq
  25.       cos_a (/ (- z_B z_A) P1->P2)
  26.       sin_a (/ (- y_B y_A) P1->P2)
  27.     )
  28.     (setq cos_a  1
  29.     sin_a  0
  30.     )
  31.   )
  32.   (setq  T_rx (list
  33.          (list 1 0 0 0)
  34.          (list 0 cos_a (* -1 sin_a) 0)
  35.          (list 0 sin_a cos_a 0)
  36.          (list 0 0 0 1)
  37.        )
  38.   )
  39.   (setq
  40.     A->B  (distance point_A point_B)
  41.     cos_b (/ P1->P2 A->B)
  42.     sin_b (/ (- x_B x_A) A->B)
  43.   )
  44.   (setq  T_ry (list
  45.          (list cos_b 0 (* -1 sin_b) 0)
  46.          (list 0 1 0 0)
  47.          (list sin_b 0 cos_b 0)
  48.          (list 0 0 0 1)
  49.        )
  50.   )
  51.   (setq  T_综合
  52.          (mapcar '(lambda  (lst)
  53.         (setq  lst (mxv T_m lst)
  54.         lst (mxv T_rx lst)
  55.         lst (mxv T_ry lst)
  56.         )
  57.       )
  58.            (list
  59.        '(1 0 0 0)
  60.        '(0 1 0 0)
  61.        '(0 0 1 0)
  62.        '(0 0 0 1)
  63.            )
  64.          )
  65.   ;; 对T_综合 进行装置
  66.   T_综合 (list (mapcar 'car T_综合)
  67.          (mapcar 'cadr T_综合)
  68.          (mapcar 'caddr T_综合)
  69.          (mapcar 'cadddr T_综合)
  70.          )
  71.   )
  72.   (mapcar '(lambda (u)
  73.        (mxv T_综合 U)
  74.      )
  75.     group
  76.   )
  77. )
  78. ;;  (reset_coordinate_system  group  point_A  point_B )  
  1. ;;定义一个三维对齐函数,既把一个三维向量P_A->P_B P_A->P_C , 经过一系列平移、旋转操作,和另外一个
  2. ;;已经知道的向量target_A->target_B target_A->target_C , 重合
  3. (defun align_3d  (group     point_A   point_B
  4.      point_C   target_A   target_B
  5.      target_C   /     normal_vector
  6.      normal_vector_target     axis_rotation_0
  7.      axis_rotation_1 T_m     U_offset
  8.      Vector_0   Vector_1
  9.     )

  10.   ;; 求平面 ABC 的 平面法向量 normal_vector
  11.   (setq  Vector_0 (mapcar '- point_B point_A)
  12.   Vector_1 (mapcar '- point_C point_A)
  13.   )
  14.   (setq  normal_vector
  15.    (G:CrossProductor Vector_0 Vector_1)
  16.   )
  17.   ;; 求平面target_A target_B target_C 的 平面法向量 normal_vector_target
  18.   (setq  Vector_0 (mapcar '- target_B target_A)
  19.   Vector_1 (mapcar '- target_C target_A)
  20.   )
  21.   (setq  normal_vector_target
  22.    (G:CrossProductor Vector_0 Vector_1)
  23.   )
  24.   ;; 求向量 normal_vector normal_vector_target 组成平面的法向量
  25.   (setq  Axis_vector
  26.    (G:CrossProductor normal_vector normal_vector_target)
  27.   )

  28.   (if (= (apply '+ Axis_vector) 0)
  29.     ;; 当Axis_vector 为0 时,表示normal_vector 和normal_vector_target 共线 ,则
  30.     ;; 平面target_A target_B target_C和 平面 ABC 共面
  31.     (setq ang 0)
  32.     ;; 建立以 '(0 0 0)  normal_vector normal_vector_target 位XY平面,'(0 0 0)->Axis_vector Z轴的坐标系
  33.     (setq lst      (reset_coordinate_system
  34.           (list normal_vector normal_vector_target)
  35.           '(0 0 0)
  36.           Axis_vector
  37.         )
  38.     ang_0      (angle '(0 0)
  39.          (mapcar '+ '(0 0) (car lst))
  40.         )
  41.     ang_1      (angle '(0 0)
  42.          (mapcar '+ '(0 0) (cadr lst))
  43.         )
  44.     ;; ang为 由平面 ABC 旋转到平面target_A target_B target_C 的旋转角度,
  45.     ;;也是向量O->normal_vector 和O->normal_vector_target 之间的夹角
  46.     ang      (- ang_1 ang_0)
  47.     ;; 求 由平面 ABC 旋转到平面target_A target_B target_C 的旋转轴
  48.     axis_rotation_0 point_A
  49.     axis_rotation_1 (mapcar '+ point_A Axis_vector)
  50.     )
  51.   )
  52.   (if (/= ang 0)
  53.     ;; 图像group 绕着旋转轴axis_rotation_0 axis_rotation_1 旋转ang度
  54.     (setq group  (rotate_3d (append (list (append point_A (list 1))
  55.            (append point_B (list 1))
  56.            )
  57.            group
  58.          )
  59.          axis_rotation_0
  60.          axis_rotation_1
  61.          ang
  62.     )
  63.     )
  64.   )
  65.   (setq  U_offset (mapcar '- target_A point_A)
  66.   T_m   (list
  67.        (list 1 0 0 (car U_offset))
  68.        (list 0 1 0 (cadr U_offset))
  69.        (list 0 0 1 (caddr U_offset))
  70.        (list 0 0 0 1)
  71.      )
  72.   )
  73.   (setq  group (mapcar '(lambda (u)
  74.        (mxv T_m U)
  75.            )
  76.           group
  77.         )
  78.   )
  79.   ;; 把point_A->point_B target_A->target_B 变成四维点
  80.   (setq
  81.     lst_四维 (mapcar
  82.          '(lambda  (x)
  83.       (append x (list 1))
  84.     )
  85.          (list (car group) (cadr group) target_A target_B)
  86.        )
  87.   )
  88.   (setq
  89.     lst    (reset_coordinate_system
  90.       lst_四维
  91.       target_A
  92.       (mapcar '+ target_A normal_vector_target)
  93.     )
  94.     ;; 计算向量 point_A->point_B  的象限角
  95.     ang_0 (angle (mapcar '+ '(0 0) (car lst))
  96.      (mapcar '+ '(0 0) (cadr lst))
  97.     )
  98.     ;;  计算向量target_A->target_B 的象限角
  99.     ang_1 (angle (mapcar '+ '(0 0) (caddr lst))
  100.      (mapcar '+ '(0 0) (cadddr lst))
  101.     )
  102.     ;; 向量 point_A->point_B  target_A->target_B 在同一个平面内时的旋转角度 Δ
  103.     Δ    (- ang_1 ang_0)
  104.   )
  105.   ;; 让图像group 绕着 point_A->normal_vector   旋转Δ ,再绕着绕着旋转轴axis_rotation_0 axis_rotation_1 旋转ang度
  106.   ;; 最后 坐标原点 移动到target_A
  107.   (rotate_3d (cddr group)
  108.        target_A
  109.        (mapcar '+ target_A normal_vector_target)
  110.        Δ
  111.   )
  112. )

  1. ;; group 为一个四维点集合 , point_A point_B 为旋转轴的两个点,φ 为旋转角度,单位弧度
  2. ;; 旋转轴point_A point_B 的距离必须大于0 ,本程序不考虑 point_A point_B 重合的情形
  3. (defun rotate_3d (group    point_A point_B φ    /    x_A
  4.       y_A    z_A    x_B    y_B    z_B    P_1
  5.       P_2    cos_a    sin_a    cos_b    sin_b    P1->P2
  6.       A->B    T_ry    T_rx    T_rZ    T_ry-1  T_rx-1
  7.       T_m-1    T_综合
  8.      )
  9.   (setq  T_m (list
  10.         (list 1 0 0 (* (car point_A) -1))
  11.         (list 0 1 0 (* (cadr point_A) -1))
  12.         (list 0 0 1 (* (caddr point_A) -1))
  13.         (list 0 0 0 1)
  14.       )
  15.   )

  16.   ;; 设置point_A point_B 的坐标 x_A y_A z_A ,x_B y_B z_B  
  17.   (mapcar 'set
  18.     '(x_A y_A z_A x_B y_B z_B)
  19.     (append point_A point_B)
  20.   )
  21.   (setq  P_1    (list y_A Z_A)
  22.   P_2    (list y_B Z_B)
  23.   P1->P2 (distance p_1 P_2)
  24.   )
  25.   (if (> P1->P2 1e-8)
  26.     ;; 当向量A->B 不平行于X 轴时  
  27.     (setq
  28.       cos_a (/ (- z_B z_A) P1->P2)
  29.       sin_a (/ (- y_B y_A) P1->P2)
  30.     )
  31.     ;; 当向量A->B 平行于X 轴时 ,既垂直于 YZ平面,此时A->B与X轴的夹角为0度  
  32.     (setq cos_a  1
  33.     sin_a  0
  34.     )
  35.   )
  36.   (setq  T_rx (list
  37.          (list 1 0 0 0)
  38.          (list 0 cos_a (* -1 sin_a) 0)
  39.          (list 0 sin_a cos_a 0)
  40.          (list 0 0 0 1)
  41.        )
  42.   )
  43.   (setq
  44.     A->B  (distance point_A point_B)
  45.     cos_b (/ P1->P2 A->B)
  46.     sin_b (/ (- x_B x_A) A->B)
  47.   )
  48.   (setq  T_ry (list
  49.          (list cos_b 0 (* -1 sin_b) 0)
  50.          (list 0 1 0 0)
  51.          (list sin_b 0 cos_b 0)
  52.          (list 0 0 0 1)
  53.        )
  54.   )
  55.   ;; 绕AB顺时针旋转 φ 角度,就变成绕新的Z 轴逆时针旋转φ 角度
  56.   (setq  T_rZ (list
  57.          (list (cos φ) (* -1 (sin φ)) 0 0)
  58.          (list (sin φ) (cos φ) 0 0)
  59.          (list 0 0 1 0)
  60.          (list 0 0 0 1)
  61.        )
  62.   )
  63.   (setq  T_ry-1 (list
  64.      (list cos_b 0 sin_b 0)
  65.      (list 0 1 0 0)
  66.      (list (* -1 sin_b) 0 cos_b 0)
  67.      (list 0 0 0 1)
  68.          )
  69.   )
  70.   (setq  T_rx-1 (list
  71.      (list 1 0 0 0)
  72.      (list 0 cos_a sin_a 0)
  73.      (list 0 (* -1 sin_a) cos_a 0)
  74.      (list 0 0 0 1)
  75.          )
  76.   )
  77.   (setq  T_m-1 (list
  78.     (list 1 0 0 (car point_A))
  79.     (list 0 1 0 (cadr point_A))
  80.     (list 0 0 1 (caddr point_A))
  81.     (list 0 0 0 1)
  82.         )
  83.   )
  84.   (setq  T_综合
  85.          (mapcar '(lambda  (lst)
  86.         (setq  lst (mxv T_m lst)
  87.         lst (mxv T_rx lst)
  88.         lst (mxv T_ry lst)
  89.         lst (mxv T_rz lst)
  90.         lst (mxv T_ry-1 lst)
  91.         lst (mxv T_rx-1 lst)
  92.         lst (mxv T_m-1 lst)
  93.         )
  94.       )
  95.            (list
  96.        '(1 0 0 0)
  97.        '(0 1 0 0)
  98.        '(0 0 1 0)
  99.        '(0 0 0 1)
  100.            )
  101.          )
  102.   ;; 对T_综合 进行装置
  103.   T_综合 (list (mapcar 'car T_综合)
  104.          (mapcar 'cadr T_综合)
  105.          (mapcar 'caddr T_综合)
  106.          (mapcar 'cadddr T_综合)
  107.          )
  108.   )
  109.   (mapcar '(lambda (u)
  110.        (mxv T_综合 U)
  111.      )
  112.     group
  113.   )
  114. )
  115. ;;  ( rotate_3d  group    point_A point_B φ  )

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 3明经币 +4 金钱 +15 收起 理由
qjchen + 2 + 15 赞一个!
zixuan203344 + 1 赞一个!
USER2128 + 1 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2018-3-14 18:42 来自手机 | 显示全部楼层
高手太多,我等惭愧跪拜
 楼主| 发表于 2018-3-15 12:01 | 显示全部楼层
都是书本上抄来的,我只是翻译下而已。
发表于 2018-3-15 16:54 | 显示全部楼层
确实好用。学习了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-20 15:51 , Processed in 0.259188 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表