内侧菱形三十面体的顶点坐标计算和点积方法Python实现

NumPy特性

      NumPy 是Python中用于科学计算的核心库,它提供了高效的多维数组对象ndarray,以及大量的数学函数来操作这些数组。

内侧菱形三十面体的顶点坐标计算和点积方法

       下面用python来实现数学模型,正好最近考虑到了一个有趣的数学问题:有没有什么多面体,它的每个面都是凹多边形? 笔者在搜索 wikipedia 的过程中,发现了一个有趣的图形:内侧菱形三十面体 (medial rhombic triacontahedron),如下图所示:

    对于构造内侧菱形三十面体,我们先选取二十四个顶点坐标如下:

    通过坐标计算可以发现:

       根据对称性,当我们选取 V17, V4, V11, V13 四个点的时候,可得其构成与之前全等的菱形。如此, 我们可以找到 30 个全等的菱形,为我们所需的三十个面。

python实现伪代码如下:

import numpy as np
# 常量定义
sqrt5 = np.sqrt(5)
C0 = 3 * (sqrt5 - 1) / 8
C1 = 3 * (sqrt5 + 1) / 8

# 顶点坐标生成 (24个顶点)
vertices = [
    (0.75, 0, C1),    # V0
    (0.75, 0, -C1),   # V1
    (-0.75, 0, C1),   # V2
    (-0.75, 0, -C1),  # V3
    (C1, 0.75, 0),    # V4
    (C1, -0.75, 0),   # V5
    (-C1, 0.75, 0),   # V6
    (-C1, -0.75, 0),  # V7
    (0, C1, 0.75),    # V8
    (0, C1, -0.75),   # V9
    (0, -C1, 0.75),   # V10
    (0, -C1, -0.75),  # V11
    (C0, 0, 0.75),    # V12
    (C0, 0, -0.75),   # V13
    (-C0, 0, 0.75),   # V14
    (-C0, 0, -0.75),  # V15
    (0.75, C0, 0),    # V16
    (0.75, -C0, 0),   # V17
    (-0.75, C0, 0),   # V18
    (-0.75, -C0, 0),  # V19
    (0, 0.75, C0),    # V20
    (0, 0.75, -C0),   # V21
    (0, -0.75, C0),   # V22
    (0, -0.75, -C0),  # V23
]

# 验证菱形面 V17, V4, V12, V10
def validate_rhombus():
    v17 = np.array(vertices[17])
    v4 = np.array(vertices[4])
    v12 = np.array(vertices[12])
    v10 = np.array(vertices[10])
    
    # 计算四条边向量
    edge1 = v4 - v17  # V17→V4
    edge2 = v12 - v4  # V4→V12
    edge3 = v10 - v12 # V12→V10
    edge4 = v17 - v10 # V10→V17
    
    # 验证平行性和模长
    print("验证对边平行且等长:")
    print(f"V17V4 与 V12V10 平行: {np.allclose(np.cross(edge1, edge3), [0,0,0])}")
    print(f"模长: {np.linalg.norm(edge1):.4f} (理论值: {3*np.sqrt(3)/4:.4f})")
    print(f"V4V12 与 V10V17 平行: {np.allclose(np.cross(edge2, edge4), [0,0,0])}")
    print(f"模长: {np.linalg.norm(edge2):.4f} (理论值: {3*np.sqrt(3)/4:.4f})")
    
    # 计算角度余弦
    cos_angle1 = np.dot(edge1, edge4) / (np.linalg.norm(edge1) * np.linalg.norm(edge4))
    cos_angle2 = np.dot(edge1, edge2) / (np.linalg.norm(edge1) * np.linalg.norm(edge2))
    print(f"\n验证凹角:")
    print(f"cos(∠V4V17V10) = {cos_angle1:.4f} (理论值: {-sqrt5/3:.4f})")
    print(f"cos(∠V17V4V12) = {cos_angle2:.4f} (理论值: {sqrt5/3:.4f})")

validate_rhombus()

# 定义30个菱形面 (示例定义部分面)
faces = [
    [17, 4, 12, 10],  # 第一个菱形
    [4, 12, 10, 17],  # 对称面
    [16, 5, 13, 11],  # 其他面
    [5, 13, 11, 16],
    [18, 7, 14, 22],
    [7, 14, 22, 18],
    # 可根据对称性补充完整30个面...
]

       另外最近看到了 Branko Grünbaum 和 G. C. Shephard 在 1998 年的论文《Isohedra with Nonconvex Faces》中给出了一些例子,这其中有些结构十分精巧,可以说如果不特别去构造几乎难以想 象。在本文中我们将引用其中一些例子,分享一下这些结构的顶点坐标和平面方程如何计算。一些 最常见的例子 (Figure 7 in Branko) 如图所示:

       如果要计算这些特定多面体的顶点坐标,我们将引用 APPENDIX 当中的一些记号和术语,并 且对于一两个特殊图形作出距离。在每一种情形中,我们都从一个正多面体 P(四面体、八面体或 二十面体)出发,其顶点记为 Di,以及其对偶多面体 P ′(四面体、立方体或十二面体),其顶点记 为 Ej。于是,根据图中所示的参数 a, b, c,面 F 的五个顶点可以按如下顺序表示:

       其中 d 与 e 是 a, b, c 的函数,选定以使这五个 (∗) 当中的点共面。不同情形下的具体表达将在 下文给出。显然,对参数做统一缩放对应于相似多面体;因此这些参数可以理解为同类多面体空间 中某种给定拓扑类型的“等面体空间”中的齐次坐标。 第一类问题是如下的这类多面体,它们看起来很夸张,但是顶点坐标是容易表示的:

       我们可以取 P,也就是这些多面体的母体作为具有以下十二个顶点坐标的二十面体:

        然后其对偶的十二面体 P ′ 的二十个顶点坐标为:

       这里关于 d, e 的计算相当复杂,我们仅给出一个 d 的式子:

第二类问题当中,图形可能更简单,它们都来自于一个正四面体:其中,P 是一个四面体,其

所有顶点为:         当中带有偶数个负号的点,表示正四面体 P 的顶点。

         而对偶四面体 P ′ 的顶点坐标为:

          当中带有奇数个负号的点。

           在公式 (∗) 中我们取:

         由此即可类似地得到 d 和 e 的计算:

       一个特别有趣的图形是如下的 12 面体,其中每个五边形都是一个由正五边形向下 “压缩”后的结果

      这个图形是完全被嵌入在立方体(cube)A1A2A3A4 − A5A6A7A8 当中的,实际上如果我们设 这个立方体的外面 8 个顶点为:

则其内部的凹陷顶点坐标可以写作: 

我们再提出一个有趣的例子:

这个图形的所有顶点位于一个正八面体上 (octahedron), 其 6 个顶点坐标为:

和它的坐标排列,这样它的对偶多面体 P ′ 就可以取为:

在(*)中我们取

import numpy as np


# ================== 通用工具函数 ==================
def normalize(v):
    return v / np.linalg.norm(v)


# ================== 第一类:二十面体衍生结构 ==================
def icosidodecahedron_case(a=1.0, b=0.5, c=0.3):
    tau = (1 + np.sqrt(5)) / 2
    
    # 定义原始二十面体顶点
    D1 = np.array([0, tau, 1])
    D2 = np.array([tau, 1, 0])
    
    # 定义对偶十二面体顶点
    E1 = np.array([1, tau**2, 0])
    E2 = np.array([tau, tau, tau])
    E3 = np.array([0, 1, tau**2])
    
    # 计算d参数(共面条件)
    numerator = a**2*c + 3*a*b*c + b**2*c - c**3 - a*c**2 + 2*a*b**2 + tau*(2*a**2*b + 2*a*b**2 + 4*a*b*c + 2*b**2*c - 2*c**3)
    denominator = a*c + 2*b*c - 2*c**2 + tau*(2*a*b + b*c - c**2)
    d = numerator / denominator
    
    # 生成五个顶点
    X1 = a*D1 + b*E1 + c*E2
    X2 = a*D2 + b*E2 + c*E1
    X3 = a*D1 + b*E2 + c*E3
    Z1 = d*D1
    
    # 计算e参数(Y2顶点)
    Y2 = (a**2*c - 2*a*b*c + 2*a*c**2 - b**2*c + c**3 - 2*a**2*b - 2*a*b**2) / (c**2 - a*c - b*c - 2*a*b) * E2
    
    return [X1, X2, X3, Y2, Z1]

# ================== 第二类:四面体衍生结构 ==================
def tetrahedral_case(a=0.8, b=0.6, c=0.4):
    # 正四面体顶点(偶数负号)
    D1 = np.array([1, 1, 1])
    D2 = np.array([-1, -1, 1])
    
    # 对偶四面体顶点(奇数负号)
    E1 = np.array([-1, 1, 1])
    E2 = np.array([1, -1, 1])
    E3 = np.array([1, 1, -1])
    
    # 计算d和e参数
    numerator = a**2*c - 2*a*b*c + 2*a*c**2 - b**2*c + c**3 - 2*a**2*b - 2*a*b**2
    d = numerator / (3*c**2 + a*c - 3*b*c - 2*a*b)
    e = numerator / (c**2 - a*c - b*c - 2*a*b)
    
    # 生成五个顶点
    X1 = a*D1 + b*E1 + c*E2
    X2 = a*D2 + b*E2 + c*E1
    X3 = a*D1 + b*E2 + c*E3
    Z1 = d*D1
    Y2 = e*E2
    
    return [X1, X2, X3, Y2, Z1]

# ================== 第三类:立方体内嵌凹十二面体 ==================
def cubic_pentagonal_dodecahedron():
    alpha = (np.sqrt(5)-1)/2
    
    # 立方体顶点
    A = [np.array(v) for v in [
        (1,1,1), (-1,1,1), (-1,-1,1), (1,-1,1),
        (1,1,-1), (-1,1,-1), (-1,-1,-1), (1,-1,-1)
    ]]
    
    # 内凹顶点
    B = [np.array(v) for v in [
        (alpha**2, alpha, 0), (alpha**2, -alpha, 0),
        (0, alpha**2, alpha), (0, alpha**2, -alpha),
        (alpha, 0, alpha**2), (-alpha, 0, alpha**2),
        (-alpha**2, alpha, 0), (-alpha**2, -alpha, 0),
        (0, -alpha**2, alpha), (0, -alpha**2, -alpha),
        (alpha, 0, -alpha**2), (-alpha, 0, -alpha**2)
    ]]
    
    # 定义五边形面(示例)
    faces = [
        [0, 8, 1, 9, 4],  # A1-B9-B2-A2-B5
        [0, 2, 10, 3, 8], # A1-B3-B4-A2-B9
        # 可根据对称性补充其他面...
    ]
    
    return A + B, faces

最后我们在开始提到的图形当中提出一个小问题,如果需要计算如下的图形的各个顶点坐标, 应当如何标注?

绘制图片代码如下:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

# 3D可视化
def plot_polyhedron():
    fig = plt.figure(figsize=(12, 10))
    ax = fig.add_subplot(111, projection='3d')
    
    # 绘制顶点
    xs, ys, zs = zip(*vertices)
    ax.scatter(xs, ys, zs, color='red', s=50)
    
    # 绘制面片
    for face in faces:
        verts = [vertices[i] for i in face]
        ax.add_collection3d(Poly3DCollection([verts], alpha=0.7, edgecolor='k', linewidths=1, facecolor='cyan'))
    
    # 设置坐标轴
    max_val = max(max(abs(x), abs(y), abs(z)) for x, y, z in vertices) * 1.2
    ax.set_xlim([-max_val, max_val])
    ax.set_ylim([-max_val, max_val])
    ax.set_zlim([-max_val, max_val])
    
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    ax.set_title('Medial Rhombic Triacontahedron (部分面展示)')
    
    # 视角调整
    ax.view_init(elev=25, azim=45)
    plt.tight_layout()
    plt.show()

导出为STL文件用于3D打印:

from stl import mesh
def export_stl():
    poly = mesh.Mesh(np.zeros(len(faces), dtype=mesh.Mesh.dtype))
    for i, f in enumerate(faces):
        poly.vectors[i] = [vertices[idx] for idx in f]
    poly.save('medial_rhombic.stl')

通过接入deepseek,对问题进行分析,测试大模型的分析与解决问题的能力。摘抄部分结果:

多面体类型关键数学工具DeepSeek实现重点
内侧菱形三十面体黄金比例τ、向量平行性验证顶点坐标精确计算、凹角可视化
二十面体衍生结构参数化共面条件(d/e公式)复杂分式运算、对称性生成
立方体内嵌十二面体五边形凹陷拓扑、平面方程自动内凹顶点生成、非凸面片渲染

对后续编程代码的启示:

  • 自动化面片生成

    • 基于图论自动识别多面体面片拓扑

  • 物理特性分析

    • 集成有限元分析(如应力分布计算)

  • 教育应用开发

    • 构建交互式几何学习工具(如Jupyter插件)

修改历史


2019-05-08

1.在帖子中增加第三类立方体内嵌凹十二面体的代码

2.修改帖子中denominator 参数的计算方式

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2020-11-20

1.帖子中的代码引入matplotlib库,增加3D可视化代码,进行简单展示。

2.解决anaconda 启动非常慢问题

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2022-07-05

1.利用NumPy1.21版本的特性,引入np.linalg.lstsqrcond参数,优化最小二乘解的稳定性。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2024-02-26

1.通过借鉴《平面设计理论》,修改代码使用半透明青色面片显示非凸面。

2.增加引入STL,可以将结果导出为STL文件用于3D打印

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2025-04-19

使用deepseek对内容代码进行优化,并测试deepseek的性能。并保留对未来的启示,待后续有新思路时继续更新帖子


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值