Документация Engee
Notebook

Построение многогранника Силаши (Силаэдра)

В этом демонстрационном примере рассмотрено построение многогранника Силаши (Силаэдра) при помощи функции mesh3d() из библиотеки Plots.jl.

Введение

Силаэдр - это невыпуклый тороидальный многогранник, для которого выполняется следующее из характеристики Эйлера-Пуанкаре равенство
$$h = \frac{(f-4)(f-3)}{12},$$
где $f = 7$ - число граней многогранника, а $h=1$ - число дыр поверхности, в которую он вложен.
Это равенство следует из условия, что в таком многограннике каждая грань имеет общее ребро с любой другой гранью.

Силаэдр имеет 7 шестиугольных граней, 14 вершин и 21 ребро. В примере мы построим этот многогранник в декартовой системе координат по имеющимся координатам вершин.

Координаты вершин

Для начала введём обозначения для граней и вершин. Вершины имеют последовательные численные обозначения от 0 до 13, попарно-конгруэнтные грани имеют последовательные буквенно-численные обозначения: А1, А2, Б1, Б2, В1, В2, а непарная грань - буквенное обозначение Г.
На развертке многогранника, представленной ниже, указаны соответствующие обозначения и введена цветовая палитра, которая будет использована далее при построении силаэдра.

net_of_szilassi_polyhedro.png

Добавим в рабочую область Engee переменные, характеризующие декартовы координаты вершин Силаэдра. Эти координаты определены из условий, что в начале координат располагается геометрический центр многогранника, а длина наименьшей его грани равна единице.

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) соответствующие индексы которых являются вершинами треугольника, принадлежащего грани многогранника. Так, например, в грани А1 существует 4 непересекающихся треугольника, образованных вершинами 0-10-12, 0-4-10, 4-2-10 и 4-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;
plotly();

Введём функцию Грань() для построения вершин и граней по индексу:

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)
Out[0]:
No description has been provided for this image

Заключение

В этом примере мы рассмотрели построение многогранника Силаши по координатам при помощи функции mesh3d() из библиотеки Plots.jl.