Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курсовая работа Онищук 2ВСб-1.doc
Скачиваний:
20
Добавлен:
07.05.2015
Размер:
262.14 Кб
Скачать

4 Параллельная проекция

Задача: Написать программу, которая строит на экране изображение выпуклого трехмерного тела при параллельной проекции. Удалить невидимые грани. Видимые грани закрасить оттенками серого цвета в зависимости от расположения соответствующей грани и источника света. Для закрашивания граней использовать метод сканирующей строки [2].

Решение:

Класс:

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 Реализация программы, которая строит на экране изображение выпуклого трехмерного тела при параллельной проекции