МИНОБРНАУКИ РОССИИ
Федеральное государственное бюджетное образовательное учреждение
высшего образования
«Ярославский государственный университет им. П. Г. Демидова»
Кафедра математического анализа
Сдано на кафедру
«16» июня 2020 г.
Заведующий кафедрой
д. ф.-м. н., доцент
Невский М. В.
Выпускная квалификационная работа
Расчёт параметров и моделирование изгибаемых многогранных
поверхностей, составленных из параллелограммов
направление подготовки
01.03.02 Прикладная математика и информатика
Научный руководитель
старший преподаватель
Алексеев В. В.
«16» июня 2020 г.
Студент группы ПМИ-41БО
Хорошева Е. В.
«16» июня 2020 г.
Ярославль 2020 г.
Реферат
Объем 40 с., 4 гл., 26 рис., 0 табл., 8 источников, 1 прил.
Ключевые слова: вектор, двугранный угол, координаты, многогранные
изгибаемые поверхности, параллелограммы, параллельный перенос,
Python, STL.
В работе рассмотрен частный случай многогранных изгибаемых поверхностей, а именно поверхностей, составленных из равных параллелограммов. Исследуется ситуация, когда при сгибе соседних параллелограммов по общему ребру
смежная пара параллелограммов сгибается в противоположную сторону.
Задача состоит в определении параметров, описывающих изгибаемую многогранную поверхность, и её моделирование.
Поставленную задачу можно решить несколькими подходами. В работе
рассмотрены два метода. Первый метод основывается на применении матриц
поворота и отражения. Второй способ заключается в анализе углов между гранями
поверхности.
Найдено соотношение, параметризующее все точки изгибаемой поверхности. По полученным результатам написана программа на языке Python. Реализованное приложение позволяет вычислить координаты вершин участка поверхности и визуализировать его. При задании различных начальных параметров можно
увидеть особенности динамики изменения изгибаемой многогранной поверхности. Проведена адаптация и подготовка модели с целью получения возможности
её 3D-печати.
Выбранная тема интересна для изучения и находит своё применение в
инженерии и промышленности.
2
Содержание
Введение
4
1. Постановка задачи
5
2. Методы решения
2.1. Линейно - алгебраический метод . . . . . . . . . . . . . . . . . .
2.2. Геометрический метод . . . . . . . . . . . . . . . . . . . . . . . .
7
7
10
3. Программная реализация
13
4. Создание трёхмерной модели
4.1. Необходимые вычисления . . . . . . . . . . . . . . . . . . . . . .
4.2. Реализация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
16
19
Заключение
24
Список литературы
25
Приложение А. Исходный код программы на Python
26
3
Введение
Многогранной поверхностью называется поверхность, состоящая из набора плоских многоугольников (например, треугольников или параллелограммов).
Элементами многогранной поверхности являются её вершины, рёбра — стороны
граней и грани, которыми являются многоугольники.
Согласно известной классификации [1], многогранные поверхности могут
быть изгибаемыми. Их особенностью является то, что пространственную форму
можно изменить непрерывной деформацией. В процессе такой деформации каждая грань не изменяет своих размеров (движется как твёрдое тело), а деформация
осуществляется только за счёт непрерывного изменения двугранных углов.
Отдельный интерес представляют изгибаемые поверхности, составленные
из равных выпуклых 4-угольников, допускающие плоскую реализацию (в виде
замощения плоскости). Они нашли применение в промышленности в качестве
солнечных панелей для космических аппаратов [2]. Также они используются и
в архитектурном дизайне: изогнутые фасады или крыши из четырехугольных
стеклянных панелей встречаются в современных городах. Известны условия, при
которых такие поверхности обладают свойством изгибаемости: комплекс, состоящий из граней и её 8 соседей, допускает непрерывное изменение [3].
В большинстве известных работ, связанных с исследованием свойств изгибаемых поверхностей, рассматриваемые случаи сводятся к рассмотрению общей
модели. Интерес состоит в том, чтобы произвести численное моделирование
изгибаемой поверхности.
Выбранная тема не только представляет собой увлекательное математическое исследование, но и будет актуальна благодаря наличию приложений в
архитектуре и технической деятельности.
В работе рассматривается частный случай изгибаемых многогранных поверхностей: поверхностей, составленных из равных параллелограммов.
Цель выпускной квалификационной работы состоит в:
1. Определении параметров, описывающих изгибаемую многранную поверхность, составленную из равных параллелограммов.
2. Поиске алгоритма, позволяющего вычислить координаты произвольного
участка поверхности по данному набору параметров.
3. Программной реализации трёхмерной модели данной поверхности.
4. Адаптации данной модели с целью обеспечения возможности её 3D-печати.
4
1.
Постановка задачи
Рассмотрим замощение плоскости равными параллелограммами (Рис. 1):
Рис. 1 — Пример составленной из равных параллелограммов
поверхности
Рассмотрим два соседних параллелограмма. Если согнуть поверхность по
их общему ребру, то следующая пара параллелограммов может согнуться в ту же
сторону (этот случай тривиален), а может в противоположную (Рис. 2, Рис. 3). В
данной работе нас будет интересовать именно второй случай.
z
z
x
Рис. 2 — Следующая пара
параллелограммов сгибается в
туже строну
x
Рис. 3 — Следующая пара
параллелограммов сгибается в
противоположную сторону
Задача состоит в моделировании такой поверхности, параметризованной
длинами сторон параллелограмма, углом α параллелограмма и двугранным углом
сгиба ψ .
Рассмотрим участок поверхности, состоящий из четырех соседних параллелограммов (Рис. 4). Будем симметрично относительно плоскости Oxz сгибать
5
закрашенный параллелограмм к верхнему параллелограмму (Рис. 5). Опишем
движение отмеченных вершин в зависимости от угла сгиба ψ . Сгибать можно
только по линиям, грани жёсткие (несгибаемые).
z
y
E
F
F
K
C
D
ψ
B
C
G
x
α
E
B
A
D
x
ω
L
K
β
G
A
Рис. 4 — Участок поверхности,
состоящий из четырех соседних
параллелограммов
Рис. 5 — Вид рассматриваемого
участка поверхности после
сгиба
6
L
2.
Методы решения
В данной главе будут рассмотрены два метода решения задачи: линейно алгебраический и геометрический. В первом элементы можно найти, используя
матрицы поворота и отражения. Второй способ будет основан на анализе углов
между гранями поверхности.
2.1.
Линейно - алгебраический метод
Пусть нам даны координаты вершин параллелограмма ABCD . Пусть B
лежит в начале координат, ψ — двугранный угол сгиба между параллелограммами
(Рис. 4).
Для того, чтобы найти точку E , необходимо осуществить поворот точки A
−−→
на угол ψ вокруг BC [5].
Любое вращение в трёхмерном пространстве может быть представлено последовательностью поворотов вокруг трёх ортогональных осей (например, вокруг
осей декартовых координат). Этой последовательности соответствует матрица,
равная произведению соответствующих матриц поворота. Матрицей поворота
назовём ортогональную матрицу, используемую для выполнения собственного
ортогонального преобразования в евклидовом пространстве.
−−→
Пусть BC = (Cx ,Cy ,Cz ). Пусть ψ — угол поворота, а ось вращения задана
→
−
единичным вектором V = (Vx ,Vy ,Vz ), где
(Cx , Cy , Cz )
→
−
V (Vx , Vy , Vz ) = q
.
2
2
2
Cx + Cy + Cz
(1)
Тогда матрица поворота в декартовых координатах имеет вид
−
→
V
M ( , ψ) =
cos ψ + (1 − cos ψ)Vx2
(1 − cos ψ)Vy Vx + (sin ψ)Vz
(1 − cos ψ)Vz Vx − (sin ψ)Vy
(1 − cos ψ)Vx Vy − (sin ψ)Vz
cos ψ + (1 − cos ψ)Vy2
(1 − cos ψ)Vz Vy + (sin ψ)Vx
(1 − cos ψ)Vx Vz + (sin ψ)Vy
(1 − cos ψ)Vy Vz − (sin ψ)Vx
cos ψ + (1 − cos ψ)Vz2
−−→
(2)
Ax
Координаты точки E определяются произведением M · Ay ,
Az
где Ax , Ay , Az — координаты точки A.
(3)
Сдвинем точки F, C и D на вектор BC . Получим новые точки K ∗ , G∗ , L∗
(Рис. 6).
7
K∗
G∗
L∗
z
F
C
σ
D
E
B
x
A
Рис. 6 — Расположение точек K ∗ , G∗ , L∗
Пусть F (Fx , Fy , Fz ), C(Cx , Cy , Cz ), D(Dx , Dy , Dz ). Уравнение плоскости [4], проходящей через точки F, C, D , в координатной форме будет иметь вид
(Рис. 6):
x − Fx y − F y z − Fz
Cx − Fx Cy − Fy Cz − Fz = 0.
Dx − Fx Dy − Fy Dz − Fz
Cy − Fy
Cz − F z
Dy − Fy Dz − Fz
·x−
Cx − Fx
Cz − Fz
Dx − Fx Dz − Fz
·y+
Cy − Fy
(4)
Cz − Fz
Dy − Fy Dz − Fz
·z =0
(5)
Получаем уравнение
∆x · x − ∆y · y + ∆z · z − (Fx · ∆x − Fy · ∆y + Fz · ∆z) = 0
(6)
→
−
Обозначим заданную плоскость за σ . Пусть N = (∆x, −∆y, ∆z) — вектор
нормали к этой плоскости. Тогда единичным вектором нормали будет
→
−
n (nx , ny , nz ) = p
(∆x, −∆y, ∆z)
(∆x)2 + (∆y)2 + (∆z)2
.
(7)
Координаты K, G, L получим отражением точек K ∗ , G∗ , L∗ относительно
плоскости σ . Рассмотрим алгоритм решения для точки K . Точки G и L находятся
аналогично.
Найдем уравнение прямой, проходящей через точку K ∗ перпендикулярно
8
плоскости σ . В качестве её направляющего вектора возьмём вектор нормали
плоскости.
x − Kx∗ y − Ky∗ z − Kz∗
=
=
∆x
−∆y
∆z
(8)
Найдем точку пересечения прямой и плоскости.
x − Kx∗ y − Ky∗ z − Kz∗
=
=
=t
∆x
−∆y
∆z
⇒
∗
x = Kx + t · ∆x
y = K ∗ − t · ∆y
y
z = K ∗ + t · ∆z
z
(9)
Найдём t, подставив координаты x, y, z в уравнение плоскости, получим
∆x · (Kx∗ + t · ∆x) − ∆y · (Ky∗ − t · ∆y) + ∆z · (Kz∗ + t · ∆z)−
− (Fx · ∆x − Fy · ∆y + Fz · ∆z) = 0.
(10)
Откуда можно записать точку K ′ (x, y, z) (Рис. 7). Точка K ′ является серединой отрезка KK ∗ , где точка K(Kx , Ky , Kz ) является точкой, симметричной
относительно проскости σ , точке K ∗ (Kx∗ , Ky∗ , Kz∗ ), поэтому
Kx + Kx∗
=
2
Ky + Ky∗
′
Ky =
2
Kz + Kz∗
′
Kz =
2
Kx′
⇒
Kx = 2Kx′ − Kx∗ ,
⇒
Ky = 2Ky′ − Ky∗ ,
⇒
Kz = 2Kz′ − Kz∗ .
(11)
z
K∗
σ
K′
K
x
Рис. 7 — Отражение точки K ∗ относительно плоскости σ
Таким образом, мы нашли все координаты точек участка поверхности.
Остальные точки получаются параллельным переносом участка поверхности на
вектор
(m · |BG|, n · |AE|, 0), m, n ∈ Z.
(12)
9
2.2.
Геометрический метод
В данном разделе будет рассмотрен метод параметризации вершин поверхности на основе геометрических соотношений.
Пусть заданы a = |BC|, b = |BA|, α — острый угол параллелограмма, ψ
— угол сгиба вдоль отрезка BC . Проведём координатные оси, как показано на
рисунке 4.
Поместим точку B в начало координат, ось Ox проведём в направлении
−−→
вектора BC .
Обозначим угол между отрезком BA и осью Ox как ω (Рис. 8).
Выразим координаты вершин A и E . Стороны BA и BE лежат в плоскости
Oxy . Из этого следует, что координата z искомых точек равна нулю.
Рассмотрим ∆ABN , изображённый на рисунке 8. Этот треугольник является прямоугольным, поэтому для угла ω будут верны следующие соотношения:
cos ω =
y
|AN |
|BN |
, sin ω =
.
|BA|
|BA|
(13)
z
E
F
C
D
a
B
ω
N
x
E
β
B
K
N
ω
b
A
Рис. 8 — Вид на плоскость Oxy
x
G
L
A
Рис. 9 — Расположение точки N
Выразим sin ω через заданные элементы. В ∆AON (Рис. 10) точка N принадлежит оси Ox (Рис. 8, Рис. 9), а грани параллелограммов движутся симметψ
ψ
рично относительно плоскости Oxz , поэтому ∠AON = 2 , |AN | = sin 2 · |AO|.
|AO|
Рассмотрим ∆ABO (Рис. 11), получим |BA| = sin α . Тогда
sin ω = sin α · sin
ψ
.
2
(14)
На рисунке 8 значение координаты x точки A будет равно длине отрезка
BN , координата y равна −|AN |. Для точки E : x = |BN |, y = |EN | = |AN | (в
силу симметрии относительно Oxz ). Запишем координаты искомых точек:
A = (b cos ω, −b sin ω, 0), E = (b cos ω, b sin ω, 0).
10
(15)
O
E
y
F
ψ
O
B
E
N
A
α
C
x
A
D
Рис. 11 — Точка O на плоскости
Рис. 10 — Расположение
элементов ∆AON
Для получения координат точки C сначала рассмотрим отрезок BC (Рис.
12). Он лежит в плоскости Oxz . Поэтому координата y этой точки принимает
нулевое значение.
Пусть β — угол между отрезком BC и осью Ox (Рис. 12), угол ω — угол
между отрезком BA и осью Ox на плоскости Oxy (Рис. 8), угол α — угол между
отрезками BA и BC (Рис. 11). Рассмотрим трёхгранный угол, ограниченный
плоскостями Oxy , Oxz и гранью параллелограмма ABCD . Запишем теорему
косинусов для трёхгранного угла. Угол между плоскостями Oxy и Oxz равен π2 .
z
C
β
B
H
x
Рис. 12 — Расположение угла β
Получаем,
π
cos α = cos β · cos ω + sin β · sin ω · cos .
2
(16)
cos α
. В прямоугольном треугольнике BCH
cos ω
для sin β и cos β справедливы следующие равенства (Рис. 12):
Из этого следует, что cos β =
cos β =
|BH|
,
|BC|
11
sin β =
|CH|
.
|BC|
(17)
Все необходимые значения найдены, и мы можем записать координаты точки.
C = (a cos β, 0, a sin β)
(18)
Перейдём к рассмотрению точки G. Она принадлежит плоскости Oxz . Поэтому y = 0. Также эта точка лежит на оси Ox. Поэтому z = 0. Пусть C(Cx , Cy , Cz ),
тогда
G(2 Cx , 0, 0).
(19)
Координаты остальных точек выражаются из следующих векторных соотношений:
−−→ −−→ −−→
BF = BC + BE,
−−→ −→ −→
CK = CG + CF ,
−−→ −−→ −→
BD = BC + BA,
−→ −→ −−→
CL = CG + CD.
(20)
Пусть C(Cx , Cy , Cz ), A(Ax , Ay , Az ), E(Ex , Ey , Ez ), F (Fx , Fy , Fz ),
D(Dx , Dy , Dz ). Тогда координаты оставшихся точек могут быть найдены по
следующим формулам:
F = (Cx + Ex , Cy + Ey , Cz + Ez ),
D = (Cx + Ax , Cy + Ay , Cz + Az ),
K = (Fx + Cx , Fy − Cy , Fz − Cz ),
L = (Dx + Cx , Dy − Cy , Dz − Cz ).
(21)
Координаты вершин всех четырёх параллелограммов найдены.
Координаты вершин произвольного участка поверхности получаются параллельным переносом на вектор
(m · |BG|, n · |AE|, 0),
12
m, n ∈ Z.
(22)
3.
Программная реализация
Для демонстрации смоделированных поверхностей по различным наборам
параметров, написана программа на языке Python. Для построения и работы с
графиками использована библиотека matplotlib [6].
Интерфейс приложения показан на рисунке 13. Программа позволяет производить построение участка поверхности произвольной величины с указанием
параметров.
Рис. 13 — Интерфейс приложения для демонстрации смоделированных
поверхностей по различным наборам параметров
Основную часть панели под названием Figure 1 занимает непосредственно
сам график поверхности в трёхмерной системе координат. На осях x, y, z указаны
значения. Под графиком добавлены слайдеры (Slider), которые позволяют изменять значения параметров «на лету». a — длина отрезка BC , b — длина отрезка
BA, α — градусная мера угла параллелограмма α, ψ — градусная мера угла ψ ,
13
угла сгиба вдоль отрезка BC (Рис. 4). Ниже расположены две кнопки (Button). По
нажатию на Save STL model программа позволяет сохранить участок поверхности
в формате STL. Подробнее см. Глава 4. Код программы см. в Приложении А.
Вычисления и построение реализованы в функциях CalkParam и Draw. В
CalkParam вычисляются длины отрезков AE, BG и координаты точек A, E, C, F,
D, G, K, L. В функции draw формируются списки всех вершин поверхности, задаются оси и их размеры, вызывается процедура отрисовки графика.
Далее продемонстрированы примеры поверхностей, смоделированных по
различным наборам параметров.
Рис. 14 — Пример многогранной поверхности, построенной с помощью
−−→
−→
второго метода при |BC| = 5, |BA| = 4, α = 45◦ , ψ = 0◦ .
14
Рис. 15 — Пример многогранной поверхности, построенной с помощью
−−→
−→
второго метода при |BC| = 5, |BA| = 4, α = 45◦ , ψ = 179◦ .
Рис. 16 — Пример многогранной поверхности, построенной с помощью
−−→
−→
второго метода при |BC| = 5, |BA| = 4, α = 45◦ , ψ = 120◦ .
15
4.
Создание трёхмерной модели
3D-моделирование - процесс (совокупность инструментов и приемов), при
помощи которого можно создавать объемные объекты. Он обеспечивает разработку наглядной копии поверхности, что представляет возможность наиболее полно
передавать информацию об изменениях объекта, анализировать характеристики.
Для создания трехмерной модели требуются специальные программные (приложения 3D-визуализации) и аппаратные средства (компьютер, 3D-мониторы,
3D-принтеры).
Полигональная трёхмерная модель состоит из множества точек, которые
соединяются между собой гранями и образуют полигоны. Вершиной является
точка, имеющая в трехмерной системе свои уникальные координаты (x, y , z ). Преимуществом трёхмерных моделей является их наглядность и информативность.
В настоящее время создание и использование 3D-моделей находит применение в различных областях деятельности: образовании, науке, строительстве,
картографии и т.д.
В данной работе требуется создать трёхмерную модель поверхности пригодной для 3D-печати. Глава 4 посвящена описанию того, каким образом можно
создать подобную модель.
4.1.
Необходимые вычисления
Построенная в Главе 3 поверхность является двумерной и не пригодной для
3D-печати. Целью данного раздела является демонстрация техники преобразования трёхмерной модели из двумерной поверхности.
Аппроксимируем реализованную изгибаемую поверхность набором многогранников (каждой грани будет соответствовать некий многогранник).
В Главе 2 показан алгоритм вычисления координат вершин двумерной изгибаемой поверхности.
Заменим грани поверхности призмами высоты e (e — параметр модели).
При этом образуется множество самопересечений поверхности на стыке граней.
Чтобы избежать самопересечений, раздвинем соседние грани на величину l ( l —
параметр модели) (Рис. 17).
Рассмотрим произвольную грань ABCD поверхности. Далее на рисунках 18 и 19 она выделена. Расположим её в декартовой системе координат, как
показано на рисунке 5. Обозначим грань ABCD , как µ 0,0 . Индексируем все грани поверхности целыми числами так, что грань µ m,n получается параллельным
переносом грани µ 0,0 на вектор (m · |BG|, n · |AE|, 0), m,n ∈ Z (Рис. 18).
16
Рис. 17 — Часть создаваемой трёхмерной модели
y
µ −1,3
µ 0,3
µ 1,3
µ 2,3
µ −1,2
µ 0,2
µ 1,2
µ 2,2
µ −1,1
µ 0,1
µ 1,1
µ 2,1
x
µ −1,0
µ 0,0
µ 1,0
µ 2,0
Рис. 18 — Индексация граней двумерной поверхности
Далее каждую грань µ m,n сдвигаем на вектор (lm , ln , 0), m,n ∈ Z. Результат преобразований покажем на рисунке 19.
На следующем этапе создадим смещённую копию полученного ранее слоя.
Это позволит получить объёмный аналог исследуемой поверхности. Построим
на гранях полученные поверхности, в отрицательном направлении оси Oz , как
17
y
µ −1,2
µ 0,2
µ 1,2
µ 2,2
µ 1,1
µ 2,1
µ 1,0
µ 2,0
l
µ −1,1
µ 0,1
l
x
µ −1,0
µ 0,0
Рис. 19 — Вид двумерной поверхности после раздвижения граней
на основаниях, призмы высотой e. В результате получим набор прямых призм с
ребром e; промежуток между соседними равен l.
Для обеспечения связности и изгибаемости модели, на каждой из боковых
граней полученных призм, как на боковой грани, построим прямую треугольную
призму, с высотой основания равного 2l . Тогда треугольные призмы, построенные на соседних гранях поверхности пересекутся по отрезку, что обеспечит изгибаемость модели (Рис. 17). Запишем формулы для расчёта координат точек
соединения (Рис. 20).
y
W
T1
W1
B
C
x
S1
A
D
S
T
H1
H
Рис. 20 — Вид трёхмерного элемента модели
18
Пусть B(x1 , y1 , z1 ), C(x2 , y2 , x2 ), D(x3 , y3 , z3 ), A(x4 , y4 , z4 ), тогда
l
e
l
e
W = (x1 , y1 + , z1 − ), W1 = (x2 , y2 + , z2 − ),
2
2
2
2
l
e
l
e
S = (x3 + , y3 , z3 − ), S1 = (x2 + , y2 , z3 − ),
2
2
2
2
l
e
l
e
H = (x3 , y3 − , z3 − ), H1 = (x4 , y4 − , z3 − ),
2
2
2
2
e
l
e
l
T = (x4 − , y4 , z4 − ), T1 = (x1 − , y1 , z1 − ).
2
2
2
2
(23)
Указанные соотношения задают трёхмерную модель изгибаемой поверхности.
4.2.
Реализация
Для хранения информации о 3D-моделях существуют различные форматы
файлов. Самые популярные из них: STL, OBJ, FBX, COLLADA.
3D-файл хранит информацию о геометрии, внешнем виде модели, а так же
другую дополнительную информацию. Геометрия модели описывает ее форму.
Внешний вид включает в себя цвета, текстуры, материал и т.д.
В работе используется STL-формат, как наиболее подходящий по функциональности и набору хранимых данных. STL — формат файла, который часто используют для хранения трёхмерных моделей объектов. Хранимые данные включают в
себя список треугольников и их нормалей, в совокупности задающих поверхность
объекта. STL-файл может быть текстовым (ASCII) или бинарным [8].
Пример файла типа ASCII STL выглядит следующим образом (Рис. 21).
Рис. 21 — Пример структуры файла STL в кодировке ASCII
Файлы этого типа начинаются со строки solid name и заканчиваются строкой endsolid name. Название объекта, обозначенное словом name — необяза19
тельно, но если name опущено, то всё равно должен быть пробел после solid.
Дальше файл заполняется списком произвольного числа треугольников, каждое n
и v — число с плавающей точкой. В строке f acet normal ni nj nk указываются
координаты вектора нормали единичной длины; важна согласованность ориентаций нормалей. Далее записываются координаты каждой вершины треугольника.
Они должны быть перечислены в порядке против часовой стрелки, относительно
вектора нормали.
Поскольку файл ASCII STL может быть очень большим, существует двоичная версия этого формата. Такой файл начинается с заголовка из 80 символов
(который обычно игнорируется, но не должен начинаться с solid, так как с этой
последовательности начинается файл ASCII STL). После заголовка идет 4-байтовое
беззнаковое целое число, указывающее количество треугольных граней в данном
файле. После этого идут данные, характеризующие треугольники. Свойства для
нормалей остаются такие же, как и в формате ASCII STL.
Каждый треугольник описывается двенадцатью 32-битными числами с
плавающей точкой: 3 числа для нормали и по 3 числа на каждую из трёх вершин для
координат x, y, z . Далее идут 2 байта беззнакового «short», который называется
attribute byte count.
Пример файла STL двоичного формата приведён на рисунке 22.
Рис. 22 — Пример структуры двоичного файла STL
В работе будет использован формат ASCII STL.
Сформированная ранее модель состоит из четырёхугольников и треугольников. Разобьём на треугольники имеющуюся поверхность. Рассмотрим часть
поверхности, состоящую из конструкции, изображённой на рисунке 20. После
разбиения четырёхугольных граней на треугольники поверхность примет вид,
показанный на рисунке 23.
20
y
W
W1
T1
C
B
x
S1
D
A
S
T
H1
H
Рис. 23 — Элемент трёхмерной модели с замощением его поверхности
треугольниками
После указанного разбиения рассматриваемая часть поверхности представляет собой набор треугольников и подходит для сохранения в формате STL.
Аналогичную операцию проделаем с каждым элементом модели.
Приведённый алгоритм создания 3D-модели реализован в виде программы
на языке Python. Преобразование данных в формат STL производится помощью
библиотеки Numpy-STL [7]. С кодом программы можно ознакомиться в Приложении А.
Интерфейс приложения показан на рисунках 13 и 24. По нажатию кнопки
Save STL Model вызывается функция ModelSTL, выполняющая преобразования
данных модели в формат STL и сохранение полученного файла.
Основными функциями программы являются функции ModelSTL и
CreateParallelogram. ModelSTL принимает на вход набор вершин параллелограммов, осуществляет преобразования координат. Затем для полученного набора
вершин вызывается функция CreateParallelogram, реализующая преобразование
набора вершин в набор призм. Далее осуществляется разбиение призм на треугольники, расчёт нормалей и сохранение модели в формате STL.
21
Рис. 24 — Иллюстрация всплывающего окна при успешном сохранении
STL-модели на компьютер
Модель, полученная в результате работы программы, продемонстрирована
на рисунках 25 и 26.
Рис. 25 — Общий вид созданной модели в интерфейсе программы
MeshLab
22
Рис. 26 — Приближенный вид модели в интерфейсе программы MeshLab
23
Заключение
В результате выполнения выпускной квалификационной работы были решены следующие задачи:
1. Описано движение вершин поверхности, параметризованной длинами сторон параллелограмма, углом α параллелограмма и двугранным углом сгиба
ψ.
2. Смоделирован полученный результат.
3. Разработана трёхмерная модель по полученному результату.
Созданная модель поверхности позволяет наглядно увидеть особенности и
свойства рассмотренного частного случая изгибаемых многогранных поверхностей. Таким образом, цель выпускной квалификационной работы считаю достигнутой.
24
Список литературы
1. Izmestiev, Ivan. (2016). Classification of Flexible Kokotsakis Polyhedra with
Quadrangular Base. International Mathematics. Research Notices. 2017.
10.1093/imrn/rnw055.
2. Nishiyama, Yutaka. (2012). Miura folding: Applying origami to space exploration.
International Journal of Pure and Applied Mathematics. 79. 269-279.
3. Karpenkov, Oleg. (2009). On the flexibility of Kokotsakis meshes. Geometriae
Dedicata. 147. 10.1007/s10711-009-9436-4.
4. Яблокова С.И. Лекции по курсу "Аналитическая геометрия". Часть 1: Учебное
пособие / Яросл. гос. ун-т. Ярославль, 2002. 108 с.
5. Яблокова С.И. Лекции по курсу "Аналитическая геометрия". Часть 2: Учебное
пособие / Яросл. гос. ун-т. Ярославль, 2003. 112 с.
6. Hunter, J. D. Matplotlib: A 2D graphics environment. Computing in Science &
Engineering, 9. 3. 90–95. Matplotlib is a 2D graphics package used for Python
for application development, interactive scripting, and publication-quality image
generation across user interfaces and operating systems. IEEE COMPUTER SOC.
10.1109/MCSE.2007.55. 2007.
7. Библиотека Numpy-STL
numpy-stl/.
2.11.2.
URL:
https://pypi.org/project/
8. The STL Format. URL: http://www.fabbers.com/tech/STL_Format.
25
Приложение А
Исходный код программы на Python
1
%matplotlib qt
2
3
4
# p i p i n s t a l l numpy− s t l
5
6
import numpy as np
8 import matplotlib.pyplot as plt
7
9
from matplotlib.collections import LineCollection
11 from matplotlib import colors as mcolors
12 import mpl_toolkits.mplot3d as plot3d
13 import matplotlib.animation as animation
10
14
15
from matplotlib.widgets import Slider, Button
16
import stl
18 from stl import mesh
17
19
20
from tkinter import Label, messagebox, Tk
21
22
a = 5
24 b = 4
25 Alpha = 45
26 Psi = 120
23
27
#
29 n
30 #
31 m
28
Количество параллелограммов по y
= 8
Количество параллелограммов по x
= 4
32
global slider_a
34 global slider_b
35 global slider_Alpha
33
26
36
global slider_Psi
37
# Точки поверхности
39 polygons1 = list()
40 polygons2 = list()
38
41
# Счетчик количества треугольников в s t l −модели
43 global k
42
44
#
46 e
47 #
48 l
45
Высота прямой призмы
= 1
Ширина раздвижения параллелограммов
= e
49
# Хранилище для набора треугольников s t l −модели
51 data = np.zeros((n * m * 4 * 28), dtype = mesh.Mesh.dtype)
50
52
53
54
def CalkParam(a, b, Alpha, Psi):
55
56
57
58
SinOmega = np.sin(np.radians(Alpha)) * np.sin(
np.radians(Psi / 2))
CosOmega = np.sqrt(1 - np.power(SinOmega, 2))
59
60
61
62
63
A
#
E
#
= [b * CosOmega, -b * SinOmega, 0]
p r i n t ( " Координаты точки А : " , A)
= [b * CosOmega, b * SinOmega, 0]
p r i n t ( " Координаты точки Е : " , E )
64
65
66
CosBeta = np.cos(np.radians(Alpha)) / CosOmega
SinBeta = np.sqrt(1 - np.power(CosBeta, 2))
67
68
69
70
71
72
73
74
75
C
#
F
#
D
#
G
#
= [a * CosBeta, 0, a * SinBeta]
p r i n t ( " Координаты точки С : " , C )
= [C[0] + E[0], C[1] + E[1], C[2] + E[2]]
p r i n t ( " Координаты точки F : " , F )
= [C[0] + A[0], C[1] + A[1], C[2] + A[2]]
p r i n t ( " Координаты точки D: " , D)
= [2 * C[0], 0, 0]
p r i n t ( " Координаты точки G: " , G)
27
76
77
78
79
K
#
L
#
= [F[0] + C[0], F[1] - C[1], F[2] - C[2]]
p r i n t ( " Координаты точки K : " , K )
= [D[0] + C[0], D[1] - C[1], D[2] - C[2]]
p r i n t ( " Координаты точки L : " , L )
80
81
82
83
84
85
86
87
88
lengthAE = np.sqrt(np.power(E[0] - A[0], 2)
+ np.power(E[1] - A[1], 2)
+ np.power(E[2] - A[2], 2))
# p r i n t ( " Сдвиг по y : " , AEdl )
lengthBG = np.sqrt(np.power(G[0], 2)
+ np.power(G[1], 2)
+ np.power(G[2], 2))
# p r i n t ( " Сдвиг по x : " , BGdl )
89
90
return A, E, C, F, D, G, K, L, lengthAE, lengthBG
91
92
93
def Draw(A, E, C, F, D, G, K, L, lengthAE, lengthBG):
94
95
96
polygons1.clear()
polygons2.clear()
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
for i in range(n):
for j in range(m):
polygons1.append([(0 + j * lengthBG,
0 + i * lengthAE, 0),
(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2]),
(D[0] + j * lengthBG,
D[1] + i * lengthAE, D[2]),
(A[0] + j * lengthBG,
A[1] + i * lengthAE, A[2])])
polygons2.append([(E[0] + j * lengthBG,
E[1] + i * lengthAE, E[2]),
(F[0] + j * lengthBG,
F[1] + i * lengthAE, F[2]),
(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2]),
(0 + j * lengthBG,
0 + i * lengthAE, 0)])
28
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
polygons1.append([(F[0] + j * lengthBG,
F[1] + i * lengthAE, F[2]),
(K[0] + j * lengthBG,
K[1] + i * lengthAE, K[2]),
(G[0] + j * lengthBG,
G[1] + i * lengthAE, G[2]),
(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2])])
polygons2.append([(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2]),
(G[0] + j * lengthBG,
G[1] + i * lengthAE, G[2]),
(L[0] + j * lengthBG,
L[1] + i * lengthAE, L[2]),
(D[0] + j * lengthBG,
D[1] + i * lengthAE, D[2])])
132
133
polygonsline = list()
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
for i in range(n):
for j in range(m):
polygonsline.append([(0 + j * lengthBG,
0 + i * lengthAE, 0),
(A[0] + j * lengthBG,
A[1] + i * lengthAE, A[2])])
polygonsline.append([(A[0] + j * lengthBG,
A[1] + i * lengthAE, A[2]),
(D[0] + j * lengthBG,
D[1] + i * lengthAE, D[2])])
polygonsline.append([(D[0] + j * lengthBG,
D[1] + i * lengthAE, D[2]),
(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2])])
polygonsline.append([(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2]),
(0 + j * lengthBG,
0 + i * lengthAE, 0)])
polygonsline.append([(0 + j * lengthBG,
0 + i * lengthAE, 0),
(E[0] + j * lengthBG,
29
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
E[1] + i * lengthAE, E[2])])
polygonsline.append([(E[0] + j * lengthBG,
E[1] + i * lengthAE, E[2]),
(F[0] + j * lengthBG,
F[1] + i * lengthAE, F[2])])
polygonsline.append([(F[0] + j * lengthBG,
F[1] + i * lengthAE, F[2]),
(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2])])
polygonsline.append([(F[0] + j * lengthBG,
F[1] + i * lengthAE, F[2]),
(K[0] + j * lengthBG,
K[1] + i * lengthAE, K[2])])
polygonsline.append([(K[0] + j * lengthBG,
K[1] + i * lengthAE, K[2]),
(G[0] + j * lengthBG,
G[1] + i * lengthAE, G[2])])
polygonsline.append([(C[0] + j * lengthBG,
C[1] + i * lengthAE, C[2]),
(G[0] + j * lengthBG,
G[1] + i * lengthAE, G[2])])
polygonsline.append([(G[0] + j * lengthBG,
G[1] + i * lengthAE, G[2]),
(L[0] + j * lengthBG,
L[1] + i * lengthAE, L[2])])
polygonsline.append([(D[0] + j * lengthBG,
D[1] + i * lengthAE, D[2]),
(L[0] + j * lengthBG,
L[1] + i * lengthAE, L[2])])
185
186
187
188
poly_collection1 = plot3d.art3d.Poly3DCollection(polygons1)
# rgb ( 7 1 , 8 1 , 9 1 ) / 255
poly_collection1.set_color((0.28, 0.32, 0.36, 0.4))
189
190
191
line_collection = plot3d.art3d.Line3DCollection(
polygonsline, colors = ’black’)
192
193
194
195
poly_collection2 = plot3d.art3d.Poly3DCollection(polygons2)
# rgb ( 9 7 , 1 7 9 , 1 7 9 ) / 255
poly_collection2.set_color((0.38, 0.7, 0.7, 0.1))
30
196
197
198
# Отрисовка плоскости в программе
ax = plt.axes(projection=’3d’)
199
200
201
202
ax.add_collection3d(line_collection)
ax.add_collection3d(poly_collection1)
ax.add_collection3d(poly_collection2)
203
204
205
206
ax.set_xlim((0, 45))
ax.set_ylim((-5, 45))
ax.set_zlim((0, 6))
207
208
209
210
ax.set_xlabel(’x’)
ax.set_ylabel(’y’)
ax.set_zlabel(’z’)
211
212
213
214
# Центрирование отображения окна
root = Tk()
root.withdraw()
215
216
217
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
218
219
220
221
222
223
224
225
x_old, y_old, width, height =
plt.get_current_fig_manager().window.geometry()
.getRect()
plt.get_current_fig_manager().window.setGeometry(
(screen_width - width)/2,
(screen_height - height)/2,
width, height)
226
227
228
# Отрисовка поверхности
plt.show()
229
230
# Формирование файла STL для плоскости
232 def ModelSTL(polygons1, polygons2):
231
233
234
polygonsAll = list()
235
31
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# Раздвигаем параллелограммы
p = 0
for i in range(0, n * 2, 2):
for j in range(0, m * 2, 2):
# 1
polygonsAll.append([(polygons1[p][0][0] + j * l,
polygons1[p][0][1] + i * l,
polygons1[p][0][2]),
(polygons1[p][1][0] + j * l,
polygons1[p][1][1] + i * l,
polygons1[p][1][2]),
(polygons1[p][2][0] + j * l,
polygons1[p][2][1] + i * l,
polygons1[p][2][2]),
(polygons1[p][3][0] + j * l,
polygons1[p][3][1] + i * l,
polygons1[p][3][2])])
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# 2
polygonsAll.append([(polygons2[p][0][0] + j
polygons2[p][0][1] + (i
polygons2[p][0][2]),
(polygons2[p][1][0] + j
polygons2[p][1][1] + (i
polygons2[p][1][2]),
(polygons2[p][2][0] + j
polygons2[p][2][1] + (i
polygons2[p][2][2]),
(polygons2[p][3][0] + j
polygons2[p][3][1] + (i
polygons2[p][3][2])])
* l,
+ 1) * l,
* l,
+ 1) * l,
* l,
+ 1) * l,
267
* l,
+ 1) * l,
268
269
270
271
272
273
274
275
# 3
polygonsAll.append([(polygons1[p + 1][0][0]
+ (j + 1) * l,
polygons1[p + 1][0][1]
+ (i + 1) * l,
polygons1[p + 1][0][2]),
(polygons1[p + 1][1][0]
+ (j + 1) * l,
32
polygons1[p + 1][1][1]
+ (i + 1) * l,
polygons1[p + 1][1][2]),
(polygons1[p + 1][2][0]
+ (j + 1) * l,
polygons1[p + 1][2][1]
+ (i + 1) * l,
polygons1[p + 1][2][2]),
(polygons1[p + 1][3][0]
+ (j + 1) * l,
polygons1[p + 1][3][1]
+ (i + 1) * l,
polygons1[p + 1][3][2])])
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# 4
polygonsAll.append([(polygons2[p + 1][0][0]
+ (j + 1) * l,
polygons2[p + 1][0][1] + i
polygons2[p + 1][0][2]),
(polygons2[p + 1][1][0]
+ (j + 1) * l,
polygons2[p + 1][1][1] + i
polygons2[p + 1][1][2]),
(polygons2[p + 1][2][0]
+ (j + 1) * l,
polygons2[p + 1][2][1] + i
polygons2[p + 1][2][2]),
(polygons2[p + 1][3][0]
+ (j + 1) * l,
polygons2[p + 1][3][1] + i
polygons2[p + 1][3][2])])
307
308
p = p + 2
309
310
311
# Создаем элементы трехмерной поверхности
k = 0
312
313
314
for i in range(n * m * 4):
k = CreateParallelogram(polygonsAll[i], k)
315
33
* l,
* l,
* l,
* l,
316
317
# Создаём сетку из треугольников поверхности
coordinatesMesh = mesh.Mesh(data, remove_empty_areas = False)
318
319
320
# Для в с е х треугольников сетки добавляем нормали
coordinatesMesh.normals
321
322
323
# Создаем вектора для доступа к вершинам треугольников
coordinatesMesh.v0, coordinatesMesh.v1, coordinatesMesh.v2
324
325
326
327
328
329
330
331
332
assert (coordinatesMesh.points[0][0:3]
== coordinatesMesh.v0[0]).all()
assert (coordinatesMesh.points[0][3:6]
== coordinatesMesh.v1[0]).all()
assert (coordinatesMesh.points[0][6:9]
== coordinatesMesh.v2[0]).all()
assert (coordinatesMesh.points[1][0:3]
== coordinatesMesh.v0[1]).all()
333
334
335
336
# Сохраняем модель в кодировке ASCII
coordinatesMesh.save(’DiplomModelSTL.stl’,
mode = stl.Mode.ASCII)
337
338
# Моделирование одного элемента трехмерной плоскости
340 def CreateParallelogram(parallelogram, k):
339
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# Сдвиг вниз
parallelogram_down = [(parallelogram[0][0],
parallelogram[0][1],
parallelogram[0][2] - e),
(parallelogram[1][0],
parallelogram[1][1],
parallelogram[1][2] - e),
(parallelogram[2][0],
parallelogram[2][1],
parallelogram[2][2] - e),
(parallelogram[3][0],
parallelogram[3][1],
parallelogram[3][2] - e)]
355
34
356
357
358
359
360
361
362
363
364
365
366
367
368
# Заносим исходный и сдвинутый вниз на е
data[’vectors’][k] = np.array([parallelogram[0],
parallelogram[3],
parallelogram[2]])
data[’vectors’][k + 1] = np.array([parallelogram[0],
parallelogram[2],
parallelogram[1]])
data[’vectors’][k + 2] = np.array([parallelogram_down[0],
parallelogram_down[2],
parallelogram_down[3]])
data[’vectors’][k + 3] = np.array([parallelogram_down[0],
parallelogram_down[1],
parallelogram_down[2]])
369
370
k = k + 4
371
372
373
374
375
376
# Добавление призм по бокам
H = (parallelogram[3][0], parallelogram[3][1] - (l / 2),
parallelogram[3][2] - (e / 2))
H1 = (parallelogram[2][0], parallelogram[2][1] - (l / 2),
parallelogram[2][2] - (e / 2))
377
378
379
380
381
382
data[’vectors’][k] = np.array([H, parallelogram[3],
parallelogram_down[3]])
data[’vectors’][k + 1] = np.array([H1,
parallelogram_down[2],
parallelogram[2]])
383
384
385
386
387
388
data[’vectors’][k + 2] = np.array([H,
parallelogram_down[2], H1])
data[’vectors’][k + 3] = np.array([H,
parallelogram_down[3],
parallelogram_down[2]])
389
390
391
392
393
data[’vectors’][k + 4] = np.array([H1,
parallelogram[3], H])
data[’vectors’][k + 5] = np.array([H1, parallelogram[2],
parallelogram[3]])
394
395
k = k + 6
35
396
397
398
399
400
W = (parallelogram[0][0], parallelogram[0][1] + (l / 2),
parallelogram[0][2] - (e / 2))
W1 = (parallelogram[1][0], parallelogram[1][1] + (l / 2),
parallelogram[1][2] - (e / 2))
401
402
403
404
405
data[’vectors’][k] = np.array([W, parallelogram_down[0],
parallelogram[0]])
data[’vectors’][k + 1] = np.array([W1, parallelogram[1],
parallelogram_down[1]])
406
407
408
409
410
data[’vectors’][k + 2] = np.array([W,
parallelogram[0], W1])
data[’vectors’][k + 3] = np.array([W1, parallelogram[0],
parallelogram[1]])
411
412
413
414
415
416
data[’vectors’][k + 4] = np.array([W1,
parallelogram_down[1], W])
data[’vectors’][k + 5] = np.array([W,
parallelogram_down[1],
parallelogram_down[0]])
417
418
k = k + 6
419
420
421
422
423
S = (parallelogram[2][0] + (l / 2), parallelogram[2][1],
parallelogram[2][2] - (e / 2))
S1 = (parallelogram[1][0] + (l / 2), parallelogram[1][1],
parallelogram[1][2] - (e / 2))
424
425
426
427
428
429
data[’vectors’][k] = np.array([S, parallelogram[2],
parallelogram_down[2]])
data[’vectors’][k + 1] = np.array([S1,
parallelogram_down[1],
parallelogram[1]])
430
431
432
433
434
435
data[’vectors’][k + 2] = np.array([S,
parallelogram_down[2], S1])
data[’vectors’][k + 3] = np.array([S1,
parallelogram_down[2],
parallelogram_down[1]])
36
436
437
438
439
440
data[’vectors’][k + 4] = np.array([S1,
parallelogram[1], S])
data[’vectors’][k + 5] = np.array([S, parallelogram[1],
parallelogram[2]])
441
442
k = k + 6
443
444
445
446
447
T = (parallelogram[3][0] - (l / 2), parallelogram[3][1],
parallelogram[3][2] - (e / 2))
T1 = (parallelogram[0][0] - (l / 2), parallelogram[0][1],
parallelogram[0][2] - (e / 2))
448
449
450
451
452
data[’vectors’][k] = np.array([T, parallelogram_down[3],
parallelogram[3]])
data[’vectors’][k + 1] = np.array([T1, parallelogram[0],
parallelogram_down[0]])
453
454
455
456
457
data[’vectors’][k + 2] = np.array([T,
parallelogram[0], T1])
data[’vectors’][k + 3] = np.array([T, parallelogram[3],
parallelogram[0]])
458
459
460
461
462
463
data[’vectors’][k + 4] = np.array([T1,
parallelogram_down[3], T])
data[’vectors’][k + 5] = np.array([T1,
parallelogram_down[0],
parallelogram_down[3]])
464
465
k = k + 6
466
467
return k
468
469
def SaveSTL(event):
471
ModelSTL(polygons1, polygons2)
470
472
473
474
475
# Создание всплывающего окна " The model i s s a v e d ! "
window = Tk()
x = (window.winfo_screenwidth() - 300) / 2
37
476
477
478
479
480
481
482
483
484
485
486
487
y = (window.winfo_screenheight() - 100) / 2
window.wm_geometry("+%d+%d" % (x, y))
window.title("Information")
window.overrideredirect(1)
window.geometry(’300x100’)
window.configure(background=’#EEF1EF’)
lbl = Label(window, text="The model is saved!",
font=("Arial Bold", 18),
background = ’#EEF1EF’)
lbl.place(x=11,y=28)
window.after(1000, window.destroy)
window.mainloop()
488
489
490
491
492
493
def Reset(event):
slider_a.reset()
slider_b.reset()
slider_Alpha.reset()
slider_Psi.reset()
494
# Кнопка для сохранения трёхмерной модели
496 resetax = plt.axes([0.05, 0.03, 0.2, 0.07])
497 button = Button(resetax, ’Save STL model’, color=’#EEF1EF’,
498
hovercolor=’#AEB9B3’)
495
499
500
button.on_clicked(SaveSTL)
501
# Кнопка , строящая поверхность по изначально заданным параметрам
503 resetaxStart = plt.axes([0.75, 0.03, 0.2, 0.07])
504 buttonStart = Button(resetaxStart, ’Reset’, color=’#EEF1EF’,
505
hovercolor=’#AEB9B3’)
502
506
507
buttonStart.on_clicked(Reset)
508
# Обработка изменений значений слайдеров
510 def onChangeValue(val):
509
511
512
513
514
515
# Атрибут v a l получает значение слайдеров
a = slider_a.val
b = slider_b.val
Alpha = slider_Alpha.val
38
516
Psi = slider_Psi.val
517
518
519
520
A, E, C, F, D, G, K, L, lengthAE, lengthBG
= CalkParam(a, b, Alpha, Psi)
Draw(A, E, C, F, D, G, K, L, lengthAE, lengthBG)
521
# Место для виджетов
523 plt.subplots_adjust(left=0.1, right=0.85, top=0.95, bottom=0.4)
522
524
525
526
527
528
529
530
531
532
533
# a
axes_slider_a = plt.axes([0.1, 0.3, 0.75, 0.02])
slider_a = Slider(axes_slider_a,
label = ’a’,
valmin = 0.0,
valmax = 5.0,
valinit = a,
valfmt = ’%1.2f’,
color = ’#5E7367’)
534
# Событие on_changed отслеживает , что значение слайдера изменилось
536 # Принимает один параметр , который будет новым значением ,
537 # установленным на слайдере
538 slider_a.on_changed(onChangeValue)
535
539
540
541
542
543
544
545
546
547
548
# b
axes_slider_b = plt.axes([0.1, 0.25, 0.75, 0.02])
slider_b = Slider(axes_slider_b,
label = ’b’,
valmin = 0.0,
valmax = 4.0,
valinit = b,
valfmt = ’%1.2f’,
color = ’#5E7367’)
549
550
slider_b.on_changed(onChangeValue)
551
# Alpha
553 axes_slider_Alpha = plt.axes([0.1, 0.20, 0.75, 0.02])
554 slider_Alpha = Slider(axes_slider_Alpha,
555
label = r’$\alpha$’,
552
39
556
557
558
559
560
valmin = 0.0,
valmax = 90.0,
valinit = Alpha,
valfmt = ’%1.2f’,
color = ’#5E7367’)
561
562
slider_Alpha.on_changed(onChangeValue)
563
564
565
566
567
568
569
570
571
572
# Psi
axes_slider_Psi = plt.axes([0.1, 0.15, 0.75, 0.02])
slider_Psi = Slider(axes_slider_Psi,
label = r’$\psi$’,
valmin = 0.0,
valmax = 179.0,
valinit = Psi,
valfmt = ’%1.2f’,
color = ’#5E7367’)
573
574
slider_Psi.on_changed(onChangeValue)
575
A, E, C, F, D, G, K, L, lengthAE, lengthBG
577 = CalkParam(a, b, Alpha, Psi)
578 Draw(A, E, C, F, D, G, K, L, lengthAE, lengthBG)
576
40
Отзывы:
Авторизуйтесь, чтобы оставить отзыв