Методические указания Форма Ф СО ПГУ 7.18.2/05 Министерство образования и науки Республики Казахстан Павлодарский государственный университет им. С. Торайгырова Кафедра Профессиональное обучение МЕТОДИЧЕСКИЕ УКАЗАНИЯ к лабораторным работам дисциплины Вычислительная геометрия и компьютерная графика для студентов специальности 050120 – Профессиональное обучение Павлодар Лист утверждения к методическим указаниям Форма Ф СО ПГУ 7.18.1/05 УТВЕРЖДАЮ Декан факультета АСФ ____________ Кудерин М.К. «____»_____________20__г. Составитель: старший преподаватель ______________ Кабдырова Л.Т. Кафедра Профессиональное обучение Методические указания к лабораторным работам дисциплины Вычислительная геометрия и компьютерная графика для студентов специальности 050120 – Профессиональное обучение Рекомендовано на заседании кафедры «____»______________20__ г., Протокол № ___ Заведующий кафедрой _________ Алинова М.Ш. Одобрена учебно-методическим советом АСФ «____» __________20__г. Протокол № ___ Председатель УМС _________ Алдунгарова А.К. Лабораторная работа № 1 Преобразование координат на плоскости Цель: Освоить на практике преобразование координат объектов на плоскости. Задача: Создать программу, формирующую заданное динамическое изображение. Преобразование координат должно выполняться в матричной форме. 1 Краткие теоретические сведения 1.1 Преобразование координат на плоскости В основе преобразования любого изображения (поворота, изменения масштаба, эмуляции движения и др.) лежит работа с его элементарными составляющими: точками и линиями. Любое линейное преобразование точки на плоскости с координатами (х,у) в точку с координатами (х',у') можно представить в следующем виде: х' = ах + by + e y' = cx + dy+f, (1) где а, b, с, d, e, f - произвольные числа. Если выполняется условие а b с d ≠ 0, (2) то преобразование называется аффинным, в противном случае вырожденным. Аффинные преобразования обладают следующими свойствами: - Прямая переходит в прямую. - Отрезок переходит в отрезок. Для того, чтобы преобразовать отрезок, достаточно преобразовать его концевые точки, а затем соединить их прямой. - Параллельные прямые переходят в параллельные прямые, точка пересечения двух прямых переходит в точку их пересечения после преобразования. Параллелограмм, например, перейдет в параллелограмм, треугольник - в треугольник, прямоугольник - в прямоугольник. Для того, чтобы преобразовать любой многоугольник, достаточно преобразовать его вершины, а затем соединить их прямыми. - Аффинное преобразование устанавливает взаимнооднозначное соответствие между исходными и преобразованными точками плоскости. Поэтому для любого аффинного преобразования всегда можно построить обратное к нему. То есть, для любого объекта можно всегда задать обратное движение, найти исходные размеры. - Последовательное применение нескольких аффинных преобразований также дает в результате аффинное преобразование. Поэтому постоянно используемые в компьютерной графике сложные преобразования координат, состоящие из ряда простых аффинных, также являются аффинными. Поэтому для них справедливы все вышеперечисленные свойства. Из возможных преобразований, которые могут быть описаны в форме (1), особую роль играют четыре следующих частных случая, с помощью которых можно описать любое преобразование или движение объектов на плоскости: I. Поворот вокруг начала координат на угол φ. Если φ > 0, то поворот совершается против часовой стрелки, если φ < 0, то - по часовой. y х' = x cos(φ) - у sin(φ) (3) у' = х sin(φ) + у cos(φ) M'(x',y') M(x,y) φ>0 φ <0 M'(x',y') x Рисунок1. Поворот на угол φ >0 0 II. Растяжение (сжатие) вдоль координатных осей. Если kx, ky < 1, то происходит сжатие. Если kx, ky > 1, то происходит растяжение. Если kx = ky, то происходит пропорциональное изменение линейных размеров объекта. y x2 х' = kx х y' = ky y (4) y2 x 0 Рисунок 2. Растяжение прямоугольника при kx = ky = 2 III. Отражение (может осуществляться относительно начала координат и координатных осей). IV. Параллельный перенос При программировании наиболее удобной формой для представления геометрических фигур являются массивы или матрицы. Например, точка А(х,у) может быть представлена в виде матрицы [x,y], отрезок прямой АВ - в виде матрицы xa xb ya yb , а треугольник ABC - в виде матрицы xa ya xb yb xс yс и т.д. При таком представлении фигур преобразования координат также удобно записывать в матричной форме: [B]= [A] [T], где [А] - матрица исходных координат вершин фигуры, [В] - матрица координат вершин после преобразования, [T] - матрица преобразования, построенная таким образом, чтобы умножение на нее матрицы исходных координат давало матрицу координат, преобразованных заданным образом (в результате параллельного переноса, поворота фигуры и т.п.). В общем случае матрица преобразования равна [T] = a b c d , где а, b, с, d - некоторые числа. Матрицы для основных преобразований координат I - III выглядят следующим образом: Преобразование IV (перенос) нельзя описать при помощи матрицы 2x2. Эта проблема решается введением однородной системы координат. Если А - точка на плоскости с координатами х и у, то ее однородными координатами можно назвать любую тройку чисел х*, у*, h (h ≠ 0), связанных с х и у следующими соотношениями: Одна и та же точка в однородных координатах может быть представлена бесконечным числом способов. Например, однородными координатами для точки (2, 3) будут являться координаты (2, 3, 1) при h = 1, координаты (4, 6, 2) при h = 2 и координаты (1, 1.5, 0.5) при h = 0.5. Для того чтобы получить обычные координаты точки из ее однородных координат, нужно воспользоваться формулами (7): точке с однородными координатами (12, 8, 4) соответствует точка с обычными координатами (3, 2), точке (1, 0.5, 0.1) - точка (10, 5). При преобразовании координат обычно используются нормированные однородные координаты, когда h = 1. При переходе к таким координатам точка М плоскости, имеющая в обычной декартовой системе координат координаты (х, у), будет иметь однородные координаты (х,у,1): М(х,у) → М' (х,у,1). В компьютерной графике однородные координаты используются также, например, при построении проекций. После введения однородной системы координат для описания преобразования на плоскости можно использовать матрицы размером 3x3. При этом матрица, соответствующая общему преобразованию (1) будет иметь следующий вид: а преобразование точки А (х, у, 1) с помощью матрицы Т точку А'(х', у', 1) будет выглядеть так: В виде матрицы 3x3 можно записать все четыре случая базовых преобразований: Например, вычисление координат точки А (х, у) после ее поворота на угол φ вокруг начала координат в матричной форме выглядит следующим образом: Произвольное сложное преобразование координат может быть представлено в виде комбинации преобразований (8). 2. Примеры использования преобразований координат. 2 Примеры Пример №1. Повернем треугольник А(10, 0)В(20, 10)С(20, -10) вокруг точки D(25, 35) на угол φ = 90°. Данное преобразование может быть получено в несколько этапов: 1) Строим матрицу исходных однородных координат вершин треугольника ABC: 2) Строим матрицу перехода к системе координат, в которой центр поворота точка D совпадает с началом координат: 3) Строим матрицу поворота на угол φ вокруг начала координат: 4) Строим матрицу возврата к исходной системе координат: 5) Для того чтобы получить теперь матрицу [V'] координат треугольника ABC после заданного поворота, нужно последовательно умножить матрицу [V] на матрицы преобразований (10) - (12): [V] [T1] [R] [T2] = [V']. Однако, пользуясь свойством ассоциативности операции умножения матриц, можно сначала вычислить общую матрицу преобразования [Р], а затем умножить на нее матрицу [V]: Общая матрица преобразования [Р] равна: 6) Применяем полученное преобразование [Р] к координатам вершин треугольника ABC: Отсюда видим, что в результате заданного поворота треугольник ABC переходит в треугольник А '(60, 20)В'(50, 30)С'(70, 30). Пример №2. Увеличим линейные размеры треугольника ABC из примера №1 в три раза таким образом, чтобы вершина А не изменила своего положения. Для того чтобы выполнить данное преобразование, нужно сначала вычислить матрицу растяжения с центром в точке А. 1) Строим матрицу перехода к системе координат, в которой вершина А совпадает с началом координат: 1 0 0 1 0 -10 0 1 [T1] = 0 2) Строим матрицу растяжения с одинаковыми коэффициентами для обеих осей координат: 3 [D] = 0 0 0 3 0 0 0 1 3) Строим матрицу возврата к исходной системе координат: 1 0 0 1 0 +10 0 1 [T2] = 0 4) Вычисляем общую матрицу преобразования: 5) Применяем полученное преобразование [Р] к координатам вершин треугольника: Таким образом получаем, что в результате растяжения треугольник ABC переходит в треугольник А'(10, 0)В'(40, 30)С'(40, -30). 3 Примеры программ. 3.1. Разноцветные треугольники Описание задачи Данный пример программы рисует на экране восемь треугольников, расположенных по кругу и окрашенных в разные, постоянно меняющиеся цвета (рис. 5). Для того, чтобы получить такой рисунок, треугольник А(140,10)В(120,80)С(160,80) восемь раз поворачивается вокруг точки D(140,140) на угол φ= π/4. Соответствующее преобразование координат строится в несколько шагов: 1) Переход к системе координат с началом в точке D: 2) Поворот на угол φ= π/4 вокруг начала координат (в текущей системе координат этот поворот будет совершаться по часовой стрелке: Рис. 5. Заданное изображение 3) Возврат к исходной системе координат: 4) Вычисление общей матрицы поворота вокруг точки D: 5) Построение матрицы вершин треугольника ABC: 6) Рисование и поворот треугольника ABC вокруг точки D восемь раз: i← 1 Пока i ≤ 8 Нарисовать ΔABC Конец Пока Реализация вычислений в среде Delphi Как уже было сказано выше, геометрические фигуры на языке высокого уровня удобнее всего описывать матрицами или массивами координат их вершин. Для представления треугольника ABC можно, например, использовать массив типа TVertex (вершина), предварительно описав его так: type //одномерный массив для представления матрицы //однородных координат одной вершины TVertex = array[0..2] of Double; const //матрица однородных координат вершин треугольника ABC : array[0..2] of TVertex = ( (140, 10, 1), (120, 80, 1), (160, 80, 1)); Для представления матрицы произвольного двумерного линейного преобразования координат можно использовать массив 3x3 вещественных чисел: type //двумерный массив для представления матриц //преобразований координат размером 3x3 Transformation = array[0..2, 0..2] of Double; С помощью типа данных Transformation можно определить матрицы всех трех базовых преобразований координат [Т1], [R] и [Т2], необходимых для поворота треугольника ABC вокруг точки D: const //координаты точки D, вокруг которой будет происходить //вращение треугольника Dx = 140; Dy = 140; //угол поворота, равен Пи/4 fi = Pi /4; var //матрица перехода к системе координат с центром в точке D Tl : TTransformation = ( ( 1, 0, 0), (0, 1, 0), (-Ох, -Оу, 1)); //матрица поворота вокруг начала координат (заполняется до конца //в обработчике события OnCreate) R : TTransformation = ( (0, 0, 0), (0, 0,0), (0, 0, 1) ) ; //матрица перехода к исходной системе координат Т2 : TTransformation = ( (1, 0, 0), (0, 1, 0), (Ох, Оу, 1)); Определенная выше матрица [R] осталась незаполненной до конца, так как при инициализации переменных в языке Паскаль можно указывать только константы и нельзя использовать значения функций. Поэтому 4-е ее элемента, равные значениям тригонометрических функций, должны быть заданы отдельно. Для этой цели можно, например, использовать событие OnCreate главной формы. Его обработчик вызывается один раз при создании формы в самом начале работы программы: //Обработчик события OnCreate. Используется для инициализации данных procedure TForml.FormCreate(Sender: TObject); begin //заполним матрицу [R] для поворота на угол fi R[0, 0] := cos(fi); R[0, 1] := sin(fi); R[l, 0] := -sin(fi); R[l, 1] := cos (fi) end; Построение сложных преобразований координат (как, например, в нашем случае для поворота вокруг точки, отличной от начала координат) осуществляется последовательным перемножением матриц базовых преобразований. Для умножения матриц преобразований можно использовать процедуру CombineTransform, приведенную ниже. Через параметр Т она возвращает произведение матриц, переданных через параметры Т1 и Т2 ([T]=[T1]∙[T2]). До окончательного вычисления матрицы [T] ее элементы хранятся во временном массиве Tmp. Благодаря этому при вызове процедуры можно указать, что произведение матриц должно быть помещено в тот же массив, в котором находится одна из перемножаемых матриц (задав, например, в качестве параметров T1 и Т один и тот же массив). //Вычисляет матрицу общего преобразования Т, перемножая матрицы Т1 и Т2 //составляющих его преобразований procedure CombineTransform(var T : TTransformation; const Tl, T2 : TTransformation); var //временный буфер для хранения преобразования Tmp : TTransformation; i, j : Integer; begin //вычислим и поместим в Tmp матрицу общего преобразования for i := 0 to 2 do //пройдем по всем строкам for j := 0 to 2 do //пройдем по всем столбцам Tmp[i, j] := T1[i, 0] * Т2[0, j] + T1[i, 1] * T2[l, j] + T1[i, 2] * T2[2, j]; Т := Tmp; end; Теперь, имея процедуру CombineTransform, легко можно объединить базовые преобразования [Т1], [R] и [T2] в одно сложное преобразование [Т] = [Т1] ∙ [R] ∙ [T2]: var Т : TTransformation; ........................ CombineTransform (Т, Tl, R); //умножение матриц: [Т] = [T1]*[R] CombineTransform (Т, Т, Т2); //умножение матриц: [Т] = [Т]*[Т2] Преобразование графического объекта осуществляются умножением матрицы координат его вершин на матрицу преобразования. Для выполнения этой операции также удобно создать отдельную процедуру ApplyTransform, показанную ниже. Как параметр V ей передается матрица координат вершин преобразуемого объекта, как параметр Т - матрица преобразования. Преобразованные координаты возвращаются через параметр V1. //Осуществляет преобразование координат вершин фигуры, //переданных в массиве V с помощью матрицы Т: [VI]:=[V]*[Т] procedure ApplyTransform(var VI : array of TVertex; const V : array of TVertex; const Т : TTransformation); var i, j : Integer; P : TVertex; begin //пройдем по всем вершинам фигуры for i := 0 to High(V) do begin //вычислим и поместим в Р преобразованные координаты i-ой вершины for j := 0 to 2 do P[j] := V[i, 0] * T[0, j] + V[i, 1] * T[l, j] + V[i, 2] * T[2, j]; //сохраним вычисленные координаты i-й вершины в массиве V V1[i] := Р; end end; Теперь для поворота треугольника ABC с помощью полученной выше матрицы [T] достаточно одной команды: ApplyTransform(ABC, ABC, Т); После выполнения процедуры ApplyTransform в массиве ABC уже будут находиться координаты вершин повернутого на 45° треугольника. Создание изображения Для того, чтобы цвета треугольников менялись равномерно через заданные промежутки времени, в программе используется компонента Timer (значок на вкладке System панели компонентов Delphi). Когда от таймера поступает сигнал (частота поступления сигналов определяется его свойством Interval), вызывается назначенный ему обработчик события OnTimer. В программе он содержит только одну команду Refresh, при вызове которой форма закрашивается фоновым цветом и вызывается обработчик события OnPaint формы. Таким образом по сигналу от таймера старое изображение стирается и рисуется новое другими цветами. //Обработчик события OnTimer. Вызывается при поступлении сигнала от таймера. procedure TForml.TimerITimer(Sender: TObject); begin //перерисуем изображение на форме Refresh; end; Рисование треугольников происходит в обработчике события OnPaint. Цвет каждого треугольника образуется в результате смешивания случайных количеств красного, зеленого и синего основных цветов. Для этого используется функция Random(N), возвращающая случайное целое число в диапазоне [0, N]: //Обработчик события OnPaint. Вызывается, когда необходимо перерисовать //содержимое формы procedure TForml.FormPaint(Sender: TObject); var .............. с : TColor; begin ............................ //выберем случайный цвет для треугольника с := RGB(random(255), random(255), random(255)); //установим этот цвет для пера и для кисти Pen.Color := с; Brush.Color := с; ............................ end; Для рисования закрашенных треугольников используется метод Polygon(Points: array of TPoint) объекта Canvas (свойство "холст" формы). Граница треугольников рисуется пером (свойство-объект Реn объекта Canvas), а внутренняя часть закрашивается кистью (свойство-объект Brush объекта Canvas). //нарисуем треугольник Canvas.Polygon( [Point(round(tmpABC[0,0]), Point(round(tmpABC[l,0]), Point(round(tmpABC[2,0]), round(tmpABC[0,1])), round(tmpABC[1,1])), round(tmpABC[2,1]))] Метод Polygon предназначен для рисования замкнутых многоугольников. В качестве единственного параметра он принимает открытый массив вершин (open array) многоугольника. Этот массив создается при вызове его с помощью конструктора открытых массивов - последовательности элементов массива, перечисленных через запятую и заключенных в квадратные скобки (аналогично в языке Паскаль создаются множества). Количество элементов может быть любым. Созданный таким образом массив является временными и существует до тех пор, пока процедура не завершит свою работу. Сразу после этого массив уничтожается и занимаемая им память освобождается. Элементы массива, передаваемого процедуре Polygon, должны быть записями типа TPoint: //задает положение пикселя на экране type TPoint = record X: Longint; Y: Longint; end; Каждая из таких записей описывает одну вершину многоугольника. В приведенном выше примере для их создания использовалась функция Point(X, Y: Integer):TPoint. Она возвращает запись типа TPoint, содержащую переданные функции координаты X и Y. Для увеличения точности вычислений координаты вершин треугольника хранятся в программе как вещественные числа типа Double: type //одномерный массив для представления матрицы //однородных координат одной вершины TVertex = array[0..2] of Double; Координаты любой точки на экране являются целыми числами и записи типа TPoint могут содержать только целочисленные координаты. Поэтому координаты каждой вершины передаются функции Point округленными при помощи функции Round(x). Полный текст программы: Ниже приводится полный текст программы, рисующей треугольники, изображенные на рис. 5. unit Unitl; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TForml = class(TForm) Timerl: TTimer; procedure FormCreate(Sender: TObject); procedure FormPaint(Sender: TObject); procedure TimerITimer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Forml: TForml; implementation {$R *.DFM} (*Используемые типы данных*) type //двумерный массив для представления матриц //преобразований координат размером 3x3 TTransformation = array[0..2, 0..2] of Double; //одномерный массив для представления матрицы //однородных координат одной вершины TVertex = array[0..2] of Double; (*Данные*) const //координаты точки D, вокруг которой будет происходить //вращение треугольника Dx = 140; Dy = 140; fi = Pi /4; //угол поворота, равен Пи/4 var //матрица однородных координат вершин треугольника ABC ABC : array[0..2] of TVertex = ((140, 10, 1), (120, 80, 1), (160, 80, 1)); //матрица перехода к системе координат с центром в точке D Tl : TTransformation = (( 1, 0, 0), ( 0, 1, 0), (-Dx, -Dy, 1)); //матрица поворота вокруг начала координат (заполняется до конца //в обработчике события OnCreate) R : TTransformation = ((0, 0, 0), (0, 0,0), (0, 0, 1)); //матрица перехода к исходной системе координат Т2 : TTransformation = (( 1, 0, 0) , ( 0, 1, 0), (Dx, Dy, 1)); //матрица общего преобразования для поворота треугольника //вокруг точки D Т : TTransformation; (*Подпрограммы для работы с матрицами*) //осуществляет преобразование координат вершин фигуры, //переданных в массиве V, с помощью матрицы Т: [VI]:=[V]*[Т] procedure ApplyTransform(var VI : array of TVertex; const V : array of TVertex; const T : TTransformation); var i, j : Integer; P : TVertex; begin //пройдем по всем вершинам фигуры for i := 0 to High(V) do begin //вычислим и поместим в Р преобразованные координаты i-ой вершины for j := 0 to 2 do P[j] := V[i, 0] * T[0, j] + V[i, 1] * T[l, j] + V[i, 2] * T[2, j]; //сохраним вычисленные координаты 1-й вершины в массиве V V1[i] := Р; end end; //Вычисляет матрицу общего преобразования Т, перемножая матрицы Т1 и Т2 //составляющих его преобразований procedure CombineTransform(var T : TTransformation; const Tl, T2 : TTransformation); var //временный буфер для хранения преобразования Tmp : TTransformation; i, j : Integer; begin //вычислим и поместим в Tmp матрицу общего преобразования for i := 0 to 2 do //пройдем по всем строкам for j := 0 to 2 do //пройдем по всем столбцам Tmp[i, j] := Tl[i, 0] * Т2[0, j] + Tl[i, 1] * T2[l, j] + Tl[i, 2] * T2[2, j]; T := Tmp; end; (*Текст основной программы*) //Обработчик события OnCreate. Используется для инициализации данных procedure TForml.FormCreate(Sender: TObject); begin //заполним матрицу [R] для преобразования вращения R[0, 0] := cos(fi); R[0, 1] := sin(fi); R[l, 0] := -sin(fi); R[l, 1] := cos(fi); //получим матрицу [Т] преобразования для поворота треугольника вокруг //точки D CombineTransform (Т, Tl, R); //умножение матриц: [Т] = [T1]*[R] CombineTransform (Т, Т, Т2); //умножение матриц: [Т] = [Т]*[Т2] end; //Обработчик события OnPaint. Вызывается, когда необходимо перерисовать //изображение на форме procedure TForml.FormPaint(Sender: TObject); var i : Integer; tmpABC : array[0..2] of TVertex; с : TColor; begin //скопируем координаты вершин треугольника во временный массив for i := 0 to 2 do tmpABC[i] := ABC[i]; //будем поворачивать треугольник вокруг точки D на угол fi //и рисовать его 8 раз for i := 0 to 7 do begin //повернем треугольник ApplyTransform(tmpABC, tmpABC, T) ; //выберем случайный цвет для треугольника с := RGB(random(255), random(255), random(255)); //нарисуем его в новом положении with Canvas do begin //установим цвет для пера и кисти Pen.Color := с; Brush.Color := с; //нарисуем треугольник Polygon([Point(round(tmpABC[0,0], round(tmpABC[0,1])), Point(round(tmpABC[l,0], round(tmpABC[1,1])), Point(round(tmpABC[2,0])), round(tmpABC[2,1]))]); end end; end; //Обработчик события OnTimer. Вызывается при поступлении сигнала //от таймера. procedure TForml.TimerITimer(Sender: TObject); begin //перерисуем изображение на форме Refresh; end; end. 4 Задание 1) Изучить свойства базовых преобразований координат на плоскости, изучить метод построения преобразований координат в матричной форме, освоить построение сложных преобразований координат (поворот с центром в точке, отличной от начала координат, отражение от прямой, отличной от координатной оси и т.п.). 2) Пользуясь методом преобразования координат в матричной форме, создать программу, формирующую заданное изображение. Для того, чтобы движение сделать равномерным, используйте компоненту Timer. 5 Варианты заданий 1 Постройте преобразования координат для поворота отрезка А(ха,уа)В(хb,уb) вокруг точки D(xd,yd) на угол φ против и по часовой стрелке. 2 Постройте преобразование координат, с помощью которого можно расплющить любой предмет: ширина должна увеличиться, а высота уменьшиться вдвое. 3 Найдите отражение треугольника А(ха,уа)В(хb,уb)С(хс,ус) относительно начала координат. 4 Найдите отражение точки А(ха,уа) относительно прямой у = kx + b . 5 Постройте преобразование для растяжения любого объекта в три раза с центром в точке С(хс,ус) вдоль прямой с направляющим вектором L = {l,m}. 6 Точка А(ха,уа) была отражена относительно оси ординат (здесь указаны ее координаты после отражения). Постройте преобразование, которому она была подвергнута, найдите обратное к нему и, пользуясь последним, найдите ее исходные координаты. 7 Треугольник А(ха,уа)В(хb,уb)С(хс,ус) был растянут вдоль оси абсцисс в К раз (здесь указаны его координаты после растяжения). Вершина А при этом не изменила своего положения. Постройте преобразование координат, которому был подвергнут треугольник, найдите обратное к нему и, пользуясь последним, определите исходные координаты вершин В и С. 8 Точка А(ха,уа) была повернута вокруг точки В(хb,уb) на угол φ (здесь даны ее координаты после поворота). Постройте преобразование, которому она была подвергнута, найдите обратное к нему и, пользуясь последним, найдите ее исходные координаты. 9 Отрезок А(ха,уа)В(хb,уb) был преобразован в отрезок С(хс,ус)D(xd,yd). Постройте преобразование, которое могло использоваться при этом. Лабораторная работа № 2 Трехмерные преобразования Цель: Освоить на практике преобразование координат объектов в пространстве. Задача: Создать программу, формирующую заданное динамическое изображение. Преобразование координат должно выполняться в матричной форме. 1 Краткие теоретические сведения Процесс вывода трехмерной графической информации по сути своей является более сложным, чем соответствующий двумерный процесс. Это связано с тем, что экран ЭВМ - это плоскость, и в процессе визуализации трехмерная информация должна быть преобразована в двумерную. Это осуществляется с помощью проекций. При этом преобразования трехмерной информации естественно осуществлять в трехмерном пространстве и построение проекций производить лишь непосредственно перед визуализацией. Рассмотрим сначала способы преобразования трехмерной информации. Для этого обобщим результаты, полученные для плоскости, на трехмерный случай. Точка в трехмерном пространстве x y z с использованием однородных координат представляет собой четырехмерный вектор x y z 1 или x y z h . Преобразование однородных координат описывается соотношениями x ~x ~y ~z h~ x y z 1 T * y* z * 1 x / h y / h z / h 1 , где Т – матрица преобразования. Обобщенная матрица Т для однородных трехмерных координат имеет порядок 44 и записывается как a d T h l b e i c f j m n p q r s Эта матрица может быть представлена как совокупность четырех частей: матрица a b d e h i c f j осуществляет покоординатное смещение и вращение; матрица l m n - перенос; p матрица q - преобразования в перспективе; r матрица s - общее изменение масштаба. изменение масштаба, Иногда преобразование матрицей T размера 33 для плоских однородных координат называется линейным. Соответственно, преобразование матрицей T размера 44 для однородных трехмерных координат называется билинейным. Рассмотрим подробнее эти преобразования. 1.1 Изменение масштаба Покоординатное изменение масштаба диагональных элементов матрицы T: выполняется с помощью a 0 0 0 0 e 0 0 x y z 1 0 0 j 0 0 0 0 1 ax ey jz 1 x * y * z * 1 Таким способом можно, например, преобразовать параллелепипед в куб: Общее изменение масштаба - либо 1 0 0 0 0 1 0 0 x y z s x y z 1 0 0 1 0 0 0 0 s x * y * z * 1 x / s y / s z / s 1 , либо 0 1 / s 0 0 1/ s 0 x y z 1 0 1/ s 0 0 0 0 * x / s y / s z / s 1 x y * 0 0 0 1 z* 1 Результат, как видим будет тот же самый. 2.2 Смещение За преобразование смещения "отвечают" недиагональные элементы верхней левой подматрицы 3x3 1 b c d 1 f x y z 1 h i 1 0 0 0 x dy hz bx y iz cx fy z 0 0 0 1 1 x * y* z* 1 2.3 Вращение вокруг координатных осей Вспомним, что на плоскости вращение вокруг оси, проходящей через начало координат и перпендикулярной плоскости, осуществлялось матрицей cos Q sin Q 0 sin Q cos Q 0 0 1 0 Положительным направлением является направление против часовой стрелки (если смотреть вдоль этой оси к началу координат!). В трехмерном случае вращение вокруг оси x: 0 0 1 0 cos Q sin Q 0 sin Q cos Q 0 0 0 0 0 при Q 90 , 0 1 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 то есть первая строка и первый столбец имеют вид 1 0 0 0 Примеры: 1 0 0 0 1 2 0 1 0 1 0 0 0 0 1 0 1 0 2 1, 0 0 0 1 0 0 1 2 0 1 1 0 0 1 0 1 0 0 0 2 1 1 , 0 0 0 0 0 1 0 1 1 2 0 1 0 0 1 0 0 0 0 0 2 1 0 1 , 0 1 0 0 0 1 Вокруг оси y – аналогично: cos 0 sin 0 0 sin 0 1 0 0 при 90 , 0 cos 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 1 cos sin 0 0 sin cos 0 0 при 90 , 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 Вокруг оси z: Положительное направление по-прежнему определяется как направление против часовой стрелки, если смотреть вдоль оси, вокруг которой осуществляется вращение, к началу координат. Отметим, что вследствие не коммутативности умножения матриц при выполнении композиции вращения порядок преобразований существенен ( в отличии от вращения на плоскости ). 2.4 Отображение относительно координатных плоскостей Отображение относительно плоскости X0Y меняет лишь знак Zкоординаты точек. Таким образом, 1 0 0 0 0 0 0 1 0 0 – отображение относительно X0Y. 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 – отображение относительно X0Z. 1 0 0 1 0 0 0 1 0 0 – отображение относительно Y0Z. 0 1 0 0 0 1 2.2.5 Пространственный перенос Трехмерный линейный перенос изображения определяется выражением: ~x ~y ~z h~ x y откуда то есть 1 0 0 1 z 1 0 0 l m 0 0 0 0 1 0 n 1 ~x ~y ~z h~ x l y m z n 1, x * y* z * 1 x l y m z n 1 . 2.2.6 Трехмерное вращение вокруг произвольной оси В двумерном случае вращение вокруг произвольной оси осуществлялось путем композиции преобразований: переноса начала координат в точку пересечения оси вращения с плоскостью XY; вращения вокруг оси; переноса начала координат в исходное состояние. При этом ось вращения должна быть перпендикулярна плоскости X0Y. В трехмерном случае ставится задача вращения вокруг произвольной оси в трехмерном пространстве. Как и для плоскости, метод заключается в последовательном выполнении переноса, вращения вокруг оси, проходящей через начало координат и обратного переноса. При этом, однако, ось, проходящая через начало координат, может иметь произвольное направление. Итак, если ось, вокруг которой выполняется вращение, проходит через точку A l , m, n, то матрица преобразования однородных координат определяется как 1 0 0 l 0 1 0 0 1 0 R 0 0 0 m n 1 l m 0 1 0 0 0 1 0 0 0 0 1 0 n 1 Определим элементы матрицы вращения R. Некоторые сведения из математики. Направление произвольной оси, проходящей через начало координат, удобно определять через так называемые направляющие косинусы. Единичный вектор направления задается как n n1i n2 j n3 k где n1 cos , n2 cos , n3 cos - направляющие косинусы, или в векторной форме n n1 n2 Скалярное произведение определяется как n3 ; n 1 вектора на n произвольный вектор Р P n P n cosW (результатом будет число) Если P x y z , то P n x y n1 z n2 n3 Векторное произведение в системе координат (i, j, k) задается как j k i n P det n1 n2 n3 x y z i n2 z n3 y j n3 x n1 z k n1 y n2 x или в матричной форме n P x y 0 z n3 n2 n3 0 n1 n2 n1 0 При этом справедливо выражение n P n P sin W P sin W Направление вектора n P перпендикулярно плоскости nОP. Теперь вернемся к получению элементов матрицы вращения R. Здесь OP OP * , PQ P * Q PQ OQ; P*Q OQ; P*S PQ Для получения элементов матрицы R необходимо координаты точки P * выразить через координаты точки P, угол поворота и направление оси вращения n. OQ QP * OP * (или Q QP * P * ) QP * QS SP* OQ QP OP (или Q QP P ) следует QP P Q Далее QS QP * cos QP cos P Q cos Поскольку направления QS и QP совпадают, то QS P Q cos . Объединяя, получим P * Q P Q cos SP* Длина вектора SP* SP* QP * sin QP sin P Q sin Направление вектора SP* перпендикулярно плоскости QОP, параллельно вектору n P . Единичный вектор в этом направлении определяется соотношением u Таким образом, SP* то есть nP nP nP P sin nP P Q sin P sin При этом: P sin QP P Q . Следовательно: SP * n P sin Перепишем (2.44): P * Q P Q cos n P sin Величина Q определяется Q P cos , направление Q совпадает с n, так как: P cos P n, то Q P n n . Тогда перепишем (2.45) P * P n n P cos P n n cos n P sin P n n 1 cos P cos P n sin . Таким образом, мы выразили координаты точки P * через координаты точки P, угол Q и вектор n. Выражение в фигурных скобках как раз и позволяет получить требуемую матрицу вращения. 2 Задание Составить программу, реализующую трехмерное преобразование с фигурой (см. таблицу). Для всех вариантов фигура должна отображаться в контурном виде без удаления невидимых линий и уметь вращаться вокруг произвольной оси. Управление преобразованием по осям осуществлять с помощью девяти клавиш (<1>…<9>) на цифровой клавиатуре. 3 Варианты заданий Варианты заданий приведены в таблице. Таблица – Варианты заданий Вари Фигура ант № 1 Параллелепипед 2 3 Параллелепипед Параллелепипед 4 Параллелепипед 5 Параллелепипед 6 Октаэдр 7 8 Октаэдр Октаэдр 9 Октаэдр 10 Октаэдр Преобразование Изменение масштаба по осям X,Y,Z и общее масштабирование по трем осям. Перенос по осям X,Y,Z. Перенос одновременно по осям XY, XZ., YZ. Отражение относительно плоскостей XOZ, YOZ, XOY. Отражение одновременно относительно плоскостей XOZ и YOZ, XOZ и XOY, XOY и YOZ. Изменение масштаба по осям X,Y,Z и общее масштабирование по трем осям. Перенос по осям X,Y,Z. Перенос одновременно по осям XY, XZ., YZ. Отражение относительно плоскостей XOZ, YOZ, XOY. Отражение одновременно относительно плоскостей XOZ и YOZ, XOZ и XOY, XOY и YOZ.