Моделирование геометрических объектов

Автор работы: Пользователь скрыл имя, 17 Октября 2014 в 11:25, курсовая работа

Краткое описание

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

Содержание

ВВЕДЕНИЕ 3
1. СОЗДАНИЕ МАТЕМАТИЧЕСКОЙ МОДЕЛИ ОБЪЕКТА 4
1.1 Преобразования координат. 4
1.2 Создание трехмерной модели 6
2 АЛГОРИТМ ИЗМЕНЕНИЯ ПОЛОЖЕНИЯ 3D ОБЪЕКТА В ПРОСТРАНСТВЕ 8
2.1 Динамическое изменение точки наблюдения. 8
2.2 Обработка нажатия клавиши. 8
Листинг 3. 8
Листинг 4. 9
3 АЛГОРИТМ ЗАКРАШИВАНИЯ ПОЛИГОНА. АЛГОРИТМ, ОПРЕДЕЛЯЮЩИЙ ВИДИМЫЕ И НЕВИДИМЫЕ ЛИНИИ. 10
3.1 Нахождение нормали по трем точкам 10
3.2 Определение невидимости граней 11
3.3 Закраска методом Гуро 12
4 ТЕСТИРОВАНИЕ 14

Вложенные файлы: 1 файл

KGIG2.docx

— 232.46 Кб (Скачать файл)

3.3 Закраска методом Гуро

Если при построении полигональной поверхности для каждой грани используется по одной нормали, то модель освещения создает изображение, состоящее из отдельных многоугольников. Методом Гуро можно получить сглаженное изображение. Для того чтобы изобразить объект методом построчного сканирования, нужно в соответствии с моделью освещения рассчитать интенсивность каждого пиксела вдоль сканирующей строки. Нормали к поверхности аппроксимируются в вершинах многоугольников так, как описано в предыдущем разделе. Однако сканирующая строка не обязательно проходит через вершины многоугольника. При закраске Гуро сначала определяется интенсивность вершин многоугольника, а затем с помощью билинейной интерполяции вычисляется интенсивность каждого пиксела на сканирующей строке.

Построенная таким образом модель выводится на экран достаточно медленно.Пример закраски Гуро можно увидеть на Рисунке 3.

Листинг 5. Метод гуро.

 

public void PaintGuro(Bitmap bmp, Polygon P)

        {

            int topY = P.V[0].s.Y;

            int downY = P.V[0].s.Y;

            foreach (Vertex Vi in P.V)

            {

                Vi.NormalVertex();

                Vi.I = KGiG_Methods.cosAoB(Vi.N, VLight);

                if (Vi.I < 0) Vi.I = 0;

                if (Vi.s.Y > downY) downY = Vi.s.Y;

                if (Vi.s.Y < topY) topY = Vi.s.Y;

            }

            for (int y = topY; y <= downY; y++)

            {

                Vertex[] ABCD = CrossBorders(y, P);

                if (ABCD != null)

                {

                    double u = ((double)(y - ABCD[0].s.Y)) / (ABCD[1].s.Y - ABCD[0].s.Y);

                    int x1 = (int)(u * ABCD[1].s.X + (1 - u) * ABCD[0].s.X);                  

                    double Iq = u * ABCD[1].I + (1 - u) * ABCD[0].I;

                    u = ((double)(y - ABCD[2].s.Y)) / (ABCD[3].s.Y - ABCD[2].s.Y);

                    int x2 = (int)(u * (ABCD[3].s.X - ABCD[2].s.X) + ABCD[2].s.X);

                    double Ir = u * ABCD[3].I + (1 - u) * ABCD[2].I;

                    if (x1 > x2) { int xt = x1; x1 = x2; x2 = xt; double It = Iq; Iq = Ir; Ir = It; }

                    for (int x = x1; x < x2; x++)

                    {

                        u = ((double)(x - x1)) / (x2 - x1);

                        double Ip = u * Ir + (1 - u) * Iq;                       

                        Color col = Color.FromArgb((byte)(P.col.R * Ip),

                                                   (byte)(P.col.G * Ip),

                                                   (byte)(P.col.B * Ip));

                        bmp.SetPixel(x, y, col);

                    }

                }

            }

        }

 

Рисунок 3

  1. ТЕСТИРОВАНИЕ

 

В ходе работы была построена трехмерная модель конуса, реализована закраска методом Гуро, фигуру можно посмотреть в любом ракурсу.

 

Рисунок 5.

 

 

Приложение

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;

using KGiG;

namespace WindowsFormsApplication4

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        public class Polygon

        {

            public List<Vertex> V = new List<Vertex>();

            public double avrZ;

            public Color col;

            public Vector3D n;

            public bool visible;

            public Polygon(Color acol, params Vertex[] Vertexes)

            {

                double sum = 0;

                foreach (Vertex Vi in Vertexes)

                {

                    Vi.LP.Add(this);

                    V.Add(Vi);

                    sum += Vi.v.z;

                }

                avrZ = sum / V.Count;

                col = acol;

                ComputeNormal();

            }

            public Polygon(Color acol, Vertex[] Vertexes, int Start, int Count, bool Order)

            {

                double sum = 0; int si = Start;  
int fi = Start + Count -1;

                if (Order)

                    for (int i = si; i < fi + 1; i++)

                    {

                        Vertexes[fi - i].LP.Add(this);

                        V.Add(Vertexes[fi - i]);

                        sum += Vertexes[fi - i].v.z;

                    }

                else

                    for (int i = si; i < fi + 1; i++)

                    {

                        Vertexes[i].LP.Add(this);

                        V.Add(Vertexes[i]);

                        sum += Vertexes[i].v.z;

                    }

                avrZ = sum / V.Count;

                col = acol;

                ComputeNormal();

            }

 

            public void Paint(Graphics gr, Pen pn, Color acol)

            {

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

                foreach (Vertex Vi in V) PS.Add(Vi.s);               

                gr.FillPolygon(new SolidBrush(acol), PS.ToArray());

                gr.DrawPolygon(pn, PS.ToArray() );

            }

                     

            public void ComputeNormal()

            {

                Vertex a = V[0];

                Vertex b = V[1];

                Vertex c = V[2];

                double nx = a.v.y * (b.v.z - c.v.z) + b.v.y * (c.v.z - a.v.z) + c.v.y * (a.v.z - b.v.z);

                double ny = a.v.z * (b.v.x - c.v.x) + b.v.z * (c.v.x - a.v.x) + c.v.z * (a.v.x - b.v.x);

                double nz = a.v.x * (b.v.y - c.v.y) + b.v.x * (c.v.y - a.v.y) + c.v.x * (a.v.y - b.v.y);

                double d = 1 / Math.Sqrt(nx * nx + ny * ny + nz * nz);

                n = new Vector3D(nx * d, ny * d, nz * d);

                double nd = -(a.v.x * (b.v.y * c.v.z - c.v.y * b.v.z) +

                              b.v.x * (c.v.y * a.v.z - a.v.y * c.v.z) +

                              c.v.x * (a.v.y * b.v.z - b.v.y * a.v.z)) * d;

                double snz = a.s.X * (b.s.Y - c.s.Y) +

                             b.s.X * (c.s.Y - a.s.Y) +

                             c.s.X * (a.s.Y - b.s.Y);

                visible = snz < 0 ? true : false;

            }

        }

        public class Vertex

        {         

            public Vector3D v;

            public Vector3D N;

            public double I;

            public List<Polygon> LP = new List<Polygon>();

            public Point s;

            public Vertex(double wx, double wy, double wz)

            {

                v.x = wx;

                v.y = wy;

                v.z = wz;

            }

            public void ScreenTrans(int d, int Ro, int xc, int yc)

            {

                if ((d != 0) && (v.z + Ro != 0))

                {                   

                    s.X = (int)(d * v.x / (v.z + Ro)) + xc;

                    s.Y = (int)(d * v.y / (v.z + Ro)) + yc;

                }

            }

            public void NormalVertex()

            {

                foreach (Polygon Pi in LP)

                {

                    N += Pi.n;

                }

                N.normalize();

            }

 

        }

 

        Bitmap bmp; Graphics g; const int NC = 40;

        Vertex[] mv = new Vertex[NC+1]; Polygon[] mp = new Polygon[NC+1]; Quaternion QRot = new Quaternion(new Vector3D(1, 1, 0), Math.PI / 4);

        Vector3D VLight = new Vector3D(0, 0, -1); int d = 600;

        int Ro = 500;

        void DefineCube()

        {

            mv[0] = new Vertex(100, 100, 100);

            mv[1] = new Vertex(100, -100, 100);

            mv[2] = new Vertex(-100, -100, 100);

            mv[3] = new Vertex(-100, 100, 100);

            mv[4] = new Vertex(100, 100, -100);

            mv[5] = new Vertex(100, -100, -100);

            mv[6] = new Vertex(-100, -100, -100);

            mv[7] = new Vertex(-100, 100, -100);

            mv[8] = new Vertex(0, 1, 0);

        }

 

        void DefineCilinder()

        {

            double R = 70;    

            double da = 2 * Math.PI / NC;

            for (int i = 0; i < NC; i++)

            {

                double x = R * Math.Cos( i * da);

                double y = R * Math.Sin( i * da);

 

                mv[i] = new Vertex(x, y, -100);

              

            }

            mv[ NC] = new Vertex(0, 0, 100);

            for (int i = 0; i < NC; i++)

            {

                mp[i] = new Polygon(Color.Blue, mv[i],mv[(i+1)%NC], mv[NC]);

            }

           

           

            mp[NC] = new Polygon(Color.Red, mv, NC, NC, true);

            //mp[NC+1] = new Polygon(Color.Green, mv, NC, NC, false);

          

        }

 

        void DefineСonus()

        {

            double R = 70;

            double da = 2 * Math.PI / NC;

            for (int i = 0; i < NC; i++)

            {

                double x = R * Math.Cos(i * da);

                double y = R * Math.Sin(i * da);

                mv[i] = new Vertex(x, y, -100);

                mv[i + NC] = new Vertex(x, y, 100);

            }

            for (int i = 0; i < NC - 1; i++)

            {

                mp[i] = new Polygon(Color.Blue, mv[i], mv[i + 1], mv[i + NC + 1], mv[i + NC]);

            }

            mp[NC - 1] = new Polygon(Color.Red, mv[NC - 1], mv[0], mv[NC], mv[NC * 2 - 1]);

            mp[NC] = new Polygon(Color.Blue, mv, 0, NC, true);

            mp[NC + 1] = new Polygon(Color.Blue, mv, NC, NC, false);

        }

 

        void DefineCubePolygons()

        {

            mp[0] = new Polygon(Color.Blue, mv[3], mv[2], mv[1], mv[0]);

            mp[1] = new Polygon(Color.Red, mv[4], mv[5], mv[6], mv[7]);

            mp[2] = new Polygon(Color.Green, mv[0], mv[1], mv[5], mv[4]);

            mp[3] = new Polygon(Color.Cyan, mv[1], mv[2], mv[6], mv[5]);

            mp[4] = new Polygon(Color.Cornsilk, mv[2], mv[3], mv[7], mv[6]);

            mp[5] = new Polygon(Color.BurlyWood, mv[3], mv[0], mv[4], mv[7]);

        }

 

        void ViewTrans()

        {

            for (int i = 0; i < mv.Length; i++)

            {

                mv[i].v = KGiG_Methods.RotateVector(mv[i].v, QRot);

                mv[i].ScreenTrans(d, Ro, pictureBox1.Width / 2, pictureBox1.Height / 2);             

            }

            QRot = new Quaternion(1, new Vector3D());

        }

 

        void SortPolygons()

        {

            for (int j = 0; j < mp.Length; j++)

                for (int i = 0; i < mp.Length-1; i++)

                {

                    if ( mp[i].avrZ < mp[i + 1].avrZ )

                    {

                        Polygon temp = mp[i];

                        mp[i] = mp[i + 1];

                        mp[i + 1] = temp;

                    }

                }

        }

 

        public Vertex[] CrossBorders(int lineY, Polygon P)

        {

            Vertex[] res = null;

            Vertex topV = null;

            Vertex downV = null;

            Vertex topV1 = null;

            Vertex downV1 = null;

            for (int i = 0; i < P.V.Count; i++)

            {

                int j = (i + 1) % P.V.Count;

                if (P.V[i].s.Y != P.V[j].s.Y)

                {

                    if (P.V[i].s.Y < P.V[j].s.Y)

                    {

                        topV = P.V[i];

                        downV = P.V[j];

                    }

                    else

                    {

                        topV = P.V[j];

                        downV = P.V[i];

                    }

                    if ((lineY >= topV.s.Y) && (lineY < downV.s.Y))

                    {

                        if (topV1 == null)

                        {

                            topV1 = topV;

                            downV1 = downV;

                        }

                        else

                        {

                            res = new Vertex[] { topV1, downV1, topV, downV };

                            break;

                        }

                    }

                }

            }

            return res;

        }

 

        public void PaintPhong(Bitmap bmp, Polygon P)

        {

            int topY = P.V[0].s.Y;

            int downY = P.V[0].s.Y;

            foreach (Vertex Vi in P.V)

            {

                Vi.NormalVertex();

                if (Vi.s.Y > downY) downY = Vi.s.Y;

                if (Vi.s.Y < topY) topY = Vi.s.Y;

            }

            for (int y = topY; y <= downY; y++)

            {

                Vertex[] ABCD = CrossBorders(y, P);

                if (ABCD != null)

                {

                    float u = ((float)(y - ABCD[0].s.Y)) / (ABCD[1].s.Y - ABCD[0].s.Y);

                    int x1 = (int)(u * ABCD[1].s.X + (1 - u) * ABCD[0].s.X);

                    Vector3D NQ = u * ABCD[1].N + (1 - u) * ABCD[0].N;

                    u = ((float)(y - ABCD[2].s.Y)) / (ABCD[3].s.Y - ABCD[2].s.Y);

                    int x2 = (int)(u * (ABCD[3].s.X - ABCD[2].s.X) + ABCD[2].s.X);

                    Vector3D NR = u * ABCD[3].N + (1 - u) * ABCD[2].N;

                    if (x1 > x2) { int xt = x1; x1 = x2; x2 = xt; Vector3D NT = NQ; NQ = NR; NR = NT; }

                    for (int x = x1; x < x2; x++)

                    {

                        u = ((float)(x - x1)) / (x2 - x1);

                        Vector3D NP = u * NR + (1 - u) * NQ;

                        double Ipm = Math.Pow(KGiG_Methods.cosAoB(NP, VLight), 4);

                        if (Ipm < 0) Ipm = 0;

                        double Ip = Ipm * 0.8 + 0.4;                   

                        int CR = (int)(P.col.R * Ip);

                        int CG = (int)(P.col.G * Ip);

                        int CB = (int)(P.col.B * Ip);

                        if (CR > 255) CR = 255;

                        if (CG > 255) CG = 255;

                        if (CB > 255) CB = 255;

                        Color colP = Color.FromArgb(CR, CG, CB);

                        bmp.SetPixel(x, y, colP);

                    }

                }

            }

        }

 

        public void PaintGuro(Bitmap bmp, Polygon P)

        {

            int topY = P.V[0].s.Y;

            int downY = P.V[0].s.Y;

            foreach (Vertex Vi in P.V)

            {

                Vi.NormalVertex();

                Vi.I = KGiG_Methods.cosAoB(Vi.N, VLight);

                if (Vi.I < 0) Vi.I = 0;

                if (Vi.s.Y > downY) downY = Vi.s.Y;

                if (Vi.s.Y < topY) topY = Vi.s.Y;

            }

            for (int y = topY; y <= downY; y++)

            {

                Vertex[] ABCD = CrossBorders(y, P);

                if (ABCD != null)

                {

                    double u = ((double)(y - ABCD[0].s.Y)) / (ABCD[1].s.Y - ABCD[0].s.Y);

                    int x1 = (int)(u * ABCD[1].s.X + (1 - u) * ABCD[0].s.X);                  

                    double Iq = u * ABCD[1].I + (1 - u) * ABCD[0].I;

                    u = ((double)(y - ABCD[2].s.Y)) / (ABCD[3].s.Y - ABCD[2].s.Y);

                    int x2 = (int)(u * (ABCD[3].s.X - ABCD[2].s.X) + ABCD[2].s.X);

                    double Ir = u * ABCD[3].I + (1 - u) * ABCD[2].I;

                    if (x1 > x2) { int xt = x1; x1 = x2; x2 = xt; double It = Iq; Iq = Ir; Ir = It; }

                    for (int x = x1; x < x2; x++)

                    {

                        u = ((double)(x - x1)) / (x2 - x1);

                        double Ip = u * Ir + (1 - u) * Iq;                       

                        Color col = Color.FromArgb((byte)(P.col.R * Ip),

                                                   (byte)(P.col.G * Ip),

                                                   (byte)(P.col.B * Ip));

Информация о работе Моделирование геометрических объектов