Лабораторная работа № 7
Ортографические и косоугольные проекции
 
1. Цель работы
 
1) Освоить программирование ортографических и косоугольных проекций трехмерных объектов с использованием методов матричного анализа.
2) Разработать программу в среде визуального проектирования C++Builder, позволяющую демонстрировать ортографические и косоугольные проекции, а также влияние параметров матриц видовых преобразований (переноса, масштабирования, сдвига) на размеры и положение, как самой фигуры, так и её проекций.
3) Освоить программирование изображения объектов в составе локальной системы координат.
 
2.  Постановка задачи
 
2.1. Создать проект программы с использованием пакета C++Builder. Порядок создания проекта и его форм Form1 и Form2 аналогичен их созданию в лабораторной работе №1 (2D-графика).
2.2. В графическом окне Form2 создать локальную систему трехмерных декартовых координат.
2.3. В составе системы координат изобразить прямоугольный параллелепипед (согласно варианту задания из табл.1). Фигура должна задаваться координатами вершин: A(x1, y1, z1), B(x2, y2, z2), C(x3, y3, z3), D(x4, y4, z4), E(x5, y5, z5) и т.д. Исходное положение фигуры - в начале координат (см. рис 1).
2.4. На координатных плоскостях  XOY, YOZ  и  ZOX  локальной системы координат вывести соответствующие изображения проекций фигуры, либо ортографические либо косоугольные. Построить лучи проецирования, связывающие вершины фигуры с одноименными вершинами её проекций (см. рис. 7 и 8).
2.5. Вершины фигуры и координатные оси снабдить буквенными обозначениями.
2.6. Задавая различные значения углов поворотов осей координат, параметров переноса и масштабирования, коэффициента искажения k и углов наклона лучей проецирования  α  и  β  с помощью движков стандартных компонентов TrackBar, продемонстрировать следующие:
1). Ортографическое проецирование фигуры на координатные плоскости XOY, YOZ, ZOX;
2). Косоугольное проецирование Ковалье на плоскости XOY, YOZ, ZOX;
3). Косоугольное проецирование Кабине на плоскости XOY, YOZ, ZOX.
 
                                                                                                                             Таблица 1
Вар.
Исходные размеры фигуры
Цвет
фигуры
Цвет
проекций
ширина
высота
длина
1
4
4
6
красный
розовый
2
3
4
2
синий
голубой
3
4
6
6
зеленый
светло зеленый
4
4
6
2
коричневый
сиреневый
5
6
4
6
черный
серый
6
6
4
2
красный
сиреневый
7
2
3
6
синий
серый
8
6
3
2
зеленый
бирюзовый
9
4
6
3
коричневый
розовый
10
3
6
4
черный
голубой
 
 
 
 
Рисунок 1 – Исходное положение фигуры в локальной системе координат XYZ
 
 
3.  Краткие теоретические сведения
 
3.1. Ортографические проекции
 
Ортографические проекции относятся к классу параллельных проекций, направление лучей проецирования в которых перпендикулярно (ортогонально) плоскости проецирования.
Проецирующие лучи в ортографических проекциях направлены вдоль главных осей координат X, Y, Z. Этот вид проецирования дает плоское изображение объекта в трех направлениях. Он широко используются в черчении, в машиностроительных чертежах, обеспечивая три вида изготавливаемой детали: спереди, сбоку и сверху.
Матрицы ортографических проекций образуются из матрицы трехмерного преобразования общего вида следующим образом. Все элементы строки и столбца, отвечающие за выбранную координату приравниваются к нулю. Оставшиеся элементы главной диагонали приравниваются к единице, а все другие приравниваются к нулю. Построенные по этому правилу матрицы ортографических проекций на плоскости YOZ (X=0), XOZ (Y=0), XOY (Z=0) имеют вид:
 
 
 
Математически преобразование исходных координат объекта в одну из его ортографических проекций производится по формуле:
 
Мисх × Торт = Мрез                                                                           (4)
 
Или в развернутом виде, для ортографического проецирования на плоскость Z=0:
 
 
 
Как видим, ортографическая матрица так влияет на исходную, что в полученной результирующей матрице обнуляется весь третий столбец, т. е.все координаты вершин фигуры по оси Z.
Аналогично, при вычислении координат боковой проекции на плоскость X=0 будет обнуляться первый столбец, т.е. координаты по оси X, а при вычислении координат вида сверху на плоскость Y=0  будет обнуляться второй столбец, т.е. координаты по оси Y. Вследствие этих преобразований получаются абсолютно плоские, двумерные изображения исходной 3-х мерной фигуры, т.е. её проекции.
На рисунке 7 изображено окно разрабатываемой программы, в котором прорисована исходная кубическая фигура и все её ортографические проекции: вид спереди (фронтальная, на Z=0), вид справа (боковая, на X=0) и вид сверху (на Y=0).
 
3.2. Косоугольные проекции
 
Косоугольные проекции - это класс параллельных проекций, включающий в себя два вида: проекцию Ковалье и проекцию Кабине.
Проецирующие лучи в этих проекциях идут под углом к осям координат, благодаря чему ими освещаются сразу три грани трехмерного объекта и поэтому он выглядит на картинной плоскости объемным. Как и в ортографическом проецировании, косоугольные проекции проецируются на главные координатные плоскости: X=0, Y=0, Z=0, [7].
На рисунке 2 показан единичный куб с вершинами A, B, C, D, E, F, G, H и параллельные проецирующие лучи, направленные на него под углом: спереди, снизу и сбоку. Косоугольная проекция единичного куба на плоскости XOY обозначена вершинами A*, B*, C*, D*, E*, F*, G*, H*.
 
 
 
Рисунок 2 - Косоугольная проекция единичного куба на плоскость YOX (Z=0)
 
Как должно быть понятно из рисунка, грани куба (плоскости ABCD и EFGH), параллельные плоскости проецирования XOY при отображении на нее не искажаются, а сохраняют свои истинные размеры, т.е. косоугольные проекции этих граней (A*B*C*D*и E*F*G*H*) эквивалентны их фронтальным ортографическим проекциям. Отличие заключается только в том, что имеет место смещение (трехмерный сдвиг) изображения этих спроектированных граней относительно осей X и Y на определенные значения. И чем дальше конкретная параллельная грань куба отстоит от плоскости отображения XOY, тем больше смещение изображения этой грани относительно осей X и Y. Именно благодаря разной степени смещения различных точек объекта на косоугольной проекции создается эффект объемного изображения. Даже если объект расположен так, что его грани не параллельны плоскости XOY, проецирующие лучи переносят на плоскость XOY совокупность параллельных, смещенных друг относительно друга срезов объекта, что дает аналогичный результат.
Результирующая матрица косоугольного проецирования на плоскость XOY(Z=0) в общем виде имеет вид:
  
                    Трез.кос = Ткос × Торт                                                                             (6)
                             Z=0              Z=0        Z=0

      где:
   Ткос– матрица косоугольного преобразования на Z=0, равная:
 
 
 
Здесь:  α – угол между осью Х  и проекцией проектирующего луча на плоскость XOY (см. рис. 3);
k– коэффициент искажения боковых сторон объекта.
 
После подстановки (7) и (3) в (6), результирующая матрица косоугольного проецирования будет иметь следующий вид:
 
 
 
Коэффициент искажения боковых сторон объекта рассчитывается из соотношения:
 
 
 
Здесь  ОР – исходный отрезок (см. рис. 3);
ОР' – проекция исходного отрезка на плоскость XOY (Z = 0) .
Как видно из рисунка 3, угол  β – это угол между проецирующим лучом и плоскостью XOY.
 
 
  
Рисунок 3 - Косоугольная проекция точки Р на плоскость XOY (Z = 0).
 
Аналогично формируются результирующие матрицы для косоугольного проецирования на плоскости YOZ(X=0) и ZOX(Y=0). Здесь матрицы косоугольного преобразования имеют вид:
 
 
 
На рисунке 4 показано построение проекций на плоскости YOZ(X=0) и ZOX(Y=0).
 
 
 
Рисунок 4 - Схемы построения косоугольных проекций на плоскости YOZ(X=0) и ZOX(Y=0)
 
В проекции Ковалье проектирующие лучи направлены на объект под углом  45о  к плоскости проецирования, т.е.   β = 45о.
Отсюда коэффициент искажения равен:      k = ctgβ = ctg(45 о) = 1
 
Это означает, что длина боковых сторон фигуры в проекции Ковалье равна её истинным размерам.
Угол  α можно задавать любым, но наиболее употребимы значения 30о и 45о или 180о-α.
В результате, матрица преобразования для проекции Ковалье на плоскость Z=0 будет иметь вид:
 
 
 
В проекции Кабине коэффициент искажения ребер принимается равным     k= 0,5.
Это позволяет устранить неестественное утолщение объекта, которое имеет место в проекции Ковалье, тогда:
                                           β = arcctg(0,5) = 63,435о
 
Тогда матрица проекции Кабине  на плоскость Z=0 будет иметь вид:
 
 
 
Аналогичным образом будут различаться между собой проекции Ковалье и Кабине на плоскостях YOZ(X=0) и ZOX(Y=0).
 
3.3. Методы улучшения реалистичности проекций
 
Улучшение реалистичности проекций трехмерных объектов заключается в добавлении в цепочку результирующей матрицы дополнительных матриц видового преобразования, например матриц переноса и масштабирования.
В данной лабораторной работе результирующие матрицы ортографического и косоугольного проецирования на плоскость Z=0 будем составлять по следующим схемам:
 
 
  

4. Интерфейс программы
 
Структура проекта для лабораторных работ по 3D-графике аналогична структуре проекта по 2D-графике. Здесь также необходимо создать главную, запускающую форму Form1 (см. рис.5).
 
 
 
Рисунок 5 – Окно главной формы проекта – Form1
 
Работа лабораторной работы №7 начинается после нажатия на кнопку Lab7 на форме Form1, после чего открывается дополнительная форма Form2, с установленными на ней графическим окном и элементами управления (см. рис. 6).
 
 
 
Рисунок 6 – Окно дополнительной формы Form2 в исходном состоянии
 
Элементы управления расположены справа, на панели Panel1. Перечислим их назначение:
- движок TrackBar1  предназначен для масштабирования фигуры
- движки TrackBar2  и TrackBar3 предназначены для изменения углов поворота системы локальных координат вместе с объектами, находящихся в ней, относительно глобальных осей Y и X;
- движки TrackBar4,  TrackBar5 и TrackBar6 предназначены для перемещения ("переноса") фигуры вдоль локальных осей XY и Z соответственно;
- движок TrackBar7 предназначен для изменения угла наклона α лучей проецирования для косоугольных проекций;
- окна Edit1Edit7 предназначены для отображения (вывода) численных значений параметров   Position компонентов TrackBar, возле которых они расположены;
- окна Edit8 и Edit9, расположенные на панели "Ковалье" предназначены для ввода угла наклона лучей проецирования "Betta" и вывода вычисленного значения коэффициента искажения k;
- окна Edit10 и Edit11, расположенные на панели "Кабине" предназначены для ввода коэффициента искажения k и вывода вычисленного значения угла наклона лучей проецирования "Betta";
- назначение флажков CheckBox1 - CheckBox5 можно понять по поясняющим надписям возле них;
- радиокнопки RadioBatton1 - RadioBatton4 служат для выбора одного из видов проецирования;
- кнопка Button1 ("Преобразовать") предназначена для запуска прорисовки косоугольных проекций.
 
 
 
Рисунок 7 – Изображение 3-х мерной кубической фигуры и её ортографических проекций на плоскости  XOY, YOZ  и  ZOX  локальной системы координат

На рисунке 7 показана форма Form2, в графическом окне которой созданы локальная трехмерная система координат, кубическая фигура и три ортографические проекции этой фигуры на плоскости  XOY, YOZ  и  ZOX.
Также здесь построены лучи проецирования и установлены буквенные обозначения для вершин фигуры. Сама фигура перенесена по осям  X,  Y  и  Z на значения параметров переноса: L=-10m=5n=8.
Локальная система координат и все объекты, находящиеся в ней (фигура, проекции и лучи проецирования) развернуты по осям X  и Y глобальной системы координат на 30 градусов в каждой.
 
 
 
Рисунок 8 – Изображение исходной фигуры и её косоугольной проекции на плоскость XOY (Z=0)
 
На рисунке 8 изображена косоугольная проекция фигуры (проекция Кабине) на плоскость XOY с углом наклона лучей проецирования к оси X равным α=32   и коэффициентом искажения K=0,5.
Угол Betta наклона лучей проецирования к плоскости XOY  вычисляется программно и равен β=63,43.
 
5. СТРУКТУРА ПРОГРАММЫ
 
Общий принцип построения структуры программы аналогичен всем предыдущим лабораторным работам, а именно: создается обработчик события для графического окна, в который помещается конвейер обработки изображения. В состав конвейера вводятся вызовы всех необходимых функций преобразования координат объектов и их прорисовки. Все активные обработчики событий для компонентов управления, установленных на форме, в обязательном порядке снабжаются командой вызова перерисовки графического окна, т.е. командой Repaint().
 
 
  
Рисунок 9 – Структурная схема программы
 
На рисунке 9 изображена структура программы с развернутым содержанием функций IzmOsi(), IzmFig() иIzmPro(), которые предназначены для обработки вершин осей, фигуры и проекций – объектов, подлежащих управляющим воздействиям со стороны пользователя.
Как видим, содержимое функций IzmOsi(), IzmFig() иIzmPro() отличаются только первым компонентом в последовательности обработки координат. Функции вычисления результирующих матриц преобразования в свою очередь зависят от тех задач по преобразованию, которые мы возложим на них.
Например, в преобразование осей будут входить только матрицы вращения осей в двух плоскостях (в соответствии с принципами аксонометрического преобразования) и матрица ортографического проецирования по схеме:

                                                              TrezOs = TvrYOs * TvrXOs * TortZ
 
В преобразование фигуры будут входить матрицы переноса, масштабирования, аксонометрического разворота (вместе с осями) и матрица ортографического проецирования:
 
                                                                    TrezFg = Tper * Tmsb * (TvrYOs * TvrXOs * TortZ)
 
В преобразование проекций будут входить матрицы переноса, масштабирования, косоугольного преобразования (только для косоугольного проецирования), ортографического проецирования на плоскости локальных осей координат, аксонометрического разворота (вместе с осями) и матрица ортографического проецирования на картинную плоскость глобальных осей координат:
- для ортографического проецирования:
 
                                                             TRezPrZ = Tper * Tmsb * TortZ * (TvrYOs * TvrXOs * TortZ)
 
- для косоугольного проецирования:
 
                                                                   TRezPrZ = Tper * Tmsb * Tkos* TortZ * (TvrYOs * TvrXOs * TortZ)
 
 
 
6. СОЗДАНИЕ ПРОЕКТА И ЕГО ФОРМ
 
6.1.  Создание и компоновка главной формы проекта - Form1
 
Порядок создания проекта, его главной формы Form1, и всех его дополнительных форм  Form2, Form3, Form4, Form5, Form6, и т.д. аналогичен порядку создания форм, изложенному в методических указаниях к лабораторной работе №1.
Компоновку формы Form1 выполните в соответствии с рисунком 5.
 
6.2. Компоновка формы Form2
 
Установите элементы управления на поле формы Form2 в соответствии с рисунком 6 со следующими настройками:
 
1). Для компонента TrackBar1 ("Масштаб фигуры"):
- Max = 50;
- Min = 1;
- Position = 10;
 
2). Для компонентов TrackBar2 и TrackBar3 ("Вращение осей"):
- Max = 360;
- Min  =-360;
- Position = 0;
 
3). Для компонентов TrackBar4TrackBar5 и TrackBar6 ("Перенос"):
- Max = 10;
- Min  =-10;
- Position = 0;
 
4). Для компонента TrackBar7, (угол "Alfa") :
- Max = 360;
- Min  =-360;
- Position = 0;
 
5). Для компонента Edit1 ("Масштаб фигуры"):
- Text = 1;
 
6). Для компонентов Edit2  - Edit7:
- Text = 0.
 
7). Для компонентов Edit9 ("K" (Ковалье)) и Edit11 ("Betta" (Кабине)):
- ReadOnly = true.
 
8). Для компонента CheckBox1 ("Показывать оси"):
- State = cbChecked;
 
7.  РАЗРАБОТКА  ФАЙЛА  РЕАЛИЗАЦИИ  Unit2.cpp
 
7.1. Предварительные пояснения
 
Разработку программного кода файла реализации выполним в 6 этапов:
1-й этап – подготовительный – описание и инициализация переменных, создание графического окна;
2-й этап – разработка управляющих функции (запуск главного конвейера и всех прорисовок);
3-й этап – построение осей координат;
4-й этап – построение фигуры;
5-й этап – построение проекций;
6-й этап – построение лучей и обозначений;


1-Й ЭТАП - ПОДГОТОВИТЕЛЬНЫЙ
 
7.2. Объявление переменных и функций
 
Согласно заданным требованиям к работе программы и в соответствии со структурной схемой, изображенной на рисунке 9, сформируем текст программного кода модуля Form2 из следующих функций:
     
- GrafKonv()                                                  - функция запуска главного графического конвейера;
- IzmOsi(), IzmFig(), IzmPro()                   - функции обработки координат осей, фигуры и проекций;
- RezMatrOs(), RezMatrFg(), RezMatrPr() - функции вычисления результирующих матриц преобразования осей, фигуры и проекций;
- MultMatr(), Preobr(), Normir()                - функции обработки матриц координат для всех объектов;
- ShowAll()                                                     - функция запуска всех прорисовок;
- ShowOsi(), ShowFig() ShowPro(), ShowLuthi(), Oboznath() – функции прорисовки осей, фигуры, проекций, лучей проецирования и обозначения вершин;

     Запуск функции GrafKonv(), как уже делалось и в предыдущих работах, будем осуществлять из обработчика PaintBox1(), который должен вызываться командой Repaint() при каждом обращении пользователя к элементам управления (кнопкам. движкам, флажкам и т.п.).
Главный графический конвейер, в свою очередь должен запускать функции обработки координат осей, координат фигуры и координат проекций - IzmOsi(), IzmFig(), IzmPro(), а затем главную функцию прорисовки всех объектов - ShowAll().
Структуры функций IzmOsi(), IzmFig(), IzmPro() практически идентичны. В каждой из них необходимо выполнить по три действия:
1) вызвать функции RezMatrOs(), RezMatrFg() или RezMatrPr() для вычисления результирующих матриц преобразования конкретного объекта с использованием функции MultMatr();
2) вызвать функцию Preobr() для выполнения непосредственного преобразования матрицы координат объекта;
3) вызвать функцию Normir() для нормировки координат объекта;
В лабораторных работах по 2D-графике не было необходимости преобразовывать оси координат. Здесь же нам приходится иметь дело с 3-х мерными осями, и для рассмотрения их в объеме мы применим к ним аксонометрические развороты с использованием движков TrackBar2 и TrackBar3. При каждом перемещении движков этих компонентов необходимо производить пересчет координат осей, т.е. преобразовывать их.
Такие же преобразования придется выполнять и с исходной фигурой и её проекциями, т. к. они находятся внутри этих осей. Кроме аксонометрических преобразований, фигура и её проекции будут подвергаться таким преобразования, как перенос и масштабирование.
Все эти воздействия на оси, фигуру и проекции необходимо ввести в состав результирующих матриц преобразования TrezOs(), TrezFg(), TrezPrX(), TrezPrY(), TrezPrZ(), которые будут использоваться в функции Preobr() для соответствующего изменения координат осей, фигуры или проекций.
Объектами обработки для функций Preobr(), Normir(), а также ShowOsi(), ShowFig() ShowPro(), ShowLuthi() и Oboznath() являются координаты локальных осей X, Y и Z, координаты фигуры ABCDEFGH и координаты её проекций, сгруппированные в матрицы. Координаты этих объектов находятся на различных стадиях обработки, и поэтому они должны быть помещены в отдельные матрицы с различными именами, соответствующими этим стадиям, а именно:
- matrIsxOs[6][4], matrIsxFg[8][4]                                                                                      - матрицы исходных координат осей и фигуры;
- matrIzmOs[6][4], matrIzmFg[8][4], matrIzmPrX[8][4], matrIzmPrY[8][4], matrIzmPrZ[8][4] - матрицы преобразованных координат осей, фигуры и проекций;
- matrOs[6][4], matrFg[8][4], matrPrX[8][4], matrPrY[8][4], matrPrZ[8][4] - матрицы результирующих координат осей, фигуры и проекций после нормировки;
Матрицы исходных координат мы создаем для того, чтобы обеспечить первоначальную прорисовку осей и фигуры, сразу после запуска проекта.
Матрицы преобразованных координат получаются после преобразования исходных координат объектов с помощью результирующих матриц преобразования TrezOs(), TrezFg(), TrezPrX(), TrezPrY(), TrezPrZ().
Как уже говорилось выше, результирующие матрицы преобразования осей, фигуры и проекций будем вычислять в функциях RezMatrOs(), RezMatrFg() и RezMatrPr(). Процесс вычисления этих матриц будет заключаться в последовательном перемножении матриц переноса, масштабирования, вращения, косоугольного и ортографического преобразования.
Кроме трех локальных осей X, Y, Z, фигуры и проекций, на рисунке должны быть изображены лучи проецирования и обозначения вершин, но для их построения вполне достаточно использовать матрицы координат фигуры matrFg[8][4] и её проекций: matrPrX[8][4], matrPrY[8][4] и matrPrZ[8][4].
 
Поэтому, с учетом вышесказанного, в начальной части файла реализации объявим глобально все матрицы координат осей, фигуры, проекций, матрицы их преобразования и прототипы всех используемых функций преобразования и прорисовки изображения, а также все наиболее употребимые переменные в следующем виде:
 
static int W,H,Z,h,i,j,k,nOs;
static float l,m,n,s,km;
static float Q2,F2,k1,k2,alfa,betta;
 
          // Объявления матриц координат осей
static float matrIsxOs[6][4];
static float matrIzmOs[6][4];
static float matrOs[6][4];
          // Объявления матриц координат фигур
static float matrIsxFg[8][4];
static float matrIzmFg[8][4];
static float matrFg[8][4];
          // Объявления матриц координат проекций
static float matrIzmPrX[8][4];
static float matrIzmPrY[8][4];
static float matrIzmPrZ[8][4];
static float matrPrX[8][4];
static float matrPrY[8][4];
static float matrPrZ[8][4];
 
          // Объявления матриц ортографического преобразования
static float TortX[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
static float TortY[4][4]={{1,0,0,0},{0,0,0,0},{0,0,1,0},{0,0,0,1}};
static float TortZ[4][4]={{1,0,0,0},{0,1,0,0},{0,0,0,0},{0,0,0,1}};
 
static float Tper[4][4];   // Матрица переноса
static float Tmsb[4][4];   // Матрица масштабирования
 
static float TkosX[4][4]; // Матрица косоугольного преобраз.на X=0
static float TkosY[4][4]; // Матрица косоугольного преобраз.на Y=0
static float TkosZ[4][4]; // Матрица косоугольного преобраз.на Z=0
 
static float TvrYOs[4][4]; // Матрица вращения относительно оси Y
static float TvrXOs[4][4]; // Матрица вращения относительно оси X
 
          // Объявления результирующих матриц преобразования
static float TrezOs[4][4];
static float TrezFg[4][4];
static float TrezPrZ[4][4];
static float TrezPrX[4][4];
static float TrezPrY[4][4];
 
         // Прототипы функций преобразования объектов
static void GrafKonv(void);
static void IzmOsi(void);
static void IzmFig(void);
static void IzmPro(void);
 
         // Прототипы функций вычисления результирующих матриц
static void RezMatrOs(void);
static void RezMatrFg(void);
static void RezMatrPr(void);
 
         // Прототипы функций вычисления и преобразования координат объектов
static void MultMatr(float Matr1[4][4],float Matr2[4][4],float Matr3[4][4]);
static void Preobr(int rows,float MatrIsx[][4],float MatrRez[4][4],float MatrIzm[][4]);
static void Normir(int rows, float MatrIzm[][4],float MatrTek[][4]);
 
         // Прототипы функций прорисовки объектов
static void ShowAll(void);
static void ShowOsi(void);
static void ShowFig(void);
static void ShowPro(float matrPr[8][4]);
static void ShowLuthi(float matrPr[8][4]);
static void Oboznath(void);
 
7.3. Разработка функции инициализации исходных данных FormCreate()
 
Создайте обработчик события FormCreate для формы Form2 аналогично тому, как это делалось в предыдущих работах. Эта функция должна обеспечивать следующее:
- инициализацию размеров графического окна;
- инициализацию параметров матриц переноса, масштабирования, косоугольного проецирования;
- инициализацию параметров осей:  nOs и h;
- инициализацию матриц исходных координат:  matrIsxOs[6][4]   и matrIsxFg[8][4];
- инициализацию матриц видовых преобразований:  Tper[4][4], Tmsb[4][4], Tkos[4][4];
- инициализацию матриц поворота осей координат:  TvrYOs[4][4], TvrXOs[4][4].
 
С учетом этого текст программного кода функции будет иметь вид:
 
void __fastcall TForm2::FormCreate(TObject *Sender)
{
 W=PaintBox1->Width;
 H=PaintBox1->Height;
 
 k2=3.1415926536/180;
 l=0;
 m=0;
 n=0;
 s=1;
 alfa=0;
 nOs=10;
 h=W/(2*(nOs+1));
 
 matrIsxOs[0][0]=-nOs; matrIsxOs[0][1]=0; matrIsxOs[0][2]=0; matrIsxOs[0][3]=1;
 matrIsxOs[1][0]= nOs; matrIsxOs[1][1]=0; matrIsxOs[1][2]=0; matrIsxOs[1][3]=1;
 matrIsxOs[2][0]=0; matrIsxOs[2][1]=-nOs; matrIsxOs[2][2]=0; matrIsxOs[2][3]=1;
 matrIsxOs[3][0]=0; matrIsxOs[3][1]= nOs; matrIsxOs[3][2]=0; matrIsxOs[3][3]=1;
 matrIsxOs[4][0]=0; matrIsxOs[4][1]=0; matrIsxOs[4][2]=-nOs; matrIsxOs[4][3]=1;
 matrIsxOs[5][0]=0; matrIsxOs[5][1]=0; matrIsxOs[5][2]= nOs; matrIsxOs[5][3]=1;
 
 matrIsxFg[0][0]=0; matrIsxFg[0][1]=0; matrIsxFg[0][2]=0; matrIsxFg[0][3]=1;
 matrIsxFg[1][0]=0; matrIsxFg[1][1]=4; matrIsxFg[1][2]=0; matrIsxFg[1][3]=1;
 matrIsxFg[2][0]=4; matrIsxFg[2][1]=4; matrIsxFg[2][2]=0; matrIsxFg[2][3]=1;
 matrIsxFg[3][0]=4; matrIsxFg[3][1]=0; matrIsxFg[3][2]=0; matrIsxFg[3][3]=1;
 matrIsxFg[4][0]=0; matrIsxFg[4][1]=0; matrIsxFg[4][2]=4; matrIsxFg[4][3]=1;
 matrIsxFg[5][0]=0; matrIsxFg[5][1]=4; matrIsxFg[5][2]=4; matrIsxFg[5][3]=1;
 matrIsxFg[6][0]=4; matrIsxFg[6][1]=4; matrIsxFg[6][2]=4; matrIsxFg[6][3]=1;
 matrIsxFg[7][0]=4; matrIsxFg[7][1]=0; matrIsxFg[7][2]=4; matrIsxFg[7][3]=1;
 
 Tper[0][0]=1; Tper[0][1]=0; Tper[0][2]=0; Tper[0][3]=0;
 Tper[1][0]=0; Tper[1][1]=1; Tper[1][2]=0; Tper[1][3]=0;
 Tper[2][0]=0; Tper[2][1]=0; Tper[2][2]=1; Tper[2][3]=0;
 Tper[3][0]=l; Tper[3][1]=m; Tper[3][2]=n; Tper[3][3]=1;
 
 Tmsb[0][0]=1; Tmsb[0][1]=0; Tmsb[0][2]=0; Tmsb[0][3]=0;
 Tmsb[1][0]=0; Tmsb[1][1]=1; Tmsb[1][2]=0; Tmsb[1][3]=0;
 Tmsb[2][0]=0; Tmsb[2][1]=0; Tmsb[2][2]=1; Tmsb[2][3]=0;
 Tmsb[3][0]=0; Tmsb[3][1]=0; Tmsb[3][2]=0; Tmsb[3][3]=s;
 
TkosZ[0][0]=1;              TkosZ[0][1]=0;              TkosZ[0][2]=0;TkosZ[0][3]=0;
TkosZ[1][0]=0;              TkosZ[1][1]=1;              TkosZ[1][2]=0;TkosZ[1][3]=0;
TkosZ[2][0]=k1*cos(k2*alfa);TkosZ[2][1]=k1*sin(k2*alfa);TkosZ[2][2]=1;TkosZ[2][3]=0;
TkosZ[3][0]=0;              TkosZ[3][1]=0;              TkosZ[3][2]=0;TkosZ[3][3]=1;
 
TkosX[0][0]=1;TkosX[0][1]=k1*sin(k2*alfa);TkosX[0][2]=k1*cos(k2*alfa);TkosX[0][3]=0;
TkosX[1][0]=0;TkosX[1][1]=1;              TkosX[1][2]=0;              TkosX[1][3]=0;
TkosX[2][0]=0;TkosX[2][1]=0;              TkosX[2][2]=1;              TkosX[2][3]=0;
TkosX[3][0]=0;TkosX[3][1]=0;              TkosX[3][2]=0;              TkosX[3][3]=1;
 
TkosY[0][0]=1;              TkosY[0][1]=0;TkosY[0][2]=0;              TkosY[0][3]=0;
TkosY[1][0]=k1*sin(k2*alfa);TkosY[1][1]=1;TkosY[1][2]=k1*cos(k2*alfa);TkosY[1][3]=0;
TkosY[2][0]=0;              TkosY[2][1]=0;TkosY[2][2]=1;              TkosY[2][3]=0;
TkosY[3][0]=0;              TkosY[3][1]=0;TkosY[3][2]=0;              TkosY[3][3]=1;
 
 Q2=0;
 F2=0;
 Form8->Edit1->Text=FloatToStr(Q2);
 Form8->Edit2->Text=FloatToStr(F2);
 
TvrYOs[0][0]=cos(k2*Q2);TvrYOs[0][1]=0; TvrYOs[0][2]=-sin(k2*Q2);TvrYOs[0][3]=0;
TvrYOs[1][0]=0;         TvrYOs[1][1]=1; TvrYOs[1][2]=0;          TvrYOs[1][3]=0;
TvrYOs[2][0]=sin(k2*Q2);TvrYOs[2][1]=0; TvrYOs[2][2]= cos(k2*Q2);TvrYOs[2][3]=0;
TvrYOs[3][0]=0;         TvrYOs[3][1]=0; TvrYOs[3][2]=0;          TvrYOs[3][3]=1;
 
TvrXOs[0][0]=1;TvrXOs[0][1]= 0;         TvrXOs[0][2]=0;          TvrXOs[0][3]=0;
TvrXOs[1][0]=0;TvrXOs[1][1]= cos(k2*F2);TvrXOs[1][2]=sin(k2*F2); TvrXOs[1][3]=0;
TvrXOs[2][0]=0;TvrXOs[2][1]=-sin(k2*F2);TvrXOs[2][2]=cos(k2*F2); TvrXOs[2][3]=0;
TvrXOs[3][0]=0;TvrXOs[3][1]= 0;         TvrXOs[3][2]=0;          TvrXOs[3][3]=1;
}
 
Прежде чем запустить программу для проверки, добавьте команды подключения следующих библиотек:
#include <math.h>
#include <Math.hpp>
Это необходимо для того, чтобы работали команды вычисления тригонометрических функций.
 
7.4. Создание  обработчика события для  PaintBox1
 
Создайте обработчик для графического окна, т.е. для компонента PaintBox1  (см. л.р. №1).
Впишите в него команды формирования белого фона канвы графического окна и запуска графического конвейера. Тогда текст функции будет иметь следующий вид:
 
void __fastcall TForm2::PaintBox1Paint(TObject *Sender)
{
 FPC->Brush->Style=bsSolid;
 FPC->Brush->Color=clWhite;
 FPC->Rectangle(Rect(0,0,W,H));
 
 GrafKonv();
}
Напоминаем, что FPC это макрос, который здесь вводится для уменьшения длины цепочки типа Form2->PaintBox1->Canvas. Поэтому, в начальной части программы введите запись:
 
#defineFPCForm2->PaintBox1->Canvas
 
Временно закомментируйте вызов функции GrafKonv() и запустите проект для проверки. В результате программа должна вывести пустое белое графическое окно.
 
2-Й ЭТАП – РАЗРАБОТКА УПРАВЛЯЮЩИХ ФУНКЦИЙ
 
7.5. Разработка графического конвейера GrafKonv()
 
Эта функция должна содержать команды, позволяющие выполнять пересчет координат осей, фигуры и проекций, а также перерисовку этих объектов с новыми координатами. Её программный код будет иметь вид:
void GrafKonv(void)
{
 IzmOsi();
 IzmFig();
 IzmPro();
 ShowAll();
}
 
Перед запуском проекта для проверки временно заглушите вызовы функций  IzmOsi()IzmFig()IzmPro() и ShowAll(). Далее, будем последовательно создавать описания этих функций и последовательно снимать заглушки с их вызовов.
 
7.6. Разработка функции прорисовки  всех объектов - ShowAll()
 
Функция ShowAll() содержит команды вызова функций, выполняющих прорисовку осей координат - ShowOsi(), фигуры - ShowFig() , её проекций ShowPro() на плоскости XOY, YOZ и ZOX,  лучей проецирования ShowLuthi() и обозначения вершин фигуры -Oboznath() . При этом должна производиться проверка состояния флажков, установленных на панели Panel1.
Как уже упоминалось ранее, порядок вызова функций прорисовки определяется степенью важности объекта для всего изображения. Сначала рисуются менее важные, затем более важные, чтобы те объекты, которые прорисованы позднее, не зарисовывали предыдущие. Тогда текст функции ShowAll() будет иметь вид:
 
voidShowAll(void)
{
 if(Form2->CheckBox1->Checked)     // Если 1-й флажок включен,
     ShowOsi();                    //  рисуем оси координат
 
 if(Form2->CheckBox3->Checked)     // Если 3-й флажок включен,
    {ShowLuthi(matrPrZ);           //  рисуем лучи проецирования на Z=0,
     ShowPro(matrPrZ);             //  рисуем проекцию на Z=0
    }
 if(Form2->CheckBox4->Checked)     // Если 4-й флажок включен,
    {ShowLuthi(matrPrX);           //  рисуем лучи проецирования на X=0,
     ShowPro(matrPrX);             //  рисуем проекцию на X=0
    }
 if(Form2->CheckBox5->Checked)     // Если 5-й флажок включен,
    {ShowLuthi(matrPrY);           //  рисуем лучи проецирования на Y=0,
     ShowPro(matrPrY);             //  рисуем проекцию на Y=0
    }
 
 if(Form2->CheckBox2->Checked)     // Если 2-й флажок включен,
     Oboznath();                   //  рисуем обозначения вершин фигуры
 
   ShowFig();                      // рисуем заданную фигуру
}
 
Чтобы можно было продолжать формировать текст программы и выполнять отладку её функций, временно закомментируйте (т.е. заглушите) здесь все команды. Снимите заглушку с вызова ShowAll() в тексте функции GrafKonv() и запустите проект для проверки. В дальнейшем, при добавлении в текст программы описаний вызываемых в ShowAll() функций, заглушки можно последовательно снимать.
 
3-й этап – построение осей координат
 
7.7. Порядок построения осей
 
Построение локальных осей координат состоит из двух основных этапов:
- пересчета координат осей;
- прорисовки осей.
Для пересчета координат осей необходимо выполнить следующее:
1) создать запускающую функцию  IzmOsi() , которая бы обеспечивала последовательный запуск следующих функций:
- функцию вычисления результирующей матрицы преобразования осей  RezMatrOs();
- функцию преобразования координат осей Preobr();
- функцию нормировки координат осей Normir().
2) поместить вызов функции IzmOsi()  в состав графического конвейера, что и было сделано раннее.
Функция вычисления результирующей матрицы RezMatrOs() в свою очередь, будет запускать несколько раз подряд функцию перемножения матриц MultMatr(), в зависимости от вида преобразования.
Кроме вышеперечисленных функций, обеспечивающих пересчет координат осей, нам необходимо создать обработчики событий, с помощью которых будут вводиться углы поворотов осей:
- обработчик события TrackBar2 – для ввода угла θ поворота по оси Y в матрицу вращения;
- обработчик события TrackBar3 – для ввода угла φ поворота по оси X в матрицу вращения.
Для прорисовки осей разработаем функцию ShowOsi(), вызов которой поместим, совместно с остальными функциями прорисовки, в функции ShowAll() (см. п.7.6).
 
7.8. Функция обработки  координат  осей IzmOsi()
 
Как уже говорилось выше, функция IzmOsi() должна обеспечить последовательный запуск следующих функций: функции вычисления результирующей матрицы преобразования  RezMatrOs(), функции преобразования координат осей Preobr() и функции нормировки координат осей Normir():
 
void IzmOsi(void)
{
 RezMatrOs();                          // Вычисление матрицы преобраз.осей
 Preobr(6,matrIsxOs,TrezOs,matrIzmOs); // Преобразование координат осей
 Normir(6,matrIzmOs,matrTekOs);        // Нормировка координат осей
 }
Снимите заглушку с вызова этой функции в GrafKonv() , закомментируйте не созданные ещё функции и запустите проект на исполнение для проверки на отсутствие ошибок.
 
7.9. Разработка функции вычисления результирующей матрицы - RezMatrOs()
 
Результирующая матрица создается в результате перемножения нескольких матриц, каждая из которых отвечает за определенный вид базовых преобразований.
Преобразование локальных осей X, Y и Z будет заключаться в развороте их сначала по оси Y, а затем по оси X  глобальной системы координат. Это даст возможность увидеть третью ось Z. Вместе с осями необходимо разворачивать и все объекты, находящиеся в этой системе. Обычно, на двумерной картинной плоскости ось Z не видна, так как она направлена на зрителя перпендикулярно, а её собственная проекция сведена в точку. Чтобы увидеть её, а также заодно и реальный объем объектов, находящихся в локальной системе координат, мы и применим здесь аксонометрическое преобразование осей X, Y и Z. Более подробно аксонометрические проекции будут рассмотрены в лаб.раб. 8.
Напомним, что под глобальной системой координат понимается система координат картинной плоскости экрана монитора. На эту двумерную систему координат мы будем проецировать вторую, трехмерную, локальную систему координат, а также все объекты, находящиеся внутри этой системы.
С учетом вышесказанного, структура результирующей матрицы осей TrezOs  будет строиться по схеме:

TrezOs = TvrYOs * TvrXOs * TortZ
 
Здесь матрицы вращения  TvrYOs  и  TvrXOs,  проинициализированные сначала при запуске в FormCreate, а затем в обработчиках  TrackBar2  и  TrackBar3,  обеспечивают аксонометрический разворот локальных осей относительно глобальных осей X  и Y.
 
Ортогональная матрица TortZ обеспечивает фронтальное проецирование локальных осей координат на картинную плоскость  XOY глобальной системы координат.
Для получения результирующей матрицы в этой функции необходимо выполнить перемножение матриц видовых преобразований с использованием функции MultMatr(). Тогда программный код функции RezMatrOs(), позволяющей реализовать это уравнение, будет имеет вид:
 
void RezMatrOs(void)
{
 float T1[4][4];
 
 MultMatr(TvrYOs,TvrXOs,T1);
 MultMatr(T1,TortZ,TrezOs);
}
 
Результирующая матрица преобразования осей TrezOs[4][4]  вычисленная здесь, будет использоваться далее во всех функциях вычисления результирующих матриц остальных объектов: фигуры и проекций.
 
Примечание 1. Никогда не путайте последовательность перемножения матриц вращения. Матрицы координат объектов всегда сначала поворачивают по оси Y,  а затем по оси X, но не наоборот. Это правило относится к правосторонним системам координат. Для левосторонних систем последовательность меняется на обратную.
 
7.10. Разработка функции перемножения матриц - MultMatr()
 
В связи с тем, что перемножения матриц в этой лабораторной работе придется применять более 10 раз, создадим универсальную функцию перемножения матриц видового преобразования следующего вида:
 
void MultMatr(float Matr1[4][4],float Matr2[4][4],float Matr3[4][4])
{
 float Sum;
 for(i=0;i<4;i++)
 {for(j=0;j<4;j++)
   {Sum=0;
    for(k=0;k<4;k++)
        Sum=Sum+Matr1[i][k]* Matr2[k][j];
    Matr3[i][j]=Sum;
   }
 }
}
 
В качестве формальных параметров в заголовке этой функции подразумеваются имена двух перемножаемых и результирующей матриц преобразования.
 
7.11. Разработка функции преобразования осей Preobr()
 
Преобразование любого графического объекта заключается в преобразовании его матрицы исходных координат в матрицу преобразованных координат с помощью результирующей матрицы видового преобразования. Для преобразования осей можно написать такое уравнение:
 
matrIsxOs * TrezOs = matrIzmOs
 
Матрица исходных координат осей заранее проинициализирована в функции FormCreate . Матрица сформирована их шести строк: в первой строке задаются координаты начала оси X, во второй строке задаются координаты конца оси X, в третьей и четвертой строках задаются координаты начала и конца оси Y, и пятой и шестой – соответствующие координаты оси Z. Значения координат задаются в виде отсчетов, которые переводятся в экранные координаты (т.е. в пиксели) только при прорисовке осей. Исходное количество отсчетов на каждую полуось задается в FormCreate в виде  nOs = 10.
После преобразования матрицу координат необходимо отнормировать, затем можно выполнять прорисовку осей.
Текст программного кода этой функции будет иметь вид:
 
void Preobr(int rows,float MatrIsx[][4],float MatrRez[4][4],float MatrIzm[][4])
{
 float Sum;
 for(i=0;i<rows;i++)
 {for(j=0;j<4;j++)
   {Sum=0;
    for(k=0;k<4;k++)
        Sum=Sum+MatrIsx[i][k]* MatrRez[k][j];
    MatrIzm[i][j]=Sum;
   }
 }
}
 
Эта функция пригодна не только для преобразования осей, но и для фигуры и для проекций и т.д.
В качестве фактических параметров в заголовке этой функции указаны имена перемножаемых и результирующих матриц, а также количество строк rows перемножаемых матриц.
 
7.12. Разработка функции нормировки осей координат Normir()
 
Функция Normir() аналогична функции Normir(), используемой в лабораторной работе №2, за той лишь разницей, что эту функцию мы также сделаем универсальной:
 
void Normir(int rows, float MatrIzm[][4],float MatrTek[][4])
{
 for(int i=0;i<rows;i++)
    for(int j=0;j<4;j++)
      {if(MatrIzm[i][3]!=1)
         {if(MatrIzm[i][3]==0)
             MatrIzm[i][3]=0.001;
          MatrTek[i][j]=MatrIzm[i][j]/MatrIzm[i][3];
         }
       else MatrTek[i][j]=MatrIzm[i][j];
      }
 }
В качестве фактических параметров в заголовке этой функции указаны имена нормируемых и отнормированных матриц координат объектов, а также количество строк rows у обрабатываемых матриц.
 
7.13. Создание обработчиков событий для движков TrackBar2 и TrackBar3
 
Движки TrackBar2 и TrackBar3 предназначены для ввода значений углов поворота локальной системы координат X, Y и Z относительно двумерной глобальной системы картинной плоскости. Рассмотрим пример программного кода для TrackBar2:
 
void __fastcall TForm2::TrackBar2Change(TObject *Sender)
{
 Q2 =(Form2->TrackBar2->Position);
 Form2->Edit2->Text=FloatToStr(Q2);
 
TvrYOs[0][0]=cos(k2*Q2); TvrYOs[0][1]=0; TvrYOs[0][2]=-sin(k2*Q2); TvrYOs[0][3]=0;
TvrYOs[1][0]=0;          TvrYOs[1][1]=1; TvrYOs[1][2]=0;           TvrYOs[1][3]=0;
TvrYOs[2][0]=sin(k2*Q2); TvrYOs[2][1]=0; TvrYOs[2][2]= cos(k2*Q2); TvrYOs[2][3]=0;
TvrYOs[3][0]=0;          TvrYOs[3][1]=0; TvrYOs[3][2]=0;           TvrYOs[3][3]=1;
 
 Repaint();
}
 
Здесь мы сначала считываем значение позиции движка в переменную Q2. Затем выводим значение Q2 в окошко Edit2, для осуществления контроля над вводом данных при перемещении движка.
Далее, выполняем перерасчет параметров матрицы преобразования, реализующей вращение системы координат по оси Y. Здесь переменная k2 служит для перевода угла поворота Q2, задаваемого в градусах, в радианы. Переменная k2 была объявлена глобально и проинициализирована в FormCreate.
Команда Repaint() в этом обработчике запускает перерисовку графического окна.
Обработчик события для TrackBar3 создайте самостоятельно. Там будут только три изменения: вместо угла Q2 надо использовать угол поворота вокруг оси X - F2, вместо матрицы TvrYOs[6][4] использовать матрицу TvrXOs[6][4], а  Edit2  заменить на Edit3.
 
Запустите программу на исполнение и проверьте правильность отображения углов в окошках Edit.
 
7.14. Разработка функций прорисовки осей координат ShowOsi()
 
Текст программного кода этой функции имеет вид:
 
void ShowOsi(void)
{
 FPC->Pen->Style=psSolid;               // Устанавливаем свойства пера
 FPC->Pen->Color=clBlack;
 
  // рисуем осьХ
 FPC->MoveTo(W/2+int(h*matrTekOs[0][0]), H/2-int(h*matrTekOs[0][1]));
 FPC->LineTo(W/2+int(h*matrTekOs[1][0]), H/2-int(h*matrTekOs[1][1]));
 // рисуем ось Y
 FPC->MoveTo(W/2+int(h*matrTekOs[2][0]), H/2-int(h*matrTekOs[2][1]));
 FPC->LineTo(W/2+int(h*matrTekOs[3][0]), H/2-int(h*matrTekOs[3][1]));
 // рисуем ось Z
 FPC->MoveTo(W/2+int(h*matrTekOs[4][0]), H/2-int(h*matrTekOs[4][1]));
 FPC->LineTo(W/2+int(h*matrTekOs[5][0]), H/2-int(h*matrTekOs[5][1]));
 
 // устанавливаем обозначения осей:
 
FPC->TextOut(W/2+int(h* matrTekOs[1][0]),
              H/2-int(h* matrTekOs[1][1])-20,"X");
 
 FPC->TextOut(W/2+int(h* matrTekOs[3][0])+10,
              H/2-int(h* matrTekOs[3][1]),"Y");
 
 FPC->TextOut(W/2+int(h* matrTekOs[5][0]),
              H/2-int(h* matrTekOs[5][1])-20,"Z");
}
 
Как видим, здесь выполняется перевод численных значений координат осей в экранные сразу, в составе команд прорисовки MoveTo и  LineTo.
Переменная h - цена деления отсчетов осей.
Кроме команд, приведенных здесь, вы можете самостоятельно написать команды прорисовки стрелок на концах каждой из осей. Для этого необходимо в матрицу координат осей добавить дополнительные строки с координатами стрелок и выполнять преобразования стрелок совместно с осями.
 
На этом разработка функций построения трехмерной системы координат в графическом окне закончена.
Снимите все заглушки, имеющие отношение к преобразованию и прорисовке осей и запустите программу на исполнение для проверки работы движков TrackBar2 и  TrackBar3 по развороту осей в разные стороны и в разных плоскостях.
 
4-й этап – построение ФИГУРЫ
 
7.15. Порядок построения фигуры
 
Порядок построения фигуры полностью совпадает с порядком построения осей:
- создадим запускающую функцию  IzmFig(), для обеспечения конвейерного запуска следующих функций: функции вычисления результирующей матрицы преобразования  RezMatrFg(), функции преобразования координат фигуры Preobr() и функции нормировки координат фигуры Normir();
- поместим вызов функции IzmFig() в главный конвейер;
- создадим функцию вычисления результирующей матрицы  RezMatrFg();
- создадим функцию ShowFg() для прорисовки фигуры с использованием отнормированных текущих координат фигуры.
- создадим обработчики для компонентов:
- обработчик события TrackBar1 – для масштабирования фигуры;
- обработчик события TrackBar4 – для переноса фигуры вдоль оси X;
- обработчик события TrackBar5 – для переноса фигуры вдоль оси Y;
- обработчик события TrackBar6 – для переноса фигуры вдоль оси Z.
 
7.16. Функция обработки  координат фигуры IzmFig()
 
Функция обработки координат фигуры должна обеспечить последовательный запуск функции вычисления результирующей матрицы преобразования  RezMatrFg(), функции преобразования координат фигуры Preobr() и функции нормировки координат фигуры Normir():
 
void IzmFig(void)
{
 RezMatrFg();                          // Вычисл.рез.матрицы преобраз. фиг.
 Preobr(8,matrIsxFg,TrezFg,matrIzmFg); // Преобразование координат фигуры
 Normir(8,matrIzmFg,matrTekFg);        // Нормировка координат фигуры
}
 
В этом тексте две последние функции: Preobr() и Normir() уже созданы при построении осей, и здесь достаточно выполнить их вызов с необходимыми параметрами.
 
7.17. Разработка функции вычисления результирующей матрицы RezMatrFg()
 
Структура результирующей матрицы преобразования фигуры TrezFg строится по схеме:
 
                                                                TrezFg = Tper * Tmsb * (TvrYOs * TvrXOs * TortZ)
 
Первые две матрицы обеспечивают перенос и масштабирование фигуры. Следующие две матрицы вращения отвечают за аксонометрический разворот фигуры вместе с локальными осями координат. Последняя ортографическая матрица служит для проецирования преобразованной фигуры на глобальную плоскость Z=0.
Здесь произведение последних трех матриц уже вычислено в функции RezMatrOs() в матрице TrezOs, поэтому структуру результирующей матрицы можно упростить:
 
                                                                 TrezFg = Tper * Tmsb * TrezOs
 
Тогда текст функции будет иметь вид:
 
void RezMatrFg(void)
{
 float T1[4][4];
 
 MultMatr(Tper, Tmsb, T1);            // 1-я промежуточн. матр. преобр.фиг.
 MultMatr(T1, TrezOs, TrezFg);        // Результирующая матрица преобр.фиг.
}
 
Используемые здесь функции MultMatr() уже созданы при построении осей, и здесь достаточно выполнить их вызов с необходимыми параметрами.
 
7.18. Создание обработчика событий для движка TrackBar1
 
Движок TrackBar1  предназначен для масштабирования размеров фигуры и её проекций с использование параметра масштабирования s. Рассмотрим пример программного кода для TrackBar1:
 
void __fastcall TForm2::TrackBar1Change(TObject *Sender)
{
 km=0.1;
 s=km*(Form2->TrackBar1->Position);
 Form2->Edit1->Text=FloatToStr(1/s);
 Tmsb[3][3]=s;
 
 Repaint();
}
Здесь мы сначала считываем значение позиции движка в переменную s, которая отвечает за масштабирование фигуры относительно центра координат. Затем выводим это же самое значение в окошко Edit1, для осуществления контроля над вводом данных при перемещении движка.
Далее, вводим считанное значение масштабирования в ячейку матрицы масштабирования Tmsb[3][3].
Вспомогательная переменная km вводится для удобства масштабирования с помощью движка, т. к. компонент TrackBar1 не позволяет устанавливать параметр Position в промежутке от 0 до 1.
Команда Repaint() выполняет перерисовку графического окна.
 
Запустите программу на исполнение и проверьте работу движков на наличие параметра масштабирования в окошке Edit1.
 
7.19. Создание обработчиков событий для движков
TrackBarTrackBar5 и TrackBar6
 
Движки TrackBar4,  TrackBar5  и TrackBar6 предназначены для перемещения ("переноса") фигуры вдоль осей  XY и Z соответственно. Рассмотрим пример программного кода для TrackBar4:
 
void __fastcall TForm2::TrackBar4Change(TObject *Sender)
{
 l=(Form2->TrackBar4->Position);
 Form2->Edit4->Text=FloatToStr(l);
 Tper[3][0]=l;
 
 Repaint();
}
Здесь мы сначала считываем значение позиции движка в переменную l (это не единица, а L), которая отвечает за перенос вдоль оси X. Затем выводим это же самое значение в окошко Edit4, для осуществления контроля над вводом данных при перемещении движка.
Далее, вводим считанное значение переноса в ячейку матрицы переноса Tper[3][0].
Обработчики событий для TrackBar5 и TrackBar6 создайте самостоятельно. Там будут три отличия: вместо параметра l надо использовать параметры m  или n,  а вместо ячейки матрицы Tper[3][0] использовать ячейки матриц Tper[3][1] и Tper[3][2] соответственно. Измените также номер окошка Edit в соответствии с установленными на форме.
 
Запустите программу на исполнение и проверьте работу движков на наличие параметров переноса в окошках Edit. Перенос фигуры, пока не разработана функция её прорисовки, мы еще не увидим.
 
7.20. Разработка функций прорисовки фигуры ShowFig()
 
Текст программного кода этой функции имеет вид:
 
void ShowFig(void)
{
 FPC->Pen->Style=psSolid; // Устанавливаем свойства пера
 FPC->Pen->Width=2;
 FPC->Pen->Color=clBlue;
                     //рисуем линию AB
 FPC->MoveTo(W/2+int(h* matrTekFg[0][0]), H/2-int(h* matrTekFg[0][1]));
 FPC->LineTo(W/2+int(h* matrTekFg[1][0]), H/2-int(h* matrTekFg[1][1]));
                    //рисуем линию BC
 FPC->MoveTo(W/2+int(h* matrTekFg[1][0]), H/2-int(h* matrTekFg[1][1]));
 FPC->LineTo(W/2+int(h* matrTekFg[2][0]), H/2-int(h* matrTekFg[2][1]));
                    //рисуем линию CD
 FPC->MoveTo(W/2+int(h* matrTekFg[2][0]), H/2-int(h* matrTekFg[2][1]));
 FPC->LineTo(W/2+int(h* matrTekFg[3][0]), H/2-int(h* matrTekFg[3][1]));
                   //рисуем линию DA
 FPC->MoveTo(W/2+int(h* matrTekFg[3][0]), H/2-int(h* matrTekFg[3][1]));
 FPC->LineTo(W/2+int(h* matrTekFg[0][0]), H/2-int(h* matrTekFg[0][1]));
 
 // Остальные линии: EF,FG,GH,HE,AE,BF,CG,DH – прорисуйте самостоятельно
 
 FPC->Pen->Width=1;
 FPC->Pen->Color=clBlack;
}
На этом разработка функций построения заданной фигуры в графическом окне закончена.
Можно запустить программу на исполнение и проверить работу движков TrackBar1TrackBar4 -  TrackBar6 по масштабированию и переносу фигуры в разных направлениях.
 
5-й этап – построение ПРОЕКЦИЙ
7.21. Порядок построения проекций
 
Порядок построения проекций почти полностью совпадает с порядком построения осей или фигуры:
- создадим запускающую функцию IzmPro(), для обеспечения последовательного запуска следующих функций: функции вычисления результирующих матриц преобразования  RezMatrPr(), функции преобразования координат проекций Preobr() и функции нормировки координат проекций Normir();
- поместим вызов функции IzmPro() в главный конвейер.
- создадим функцию вычисления результирующих матриц  RezMatrPr();
- создадим функцию ShowPro() для прорисовки проекций с использованием отнормированных текущих координат проекций.
Для включения прорисовки проекций заданной фигуры в трех координатных плоскостях локальной системы координат создадим следующие обработчики:
- обработчик события CheckBox3 – флажок запуска прорисовки проекции на плоскость Z=0;
- обработчик события CheckBox4 – флажок запуска прорисовки проекции на плоскость Y=0;
- обработчик события CheckBox5 – флажок запуска прорисовки проекции на плоскость X=0;
Для включения прорисовки косоугольных проекций создадим следующие обработчики:
- обработчик события Button1 –  для запуска прорисовки проекции на плоскость Z=0;
- обработчик события RadioButton1 – кнопка переключения на ортографическое проецирование;
- обработчик события RadioButton2 – кнопка переключения на косоугольное проецирование;
- обработчик события TrackBar7 – для изменения угла наклона α лучей проецирования в косоугольных проекциях;
 
7.22. Функция  обработки  координат проекций IzmPro()
 
Функция обработки координат трех проекций должна обеспечить последовательный запуск следующих функции:
- RezMatrPr(), для вычисления трех результирующих матриц преобразования;
- Preobr() - функции преобразования координат трех проекций;
- Normir() - функции нормировки координат трех проекций.
Поэтому, программный код этой функции будет иметь вид:
 
 
void IzmPro(void)
{
 RezMatrPr();                // Вычисление рез. матриц преобразования проекц.
 Preobr(8,matrIsxFg,TrezPrX,matrIzmPrX);// Преобразование координат проекц.X
 Preobr(8,matrIsxFg,TrezPrY,matrIzmPrY);// Преобразование координат проекц.Y
 Preobr(8,matrIsxFg,TrezPrZ,matrIzmPrZ);// Преобразование координат проекц.Z
 
 Normir(8,matrIzmPrX,matrPrX);          // Нормировка координат проекции X
 Normir(8,matrIzmPrY,matrPrY);          // Нормировка координат проекции Y
 Normir(8,matrIzmPrZ,matrPrZ);          // Нормировка координат проекции Z
}
 
7.23. Разработка функции вычисления результирующих матриц RezMatrPr()
 
Для трех проекций фигуры на локальные плоскости Z=0X=0 и Y=0 необходимо сформировать три матрицы преобразования TRezPrZ[4][4], TRezPrX[4][4], TRezPrY[4][4]. Эта задача и возложена на функцию RezMatrPr().
Схема формирования результирующих матриц преобразования проекций на локальные плоскости Z=0, X=0 и Y=0   для ортографического проецирования будет иметь вид:
 
TRezPrZ = Tper * Tmsb * TortZ * (TvrYOs * TvrXOs * TortZ)
TRezPrX = Tper * Tmsb * TortX * (TvrYOs * TvrXOs * TortZ)
TRezPrY = Tper * Tmsb * TortY * (TvrYOs * TvrXOs * TortZ)
 
для косоугольного проецирования:
 
TRezPrZ = Tper * Tmsb * TkosZ* TortZ * (TvrYOs * TvrXOs * TortZ)
TRezPrX = Tper * Tmsb * TkosX* TortX * (TvrYOs * TvrXOs * TortZ)
TRezPrY = Tper * Tmsb * TkosY* TortY * (TvrYOs * TvrXOs * TortZ)
 
Здесь ортографическая матрица, находящаяся в середине цепочки, обеспечивает ортогональное проецирование на плоскости локальной системы координат, а та, что находится в конце цепочки – на плоскость глобальной системы, т.е. на плоскость графического окна проекта.
Произведение последних трех матриц вычислено в функции RezMatrOs() в матрице TrezOs поэтому, перепишем схему вычисления матрицы преобразования проекций в другом виде:
- для ортографического проецирования:
 
TRezPrZ = Tper * Tmsb * TortZ * TrezOs
TRezPrX = Tper * Tmsb * TortX * TrezOs
TRezPrY = Tper * Tmsb * TortY * TrezOs
 
- для косоугольного проецирования:
 
TRezPrZ = Tper * Tmsb * TkosZ* TortZ * TrezOs
TRezPrX = Tper * Tmsb * TkosZ* TortX * TrezOs
TRezPrY = Tper * Tmsb * TkosZ* TortY * TrezOs
 
В результате, текст функции будет иметь вид:
 
void RezMatrPr(void)
{
 float T1[4][4],T2[4][4];
 float Tx[4][4],Ty[4][4],Tz[4][4];
 
 MultMatr(Tper, Tmsb, T1);          // 1-я промежуточн. матр. преобр.проекц.
 
 if(Form8->RadioButton1->Checked)   // Если включ. ортографич. проецирование
    {MultMatr(T1, TortX, Tx);        // Промежуточн. матр. преобр. проекц. X
     MultMatr(T1, TortY, Ty);        // Промежуточн. матр. преобр. проекц. Y
     MultMatr(T1, TortZ, Tz);        // Промежуточн. матр. преобр. проекц. Z
    }
 else                               // Если включ. косоугольное проецирование
    {MultMatr(T1, TkosX, T2);
     MultMatr(T2, TortX, Tx);        // Промежуточн. матр. преобр. проекц. X
     MultMatr(T1, TkosY, T2);
     MultMatr(T2, TortY, Ty);        // Промежуточн. матр. преобр. проекц. Y
     MultMatr(T1, TkosZ, T2);
     MultMatr(T2, TortZ, Tz);        // Промежуточн. матр. преобр. проекц. Z
    }
 MultMatr(Tx, TrezOs, TrezPrX); // Результирующая матрица преобр.проекц.X
 MultMatr(Ty, TrezOs, TrezPrY); // Результирующая матрица преобр.проекц.Y
 MultMatr(Tz, TrezOs, TrezPrZ); // Результирующая матрица преобр.проекц.Z
}
 
7.24. Создание  обработчиков  для  флажков  CheckBox3,  CheckBox4  и  CheckBox5
 
Создайте обработчики для этих компонентов и впишите в них только одну команду:   Repaint().
 
7.25. Создание обработчика для кнопки Button1
 
В составе этого обработчика необходимо выполнить чтение параметров косоугольного преобразования из окон Edit8 и Edit10, произвести необходимые перерасчеты, затем ввести результаты в матрицы косоугольного преобразования и вызвать функцию перерисовки:
 
void __fastcall TForm8::Button1Click(TObject *Sender)
{
 if(RadioButton2->Checked)
   {if(RadioButton3->Checked)
      {betta=StrToFloat(Form8->Edit8->Text);
       if(betta==45)
         {k1=Cotan(k2*betta);
          Form8->Edit9->Text=FloatToStr(k1);
 
          TkosZ[2][0]=k1*cos(k2*alfa);
          TkosZ[2][1]=k1*sin(k2*alfa);
 
          TkosX[0][1]=k1*sin(k2*alfa);
          TkosX[0][2]=k1*cos(k2*alfa);
 
          TkosY[1][0]=k1*sin(k2*alfa);
          TkosY[1][2]=k1*cos(k2*alfa);
         }
      }
    if(RadioButton4->Checked)
      {k1=StrToFloat(Form8->Edit10->Text);
      if(k1==0.5)
         {betta=atan(1/k1);
          Form8->Edit11->Text=FloatToStr(betta/k2);
 
          TkosZ[2][0]=k1*cos(k2*alfa);
          TkosZ[2][1]=k1*sin(k2*alfa);
 
          TkosX[0][1]=k1*sin(k2*alfa);
          TkosX[0][2]=k1*cos(k2*alfa);
 
          TkosY[1][0]=k1*sin(k2*alfa);
          TkosY[1][2]=k1*cos(k2*alfa);
         }
       }
   }
 Repaint();
}
 
7.26. Создание обработчика для движка TrackBar7
 
Этот обработчик предназначен для регулирования угла наклона α лучей проецирования в косоугольных проекциях. Здесь необходимо ввести значение Position в переменную alfa, а затем значение этой переменной использовать для перерасчета параметров матриц косоугольного преобразования:
 
void __fastcall TForm8::TrackBar7Change(TObject *Sender)
{
 alfa=(Form8->TrackBar7->Position);
 Form8->Edit3->Text=FloatToStr(alfa);
 
 TkosZ[2][0]=k1*cos(k2*alfa);
 TkosZ[2][1]=k1*sin(k2*alfa);
 
 TkosX[0][1]=k1*sin(k2*alfa);
 TkosX[0][2]=k1*cos(k2*alfa);
 
 TkosY[1][0]=k1*sin(k2*alfa);
 TkosY[1][2]=k1*cos(k2*alfa);
 
 Repaint();
}
 
7.27. Создание  обработчиков  для  радиокнопок  RadioButton1 и RadioButton2
 
Создайте обработчики для этих компонентов и впишите в них только одну команду: Repaint().
 
7.28. Разработка функции прорисовки проекций ShowPro()
 
Процесс прорисовки проекций на координатные плоскости XOY, YOZ и  ZOX полностью идентичен прорисовке самой фигуры, с той разницей, что здесь мы будем использовать другие матрицы координат.
Пример программного кода этой функции прорисовки 4-х линий (из 12-ти) для фигуры кубической формы имеет вид:
 
void ShowPro(float matrPr[8][4])
{
 FPC->Pen->Style=psSolid;
 FPC->Pen->Color=clMaroon;
 
                     //рисуем линию AB
 FPC->MoveTo(W/2+int(h* matrPr[0][0]), H/2-int(h* matrPr[0][1]));
 FPC->LineTo(W/2+int(h* matrPr[1][0]), H/2-int(h* matrPr[1][1]));
 
                    //рисуем линию BC
 FPC->MoveTo(W/2+int(h* matrPr[1][0]), H/2-int(h* matrPr[1][1]));
 FPC->LineTo(W/2+int(h* matrPr[2][0]), H/2-int(h* matrPr[2][1]));
 
                     //рисуем линию CD
 FPC->MoveTo(W/2+int(h* matrPr[2][0]), H/2-int(h* matrPr[2][1]));
 FPC->LineTo(W/2+int(h* matrPr[3][0]), H/2-int(h* matrPr[3][1]));
 
                    //рисуем линию DA
 FPC->MoveTo(W/2+int(h* matrPr[3][0]), H/2-int(h* matrPr[3][1]));
 FPC->LineTo(W/2+int(h* matrPr[0][0]), H/2-int(h* matrPr[0][1]));
 
// Остальные 8 линий EF, FG, GH, HE, AE, BF, CG, DH прорисуйте самостоятельно
 
 FPC->Pen->Color=clBlack;
}
Запустите программу на исполнение и проверьте работу флажков CheckBox3, CheckBox4  и  CheckBox5  для включения прорисовки всех трех проекций.
 
6-й этап – пРОРИСОВКА ЛУЧЕЙ ПРОЕЦИРОВАНИЯ И ОБОЗНАЧЕНИЙ
 
7.29. Разработка функции прорисовки лучей проецирования ShowLuthi()
 
Функция ShowLuthi() выполняет прорисовку лучей проецирования штриховыми линиями.
Здесь необходимо прорисовать каждый луч по отдельности, в виде линий, связывающих вершины фигуры с вершинами каждой из трех проекций.
Для нашего примера с фигурой кубической формы нам необходимо прорисовать 8 штриховых линий, по количеству вершин фигуры. И это только для одной проекции. Чтобы прорисовать три группы лучей проецирования, функция ShowLuthi() вызывается три раза из функции ShowAll().
Пример описания функции ShowLuthi() имеет следующий вид:
 
void ShowLuthi(float matrPr[8][4])
{
 FPC->Pen->Style=psDot;                 // стиль линий - штриховой
 FPC->Pen->Color=clMaroon;              // цвет линий - коричневый
 
                     //рисуем луч A
 FPC->MoveTo(W/2+int(h* matrFg[0][0]), H/2-int(h* matrFg[0][1]));
 FPC->LineTo(W/2+int(h* matrPr[0][0]), H/2-int(h* matrPr[0][1]));
 
                     //рисуем луч B
 FPC->MoveTo(W/2+int(h* matrFg[1][0]), H/2-int(h* matrFg[1][1]));
 FPC->LineTo(W/2+int(h* matrPr[1][0]), H/2-int(h* matrPr[1][1]));
 
                     //рисуем луч C
 FPC->MoveTo(W/2+int(h* matrFg[2][0]), H/2-int(h* matrFg[2][1]));
 FPC->LineTo(W/2+int(h* matrPr[2][0]), H/2-int(h* matrPr[2][1]));
 
                    //рисуем луч D
 FPC->MoveTo(W/2+int(h* matrFg[3][0]), H/2-int(h* matrFg[3][1]));
 FPC->LineTo(W/2+int(h* matrPr[3][0]), H/2-int(h* matrPr[3][1]));
 
// Остальные 4 луча E, F, G, H   прорисуйте самостоятельно
 
 FPC->Pen->Style=psSolid;         // стиль линий – в исходное состояние
}
 
Добавьте недостающие команды прорисовки лучей  E, F, G, H  и запустите программу на исполнение.
Прорисовка лучей будет выполняться вместе с прорисовкой каждой из проекций, после установки флажков в компонентах CheckBox3 - CheckBox5.
 
7.30. Разработка функции прорисовки обозначений  Oboznath ()
 
Создайте заголовок функции в соответствии с объявлением её прототипа и впишите необходимые команды. Пример команды вывода обозначения для вершины А фигуры имеет следующий вид:
 
FPC->TextOut(W/2+int(h* matrFg[0][0])+5,
             H/2-int(h* matrFg[0][1])-20,"A");}
 
Как видно из текста программного кода функции ShowAll(),  прорисовка обозначений осуществляется только в том случае, если включен флажок компонента CheckBox2. Поэтому, создайте обработчик события CheckBox2Click, и впишите в нем команду Repaint()  для перерисовки графического окна при переключении флажка.
После этого можно запустить программу на исполнение и убедиться в том, что обозначения прорисовываются после включения флажка компонента “Обозначения” и наоборот, исчезают после его выключения.
 
 
 
8. Контрольные вопросы
 
1. К какому классу относятся ортографические и косоугольные проекции? В чем сходство и различие между ними?
2. Напишите матрицы ортографического преобразования.
3. Напишите схему формирования результирующей матрицы ортографического проецирования.
4. Напишите матрицу косоугольного преобразования.
5. Напишите схему формирования результирующей матрицы косоугольного проецирования.
6. В чем сходство и различие между проекциями Ковалье и Кабине?
7. Приведите формулы для расчета коэффициентов искажений в косоугольных проекциях?
8. Приведите формулу для расчета угла наклона проецирующих лучей к плоскости проекций в косоугольных проекциях.
9. В чем заключается различие между углами наклона лучей проецирования α и β.
10. Изобразите структурную схему классификации плоских проекций.