Общий вид матрицы переноса. Общий вид матрицы масштабирования. Аффинные преобразования на плоскости

Страницы работы

Уважаемые коллеги! Предлагаем вам разработку программного обеспечения под ключ.

Опытные программисты сделают для вас мобильное приложение, нейронную сеть, систему искусственного интеллекта, SaaS-сервис, производственную систему, внедрят или разработают ERP/CRM, запустят стартап.

Сферы - промышленность, ритейл, производственные компании, стартапы, финансы и другие направления.

Языки программирования: Java, PHP, Ruby, C++, .NET, Python, Go, Kotlin, Swift, React Native, Flutter и многие другие.

Всегда на связи. Соблюдаем сроки. Предложим адекватную конкурентную цену.

Заходите к нам на сайт и пишите, с удовольствием вам во всем поможем.

Фрагмент текста работы

Лабораторная работа №3

«Аффинные преобразования на плоскости»

Цель работы: научиться выполнять простейшие аффинные преобразования на плоскости: перенос, сдвиг, поворот, масштабирование с зеркальным отражением. Написать программу, которая реализует последовательность этих преобразований для некоторого графического объекта.

Пусть имеется треугольник, однородные координаты вершин которого:

         

Выполним следующую последовательность преобразований:

1. Перенос на X = -3, Y = -5

2. Масштабирование относительно точки (1, 3):  kx = 1, ky = -1

3. Поворот относительно точки (0, 8)  на угол

4. Сдвиг относительно прямой  y = 4 вдоль оси OX с параметром сдвига

kx = 1

1. Перенос на X = -3, Y = -5:

Общий вид матрицы переноса:

в данном случае ,

После переноса координаты вершин треугольника:

            

2. Масштабирование относительно точки (1, 3):  kx = 1, ky = -1

Общий вид матрицы масштабирования:

Преобразование является сложным, поэтому надо выполнить последовательность преобразований:

а) перенос на X = -1, Y = -3

б) масштабирование с параметрами kx = 1, ky = -1

в) перенос на X = 1, Y = 3

Тогда матрица преобразования будет иметь вид:

    ,

После масштабирования координаты вершин треугольника:

                   

3. Поворот относительно точки (0, 8) на угол

Общий вид матрицы поворота:   

Преобразование является сложным, поэтому надо выполнить последовательность преобразований:

а) перенос на X = 0, Y = -8

б) поворот на угол

в) перенос на X = 0, Y = 8

Тогда матрица преобразования будет иметь вид:

После поворота координаты вершин треугольника:

         

4. Сдвиг относительно прямой  y = 4 вдоль оси OX с параметром сдвига

kx = 1

Общий вид матрицы сдвига вдоль оси X: 

Преобразование является сложным, поэтому надо выполнить последовательность преобразований:

а) перенос на X = 0, Y = -4

б) сдвиг вдоль оси OX с параметром сдвига kx = 1 в) перенос на X = 0, Y = 4

Тогда матрица преобразования будет иметь вид:

 

После сдвига координаты вершин треугольника:

          

Алгоритм работы программы:

Исходный текст программы на языке С#:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace FlatCurve

{

public partial class frmFlatCurve : Form

{

int aff_number = 0; //номер аффинного преобразования

int dkx = 20, dky = 20; // приращения в экранных точках при сдвиге начала координат

bool begin = false; //признак ввода начальных значений

float sizeX,sizeY; //масштаб по  x и y

float stepX, stepY; // приращение по x и y в одном пикселе

float relX, relY;   //координаты точки относительно начала координат

float[,] points = new float[3, 3]; // точки фигуры

PointF[] scr_points = new PointF[3];  // экранные точки

PointF XY = new PointF(); //текущая точка на экране

PointF center = new PointF(); // точка начала координат

public frmFlatCurve()

{

InitializeComponent();

center.X = pnlGrafik.Size.Width / 2-250;

center.Y = pnlGrafik.Size.Height / 2+150;

}

void mashtab(float kx,float ky)  //масштабирование

{

float[,] matr = { { kx, 0, 0 }, { 0, ky, 0 }, { 0, 0, 1 } };

points = matr_mult(matr, points);

}

void perenos(float tx, float ty)    //перенос

{

float[,] matr = { { 1, 0, tx }, { 0, 1, ty }, { 0, 0, 1 } };

points = matr_mult(matr, points);    

}

void povorot(float ugol)         //поворот на угол

{

float rad = (float) (ugol * Math.PI / 180);

float[,] matr = { {(float) Math.Cos(rad), (float)(-1*Math.Sin(rad)), 0 }, { (float) Math.Sin(rad), (float) Math.Cos(rad), 0 }, { 0, 0, 1 } };

points = matr_mult(matr, points);

}

void sdvig(float kx) //Сдвиг

{

float[,] matr = { { 1, kx, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };

points = matr_mult(matr, points);

}

float[,] matr_mult(float[,] matr, float[,] points)  //умножение матриц

{

int i, j, k;

float[,] rez = new float[3, 3];

for (i = 0; i < 3; i++)

for (j = 0; j < 3; j++)

{

rez[i, j] = 0;

for (k = 0; k < 3; k++)

rez[i, j] += matr[i, k] * points[k, j];

}

for (i = 0; i < 3; i++)

for (j = 0; j < 3; j++) points[i, j] = rez[i, j];

return rez;

}

//графическое построение

private void pnlGrafik_Paint(object sender, PaintEventArgs e)

{

Pen OXY = new Pen(Color.Blue, 2); //перо оси XOY

Pen setka = new Pen(Color.Gray, 1); //перо масштабной сетки

Pen figur = new Pen(Color.Red, 3); //перо для рисования фигуры

Graphics g = e.Graphics;

Font txt = new Font("Arial", 14, FontStyle.Bold);

int count = 0;

float cx, cy;  //текущие точки плоскости XOY

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

g.FillRectangle(Brushes.White, 0, 0, pnlGrafik.Size.Width, pnlGrafik.Size.Height);

sizeX = int.Parse(mashtab_ox.Value.ToString());

sizeY = int.Parse(mashtab_oy.Value.ToString());

stepX = 1 / sizeX;

stepY = 1 / sizeY;

//рисование масштабной сетки по x

for (XY.X = center.X, count = 0; XY.X < pnlGrafik.Size.Width; XY.X += sizeX, count++)

{

g.DrawLine(setka, XY.X, 0, XY.X, pnlGrafik.Size.Height);

g.DrawString(count.ToString(), txt, Brushes.Black, XY.X - txt.Size, center.Y);

}

for (XY.X = center.X, count = 0; XY.X > 0; XY.X -= sizeX, count--)

{

g.DrawLine(setka, XY.X, 0, XY.X, pnlGrafik.Size.Height);

if (count != 0)

g.DrawString(count.ToString(), txt, Brushes.Black, XY.X - 1.5f * txt.Size, center.Y);

}

//по y

for (XY.Y = center.Y, count = 0; XY.Y > 0; XY.Y -= sizeY, count++)

{

g.DrawLine(setka, 0, XY.Y, pnlGrafik.Size.Width, XY.Y);

g.DrawString(count.ToString(), txt, Brushes.Black, center.X - txt.Size, XY.Y);

}

for (XY.Y = center.Y, count = 0; XY.Y < pnlGrafik.Size.Height; XY.Y += sizeY, count--)

{

g.DrawLine(setka, 0, XY.Y, pnlGrafik.Size.Width, XY.Y);

if (count != 0)

g.DrawString(count.ToString(), txt, Brushes.Black, center.X - 1.5f * txt.Size, XY.Y);

}

//рисование координатных осей

g.DrawLine(OXY, 0, center.Y, pnlGrafik.Size.Width, center.Y);

g.DrawLine(OXY, center.X, 0, center.X, pnlGrafik.Size.Height);

g.DrawString("0", txt, Brushes.Black, center.X - txt.Size, center.Y);

if (begin)

{

for (int i = 0; i < 3; i++) //преобразование точек плоскости в экранные

{

cx = points[0, i];

cy = points[1, i];

relX = cx / stepX;

relY = cy / stepY;

XY.X = relX + center.X;

XY.Y = center.Y - relY;

scr_points[i].X = XY.X;

scr_points[i].Y = XY.Y;

}

g.DrawLine(figur, scr_points[0], scr_points[1]); //рисование фигуры

g.DrawLine(figur, scr_points[1], scr_points[2]);

g.DrawLine(figur, scr_points[0], scr_points[2]);

}

}

//обновление после масштабирования изображения

private void btn_update_Click(object sender, EventArgs e)

{

this.pnlGrafik.Invalidate();

}

//сдвиг по оси X влево

private void btnXdown_Click(object sender, EventArgs e)

{

center.X += dkx;

this.pnlGrafik.Invalidate();

}

//сдвиг по оси X вправо

private void btnXup_Click(object sender, EventArgs e)

{

center.X -= dkx;

this.pnlGrafik.Invalidate();

}

//сдвиг по оси Y вниз

private void btnYdown_Click(object sender, EventArgs e)

{

center.Y -= dky;

this.pnlGrafik.Invalidate();

}

//сдвиг по оси Y вверх

private void btnYup_Click(object sender, EventArgs e)

{

center.Y += dky;

this.pnlGrafik.Invalidate();

}

//кнопка Выполнить

private void btnAFF_preob_Click(object sender, EventArgs e)

{

float kx, ky, rel_x,rel_y;

try

{

kx = float.Parse(txtparam_1.Text);

ky = float.Parse(txtparam_2.Text);

rel_x = float.Parse(txt_rel_point_x.Text);

rel_y = float.Parse(txt_rel_point_y.Text);

}

catch (Exception)

{

MessageBox.Show("Неправильно введены данные!");

return;

}

// в зависимости от выбранного преобразования

switch (aff_number)

{

case 1:

perenos(-rel_x, -rel_y);

perenos(kx, ky);

perenos(rel_x, rel_y);

break;

case 2:

perenos(-rel_x, -rel_y);

mashtab(kx, ky);

perenos(rel_x, rel_y);

break;

case 3:

perenos(-rel_x, -rel_y);

povorot(kx);

perenos(rel_x, rel_y);

break;

case 4:

perenos(0, -ky);

sdvig(kx);

perenos(0, ky);

label16.Visible = true;

label17.Visible = true;

label18.Visible = true;

txt_rel_point_x.Visible = true;

txt_rel_point_y.Visible = true;

break;

}

button_unlock();

this.pnlGrafik.Invalidate();

//вывод значений точек

txtX1.Text = points[0, 0].ToString();

txtX2.Text = points[0, 1].ToString();

txtX3.Text = points[0, 2].ToString();

txtY1.Text = points[1, 0].ToString();

txtY2.Text = points[1, 1].ToString();

txtY3.Text = points[1, 2].ToString();

}

void clear_txt()

{

txt_rel_point_x.Text = "0";

txt_rel_point_y.Text = "0";

txtparam_1.Text = "0";

txtparam_2.Text = "0";

}

private void btn_enter_Click(object sender, EventArgs e)

{

try

{

//X1,Y1

points[0, 0] = float.Parse(txtX1.Text);

points[1, 0] = float.Parse(txtY1.Text);

points[2, 0] = 1;

//X2,Y2

points[0, 1] = float.Parse(txtX2.Text);

points[1, 1] = float.Parse(txtY2.Text);

points[2, 1] = 1;

//X3,Y3

points[0, 2] = float.Parse(txtX3.Text);

points[1, 2] = float.Parse(txtY3.Text);

points[2, 2] = 1;

}

catch (Exception)

{

MessageBox.Show("Неправильно введены данные!");

return;

}

begin = true;

pnl_begin.Visible = false;

label4.Text = "Информация о точках:";

btn_enter.Visible = false;

clear_txt();

pnl_aff_preob.Visible = true;

pnlGrafik.Invalidate();

btnAFF_preob.BackColor = Color.FromArgb(150, 150, 150);

btnAFF_preob.Enabled = false;

}

void button_unlock()

{

btnAFF_preob.BackColor = Color.FromArgb(150, 150, 150);

btnAFF_preob.Enabled = false;

btn_translate.BackColor = Color.FromArgb(224, 224, 224);

btn_translate.Enabled = true;

btn_rotate.BackColor = Color.FromArgb(224, 224, 224);

btn_rotate.Enabled = true;

btn_mashtab.BackColor = Color.FromArgb(224, 224, 224);

btn_mashtab.Enabled = true;

btn_shift.BackColor = Color.FromArgb(224, 224, 224);

btn_shift.Enabled = true;

}

void button_lock()

{

btnAFF_preob.BackColor = Color.FromArgb(224, 224, 224);

btnAFF_preob.Enabled = true;

btn_translate.BackColor = Color.FromArgb(150, 150, 150);

btn_translate.Enabled = false;

btn_rotate.BackColor = Color.FromArgb(150, 150, 150);

btn_rotate.Enabled = false;

btn_mashtab.BackColor = Color.FromArgb(150, 150, 150);

btn_mashtab.Enabled = false;

btn_shift.BackColor = Color.FromArgb(150, 150, 150);

btn_shift.Enabled = false;

}

private void btn_translate_Click(object sender, EventArgs e)

{

aff_number = 1;

clear_txt();

label1.Text = "X = ";

label1.Visible = true;

txtparam_1.Visible = true;

label2.Text = "Y = ";

label2.Visible = true;

txtparam_2.Visible = true;

button_lock();

btn_translate.BackColor = Color.White;

}

private void btn_mashtab_Click(object sender, EventArgs e)

{

aff_number = 2;

clear_txt();

label1.Text = "kx = ";

label1.Visible = true;

txtparam_1.Visible = true;

label2.Text = "ky = ";

label2.Visible = true;

txtparam_2.Visible = true;

button_lock();

btn_mashtab.BackColor = Color.White;

}

private void btn_rotate_Click(object sender, EventArgs e)

{

aff_number = 3;

clear_txt();

label1.Text = "F = ";

label1.Visible = true;

txtparam_1.Visible = true;

label2.Visible = false;

txtparam_2.Visible = false;

button_lock();

btn_rotate.BackColor = Color.White;

}

private void btn_shift_Click(object sender, EventArgs e)

{

aff_number = 4;

clear_txt();

label1.Text = "kx = ";

label1.Visible = true;

label2.Text = "Y = ";

label2.Visible = true;

txtparam_2.Visible = true;

label16.Visible = false;

label17.Visible = false;

label18.Visible = false;

txt_rel_point_x.Visible = false;

txt_rel_point_y.Visible = false;

button_lock();

btn_shift.BackColor = Color.White;

}

private void pnlGrafik_Click(object sender, EventArgs e)

{

pnl_begin.Visible = true;

}

private void pnlGrafik_DoubleClick(object sender, EventArgs e)

{

pnl_begin.Visible = false;

}}

}

Работа программы: при запуске появляется окно, при этом необходимо задать начальные координаты объекта:

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

Для выполнения преобразования необходимо нажать на соответствующую

Похожие материалы

Информация о работе

Уважаемые коллеги! Предлагаем вам разработку программного обеспечения под ключ.

Опытные программисты сделают для вас мобильное приложение, нейронную сеть, систему искусственного интеллекта, SaaS-сервис, производственную систему, внедрят или разработают ERP/CRM, запустят стартап.

Сферы - промышленность, ритейл, производственные компании, стартапы, финансы и другие направления.

Языки программирования: Java, PHP, Ruby, C++, .NET, Python, Go, Kotlin, Swift, React Native, Flutter и многие другие.

Всегда на связи. Соблюдаем сроки. Предложим адекватную конкурентную цену.

Заходите к нам на сайт и пишите, с удовольствием вам во всем поможем.