Алгоритми растрової графіки


Завдання 1

Растровий сплайн сканування

Растрове розгорнення ліній

Реалізувати на вибір один з наступних алгоритмів

Алгоритм Брезенхэма побудови відрізка з довільним кутовим коефіцієнтом розташованого в будь-якому чотирьох квадрантів;

Алгоритм Брезенхэма побудови кола;

Побудувати довільну криву, задану як таблиця, на множині не рівновіддалених вузлів за допомогою сплайнів, що згладжують.

Виконання завдання 1

#include <windows. h>

#include "draw. h"

Const double PI = 3.141592653;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

Char szClassName[] = "CG_DDA_Fixed";

Int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

HWND hWnd;

MSG lpMsg;

WNDCLASS wc;

// Заполняем структуру класса окна

Wc. style = CS_HREDRAW | CS_VREDRAW;

Wc. lpfnWndProc = WndProc;

Wc. cbClsExtra = 0;

Wc. cbWndExtra = 0;

Wc. hInstance = hInstance;

Wc. hIcon = NULL;

Wc. hCursor = LoadCursor(NULL, IDC_ARROW);

Wc. hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

Wc. lpszMenuName = NULL;

Wc. lpszClassName = szClassName;

// Регистрируем класс окна

If (!RegisterClass(&;wc))

{

MessageBox(NULL, "Cannot register class", "Error", MB_OK);

Return 0;

}

// Создаем основное окно приложения

HWnd = CreateWindow(

SzClassName, // Имя класса

"Алгоритм Брезенхэма", // Текст заголовка

WS_OVERLAPPEDWINDOW, // Стиль окна

    50, 50, // Позиция левого верхнего угла 600, 500, // Ширина и высота окна (HWND)NULL, // Указатель на родительское окно NULL (HMENU)NULL, // Используется меню класса окна (HINSTANCE)hInstance, // Указатель на текущее приложение

NULL); // Передается в качестве lParam в событие WM_CREATE

If (!hWnd)

{

MessageBox(NULL, "Не удается создать главное окно!", "Ошибка", MB_OK);

Return 0;

}

// Показываем наше окно

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

// Выполняем цикл обработки сообщений до закрытия приложения

While (GetMessage(&;lpMsg, NULL, 0, 0)) {

TranslateMessage(&;lpMsg);

DispatchMessage(&;lpMsg);

}

Return (lpMsg. wParam);

}

////////////////////////////////////////////////////////////////////////////////////////////////////

LRESULT CALLBACK WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)

{

PAINTSTRUCT ps;

RECT Rect ;

HDC hdc, hCmpDC;

HBITMAP hBmp;

Static int x1, y1, x2, y2;

Static bool draw_line = false;

Switch (messg)

{

Case WM_PAINT:

GetClientRect(hWnd, &;Rect);

Hdc = BeginPaint(hWnd, &;ps);

// Создание нового контекста для двойной буфферизации

HCmpDC = CreateCompatibleDC(hdc);

HBmp = CreateCompatibleBitmap(hdc, Rect. right - Rect. left,

Rect. bottom - Rect. top);

SelectObject(hCmpDC, hBmp);

// Закраска фоновым цветом

LOGBRUSH br;

Br. lbStyle = BS_SOLID;

Br. lbColor = 0xE1E4E7;

HBRUSH brush;

Brush = CreateBrushIndirect(&;br);

FillRect(hCmpDC, &;Rect, brush);

DeleteObject(brush);

// Рисование

If (draw_line)

{

Line(hCmpDC, x1, y1, x2, y2);

}

// Вывод на экран

SetStretchBltMode(hdc, COLORONCOLOR);

BitBlt(hdc, 0, 0, Rect. right - Rect. left, Rect. bottom - Rect. top,//hdc, 0, 0,...

HCmpDC, 0, 0, SRCCOPY);//hCmpDC, 0, 0

DeleteDC(hCmpDC);

DeleteObject(hBmp);

HCmpDC = NULL;

EndPaint(hWnd, &;ps);

Break;

Case WM_LBUTTONDOWN:

X1 = LOWORD(lParam);

Y1 = HIWORD(lParam);

Draw_line = false;

InvalidateRect(hWnd, NULL, FALSE);

Break;

Case WM_MOUSEMOVE:

If (UINT(wParam) &; MK_LBUTTON) {

X2 = LOWORD(lParam);

Y2 = HIWORD(lParam);

Draw_line = true;

InvalidateRect(hWnd, NULL, FALSE);

}

Break;

Case WM_LBUTTONUP:

Draw_line = true;

Break;

Case WM_DESTROY:

PostQuitMessage(0);

Break;

Default:

Return (DefWindowProc(hWnd, messg, wParam, lParam));

}

Return (0);

}

Скріншоти завдання 1

Завдання 2

Растрове розгорнення двовимірних областей

Зафарбувати внутрішню область довільного неопуклого багатокутника за допомогою методу сканування зі списком активних ребер.

Виконання завдання 2

Using System;

Using System. Collections. Generic;

Using System. ComponentModel;

Using System. Data;

Using System. Drawing;

Using System. Drawing. Imaging;

Using System. Linq;

Using System. Runtime. InteropServices;

Using System. Text;

Using System. Threading. Tasks;

Using System. Windows. Forms;

Namespace ZacraskaFigure2D

{

Public partial class Form1 : Form

{

Public Form1()

{

InitializeComponent();

}

Private void Form1_Paint(object sender, PaintEventArgs e)

{

}

Void PictureFill(Bitmap bitmap, int x, int y, Color color)

{

BitmapData data = bitmap. LockBits(

New Rectangle(0, 0, bitmap. Width, bitmap. Height),

ImageLockMode. ReadWrite, PixelFormat. Format32bppArgb);

Int[] bits = new int[data. Stride / 4 * data. Height];

Marshal. Copy(data. Scan0, bits, 0, bits. Length);

LinkedList<Point> check = new LinkedList<Point>();

Int floodTo = color. ToArgb();

Int floodFrom = bits[x + y * data. Stride / 4];

Bits[x + y * data. Stride / 4] = floodTo;

If (floodFrom!= floodTo)

{

Check. AddLast(new Point(x, y));

While (check. Count > 0)

{

Point cur = check. First. Value;

Check. RemoveFirst();

Foreach (Point off in new Point[] {

New Point(0, -1), new Point(0, 1),

New Point(-1, 0), new Point(1, 0)})

{

Point next = new Point(cur. X + off. X, cur. Y + off. Y);

If (next. X >= 0 &;&; next. Y >= 0 &;&;

Next. X < data. Width &;&;

Next. Y < data. Height)

{

If (bits[next. X + next. Y * data. Stride / 4] == floodFrom)

{

Check. AddLast(next);

Bits[next. X + next. Y * data. Stride / 4] = floodTo;

}

}

}

}

}

Marshal. Copy(bits, 0, data. Scan0, bits. Length);

Bitmap. UnlockBits(data);

}

Private void pictureBox1_Paint(object sender, PaintEventArgs e)

{

Using (Bitmap bitmap = new Bitmap(this. Width, this. Height))

{

Using (Graphics g = Graphics. FromImage(bitmap))

{

G. Clear(Color. LightGray);

List<Point> points = new List<Point>();

For (double i = 0; i < 10000; i++)

{

Double dist = (i % 2 == 0) ?200: 70;

Double x = 200 + Math. Cos(i / 10d * Math. PI * 2d) * dist;

Double y = 200 + Math. Sin(i / 10d * Math. PI * 2d) * dist;

Points. Add(new Point((int)x, (int)y));

}

G. DrawPolygon(Pens. Black, points. ToArray());

}

PictureFill(bitmap, 200,200, Color. GreenYellow);

E. Graphics. DrawImage(bitmap, 0, 0);

}

}

}

}

Скріншоти завдання 2

Завдання 3

Дротова модель опуклого багатогранника

Задати багатогранник (куб або тетраедр) координатами вершин з врахуванням належності до грані в системі світових координат

Задати вектор спостереження його початковою точкою в сферичних координатах.

За допомогою матриці видових перетворень перевести координати вершин у систему координат, зв'язану з точкою спостереження.

За допомогою проективних перетворень перейти від видових координат до системи координат екранної площини.

Виконання завдання 3

Using System;

Using System. Collections. Generic;

Using System. ComponentModel;

Using System. Data;

Using System. Drawing;

Using System. Linq;

Using System. Text;

Using System. Threading. Tasks;

Using System. Windows. Forms;

Namespace CubeTrheeD3

{

Public partial class Form1 : Form

{

//Начало координат:

Private const double x_focus = 0;

Private const double y_focus = 0;

Private const double z_focus = 0;

//Сферические координаты глаза наблюдателя (точки E):

Private float r_Eye;

Private float phi_Eye;

Private float theta_Eye;

//Переменные и матрица (как массив) MatrixProjection:

//(во всех массивах нулевые индексы не используем):

Private const double pi = Math. PI;

Private int Tetrahedron;

Private int Cube;

Private int Octahedron;

Private int Dodecahedron;

Private int Icosahedron_first;

Private int Icosahedron_last;

Private float[,] MatrixProjection = new float[5, 5];

//Для параллельного проецирования объекта на экран

//(parallel projection) задаем константу:

Private const int ParallelProjection = 0;

//Для перспективного проецирования объекта на экран

//(perspective projection) задаем константу:

Private const int PerspectiveProjection = 1;

//Объявляем массив Lines структуры Line, оператором new

//создаем массив из 100 элементов и инициализируем его,

//т. е всем элементам этого массива присваиваем значение null:

Public Line[] Lines = new Line[100];

//Объявляем и инициализируем переменную для индекса массива:

Public int NumLines = 0;

Public Form1()

{

InitializeComponent();

}

Private void btnPlay_Click(object sender, EventArgs e)

{

//Вызываем метод для перспективного проецирования,

Projection(ref MatrixProjection, PerspectiveProjection,

R_Eye, phi_Eye, theta_Eye,

(float)x_focus, (float)y_focus, (float)z_focus, 0, 1, 0);

//Рассчитываем параметры геометрического тела:

СalculateParameters();

//Связываем элемент PictureBox1 с классом Bitmap:

PictureBox1.Image = new Bitmap(pictureBox1.Width,

PictureBox1.Height);

//Проектируем и в PictureBox рисуем выбранное нами тело:

Designing((Bitmap)pictureBox1.Image);

}

Private void btnClose_Click(object sender, EventArgs e)

{

Application. Exit();

}

Private void Form1_Load(object sender, EventArgs e)

{

//Задаем координаты глаза наблюдателя, например:

R_Eye = 4;

Phi_Eye = (float)(0.05 * pi);

Theta_Eye = (float)(0.03 * pi);//0.03

}

Protected override bool ProcessCmdKey(ref Message msg, Keys keyData)

{

//Задаем угол поворота фигуры после нажатия клавиши:

Const float delta_theta = (float)pi / 50; ;

//Рассчитываем новые координаты глаза наблюдателя:

If (keyData == Keys. Left)

Theta_Eye = theta_Eye - delta_theta;

If (keyData == Keys. Right)

Theta_Eye = theta_Eye + delta_theta;

If (keyData == Keys. Up)

Phi_Eye = phi_Eye - delta_theta;

If (keyData == Keys. Down)

Phi_Eye = phi_Eye + delta_theta;

//Проектируем выбранное нами геометрическое тело:

Projection(ref MatrixProjection, PerspectiveProjection,

R_Eye, phi_Eye, theta_Eye,

    (float)x_focus, (float)y_focus, (float)z_focus, 0, 1, 0);

Designing((Bitmap)pictureBox1.Image);

//В элементе PictureBox перерисовываем объект:

PictureBox1.Refresh();

Return true;

}

//Проектируем и при помощи процедуры DrawSolid

Private void Designing(Bitmap bmp)

{

//Создаем объект g класса Graphics:

Graphics g;

//Связываем объект g с изображением bmp:

G = Graphics. FromImage(bmp);

//Задаем белый цвет типа Window

//для элемента управления PictureBox1:

G. Clear(SystemColors. ControlLight);

//Высвобождаем ресурсы от графического объекта g:

G. Dispose();

//Преобразуем точки:

TransformAllDataFull(ref MatrixProjection);

// DrawSolid(bmp, Cube, Octahedron - 1,Color. Black, false);

DrawSolid(bmp, Octahedron, Dodecahedron - 1,Color. Blue, false);

}

//Рассчитываем параметры геометрических тел и осей:

Private void СalculateParameters()

{

Float theta1; float theta2;

Float s1; float s2; float c1; float c2;

Float S; float R; float H; float A;

Float B; float C; float D; float X;

Float Y; float y2; float M; float N;

//Оси координат:

DesigningLine(0, 0, 0, 0.5f, 0, 0); //Ось x.

DesigningLine(0, 0, 0, 0, 0.5f, 0); //Ось y.

DesigningLine(0, 0, 0, 0, 0, 0.5f); //Ось z.

//Октаэдр (Octahedron):

Octahedron = NumLines + 1;

DesigningLine(0, 1, 0, 1, 0, 0);

DesigningLine(0, 1, 0, -1, 0, 0);

DesigningLine(0, 1, 0, 0, 0, 1);

DesigningLine(0, 1, 0, 0, 0, -1);

DesigningLine(0, -1, 0, 1, 0, 0);

DesigningLine(0, -1, 0, -1, 0, 0);

DesigningLine(0, -1, 0, 0, 0, 1);

DesigningLine(0, -1, 0, 0, 0, -1);

DesigningLine(0, 0, 1, 1, 0, 0);

DesigningLine(0, 0, 1, -1, 0, 0);

DesigningLine(0, 0, -1, 1, 0, 0);

DesigningLine(0, 0, -1, -1, 0, 0);

}

//Объявляем структуру Line и массивы этой структуры:

Public struct Line

{

//Объявляем массивы для соединения точек (points):

Public float[] fr_points;

Public float[] to_points;

//Массивы для соединения преобразованных точек:

//(transformed (tr) points):

Public float[] fr_tr_points;

Public float[] to_tr_points;

//Создаем и инициализируем массивы, т. е.

//всем пяти элементам каждого массива присваиваем 0:

Public void Initialize()

{

Fr_points = new float[5];

To_points = new float[5];

Fr_tr_points = new float[5];

To_tr_points = new float[5];

}

}

//Проектируем линию между точками (x1,y1,z1),(x2,y2,z2):

Public void DesigningLine(float x1, float y1, float z1,

Float x2, float y2, float z2)

{

NumLines = NumLines + 1;

//Инициализируем и рассчитываем массив:

Lines[NumLines].Initialize();

Lines[NumLines].fr_points[1] = x1;

Lines[NumLines].fr_points[2] = y1;

Lines[NumLines].fr_points[3] = z1;

Lines[NumLines].fr_points[4] = 1;

Lines[NumLines].to_points[1] = x2;

Lines[NumLines].to_points[2] = y2;

Lines[NumLines].to_points[3] = z2;

Lines[NumLines].to_points[4] = 1;

}

//Применяем матрицу переноса (translation matrix)

//ко всем линиям, используя MatrixApplyFull.

//Преобразование не имеет 0, 0, 0, 1 в последнем столбце:

Public void TransformAllDataFull(ref float[,] M)

{

TransformDataFull(ref M, 1, NumLines);

}

//Применяем матрицу переноса (translation matrix)

//ко всем выделенным линиям, используя MatrixApplyFull.

//Преобразование не имеет 0, 0, 0, 1 в последнем столбце:

Public void TransformDataFull(ref float[,] M,

Int line1, int line2)

{

For (int i = line1; i <= line2; i++)

{

MatrixApplyFull(ref Lines[i].fr_points, ref M,

Ref Lines[i].fr_tr_points);

MatrixApplyFull(ref Lines[i].to_points, ref M,

Ref Lines[i].to_tr_points);

}

}

//Рисуем выделенные преобразованные линии:

Public void DrawSolid(Bitmap bmp,

Int first_line, int last_line, Color color, bool clear)

{

Float x1, y1, x2, y2;

Graphics g; Pen pen;

//Задаем толщину линии рисования, например, 2

//(цвет линии мы задали в процедуре Designing):

Pen = new Pen(color, 2);

//Связываем объект g с изображением bmp:

G = Graphics. FromImage(bmp);

If (clear) g. Clear(System. Drawing. Color. Black);

//Рисуем линии:

For (int i = first_line; i <= last_line; i++)

{

X1 = Lines[i].fr_tr_points[1];

Y1 = Lines[i].fr_tr_points[2];

X2 = Lines[i].to_tr_points[1];

Y2 = Lines[i].to_tr_points[2];

//Нормализуем и рисуем многогранник:

G. DrawLine(pen,

(x1 * bmp. Width / 4) + bmp. Width / 2.0F,

Bmp. Height / 2.0F - (y1 * bmp. Height / 4),

(x2 * bmp. Width / 4) + bmp. Width / 2.0F,

Bmp. Height / 2.0F - (y2 * bmp. Height / 4));

}

//Высвобождаем ресурсы от объектов g и pen:

G. Dispose(); pen. Dispose();

}

//Строим единичную матрицу:

Public void MatrixIdentity(ref float[,] M)

{

For (int i = 1; i <= 4; i++)

{

For (int j = 1; j <= 4; j++)

{

If (i == j) M[i, j] = 1;

Else M[i, j] = 0;

}

}

}

//Строим матрицу преобразования для поворота на угол theta

Public void m3LineRotate(ref float[,] M,

Float p1, float p2, float p3,

Float d1, float d2, float d3, float theta)

{

Float[,] T = new float[5, 5]; //Перенос.

Float[,] R1 = new float[5, 5]; //Вращение 1.

Float[,] r2 = new float[5, 5]; //Вращение 2.

Float[,] Rot3 = new float[5, 5]; //Вращение.

Float[,] R2i = new float[5, 5]; //Стоп вращению 2.

Float[,] R1i = new float[5, 5]; //Стоп вращению 1.

Float[,] Ti = new float[5, 5]; //Стоп переносу.

Float D, L;

Float[,] M12 = new float[5, 5];

Float[,] M34 = new float[5, 5];

Float[,] M1234 = new float[5, 5];

Float[,] M56 = new float[5, 5];

Float[,] M567 = new float[5, 5];

//Переносим плоскость к началу координат:

MatrixTranslate(ref T, - p1, - p2, - p3);

MatrixTranslate(ref Ti, p1, p2, p3);

//Вращаем вокруг оси z,

//пока линия не окажется в y-z плоскости:

MatrixIdentity(ref R1);

D = (float)Math. Sqrt(d1 * d1 + d2 * d2);

R1[1, 1] = d2 / D; R1[1, 2] = d1 / D;

R1[2, 1] = - R1[1, 2]; R1[2, 2] = R1[1, 1];

MatrixIdentity(ref R1i);

R1i[1, 1] = R1[1, 1]; R1i[1, 2] = - R1[1, 2];

R1i[2, 1] = - R1[2, 1]; R1i[2, 2] = R1[2, 2];

//Вращаем вокруг оси x, когда линия будет по оси y:

MatrixIdentity(ref r2);

L = (float)Math. Sqrt(d1 * d1 + d2 * d2 + d3 * d3);

R2[2, 2] = D / L; r2[2, 3] = - d3 / L;

R2[3, 2] = - r2[2, 3]; r2[3, 3] = r2[2, 2];

MatrixIdentity(ref R2i);

R2i[2, 2] = r2[2, 2]; R2i[2, 3] = - r2[2, 3];

R2i[3, 2] = - r2[3, 2]; R2i[3, 3] = r2[3, 3];

//Вращаем вокруг линии (оси y):

MatrixYRotate(ref Rot3, theta);

//Комбинируем матрицы:

M3MatMultiply(ref M12, ref T, ref R1);

M3MatMultiply(ref M34, ref r2, ref Rot3);

M3MatMultiply(ref M1234, ref M12, ref M34);

M3MatMultiply(ref M56, ref R2i, ref R1i);

M3MatMultiply(ref M567, ref M56, ref Ti);

M3MatMultiply(ref M, ref M1234, ref M567);

}

}

Скріншоти завдання 3

Похожие статьи




Алгоритми растрової графіки

Предыдущая | Следующая