Engee 文档
Notebook

构建西拉多面体(西拉多面体)

本演示介绍如何使用Plots.jl 库中的函数mesh3d() 构建西拉多面体(Silahedron)。

简介

Силаэдр- 是一个非凸环形多面体,欧拉-平卡列特性中的以下等式成立
$$h = \frac{(f-4)(f-3)}{12},$$ 其中$f = 7$ 是多面体的面数,$h=1$ 是嵌入多面体的曲面的孔数。
这个等式源于这样一个条件,即在这样的多面体中,每个面都与其他面有一条公共边。

一个正六面体有 7 个六面体面、14 个顶点和 21 条边。在本例中,我们将利用现有的顶点坐标在直角坐标系中构建这个多面体。

顶点坐标

首先,让我们介绍一下面和顶点的符号。顶点有 0 至 13 的连续数字符号,成对的面有连续的字母数字符号:A1、A2、B1、B2、B1、B2、B1、B2,未配对的边用字母G表示。
下面的多面体扫面图显示了相应的名称和色调,这些名称和色调将进一步用于构造正 silahedron。

net_of_szilassi_polyhedro.png

让我们在Engee工作空间中添加描述正四面体顶点笛卡尔坐标的变量。这些坐标是根据多面体的几何中心位于原点和最小面的长度等于 1 的条件确定的。

In [ ]:
# Координаты вершин: 
#           координаты [x, y, z]    № вершины
Вершины = [
            [12,  0, 12],           # 0
            [-12, 0, 12],           # 1
            [0, 12.6, -12],         # 2
            [0, -12.6, -12],        # 3
            [2, -5, -8],            # 4
            [-2, 5, -8],            # 5
            [3.75, 3.75, -3],       # 6
            [-3.75, -3.75, -3],     # 7
            [4.5, -2.5, 2],         # 8
            [-4.5, 2.5, 2],         # 9
            [7, 0, 2],              # 10
            [-7, 0, 2],             # 11
            [7, 2.5, 2],            # 12
            [-7, -2.5, 2]           # 13
          ];

# извлечение векторов координат вершин по осям
Вершины_матрица = Base.stack(Вершины, dims = 1);
Вершины_x = Вершины_матрица[:, 1];
Вершины_y = Вершины_матрица[:, 2];
Вершины_z = Вершины_матрица[:, 3];

在向量Вершины 中,给出了注释中指定序号的顶点坐标向量。为便于构建,沿坐标轴的坐标被提取为单独的矢量。

顶点连接

要使用Plots.mesh3d() 函数构造面,必须定义三个向量(I、J、K),其对应的索引是属于多面体面的三角形顶点。例如,在面 A1 中有 4 个不相交的三角形,分别由顶点 0-10-12、0-4-10、4-2-104-3-2构成。
因此,让我们将正方体的每个面划分为不相交的三角形,并将形成这些三角形的顶点写入向量 I、J、K 的相应索引中。为了在构建过程中正确显示面的颜色填充,应在不改变一个面的顶点遍历方向的情况下将三角形的顶点输入向量。

In [ ]:
# разбиение граней на треугольники:
# грань А1 (состоит из треугольников 0-10-12, 0-4-10, 4-2-10, 4-3-2)
А1_i = [0,  0,  4,  4];
А1_j = [10, 4,  2,  3];
A1_k = [12, 10, 10, 2];
Соединения_А1 = (А1_i, А1_j, A1_k);

# грань А2
А2_i = [1,  1,  5,  5];
А2_j = [11, 5,  3,  2];
A2_k = [13, 11, 11, 3];
Соединения_А2 = (А2_i, А2_j, A2_k);

# грань Б1
Б1_i = [0, 0,  0,  4];
Б1_j = [8, 1,  13, 8];
Б1_k = [4, 13, 8,  7];
Соединения_Б1 = (Б1_i, Б1_j, Б1_k);

# грань Б2
Б2_i = [1, 1,  1,  5];
Б2_j = [9, 0,  12, 9];
Б2_k = [5, 12, 9,  6];
Соединения_Б2 = (Б2_i, Б2_j, Б2_k);

# грань В1
В1_i = [10, 10, 10, 5];
В1_j = [8,  7,  6,  2];
В1_k = [7,  6,  2,  6];
Соединения_В1 = (В1_i, В1_j, В1_k);

# грань В2
В2_i = [11, 11, 11, 7];
В2_j = [9,  6,  7,  4];
В2_k = [6,  7,  3,  3];
Соединения_В2 = (В2_i, В2_j, В2_k);

# грань Г
Г_i = [11, 10, 8,  8];
Г_j = [8,  9,  11, 9];
Г_k = [13, 12, 9,  10];
Соединения_Г = (Г_i, Г_j, Г_k);

# вектора значений для построения граней
Соединения = [Соединения_А1, Соединения_А2, Соединения_Б1, 
              Соединения_Б2, Соединения_В1, Соединения_В2, Соединения_Г];
Радуга =  [:red, :orange, :yellow, :green, :cyan, :blue, :purple];
Подпись = ["A1", "A2",    "Б1",    "Б2",   "В1",  "В2",  "Г"    ];

将获得的向量组合成图元传递给函数mesh3d() ,并定义调色板变量和多面体面的名称。

构建正二面体

连接图书馆Plots.jl 和后台进行构建:

In [ ]:
# подключение библиотеки и бэкенда
using Plots;
plotlyjs();

让我们来介绍函数Грань() ,它可以按索引构建顶点和面:

In [ ]:
# функция для построения вершин и граней
function Грань(номер)
    if номер == 0 
        Plots.scatter3d(Вершины_x, Вершины_y, Вершины_z;
                        label="вершины", color = :black, markersize = 1,
                        xlabel = "x", ylabel = "y", zlabel = "z",
                        camera = (130, 20))
    else
        Plots.mesh3d!(Вершины_x, Вершины_y, Вершины_z;
                      connections = Соединения[номер],
                      color = Радуга[номер], label = Подпись[номер])
    end
end;

让我们在循环中构建顶点并获得面:

In [ ]:
# построение вершин
Plots.scatter3d(Вершины_x, Вершины_y, Вершины_z;
                label="вершины", color = :black, markersize = 1)

# построение граней в цикле
for N in 1:7
    Грань(N)
end

# оформление сцены
plot!(xlabel = "x", ylabel = "y", zlabel = "z", camera = (130, 20))
Out[0]:

连接后端可构建具有高度交互性的多面体。正方体可以缩放、旋转,元素(面和顶点)的显示可以打开或关闭。

最后,让我们来制作一个按顺序构建正方体面的动画:

In [ ]:
# анимация последовательного построения граней
анимация = @animate for N in [0, 7, 6, 5, 2, 1, 3, 4]
    Грань(N)
end;

gif(анимация, "Силаэдр.gif", fps = 1)
[ Info: Saved animation to /user/start/examples/math_and_optimization/silaedr/Силаэдр.gif
Out[0]:
No description has been provided for this image

结论

在本例中,我们使用Plots.jl 库中的函数mesh3d() 根据坐标构建了西拉多面体。