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

5 Центральная проекция

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

Решение:

Класс:

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