Отчет по лабораторной работе №5 по дисциплине компьютерная графика
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
Федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
«НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ
ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»
Институт кибернетики
Кафедра информатики и проектирования систем
Отчет по лабораторной работе №5
по дисциплине КОМПЬЮТЕРНАЯ ГРАФИКА
Вариант 25
Разработчик:
студент группы 8в83
Сафронов Б.А.
Согласовано:
доцент
Демин А. Ю.
Томск 2011
ПРЕОБРАЗОВАНИЯ В ПРОСТРАНСТВЕ. ПРОЕКЦИИ
Задание:
Реализовать с заданным телом все виды преобразований в пространстве: перенос по осям , отражение относительно основных плоскостей, масштабирование, поворот на заданные углы относительно осей. Предусмотреть восстановление исходной позиции тела. Предусмотреть переключение в различные виды проекций: вид спереди, косоугольные, перспективную. Управление организовать как через интерфейсные элементы (меню, кнопки, строки редактирования и пр.), так и через "горячие" клавиши.
Код программы:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace _3D_graph
{
class Figure
{
public static int Width, Height;
public Figure(int w, int h)
{
Width = w;
Height = h;
}
const int arraySize = 12;
// Матрица ромба для проекции
public static double[,] _Diamond = new double[arraySize, 4] { { 0, 0, 0, 1},
{ 0, 0,-50, 1},
{ 30, 0,-80, 1},
{ 80, 0, -80, 1},
{ 80, 0, 0, 1},
{ 0, 80, 0, 1},
{ 0, 80,-80, 1},
{ 80, 80,-80, 1},
{ 80, 80, -30, 1},
{ 50, 80, 0, 1},
{ 0, 30, -80, 1},
{ 80, 50, 0, 1}
};
// Матрица ромба для преобразований без проекции
public static double[,] _WorkingDiamond = (double[,])_Diamond.Clone();
// Матрица ромба для восстановления
public static double[,] _RecoveredDiamond = (double[,])_Diamond.Clone();
// Матрица для перевода ромба в проекцию
public static double[,] _ProjectionMatrixStand = new double[4, 4] {{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}};
public static double[,] _ProjectionMatrixPersp = new double[4, 4] {{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 1, 0.005},
{ 0, 0, 0, 1}};
public static double[,] _ProjectionMatrixKaval = new double[4, 4] {{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ Math.Cos(Math.PI * 5 / 45.0), Math.Sin(Math.PI * 5 / 45.0), 0, 0},
{ 0, 0, 0, 1}};
// Матрица масштабирования, везде стоит значение 1, потому что значение масштаба будет присваиваться в функции
public static double[,] _Zoom = new double[4, 4] {{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1}};
// Матрица поворота
public static double o = Math.PI * 5 / 180.0;
public static double[,] _Rotate = new double[3, 3] { { Math.Cos(o), Math.Sin(o), Math.Sin(o)},
{ -Math.Sin(o), Math.Cos(o), Math.Sin(o)},
{ Math.Sin(o), -Math.Sin(o), Math.Cos(o)} };
/*
* Перенос фигуры в условный центр координат
*/
public static void ToScreen(double[,] Matrix)
{
for (int i = 0; i < arraySize; i++)
{
Matrix[i, 0] = Width / 2 + Matrix[i, 0];
Matrix[i, 1] = Height / 2 - Matrix[i, 1];
}
}
/*
* Перенос фигуры в рабочую точку
*/
public static void ToCoor(double[,] Matrix)
{
for (int i = 0; i < arraySize; i++)
{
Matrix[i, 0] = Width / 2 - Matrix[i, 0];
Matrix[i, 1] = Height / 2 - Matrix[i, 1];
}
}
/*
* Перевод изображения в центральную одноточечную проекцию
*/
public static void ToProjection(double[,] Matrix, int projection)
{
if (projection == 1)
{
for (int i = 0; i < arraySize; i++)
{
for (int j = 0; j < 4; j++)
{
Matrix[i, j] = Matrix[i, 0] * _ProjectionMatrixStand[0, j] +
Matrix[i, 1] * _ProjectionMatrixStand[1, j] +
Matrix[i, 2] * _ProjectionMatrixStand[2, j] +
Matrix[i, 3] * _ProjectionMatrixStand[3, j];
}
}
for (int i = 0; i < arraySize; i++)
for (int j = 0; j < 4; j++)
Matrix[i, j] = Matrix[i, j] / Matrix[i, 3];
} else if (projection == 2)
{
for (int i = 0; i < arraySize; i++)
{
for (int j = 0; j < 4; j++)
{
Matrix[i, j] = Matrix[i, 0] * _ProjectionMatrixPersp[0, j] +
Matrix[i, 1] * _ProjectionMatrixPersp[1, j] +
Matrix[i, 2] * _ProjectionMatrixPersp[2, j] +
Matrix[i, 3] * _ProjectionMatrixPersp[3, j];
}
}
for (int i = 0; i < arraySize; i++)
for (int j = 0; j < 4; j++)
Matrix[i, j] = Matrix[i, j] / Matrix[i, 3];
} else if (projection == 3)
{
for (int i = 0; i < arraySize; i++)
{
for (int j = 0; j < 4; j++)
{
Matrix[i, j] = Matrix[i, 0] * _ProjectionMatrixKaval[0, j] +
Matrix[i, 1] * _ProjectionMatrixKaval[1, j] +
Matrix[i, 2] * _ProjectionMatrixKaval[2, j] +
Matrix[i, 3] * _ProjectionMatrixKaval[3, j];
}
}
for (int i = 0; i < arraySize; i++)
for (int j = 0; j < 4; j++)
Matrix[i, j] = Matrix[i, j] / Matrix[i, 3];
}
}
/*
* Копирование элементов рабочей матрицы
*/
public static void Trans()
{
for (int i = 0; i < arraySize; i++)
for (int j = 0; j < 4; j++)
_Diamond[i, j] = _WorkingDiamond[i, j];
}
/*
* Сдвиг изображения по осям
*/
public static void Movement(double[,] Matrix, int Value, int axis)
{
if (Value < 0) for (int i = 0; i < arraySize; i++) Matrix[i, axis] = Matrix[i, axis] - 10;
if (Value > 0) for (int i = 0; i < arraySize; i++) Matrix[i, axis] = Matrix[i, axis] + 10;
}
/*
* Масштабирование
*/
public static void Zoom(double[,] Matrix, int axis, double Scale)
{
double[] StartCoor = new double[3];
for (int k = 0; k < 3; k++) StartCoor[k] = Matrix[0, k];
for (int t = 0; t < arraySize; t++)
for (int j = 0; j < 3; j++) Matrix[t, j] = Matrix[t, j] - StartCoor[j];
// Преобразование матрицы масштабирования в соответствии с осью
if (Scale > 0) _Zoom[axis, axis] = Scale;
if (Scale < 0) _Zoom[axis, axis] = -1 / Scale;
if (Scale == 0) MessageBox.Show("Задайте значение масштаба");
for (int i = 0; i < arraySize; i++)
{
for (int j = 0; j < 3; j++)
{
Matrix[i, j] = Matrix[i, 0] * _Zoom[0, j] + Matrix[i, 1] * _Zoom[1, j] + Matrix[i, 2] * _Zoom[2, j] + Matrix[i, 3] * _Zoom[3, j];
}
}
// Возврат матрицы масштабирования в исходный вид
_Zoom[axis, axis] = 1;
for (int t = 0; t < arraySize; t++)
for (int j = 0; j < 3; j++) Matrix[t, j] = Matrix[t, j] + StartCoor[j];
}
/*
* Поворот фигуры
*/
public static void Rotate(double[,] Matrix, int axis, double angle)
{
angle = Math.PI * angle / 180.0;
_Rotate = new double[3, 3] { { (double)Math.Cos(angle), (double)Math.Sin(angle), -(double)Math.Sin(angle)},
{ -(double)Math.Sin(angle), (double)Math.Cos(angle), (double)Math.Sin(angle)},
{ (double)Math.Sin(angle), -(double)Math.Sin(angle), (double)Math.Cos(angle)} };
double[,] RecoveredRotate = new double[3, 3];
// Изменение матрицы поворота, для поворота вокруг заданной оси
for (int j = 0; j < 3; j++)
{
RecoveredRotate[0, j] = _Rotate[axis, j];
_Rotate[axis, j] = 0;
RecoveredRotate[1, j] = _Rotate[j, axis];
_Rotate[j, axis] = 0;
}
_Rotate[axis, axis] = 1;
for (int i = 0; i < arraySize; i++)
{
double x, y, z;
x = Matrix[i, 0];
y = Matrix[i, 1];
z = Matrix[i, 2];
for (int j = 0; j < 3; j++)
{
Matrix[i, j] = x * _Rotate[0, j] + y * _Rotate[1, j] + z * _Rotate[2, j];
}
}
}
/*
* Отражение фигуры
*/
public static void Reflect(double[,] Matrix, int axis)
{
double[,] ReflMatrixXoZ = { {1,0,0},
{0,-1,0},
{0,0,1} };
double[,] ReflMatrixXoY = { {1,0,0},
{0,1,0},
{0,0,-1} };
double[,] ReflMatrixYoZ = { {-1,0,0},
{0,1,0},
{0,0,1} };
if (axis == 0)
{
for (int i = 0; i < arraySize; i++)
{
double x, y, z;
x = Matrix[i, 0];
y = Matrix[i, 1];
z = Matrix[i, 2];
for (int j = 0; j < 3; j++)
{
Matrix[i, j] = x * ReflMatrixXoZ[0, j] + y * ReflMatrixXoZ[1, j] + z * ReflMatrixXoZ[2, j];
}
}
} else
if (axis == 1)
{
for (int i = 0; i < arraySize; i++)
{
double x, y, z;
x = Matrix[i, 0];
y = Matrix[i, 1];
z = Matrix[i, 2];
for (int j = 0; j < 3; j++)
{
Matrix[i, j] = x * ReflMatrixXoY[0, j] + y * ReflMatrixXoY[1, j] + z * ReflMatrixXoY[2, j];
}
}
} else
if (axis == 2)
{
for (int i = 0; i < arraySize; i++)
{
double x, y, z;
x = Matrix[i, 0];
y = Matrix[i, 1];
z = Matrix[i, 2];
for (int j = 0; j < 3; j++)
{
Matrix[i, j] = x * ReflMatrixYoZ[0, j] + y * ReflMatrixYoZ[1, j] + z * ReflMatrixYoZ[2, j];
}
}
}
}
/*
* Восстановление ромба в исходное положение
*/
public static void Recover()
{
for (int i = 0; i < arraySize; i++)
for (int j = 0; j < 4; j++) _WorkingDiamond[i, j] = _RecoveredDiamond[i, j];
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace _3D_graph
{
public partial class Graph : Form
{ Pen figurePen = new Pen(Color.White);
Pen axisPen = new Pen(Color.White);
Object senderNew;
Graphics graph;
Rectangle Rect;
PaintEventArgs q;
/*
* Конструктор класса
*/
public Graph()
{ InitializeComponent();
graph = pictureBox1.CreateGraphics();
Rect = new Rectangle(pictureBox1.Location.X, pictureBox1.Location.Y,
pictureBox1.Width, pictureBox1.Height);
q = new PaintEventArgs(graph, Rect);
this.KeyPreview = true;
Figure.Width = this.pictureBox1.Width;
Figure.Height = this.pictureBox1.Height;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
e.Graphics.DrawLine(axisPen, (this.pictureBox1.Width / 2), 0, (this.pictureBox1.Width / 2), this.pictureBox1.Height);
e.Graphics.DrawLine(axisPen, 0, (this.pictureBox1.Height / 2), this.pictureBox1.Width, (this.pictureBox1.Height / 2));
if (radioButton1.Checked) Figure.ToProjection(Figure._Diamond, 1);
if (radioButton2.Checked) Figure.ToProjection(Figure._Diamond, 2);
if (radioButton3.Checked) Figure.ToProjection(Figure._Diamond, 3);
Figure.ToScreen(Figure._Diamond);
PaintFigures(7, Figure._Diamond, e);
}
/*
* Рисование фигуры
*/
private void PaintFigures(int Index, double[,] _Matrix, PaintEventArgs e)
{
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[0, 0]), (int)Math.Round(_Matrix[0, 1]), (int)Math.Round(_Matrix[1, 0]), (int)Math.Round(_Matrix[1, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[1, 0]), (int)Math.Round(_Matrix[1, 1]), (int)Math.Round(_Matrix[2, 0]), (int)Math.Round(_Matrix[2, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[2, 0]), (int)Math.Round(_Matrix[2, 1]), (int)Math.Round(_Matrix[3, 0]), (int)Math.Round(_Matrix[3, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[3, 0]), (int)Math.Round(_Matrix[3, 1]), (int)Math.Round(_Matrix[4, 0]), (int)Math.Round(_Matrix[4, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[4, 0]), (int)Math.Round(_Matrix[4, 1]), (int)Math.Round(_Matrix[0, 0]), (int)Math.Round(_Matrix[0, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[5, 0]), (int)Math.Round(_Matrix[5, 1]), (int)Math.Round(_Matrix[6, 0]), (int)Math.Round(_Matrix[6, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[6, 0]), (int)Math.Round(_Matrix[6, 1]), (int)Math.Round(_Matrix[7, 0]), (int)Math.Round(_Matrix[7, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[7, 0]), (int)Math.Round(_Matrix[7, 1]), (int)Math.Round(_Matrix[8, 0]), (int)Math.Round(_Matrix[8, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[8, 0]), (int)Math.Round(_Matrix[8, 1]), (int)Math.Round(_Matrix[9, 0]), (int)Math.Round(_Matrix[9, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[9, 0]), (int)Math.Round(_Matrix[9, 1]), (int)Math.Round(_Matrix[5, 0]), (int)Math.Round(_Matrix[5, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[0, 0]), (int)Math.Round(_Matrix[0, 1]), (int)Math.Round(_Matrix[5, 0]), (int)Math.Round(_Matrix[5, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[3, 0]), (int)Math.Round(_Matrix[3, 1]), (int)Math.Round(_Matrix[7, 0]), (int)Math.Round(_Matrix[7, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[1, 0]), (int)Math.Round(_Matrix[1, 1]), (int)Math.Round(_Matrix[10, 0]), (int)Math.Round(_Matrix[10, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[2, 0]), (int)Math.Round(_Matrix[2, 1]), (int)Math.Round(_Matrix[10, 0]), (int)Math.Round(_Matrix[10, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[10, 0]), (int)Math.Round(_Matrix[10, 1]), (int)Math.Round(_Matrix[6, 0]), (int)Math.Round(_Matrix[6, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[8, 0]), (int)Math.Round(_Matrix[8, 1]), (int)Math.Round(_Matrix[11, 0]), (int)Math.Round(_Matrix[11, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[9, 0]), (int)Math.Round(_Matrix[9, 1]), (int)Math.Round(_Matrix[11, 0]), (int)Math.Round(_Matrix[11, 1]));
e.Graphics.DrawLine(figurePen, (int)Math.Round(_Matrix[11, 0]), (int)Math.Round(_Matrix[11, 1]), (int)Math.Round(_Matrix[4, 0]), (int)Math.Round(_Matrix[4, 1]));
}
/*
* Перемещение по осям
*/
private void NegativeMoveX_Click(object sender, EventArgs e)
{ Figure.Movement(Figure._WorkingDiamond, -1, 0);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void PositiveMoveX_Click(object sender, EventArgs e)
{ Figure.Movement(Figure._WorkingDiamond, 1, 0);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void NegativeMoveY_Click(object sender, EventArgs e)
{ Figure.Movement(Figure._WorkingDiamond, -1, 1);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void PositiveMoveY_Click(object sender, EventArgs e)
{ Figure.Movement(Figure._WorkingDiamond, 1, 1);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void PositiveMoveZ_Click(object sender, EventArgs e)
{ Figure.Movement(Figure._WorkingDiamond, 1, 2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void NegativeMoveZ_Click(object sender, EventArgs e)
{ Figure.Movement(Figure._WorkingDiamond, -1, 2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
/*
* Масштабирование по осям
*/
private void ZoomX_Click(object sender, EventArgs e)
{
Figure.Zoom(Figure._WorkingDiamond,0,2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void ZoomY_Click(object sender, EventArgs e)
{
Figure.Zoom(Figure._WorkingDiamond,1,2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void ZoomZ_Click(object sender, EventArgs e)
{
Figure.Zoom(Figure._WorkingDiamond,2,2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void UnZoomX_Click(object sender, EventArgs e)
{
Figure.Zoom(Figure._WorkingDiamond, 0, -2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void UnZoomY_Click(object sender, EventArgs e)
{
Figure.Zoom(Figure._WorkingDiamond, 1, -2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void UnZoomZ_Click(object sender, EventArgs e)
{
Figure.Zoom(Figure._WorkingDiamond, 2, -2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
/*
* Вращение вокруг осей
*/
private void RotateX_Click(object sender, EventArgs e)
{ Figure.Rotate(Figure._WorkingDiamond,0, Double.Parse(textBoxAngle.Text));
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void RotateY_Click(object sender, EventArgs e)
{
Figure.Rotate(Figure._WorkingDiamond, 1, Double.Parse(textBoxAngle.Text));
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void RotateZ_Click(object sender, EventArgs e)
{
Figure.Rotate(Figure._WorkingDiamond, 2, Double.Parse(textBoxAngle.Text));
Figure.Trans();
pictureBox1_Paint(sender, q);
}
/*
* Восстановление фигуры
*/
private void RecoverMatrix_Click(object sender, EventArgs e)
{ Figure.Recover();
Figure.Trans();
pictureBox1_Paint(sender, q);
}
/*
* Отражение фигуры от плоскостей
*/
private void bReflX_Click(object sender, EventArgs e)
{
Figure.Reflect(Figure._WorkingDiamond, 0);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void bReflXoY_Click(object sender, EventArgs e)
{
Figure.Reflect(Figure._WorkingDiamond, 1);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
private void bReflYoZ_Click(object sender, EventArgs e)
{
Figure.Reflect(Figure._WorkingDiamond, 2);
Figure.Trans();
pictureBox1_Paint(sender, q);
}
/*
* Выбор проекции
*/
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
pictureBox1_Paint(sender, q);
}
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
pictureBox1_Paint(sender, q);
}
private void radioButton3_CheckedChanged(object sender, EventArgs e)
{
pictureBox1_Paint(sender, q);
}
private void radioButton1_Click(object sender, EventArgs e)
{
pictureBox1_Paint(sender, q);
}
//--------------------------------------------------------------------------------------------------
/*
* Управление с клавиатуры
*/
protected override void OnKeyDown(KeyEventArgs e)
{ base.OnKeyDown(e);
if (e.KeyCode == Keys.X) RotateX_Click(senderNew, q);
if (e.KeyCode == Keys.Y) RotateY_Click(senderNew, q);
if (e.KeyCode == Keys.Z) RotateZ_Click(senderNew, q);
if (e.KeyCode == Keys.NumPad8) PositiveMoveY_Click(senderNew, q);
if (e.KeyCode == Keys.NumPad5) NegativeMoveY_Click(senderNew, q);
if (e.KeyCode == Keys.NumPad4) NegativeMoveX_Click(senderNew, q);
if (e.KeyCode == Keys.NumPad6) PositiveMoveX_Click(senderNew, q);
if (e.KeyCode == Keys.NumPad7) NegativeMoveZ_Click(senderNew, q);
if (e.KeyCode == Keys.NumPad1) PositiveMoveZ_Click(senderNew, q);
}
private void Graph_Load(object sender, EventArgs e)
{ senderNew = sender;
}
private void Graph_Paint(object sender, PaintEventArgs e)
{
pictureBox1_Paint(sender, q);
}
}
}
Результат работы программы:
Рисунок - Скриншот работы программы
Вывод:
В результате проделанной работы были реализованы алгоритмы, производящие все виды преобразований в пространстве, такие как перенос по осям OX, OY, OZ, отражение относительно плоскостей, масштабирование независимо по осям, поворот на заданные углы относительно произвольной точки, указываемой в ходе выполнения программы. При реализации использовалась подпрограмма перемножения матриц, для осуществления поворота, масштабирования и отражения фигуры. Каждая матрица предназначена для определенного вида преобразований. Для преобразования трехмерного изображения в двумерное, использовались матрицы перевода в различные виды проекций (перспективная одноточечная или Кавалье).
страница 1
скачать
Другие похожие работы: