Особенности практической реализации интерактивной графики средствами C#
Анализ особенностей разработки программы, которая строит двумерный график функции, заданной явно, с одной точкой разрыва на языке программирования C#. Алгоритм программной реализации метода сканирующей строки для закрашивания треугольных областей.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 20.09.2017 |
Размер файла | 211,7 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru
Размещено на http://www.allbest.ru
Введение
Существует немало языков программирования, но лишь немногие из них действительно хороши. Хороший язык программирования должен быть одновременно эффективным и гибким, а его синтаксис -- кратким, но ясным. Он должен облегчать создание правильного кода, не мешая делать это, а также поддерживать самые современные возможности программирования, но не ультрамодные тенденции, заводящие в тупик. И наконец, хороший язык программирования должен обладать еще одним, едва уловимым качеством: вызывать у нас такое ощущение, будто мы находимся в своей стихии, когда пользуемся им. Именно таким языком и является С#.
Данная работа посвящена изучению некоторых разделов интерактивной компьютерной графики средствами C#.
1. Двумерная графика
Написать программу, которая строит график функции на отрезке [a, b], заданной явно. Подобрать отрезок [a, b], который содержит только одну точку разрыва.
Решение:
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;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
float xmin, xmax, ymin, ymax, x, y, h;
int r = 3;
double eps = 0.001;
xmin = 1; xmax = 6;
h = (xmax - xmin) / 500;
ymin = F(xmin);
ymax = ymin;
x = xmin + h;
for (x = xmin; x < r-eps; x = x + h)
{
y = F(x);
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
}
for (x = r + h; x <= xmax; x = x + h)
{
y = F(x);
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
}
float dx = (xmax - xmin) * 0.03f;
float dy = (ymax - ymin) * 0.03f;
float ax = ClientSize.Width / (xmax - xmin + 2 * dx);
float ay = -ClientSize.Height / (ymax - ymin + 2 * dy);
float bx = -ax * (xmin - dx);
float by = -ay * (ymax + dy);
g.Transform = new Matrix(ax, 0, 0, ay, bx, by);
float hf, wf, a, b, c, d;
float asm = (xmax - xmin) / (ymax - ymin);
float asf = (float)ClientSize.Width / (float)ClientSize.Height;
if (asm > asf)
{
wf = ClientSize.Width;
hf = (ymax - ymin) * wf / (xmax - xmin);
a = 0;
b = (ClientSize.Height - hf) / 2;
c = ClientSize.Width;
d = (ClientSize.Height + hf) / 2;
}
else
{
hf = ClientSize.Height;
wf = (xmax - xmin) * hf / (ymax - ymin);
a = (ClientSize.Width - wf) / 2;
b = 0;
c = (ClientSize.Width + wf) / 2;
d = ClientSize.Height;
}
ax = (c - a) / (xmax - xmin + 2 * dx);
ay = (b - d) / (ymax - ymin + 2 * dy);
bx = a - ax * (xmin - dx);
by = b - ay * (ymax + dy);
float hline = (xmax - xmin) * 0.001f;
Pen blackPen = new Pen(Color.Black, hline);
Pen bluePen = new Pen(Color.Blue, hline);
x = xmin;
g.DrawLine(bluePen, xmin, 0, xmax, 0);
g.DrawLine(bluePen, 0, ymin, 0, ymax);
while (x <= r - h)
{
g.DrawLine(blackPen, x, F(x), x + h, F(x + h));
x = x + h;
}
x = r + h;
while (x <= xmax)
{
g.DrawLine(blackPen, x, F(x), x + h, F(x + h));
x = x + h;
}
}
private float F(float x)
{
return x / (x * x - 9);
}
private void Form1_Resize(object sender, EventArgs e)
{
Invalidate();
}
}
}
Рисунок 1.1. Реализация программы, которая строит двумерный график функции, заданной явно, с одной точкой разрыва
Написать программу, которая строит график функции на отрезке [a, b], заданной параметрически.
Решение:
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;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
float xmin, xmax, ymin, ymax, x, t, y, h;
float tmin = -5, tmax = 5;
xmin = F1(tmin); xmax = F1(tmax);
h = (tmax - tmin) / 500;
ymin = F2(tmin);
ymax = ymin;
t = tmin + h;
for (t = tmin; t < tmax; t = t + h)
{
x = F1(t);
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
y = F2(t);
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
}
float dx = (xmax - xmin) * 0.03f;
float dy = (ymax - ymin) * 0.03f;
float ax = ClientSize.Width / (xmax - xmin + 2 * dx);
float ay = -ClientSize.Height / (ymax - ymin + 2 * dy);
float bx = -ax * (xmin - dx);
float by = -ay * (ymax + dy);
float hf, wf, a, b, c, d;
float asm = (xmax - xmin) / (ymax - ymin);
float asf = (float)ClientSize.Width / (float)ClientSize.Height;
if (asm > asf)
{
wf = ClientSize.Width;
hf = (ymax - ymin) * wf / (xmax - xmin);
a = 0;
b = (ClientSize.Height - hf) / 2;
c = ClientSize.Width;
d = (ClientSize.Height + hf) / 2;
}
else
{
hf = ClientSize.Height;
wf = (xmax - xmin) * hf / (ymax - ymin);
a = (ClientSize.Width - wf) / 2;
b = 0;
c = (ClientSize.Width + wf) / 2;
d = ClientSize.Height;
}
ax = (c - a) / (xmax - xmin + 2 * dx);
ay = (b - d) / (ymax - ymin + 2 * dy);
bx = a - ax * (xmin - dx);
by = b - ay * (ymax + dy);
g.Transform = new Matrix(ax, 0, 0, ay, bx, by);
float hline = (xmax - xmin) * 0.001f;
Pen blackPen = new Pen(Color.Black, hline);
Pen bluePen = new Pen(Color.Blue, hline);
t = tmin;
g.DrawLine(bluePen, xmin, 0, xmax, 0);
g.DrawLine(bluePen, 0, ymin, 0, ymax);
while (t <= tmax)
{
g.DrawLine(blackPen, F1(t), F2(t), F1(t + h), F2(t + h));
t = t + h;
}
}
private float F1(float x)
{
return (float)(6 * Math.Cos(x) + 2 * Math.Cos(6 * x));
}
private float F2(float x)
{
return (float)(6 * Math.Sin(x) - 2 * Math.Sin(6 * x));
}
private void Form1_Resize(object sender, EventArgs e)
{
Invalidate();
}
}
}
Рисунок 1.2. Реализация программы, которая строит двумерный график функции, заданной параметрически
2. Преобразование двумерных координат
Задача: Написать программу, демонстрирующую преобразование двумерных координат (перенос, поворот и масштабирование). Вывести график функции до преобразования и после него в одном окне.
Решение:
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;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public float transX(float x, float y, float Alfa, float d, float s)
{
return (float)((s * x * Math.Cos(Alfa) + s * y * Math.Sin(Alfa) + d));
}
public float transY(float x, float y, float Alfa, float d, float s)
{
return (float)(-s * x * Math.Sin(Alfa) + s * y * Math.Cos(Alfa) + d);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
float fi, fimin, fimax, xmin, xmax, ymin, ymax, x, y, h, x2, y2;
float tx, ty, Alfa, s;
s = 2;
tx = 10; ty = 7; Alfa = (float)(Math.PI) / 6;
fimin = 0; fimax = (float)(4 * (Math.PI));
h = (fimax - fimin) / 100;
xmin = (float)(F(fimin) * Math.Cos(fimin));
ymin = (float)(F(fimin) * Math.Sin(fimin));
xmax = xmin;
ymax = ymin;
fi = fimin + h;
while (fi < fimax)
{
x = (float)(F(fi) * Math.Cos(fi));
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
y = (float)(F(fi) * Math.Sin(fi));
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
x2 = transX(x, y, Alfa, tx, s);
if (x2 < xmin) xmin = x2;
if (x2 > xmax) xmax = x2;
y2 = transY(x, y, Alfa, ty, s);
if (y2 < ymin) ymin = y2;
if (y2 > ymax) ymax = y2;
fi = fi + h;
}
float dx = (xmax - xmin) * 0.03f;
float dy = (ymax - ymin) * 0.03f;
float ax = ClientSize.Width / (xmax - xmin + 2 * dx);
float ay = -ClientSize.Height / (ymax - ymin + 2 * dy);
float bx = -ax * (xmin - dx);
float by = -ay * (ymax + dy);
float hf, wf, a, b, c, d;
float asm = (xmax - xmin) / (ymax - ymin);
float asf = (float)ClientSize.Width / (float)ClientSize.Height;
if (asm > asf)
{
wf = ClientSize.Width;
hf = (ymax - ymin) * wf / (xmax - xmin);
a = 0;
b = (ClientSize.Height - hf) / 2;
c = ClientSize.Width;
d = (ClientSize.Height + hf) / 2;
}
else
{
hf = ClientSize.Height;
wf = (xmax - xmin) * hf / (ymax - ymin);
a = (ClientSize.Width - wf) / 2;
b = 0;
c = (ClientSize.Width + wf) / 2;
d = ClientSize.Height;
}
ax = (c - a) / (xmax - xmin + 2 * dx);
ay = (b - d) / (ymax - ymin + 2 * dy);
bx = a - ax * (xmin - dx);
by = b - ay * (ymax + dy);
g.Transform = new Matrix(ax, 0, 0, ay, bx, by);
float hline = (xmax - xmin) * 0.001f;
Pen blackPen = new Pen(Color.Black, hline);
Pen bluePen = new Pen(Color.Blue, hline);
g.DrawLine(bluePen, xmin, 0, xmax, 0);
g.DrawLine(bluePen, 0, ymin, 0, ymax);
fi = fimin;
while (fi <= fimax)
{
g.DrawLine(blackPen, (float)(F(fi) * Math.Cos(fi)), (float)(F(fi) * Math.Sin(fi)), (float)(F(fi + h) * Math.Cos(fi + h)), (float)(F(fi + h) * Math.Sin(fi + h)));
fi = fi + h;
}
fi = fimin;
while (fi <= fimax)
{
x = (float)(F(fi) * Math.Cos(fi));
y = (float)(F(fi) * Math.Sin(fi));
x2 = (float)(F(fi + h) * Math.Cos(fi + h));
y2 = (float)(F(fi + h) * Math.Sin(fi + h));
g.DrawLine(blackPen, transX(x, y, Alfa, tx, s), transY(x, y, Alfa, ty, s), transX(x2, y2, Alfa, tx, s), transY(x2, y2, Alfa, ty, s));
fi = fi + h;
}
}
private float F(float fi)
{
return 3 * (1 + (float)(Math.Cos(fi)));
}
private void Form1_Resize(object sender, EventArgs e)
{
Invalidate();
}
}
}
Рисунок 2.1. Реализация программы, демонстрирующей преобразование двумерных координат
3. Метод сканирующей строки
Разработать алгоритм и написать программу, демонстрирующую метод сканирующей строки для закрашивания треугольных областей.
программный алгоритм двумерный
Решение:
Класс:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
namespace Laba3
{
class FillTriangle
{
public void Fill(Graphics g, int[] x, int[] y, int[] rgb)
{
int maxy, miny;
maxy = y[0];
miny = maxy;
if(y[1] > maxy) maxy = y[1];
if(y[2] > maxy) maxy = y[2];
if(y[1] < miny) miny = y[1];
if(y[2] < miny) miny = y[2];
float t;
ArrayList mas = new ArrayList();
Pen myPen = new Pen(Color.FromArgb(255, rgb[0], rgb[1], rgb[2]));
for (int yt = miny; yt <= maxy; yt++)
{
mas.Clear();
if(y[0]!=y[1])
{
t = (float)(yt-y[1])/(float)(y[0] - y[1]);
if(t>=0 && t<=1)
mas.Insert(0,(int)(t*x[0] + (1-t)*x[1]));
}
{
t = (float)(yt-y[2])/(float)(y[1] - y[2]);
if(t>=0 && t<=1)
mas.Insert(0,(int)(t*x[1] + (1-t)*x[2]));
}
{
t = (float)(yt-y[2])/(float)(y[0] - y[2]);
if(t>=0 && t<=1)
mas.Insert(0,(int)(t*x[0] + (1-t)*x[2]));
}
g.DrawLine(myPen, (int)mas[0], yt, (int)mas[1], yt);
if(mas.Count == 3)
{
g.DrawLine(myPen, (int)mas[1], yt, (int)mas[2], yt);
}
}
}
}
}
Форма:
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;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Laba3
{
public partial class Form1 : Form
{
private int k = 0;
private int[] x = new int[3];
private int[] y = new int[3];
private int[] rgb = new int[3];
public Form1()
{
InitializeComponent();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (k <= 2)
{
x[k] = e.X;
y[k] = e.Y;
if (k == 2)
{
rgb[0] = 255;
rgb[2] = 0;
rgb[2] = 0;
Graphics g = Graphics.FromHwnd(this.Handle);
FillTriangle f = new FillTriangle();
f.Fill(g, x, y, rgb);
g.Dispose();
}
k++;
}
else
return;
}
}
}
Рисунок 3.1. Реализация программы, демонстрирующей метод сканирующей строки для закрашивания треугольных областей
4. Параллельная проекция
Написать программу, которая строит на экране изображение выпуклого трехмерного тела при параллельной проекции. Удалить невидимые грани. Видимые грани закрасить оттенками серого цвета в зависимости от расположения соответствующей грани и источника света. Для закрашивания граней использовать метод сканирующей строки.
Решение:
Класс:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
namespace Triangle
{
class FillTriangle
{
public void Fill(Graphics g, int[] x, int[] y, int[] rgb)
{
int maxy, miny;
ArrayList mas = new ArrayList();
float a;
Pen myPen = new Pen(Color.FromArgb(255, rgb[0], rgb[1], rgb[2]));
if (Math.Abs((x[1] - x[0]) * (y[2] - y[0]) - (x[2] - x[0]) * (y[1] - y[0])) <= 0.001)
{
g.DrawLine(myPen, x[0], y[0], x[1], y[1]);
g.DrawLine(myPen, x[1], y[1], x[2], y[2]);
return;
}
maxy = y[0];
miny = maxy;
for (int i = 1; i <= 2; i++)
{
if (y[i] > maxy) maxy = y[i];
if (y[i] < miny) miny = y[i];
}
for (int yt = miny; yt <= maxy; yt++)
{
mas.Clear();
if (y[0] != y[1])
{
a = (float)(yt - y[1])/(float)(y[0] - y[1]);
if(a >= 0 && a <= 1)
{
mas.Insert(0, (int)(a * x[0] + (1 - a) * x[1]));
}
}
if (y[1] != y[2])
{
a = (float)(yt - y[2]) / (float)(y[1] - y[2]);
if (a >= 0 && a <= 1)
{
mas.Insert(0, (int)(a * x[1] + (1 - a) * x[2]));
}
}
if (y[0] != y[2])
{
a = (float)(yt - y[2]) / (float)(y[0] - y[2]);
if (a >= 0 && a <= 1)
{
mas.Insert(0, (int)(a * x[0] + (1 - a) * x[2]));
}
}
if(mas.Count == 3)
{
g.DrawLine(myPen,(int)mas[0],yt,(int)mas[1],yt);
g.DrawLine(myPen,(int)mas[1],yt,(int)mas[2],yt);
}
else
g.DrawLine(myPen,(int)mas[0],yt,(int)mas[1],yt);
}
}
}
}
Форма:
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;
using System.Drawing.Drawing2D;
namespace Lab_4
{
public partial class Form1 : Form
{
private double[] xv = { 0, 2, 0, 0, 2, 0};
private double[] yv = { 0, 0, 2, 0, 0, 2};
private double[] zv = { 0, 0, 0, 2, 2, 2};
private double[] xpl = new double[6];
private double[] ypl = new double[6];
private int[] xfrm = new int[6];
private int[] yfrm = new int[6];
private int[,] gran1 = new int[3, 4];
private int[,] gran2 = new int[2, 3];
private double u1x, u1y, u1z, u2x, u2y, u2z, u3x, u3y, u3z;
private double rx, ry, rz;
private double ax, ay, az;
private double sx, sy, sz;
private double r;
private double a, b, c, d;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
rx = 10; ry = 5; rz = 5;
ax = 1; ay = 1; az = 1;
sx = -5; sy = 1; sz = 5;
r = Math.Sqrt(3);
u3x = ax - rx; u3y = ay - ry; u3z = az - rz;
double t = Math.Sqrt(u3x * u3x + u3y * u3y + u3z * u3z);
u3x = u3x / t; u3y = u3y / t; u3z = u3z / t;
u1x = u3y; u1y = -u3x; u1z = 0;
t = Math.Sqrt(u1x * u1x + u1y * u1y + u1z * u1z);
u1x = u1x / t; u1y = u1y / t; u1z = u1z / t;
u2x = u1y * u3z - u3y * u1z; u2y = u3x * u1z - u1x * u3z; u2z = u1x * u3y - u3x * u1y;
t = Math.Sqrt(u2x * u2x + u2y * u2y + u2z * u2z);
u2x = u2x / t; u2y = u2y / t; u2z = u2z / t;
gran1[1, 0] = 0; gran1[1, 1] = 1; gran1[1, 2] = 4; gran1[1, 3] = 3;
gran1[0, 0] = 0; gran1[0, 1] = 3; gran1[0, 2] = 5; gran1[0, 3] = 2;
gran1[2, 0] = 1; gran1[2, 1] = 2; gran1[2, 2] = 5; gran1[2, 3] = 4;
gran2[0, 0] = 0; gran2[0, 1] = 2; gran2[0, 2] = 1;
gran2[1, 0] = 3; gran2[1, 1] = 4; gran2[1, 2] = 5;
for (int i = 0; i < xv.Length; i++)
{
xpl[i] = px(xv[i], yv[i], zv[i]);
ypl[i] = py(xv[i], yv[i], zv[i]);
}
Ini();
}
private double px(double x,double y,double z)
{
return ((x - rx) * u1x + (y - ry) * u1y + (z - rz) * u1z);
}
private double py(double x,double y,double z)
{
return ((x - rx) * u2x + (y - ry) * u2y + (z - rz) * u2z);
}
private void Ini()
{
double wp, hp;
if (ClientSize.Width >= ClientSize.Height)
{
wp = 2 * r * ClientSize.Width / ClientSize.Height; hp = 2 * r;
}
else
{
wp = 2 * r; hp = 2 * r * ClientSize.Height / ClientSize.Width;
}
a = ClientSize.Width / wp;
b = ClientSize.Width / 2;
c = -ClientSize.Height / hp;
d = ClientSize.Height / 2;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g=e.Graphics;
g.Clear(Color.White);
for(int i=0;i<xv.Length;i++)
{
xfrm[i]=fx(xpl[i]);
yfrm[i]=fy(ypl[i]);
}
double bx,by,bz,cx,cy,cz,nx,ny,nz;
int[]rgb=new int[3];
int[]x=new int[3]; int[]y=new int[3];
double cosfi;
Triangle.FillTriangle myFill=new Triangle.FillTriangle();
for(int i=0;i<=2;i++)
{
bx=xv[gran1[i,1]]-xv[gran1[i,0]];
by=yv[gran1[i,1]]-yv[gran1[i,0]];
bz=zv[gran1[i,1]]-zv[gran1[i,0]];
cx=xv[gran1[i,2]]-xv[gran1[i,0]];
cy=yv[gran1[i,2]]-yv[gran1[i,0]];
cz=zv[gran1[i,2]]-zv[gran1[i,0]];
nx=by*cz-bz*cy;
ny=bz*cx-bx*cz;
nz=bx*cy-by*cx;
if(nx*u3x+ny*u3y+nz*u3z>0)
{
bx=xv[gran1[i,0]]; by=yv[gran1[i,0]];bz=zv[gran1[i,0]];
for(int j=1;j<=3;j++)
{
bx+=xv[gran1[i,j]];by+=yv[gran1[i,j]];bz+=zv[gran1[i,j]];
}
bx=bx/4;by=by/4;bz=bz/4;
cx=bx-sx;cy=by-sy;cz=bz-sz;
cosfi=(nx*cx+ny*cy+nz*cz)/ (Math.Sqrt(nx*nx+ny*ny+nz*nz)*Math.Sqrt(cx*cx+cy*cy+cz*cz));
rgb[0]=(int)(-255*cosfi/2+255/2);
rgb[1]=rgb[0]; rgb[2]=rgb[0];
x[0]=xfrm[gran1[i,0]];y[0]=yfrm[gran1[i,0]];
x[1]=xfrm[gran1[i,1]];y[1]=yfrm[gran1[i,1]];
x[2]=xfrm[gran1[i,2]];y[2]=yfrm[gran1[i,2]];
myFill.Fill(g,x,y,rgb);
x[0]=xfrm[gran1[i,0]];y[0]=yfrm[gran1[i,0]];
x[1]=xfrm[gran1[i,2]];y[1]=yfrm[gran1[i,2]];
x[2]=xfrm[gran1[i,3]];y[2]=yfrm[gran1[i,3]];
myFill.Fill(g, x, y, rgb);
}
}
for (int i = 0; i <= 1; i++)
{
bx = xv[gran2[i, 1]] - xv[gran2[i, 0]];
by = yv[gran2[i, 1]] - yv[gran2[i, 0]];
bz = zv[gran2[i, 1]] - zv[gran2[i, 0]];
cx = xv[gran2[i, 2]] - xv[gran2[i, 0]];
cy = yv[gran2[i, 2]] - yv[gran2[i, 0]];
cz = zv[gran2[i, 2]] - zv[gran2[i, 0]];
nx = by * cz - bz * cy;
ny = bz * cx - bx * cz;
nz = bx * cy - by * cx;
if (nx * u3x + ny * u3y + nz * u3z > 0)
{
bx = xv[gran2[i, 0]]; by = yv[gran2[i, 0]]; bz = zv[gran2[i, 0]];
for (int j = 1; j <= 2; j++)
{
bx += xv[gran2[i, j]]; by += yv[gran2[i, j]]; bz += zv[gran2[i, j]];
}
bx = bx / 3; by = by / 3; bz = bz / 3;
cx = bx - sx; cy = by - sy; cz = bz - sz;
cosfi = (nx * cx + ny * cy + nz * cz) / (Math.Sqrt(nx * nx + ny * ny + nz * nz) * Math.Sqrt(cx * cx + cy * cy + cz * cz));
rgb[0] = (int)(-255 * cosfi/2+255/2);
rgb[1] = rgb[0]; rgb[2] = rgb[0];
x[0] = xfrm[gran2[i, 0]]; y[0] = yfrm[gran2[i, 0]];
x[1] = xfrm[gran2[i, 1]]; y[1] = yfrm[gran2[i, 1]];
x[2] = xfrm[gran2[i, 2]]; y[2] = yfrm[gran2[i, 2]];
myFill.Fill(g, x, y, rgb);
x[0] = xfrm[gran2[i, 0]]; y[0] = yfrm[gran2[i, 0]];
x[1] = xfrm[gran2[i, 1]]; y[1] = yfrm[gran2[i, 1]];
x[2] = xfrm[gran2[i, 2]]; y[2] = yfrm[gran2[i, 2]];
myFill.Fill(g, x, y, rgb);
}
}
}
private int fx(double x)
{
return(int)(a*x+b);
}
private int fy(double y)
{
return(int)(c*y+d);
}
private void Form1_Resize(object sender, EventArgs e)
{
Ini();
Invalidate();
}
}
}
Рисунок 4.1. Реализация программы, которая строит на экране изображение выпуклого трехмерного тела при параллельной проекции
5. Центральная проекция
Задача: Написать программу, которая строит на экране изображение выпуклого трехмерного тела при центральной проекции. Удалить невидимые грани. Видимые грани закрасить оттенками серого цвета в зависимости от расположения соответствующей грани и источника света. Для закрашивания граней использовать метод сканирующей строки.
Решение:
Класс:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
namespace WindowsFormsApplication1
{
class FillTriangle
{
public void Fill(Graphics g, int[] x, int[] y, int[] rgb)
{
int maxy, miny;
ArrayList mas = new ArrayList();
float a; // Параметр альфа
miny = y[0]; maxy = miny;
for (int i = 1; i < 3; i++)
{
if (y[i] > maxy) maxy = y[i];
if (y[i] < miny) miny = y[i];
}
Pen myPen = new Pen(Color.FromArgb(255, rgb[0], rgb[1], rgb[2]));
for (int yt = miny; yt < maxy; yt++)
{
mas.Clear();
if (y[0] != y[1])
{
a = (float)(yt-y[1]) / (float)(y[0]-y[1]);
if (a>=0&&a<=1)
mas.Insert(0,(int)(a*x[0]+(1-a)*x[1]) );
}
if (y[0] != y[2])
{
a = (float)(yt - y[2]) / (float)(y[0] - y[2]);
if (a >= 0 && a <= 1)
mas.Insert(0, (int)(a * x[0] + (1 - a) * x[2]));
}
if (y[1] != y[2])
{
a = (float)(yt - y[2]) / (float)(y[1] - y[2]);
if (a >= 0 && a <= 1)
mas.Insert(0, (int)(a * x[1] + (1 - a) * x[2]));
}
if (mas.Count == 3)
g.DrawLine(myPen, (int)mas[1], yt, (int)mas[2], yt);
g.DrawLine(myPen, (int)mas[0], yt, (int)mas[1], yt);
}
}
}
}
Форма:
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double[] xv = { 0, 0, 30, 30, 15, 15 };
double[] yv = { 0, -30, -30, 0, -15, -15 };
double[] zv = { 0, 0, 0, 0, 30, -30 };
double[] xpl = new double[6];
double[] ypl = new double[6];
int[] xfrm = new int[6];
int[] yfrm = new int[6];
int[,] gran = new int[8, 3];
double u1x, u1y, u1z, u2x, u2y, u2z, u3x, u3y, u3z;
double rx, ry, rz, ax, ay, az, sx, sy, sz;
double r1, r2, a, b, c, d, fd, rd, gx, gy, gz;
private void Form1_Load(object sender, EventArgs e)
{
ax = 15; ay = -15; az = 0;
fd = 20;
sx = 90; sy = -60; sz = 50;
gx = 100; gy = 30; gz = 20;
r1 = 35;
u3x = ax - gx; u3y = ay - gy; u3z = az - gz;
double m = Math.Sqrt(u3x * u3x + u3y * u3y + u3z * u3z);
u3x = u3x / m; u3y = u3y / m; u3z = u3z / m;
u1x = u3y; u1y = -u3x; u1z = 0;
m = Math.Sqrt(u1x * u1x + u1y * u1y + u1z * u1z);
u1x = u1x / m; u1y = u1y / m; u1z = u1z / m;
u2x = -u3y * u1z + u1y * u3z;
u2y = -u1x * u3z + u3x * u1z;
u2z = -u3x * u1y + u1x * u3y;
m = Math.Sqrt(u2x * u2x + u2y * u2y + u2z * u2z);
u2x = u2x / m; u2y = u2y / m; u2z = u2z / m;
rx = gx + u3x * fd;
ry = gy + u3y * fd;
rz = gz + u3z * fd;
rd=Math.Sqrt(Math.Pow(rx-ax,2)+Math.Pow(ry-ay,2)+Math.Pow(rz-az,2));
r2= r1*fd/(rd+fd);
gran[0, 0] = 1; gran[0, 1] = 4; gran[0, 2] = 0;
gran[1, 0] = 1; gran[1, 1] = 2; gran[1, 2] = 4;
gran[2, 0] = 2; gran[2, 1] = 3; gran[2, 2] = 4;
gran[3, 0] = 3; gran[3, 1] = 0; gran[3, 2] = 4;
gran[4, 0] = 5; gran[4, 1] = 1; gran[4, 2] = 0;
gran[5, 0] = 1; gran[5, 1] = 5; gran[5, 2] = 2;
gran[6, 0] = 5; gran[6, 1] = 3; gran[6, 2] = 2;
gran[7, 0] = 5; gran[7, 1] = 0; gran[7, 2] = 3;
for (int i = 0; i < 6; i++)
{
xpl[i] = px(xv[i], yv[i], zv[i]);
ypl[i] = py(xv[i], yv[i], zv[i]);
}
Ini();
}
private double px(double x, double y, double z)
{
double sc1 = ((x - rx) * u1x + (y - ry) * u1y + (z - rz) * u1z);
double sc2 = ((x - rx) * u3x + (y - ry) * u3y + (z - rz) * u3z);
return fd * sc1 / (sc2 + fd);
}
private double py(double x, double y, double z)
{
double sc1 = ((x - rx) * u2x + (y - ry) * u2y + (z - rz) * u2z);
double sc2 = ((x - rx) * u3x + (y - ry) * u3y + (z - rz) * u3z);
return fd * sc1 / (sc2 + fd);
}
private void Ini()
{
double wp, hp;
if (ClientSize.Width >= ClientSize.Height)
{
wp = 2 * r2 * ClientSize.Width / ClientSize.Height;
hp = 2 * r2;
}
else
{
wp = 2 * r2;
hp = 2 * r2 * ClientSize.Height / ClientSize.Width;
}
a = ClientSize.Width / wp;
b = ClientSize.Width / 2;
c = -ClientSize.Height / hp;
d = ClientSize.Height / 2;
}
private int fx(double x)
{
return (int)(a * x + b);
}
private int fy(double y)
{
return (int)(c * y + d);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.Clear(Color.White);
for (int i = 0; i < xv.Length; i++)
{
xfrm[i] = fx(xpl[i]);
yfrm[i] = fy(ypl[i]);
}
double bx, by, bz, cx, cy, cz, nx, ny, nz;
int[] rgb = new int[3];
double cosfi;
int[] x = new int [3];
int[] y = new int [3];
FillTriangle myFill = new FillTriangle();
for (int i = 0; i < 8; i++)
{
bx = xv[gran[i, 1]] - xv[gran[i, 0]];
by = yv[gran[i, 1]] - yv[gran[i, 0]];
bz = zv[gran[i, 1]] - zv[gran[i, 0]];
cx = xv[gran[i, 2]] - xv[gran[i, 0]];
cy = yv[gran[i, 2]] - yv[gran[i, 0]];
cz = zv[gran[i, 2]] - zv[gran[i, 0]];
nx = by * cz - bz * cy;
ny = bz * cx - bx * cz;
nz = bx * cy - by * cx;
bx = (xv[gran[i, 0]] + xv[gran[i, 1]] + xv[gran[i, 2]]) / 3;
by = (yv[gran[i, 0]] + yv[gran[i, 1]] + yv[gran[i, 2]]) / 3;
bz = (zv[gran[i, 0]] + zv[gran[i, 1]] + zv[gran[i, 2]]) / 3;
cx = bx - gx; cy = by - gy; cz = bz - gz;
if (nx * cx + ny * cy + nz * cz < 0)
{
cx = bx - sx; cy = by - sy; cz = bz - sz;
cosfi = (nx * cx + ny * cy + nz * cz) / (Math.Sqrt(nx * nx + ny * ny + nz * nz) * (Math.Sqrt(cx * cx + cy * cy + cz * cz)));
rgb[0] = (int)(-255 * cosfi / 2 + 255 / 2);//red
rgb[1] = rgb [0]; //green
rgb[2] = rgb[0];//blue
x[0] = xfrm[gran[i, 0]]; y[0] = yfrm[gran[i, 0]];
x[1] = xfrm[gran[i, 1]]; y[1] = yfrm[gran[i, 1]];
x[2] = xfrm[gran[i, 2]]; y[2] = yfrm[gran[i, 2]];
myFill.Fill(g, x, y, rgb);
}
}
}
private void Form1_Resize(object sender, EventArgs e)
{
Ini();
Invalidate();
}
}
}
Рисунок 5.1. Реализация программы, которая строит на экране изображение выпуклого трехмерного тела при центральной проекции
Заключение
В работе были изучены некоторые разделы интерактивной графики средствами C# при помощи примеров. Данные задачи позволили хорошо рассмотреть самые главные аспекты программирования.
Благодаря своей способности быстро приспосабливаться к постоянно меняющимся потребностям в области программирования С# по-прежнему остается живым и новаторским языком. А следовательно, он представляет собой один из самых эффективных и богатых своими возможностями языков в современном программировании. Это язык, пренебречь которым не может позволить себе ни один программист. И эта книга призвана помочь вам овладеть им.
Литература
1. Шилдт Г. Полное руководство С#4.0 / Г. Шилдт. - М.: Вильямс, 2011.
2. Мак-Дональд, М. WPF Windows Presentation Foundation в .NET 4.0 с примерами на C# 2010 для профессионалов / М. Мак-Дональд. - М.: Вильямс, 2011.
3. Порев В. Компьютерная графика: учеб. Пособие / В. Порев. - БХВ-Петербург: 2004.
Размещено на Allbest.ru
Подобные документы
Составление программы для вычисления по двум формулам одной и той же переменной "X". Создание программы, которая по введенному значению аргумента вычислят значение функции, заданной в виде графика. Вывод на экран значения функции, заданной графически.
курсовая работа [4,9 M], добавлен 14.03.2014Особенности разработки и реализации обучающей программы и схемы алгоритмов на языке программирования С++. Понятие равномерной и неравномерной дискретизации. Представление информации (составление кода) в виде таблицы перекодировки или многочлена.
курсовая работа [704,6 K], добавлен 06.03.2013Понятие графика функции и его представление на ЭВМ. Алгоритм реализации, блок-схема и функциональные тесты графического метода решения частного случая задачи нелинейного программирования, его математическая модель. Диалог программы с пользователем.
курсовая работа [1,6 M], добавлен 15.05.2012Разработка алгоритма и программы, обеспечивающей вычисление максимального значения функции на заданном отрезке, первой производной заданной функции. Методика расчёта, алгоритм решения задачи, описание программы. Результаты расчётов и графики функций.
курсовая работа [576,6 K], добавлен 17.05.2011Разработка программы для работы с последовательностью прописных латинских букв. Алгоритм программы, результаты ее работы и вывод о работоспособности. Поиск количества вхождений элементов одной строки в другую. Тестирование программы, ее результаты.
лабораторная работа [858,0 K], добавлен 23.11.2014Особенности метода неопределенных множителей Лагранжа, градиентного метода и метода перебора и динамического программирования. Конструирование алгоритма решения задачи. Структурная схема алгоритма сценария диалога и описание его программной реализации.
курсовая работа [1010,4 K], добавлен 10.08.2014Двумерная графика: понятие и принципы формирования, правила преобразования координат. Сущность и работа с методом сканирующей строки. Параллельная и центральная проекция: сравнительная характеристика, главные условия и возможности использования.
курсовая работа [194,2 K], добавлен 11.04.2015Создание программы с использованием принципов объектно-ориентированного программирования на языке высокого уровня С# средствами Microsoft Visual Studio 2010. Построение алгоритма реализации. Определение математического аппарата, применение его в задаче.
курсовая работа [500,4 K], добавлен 13.01.2015Структура и назначение программного кода программы по созданию 3D-графики средствами языка программирования Visual Basic. Элементы управления "Окно формы" и "Таймер", выполняемые ими функции и основные свойства, значение в работе программного кода.
лабораторная работа [362,4 K], добавлен 06.07.2009Исследование теоретических аспектов разработки программы посредством использования Visual Basic. Анализ достоинств и недостатков данного языка программирования. Изучение особенностей создания интерфейса приложения. Основные этапы реализации программы.
практическая работа [460,6 K], добавлен 22.01.2013