Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Grafica pe calculator / Geometrie computationala Computer Graphics / Computation Geometry Titular curs : Conf. Dr. Marin Vlada, Universitatea din Bucuresti WEB: http://marinvlada.googlepages.com/, www.ad-astra.ro/marinvlada E-mail: marinvlada[at]yahoo.com, marinvlada[at]gmail.com Course: COMPUTER GRAPHICS | Bachelor of Science (Computer Science) Software: C++, OpenGL, Java 3D, Java Script, VRML, SVG http://marinvlada.googlepages.com/prog_grafic.htm www.cniv.ro
www.icvl.eu ©
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
PROIECT – Algoritmul Bresenham (linie, cerc, elipsa) Nota: Codul Visual Studio (Visual
C++); Visual Studio .NET 2003
Autor: Chitu Octavian, student Facultatea de Matematica si Informatica, Universitatea din Bucuresti -Utilizeaza algoritmul Bresenham pentru trasarea liniei, cercului si elipsei
Programul ofera o fereastra pentru aplicatie: un meniu in partea stanga si o zona in partea dreapta (OUTPUT) pentru trasare. Trasarea se realizeaza intr-o zona ce ofera o grila de linii ce sugereaza rezolutia oferita de o zona de pixeli: 0-49 x 0-49., originea fiind punctul din coltul stanga-sus al zonei OUTPUT. Meniul din stanga se utilizeaza pentru a valida butonul (FIGURA) corespunzator obiectului ce se doreste a fi tarsat (Linie, Cerc, Elipsa), optiunea determina aparitia casetelor pentru introducerea datelor de identificare (CORDONATE) a obiectului selectat (x1, y1, x2, y2 pentru Linie; x1, y1, Raza pentru Cerc; x1, y1 , r, r pentru Elipsa). Se valideaza butunul pentru „Arata linia ideala” si apoi se actioneaza butunul „Deseneaza”. Butonul „Reset” se utilizeaza pentru a sterge trasarea din zona „OUTPUT”.
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Program.cs using System; using System.Collections.Generic; using System.Windows.Forms; namespace Bresenham { static class Program { /// <summary> /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Form1.cs using using using using using using using using
System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms; System.Threading;
namespace Bresenham { public partial class Form1 : Form { private bool draw = false, pause =false; public Form1() { InitializeComponent(); panel1.Paint += new PaintEventHandler(panel1_Paint); }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada void panel1_Paint(object sender, PaintEventArgs e) { Graphics grfx = e.Graphics; //intializare grila for (int i = 1; i < 50; i++) { grfx.DrawLine(Pens.LightGray, new Point(0, 10 * i), new Point(500, 10 * i)); grfx.DrawLine(Pens.LightGray, new Point(10 * i, 0), new Point(10 * i, 500)); } //daca nu trebuie sa dezenez figura, ma opresc dupa desenarea grilei if (!draw) return; if (rbLine.Checked) { //puncte pentru linie int x1, x2, y1, y2; //puncte initiale, folosite la desenarea liniei ideale int x1i, x2i, y1i, y2i; try { //extragere coordonate //sunt dublate in xxi pentru a putea trasa dreapta ideala x1i y1i x2i y2i
= = = =
x1 y1 x2 y2
= = = =
Int32.Parse(txtX1.Text); Int32.Parse(txtY1.Text); Int32.Parse(textBox3.Text); Int32.Parse(textBox4.Text);
} catch (FormatException fe) { draw = false; MessageBox.Show("Eroare la parsarea parametrilor", "Eroare", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //panta bool steep = (Math.Abs(y2 - y1) > Math.Abs(x2 - x1)); int aux; if (steep) { aux = x1; x1 = y1; y1 = aux; aux = x2; x2 = y2; y2 = aux; } if (x1 > x2) { aux = x1; x1 = x2; x2 = aux; aux = y1; y1 = y2; y2 = aux; }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada int dx = x2 - x1; int dy = Math.Abs(y2 - y1); int error = 0; int ystep; int y = y1; if (y1 < y2) ystep = 1; else ystep = -1; for (int x = x1; x <= x2; x++) { // desenare pixel curent if (steep) grfx.FillRectangle(Brushes.Black, y * 10, x * 10, 10, 10); else grfx.FillRectangle(Brushes.Black, x * 10, y * 10, 10, 10); if (pause) Thread.Sleep(500); error = error + dy; if (2 * error >= dx) { y = y + ystep; error = error - dx; } } //linia ideala if (cbIdeal.Checked) { Pen p = new Pen(Color.Red, 3); grfx.DrawLine(p, x1i * 10 + 5, y1i * 10 + 5, x2i * 10 + 5, y2i * 10 + 5); } } if (rbCircle.Checked) { //coordonate centru, raza int x1, y1, r; try { x1 = Int32.Parse(txtX1.Text); y1 = Int32.Parse(txtY1.Text); r = Int32.Parse(textBox3.Text); } catch (FormatException fe) { draw = false; MessageBox.Show("Eroare la parsarea parametrilor", "Eroare", MessageBoxButtons.OK, MessageBoxIcon.Error); return;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada } if (r < 0) { draw = false; MessageBox.Show("Raza nu poate fi negativa", "Eroare", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } int int int int int
f = 1 - r; ddF_x = 0; ddF_y = -2 * r; x = 0; y = r;
//marcam centrul //grfx.FillRectangle(Brushes.Black, x1 * 10, y1 * 10, 10, 10); //desenare puncte initiale if (y1 + r < 50) grfx.FillRectangle(Brushes.Black, 10, (y1 + r) * 10, 10, 10); if (y1 - r >= 0) grfx.FillRectangle(Brushes.Black, 10, (y1 - r) * 10, 10, 10); if (x1 + r < 50) grfx.FillRectangle(Brushes.Black, + r) * 10, y1 * 10, 10, 10); if (x1 - r >= 0) grfx.FillRectangle(Brushes.Black, - r) * 10, y1 * 10, 10, 10); while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x + 1; //punctatarea celor 8 puncte pentru x,y, //cate unul in fiecare octan if (x1 + x >= 0 && x1 + x < 50 && y1 + y + y < 50) grfx.FillRectangle(Brushes.Black, (x1 + x)*10, (y1 y)*10,10,10); if (x1 - x >= 0 && x1 - x < 50 && y1 + y + y < 50) grfx.FillRectangle(Brushes.Black, (x1 - x)*10, (y1 y)*10,10,10); if (x1 + x >= 0 && x1 + x < 50 && y1 - y - y < 50) grfx.FillRectangle(Brushes.Black, (x1 + x)*10, (y1 y)*10,10,10); if (x1 - x >= 0 && x1 - x < 50 && y1 - y - y < 50) grfx.FillRectangle(Brushes.Black, (x1 - x)*10, (y1 y)*10,10,10);
x1 * x1 * (x1 (x1
>= 0 && y1 + >= 0 && y1 + >= 0 && y1 >= 0 && y1 -
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada if (x1 + y >= 0 && x1 + + x < 50) grfx.FillRectangle(Brushes.Black, x)*10,10,10); if (x1 - y >= 0 && x1 + x < 50) grfx.FillRectangle(Brushes.Black, x)*10,10,10); if (x1 + y >= 0 && x1 + - x < 50) grfx.FillRectangle(Brushes.Black, x)*10,10,10); if (x1 - y >= 0 && x1 - x < 50) grfx.FillRectangle(Brushes.Black, 10, 10, 10);
y < 50 && y1 + x >= 0 && y1 (x1 + y)*10, (y1 + y < 50 && y1 + x >= 0 && y1 (x1 - y)*10, (y1 + y < 50 && y1 - x >= 0 && y1 (x1 + y)*10, (y1 y < 50 && y1 - x >= 0 && y1 (x1 - y) * 10, (y1 - x) *
if (pause) Thread.Sleep(500); } //cerc ideal if (cbIdeal.Checked) { Pen p = new Pen(Color.Red, 2); grfx.DrawEllipse(p, (x1 - r) * 10 + 5, (y1 - r) * 10 + 5, r * 20, r * 20); } } if (rbEllipse.Checked) { //date initiale int x1, y1, r, R; try { x1 = Int32.Parse(txtX1.Text); y1 = Int32.Parse(txtY1.Text); r = Int32.Parse(textBox3.Text); R = Int32.Parse(textBox4.Text); } catch (FormatException fe) { draw = false; MessageBox.Show("Eroare la parsarea parametrilor", "Eroare", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (r < 0 || R < 0) { draw = false; MessageBox.Show("Raza nu poate fi negativa", "Eroare", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //initializare variabile ajutatoare int dAPatrat = 2 * r * r, dBPatrat = 2 * R * R, stopX = dBPatrat * r, stopY = 0;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada int x = r, y=0; int xChange = R * R * (1 - 2 * r), yChange = r * r; int error = 0;
(y1 + y) * 10, (y1 + y) * 10, (y1 - y) * 10, (y1 - y) * 10,
while (stopX >= stopY) //primul set de puncte { //se deseneaza cate un punct in fiecare cadran grfx.FillRectangle(Brushes.Black, (x1 + x) * 10, 10, 10); grfx.FillRectangle(Brushes.Black, (x1 - x) * 10, 10, 10); grfx.FillRectangle(Brushes.Black, (x1 - x) * 10, 10, 10); grfx.FillRectangle(Brushes.Black, (x1 + x) * 10, 10, 10); y++; stopY += dAPatrat; error += yChange; yChange += dAPatrat; if (2*error + xChange >0) { x--; stopX -= dBPatrat; error += xChange; xChange += dBPatrat; } if (pause) Thread.Sleep(300); } x = 0; y = R; xChange yChange error = stopX = stopY =
(y1 + y) * 10, (y1 + y) * 10, (y1 - y) * 10, (y1 - y) * 10,
= R * R; = r * r * (1 - 2 * R); 0; 0; dAPatrat * R;
// al doilea set de puncte while(stopX <= stopY) { //se deseneaza cate un punct in fiecare grfx.FillRectangle(Brushes.Black, (x1 + 10, 10); grfx.FillRectangle(Brushes.Black, (x1 10, 10); grfx.FillRectangle(Brushes.Black, (x1 10, 10); grfx.FillRectangle(Brushes.Black, (x1 + 10, 10); x++; stopX += dBPatrat; error += xChange; xChange += dBPatrat;
cadran x) * 10, x) * 10, x) * 10, x) * 10,
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada if (2*error + y > 0) { y--; stopY -= dAPatrat; error += yChange; yChange += dAPatrat; } if (pause) Thread.Sleep(300); } //desenam elipsa ideala if (cbIdeal.Checked) { grfx.DrawEllipse(Pens.Red, (x1 - r) * 10 + 5 , (y1 - R) * 10 + 5, r * 20, R * 20); } } } private void rbLine_CheckedChanged(object sender, EventArgs e) { label3.Text = "X2"; label4.Text = "Y2"; label4.Visible = true; textBox4.Visible = true; //curata campurile si zona de desen btnReset_Click(null, null); } private void rbCircle_CheckedChanged(object sender, EventArgs e) { label3.Text = "Raza"; label4.Visible = false; textBox4.Visible = false; //curata campurile si zona de desen btnReset_Click(null, null); } private void rbEllipse_CheckedChanged(object sender, EventArgs e) { label3.Text = "r"; label4.Text = "R"; label4.Visible = true; textBox4.Visible = true; //curata campurile si zona de desen btnReset_Click(null, null); } private void btnDraw_Click(object sender, EventArgs e) {
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada //flag folosit pentru a desena figurile secvential, se face o scurta pauza pt fiecare punct sau set de puncte pause = cbPause.Checked; // flag pentru desenare, daca draw este false, se deseneaza doar grila // folosit la desenarea initiala si in caz de erori draw = true; panel1.Invalidate(); } private void btnReset_Click(object sender, EventArgs e) { // draw devine false, pentru a desena doar grila draw = false; //curata toate datele introduse txtX1.Text = ""; txtY1.Text = ""; textBox3.Text = ""; textBox4.Text = ""; //fortez redesenarea panel-ului panel1.Invalidate(); } } }
PROIECT – Algoritmul Bresenham (linie, cerc, elipsa) Nota: Codul Visual Studio (Visual
C++); Visual Studio .NET 2003
Autor: Dumitrel Ciprian, student Facultatea de Matematica si Informatica, Universitatea din Bucuresti -Utilizeaza algoritmul Bresenham pentru trasarea liniei, cercului si elipsei
Programul ofera o fereastra pentru aplicatie: un meniu in partea de sus-stanga si o zona pentru trasare in partea centrala. Meniul ofera trei butoane: • Linie; • Cerc; • Elipsa Pentru trasare se executa click-stanga pe butonul corespunzator si apoi in zona de trasare si trage cu mouse-ul pentru a indica forma elementului dorit. Cu culoarea rosie se traseaza folosind functia/metoda/procedura din software de baza, iar cu culoarea neagra se traseaza folosind algoritmul Bresenham.
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Program.cs using System; using System.Collections.Generic; using System.Windows.Forms; namespace Bersenham { static class Program { /// <summary> /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles( ); Application.SetCompatibleTextRe nderingDefault(false); Application.Run(new FormBresenham()); } } }
FormBresenham.cs using using using using using using using
System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms;
namespace Bersenham { /// <summary> /// Clasa pentru a desena linie, cerc si elipsa cu algoritmul lui Bresenham /// public partial class FormBresenham : Form { private int type;//0 linie, 1 cerc 2 elipsa private bool click; private int xprim = -1, yprim = -1;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada private int xsec = -1, ysec = -1; /// <summary> /// Constructorul principal /// public FormBresenham()//done { InitializeComponent(); type = 0; click = false; xprim = yprim = -1; xsec = ysec = -1; } /// <summary> /// Schimba textul ferestrei si tipul de desen la schimbarea tab-ului /// /// <param name="sender">Obiectul care a facut apelul /// <param name="e">Eveniment de tip EventArgs private void TabControl_SelectedIndexChanged(object sender, EventArgs e)//done { type = TabControl.SelectedIndex; PanelDraw.Refresh(); } /// <summary> /// La apasarea mouse-ului cu butonul STANGA se deseneaza linia /// /// <param name="sender">Obiectul care a facut apelul /// <param name="e">Eveniment de tip MouseEventArgs private void PanelDraw_MouseClick(object sender, MouseEventArgs e) { if (e.Button != MouseButtons.Left) return; if (click == false)//apasat prima oara { click = true; PanelDraw.Refresh(); Rectangle r = new Rectangle(); r = PanelDraw.RectangleToScreen(PanelDraw.ClientRectangle); xprim = MousePosition.X - r.X; yprim = MousePosition.Y - r.Y; } else { click = false; PanelDraw.Refresh(); Rectangle r = new Rectangle(); r = PanelDraw.RectangleToScreen(PanelDraw.ClientRectangle);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada xsec = MousePosition.X - r.X; ysec = MousePosition.Y - r.Y; Graphics graph = PanelDraw.CreateGraphics(); if (type == 0) { graph.DrawLine(Pens.Red, xprim, yprim, xsec, ysec); linie(xprim, yprim, xsec, ysec); } else if (type == 1)//cerc { int radius = Math.Min(Math.Abs(xsec - xprim), Math.Abs(ysec - yprim)); int cx = (xprim + xsec - radius) / 2; int cy = (yprim + ysec - radius) / 2; graph.DrawEllipse(Pens.Red, cx, cy, radius, radius); cerc(xprim, yprim, xsec, ysec); } else if (type == 2) { graph.DrawEllipse(Pens.Red, Math.Min(xprim, xsec), Math.Min(yprim, ysec), Math.Abs(xsec - xprim), Math.Abs(ysec - yprim)); elipsa(xprim, yprim, xsec, ysec); } } } public void LinePos1(int x_1, int y_1, int x_2, int y_2) { int dx, dy, p, twody, twodydx, x, y, xend; dx = Math.Abs(x_1 - x_2); dy = Math.Abs(y_1 - y_2); twody = 2 * dy; p = twody - dx; twodydx = 2 * (dy - dx); if (x_1 > x_2) { x = x_2; y = y_2; xend = x_1; } else { x = x_1; y = y_1; xend = x_2; } pixel(x, y); while (x < xend) { x++;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada if (p < 0) p += twody; else { y++; p += twodydx; } pixel(x, y); } } public void LinePos2(int x_1, int y_1, int x_2, int y_2) { int dx, dy, p, twodx, twodxdy, x, y, yend; dx = Math.Abs(x_1 dy = Math.Abs(y_1 twodx = 2 * dx; p = twodx - dy; twodxdy = 2 * (dx y = y_1; yend = y_2; x = x_1;
- x_2); - y_2); - dy); // Dummy initialization // Ditto
if (x_1 == x_2) // Vertical line { if (y_2 > y_1) { yend = y_2; y = y_1; } else { yend = y_1; y = y_2; } for (; y <= yend; y++) pixel(x_1, y); } if (x_1 > x_2) { x = x_2; y = y_2; yend = y_1; } if (x_1 < x_2) { x = x_1; y = y_1; yend = y_2; } if (x_1 != x_2) { pixel(x_1, y_1); while (y < yend) { y++;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada if (p < 0) p += twodx; else { x++; p += twodxdy; } pixel(x, y); } } } public void LineNeg1(int x_1, int y_1, int x_2, int y_2) { int dx, dy, p, twody, twodydx, x, y, xend; dx = Math.Abs(x_2 - x_1); dy = Math.Abs(y_2 - y_1); p = 2 * dy - dx; twody = 2 * dy; twodydx = 2 * (dy - dx); if (x_1 > x_2) { x = x_2; y = y_2; xend = x_1; } else { x = x_1; y = y_1; xend = x_2; } pixel(x, y); while (x < xend) { x++; if (p < 0) p += twody; else { y--; p += twodydx; } pixel(x, y); } } public void LineNeg2(int x_1, int y_1, int x_2, int y_2) { int dx, dy, p, twodx, twodxdy, x, y, yend; dx = Math.Abs(x_2 - x_1); dy = Math.Abs(y_2 - y_1); p = 2 * dx - dy;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada twodx = 2 * dx; twodxdy = 2 * (dx - dy); if (x_1 > x_2) { x = x_2; y = y_2; yend = y_1; } else { x = x_1; y = y_1; yend = y_2; } pixel(x, y); while (y > yend) { y--; if (p < 0) p += twodx; else { x++; p += twodxdy; } pixel(x, y); } } public void linie(int x1, int y1, int x2, int y2) { double deltax, deltay; // For Bresenham's double slope; // Ditto deltax = x2 - x1; deltay = y2 - y1;
// Change in x // Change in y
if (deltax == 0) // Need to avoid div by zero LinePos2(x1, y1, x2, y2); else { slope = deltay / deltax; if (slope > 0.0) { if (slope > 1.0) LinePos2(x1, y1, x2, y2); else LinePos1(x1, y1, x2, y2); } else { if (slope > -1.0) LineNeg1(x1, y1, x2, y2);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada else LineNeg2(x1, y1, x2, y2); } } } private void elipsa(int x1, int y1, int x2, int y2) { int cx, cy; int a, b; int x, y; double d1, d2; cx = Math.Abs(x1 + x2) / 2; cy = Math.Abs(y1 + y2) / 2; a = Math.Abs(x2 - x1) / 2; b = Math.Abs(y2 - y1) / 2; x = 0; y = b; d1 = b * b - a * a * b + a * a / 4; pixel(cx + x, cy + y); pixel(cx + x, cy - y); pixel(cx - x, cy + y); pixel(cx - x, cy - y); while (a * a * (y - .5) > b * b * (x + 1)) { if (d1 < 0) { d1 += b * b * (2 * x + 3); x++; } else { d1 += b * b * (2 * x + 3) + a * a * (-2 * y + 2); x++; y--; } pixel(cx + x, cy + y); pixel(cx + x, cy - y); pixel(cx - x, cy + y); pixel(cx - x, cy - y); } d2 = b * b * (x + .5) * (x + .5) + a * a * (y - 1) * (y 1) - a * a * b * b; while (y > 0) { if (d2 < 0) { d2 += b * b * (2 * x + 2) + a * a * (-2 * y + 3); y--; x++; } else { d2 += a * a * (-2 * y + 3); y--; } pixel(cx + x, cy + y);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada pixel(cx + x, cy - y); pixel(cx - x, cy + y); pixel(cx - x, cy - y); } } private void cerc(int x1, int y1, int x2, int y2) { int cx, cy; int r; int x, y; double d1, d2; cx = Math.Abs(x1 + x2) / 2; cy = Math.Abs(y1 + y2) / 2; r = Math.Min(Math.Abs(x2 - x1), Math.Abs(y2 - y1)) / 2; x = 0; y = r; d1 = r * r * 5 / 4 - r * r * r; pixel(cx + x, cy + y); pixel(cx + x, cy - y); pixel(cx - x, cy + y); pixel(cx - x, cy - y); while ((y - .5) >(x + 1)) { if (d1 < 0) { d1 += r * r * (2 * x + 3); x++; } else { d1 += r * r * (2 * x - 2 * y + 5); x++; y--; } pixel(cx + x, cy + y); pixel(cx + x, cy - y); pixel(cx - x, cy + y); pixel(cx - x, cy - y); } d2 = r * r * ((x + .5) * (x + .5) + (y - 1) * (y - 1)) - r * r * r * r; while (y > 0) { if (d2 < 0) { d2 += r * r * (2 * x - 2 * y + 5); y--; x++; } else { d2 += r * r * (-2 * y + 3); y--; } pixel(cx + x, cy + y); pixel(cx + x, cy - y);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada pixel(cx - x, cy + y); pixel(cx - x, cy - y); } } private void pixel(int x, int y) { Graphics graph = PanelDraw.CreateGraphics(); graph.FillRectangle(Brushes.Black, x, y, 1, 1); System.Threading.Thread.Sleep(1); } } }
PROIECT – Algoritmul Bresenham (linie, cerc, elipsa) Nota: Codul Visual Studio (Visual
C++); Visual Studio .NET 2003
Autor: Vorovenci, Radoi, Mihaita, studenti Facultatea de Matematica si Informatica, Universitatea din Bucuresti -Utilizeaza algoritmul Bresenham pentru trasarea liniei, cercului si elipsei
Programul ofera o fereastra pentru aplicatie: un meniu in partea de sus (OPTIUNI) si o zona pentru trasare in partea centrala. Zona „Introduceti datele” ofera posibilitatea de a introduce coordonatele corespunzatoare figurii alese pentru trasare (linie, cerc, elipsa) dupa care se executa click-stanga pe butonul „Aplica Algoritm”. Butonul „Date noi” sterge desenarea din zona de trasare pentru a realiza o noua trasare. Lista de optiuni din caseta ofera optiunile: • Linie; • Cerc; • Elipsa Program.cs using System; using System.Collections.Generic; using System.Windows.Forms; namespace alg_bresenham { static class Program { /// <summary> /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada Application.Run(new Form1()); } } }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Form1.cs using using using using using using using
System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms;
namespace alg_bresenham { public partial class Form1 : Form {
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada public Int32 cbox_opt = 10; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void groupBox1_Enter(object sender, EventArgs e) { } private void textBox4_TextChanged(object sender, EventArgs e) { } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { gbox2.Visible = true; btn1.Visible = true; btn2.Visible = true; tb1.Text tb2.Text tb3.Text tb4.Text
= = = =
""; ""; ""; "";
pnlDesen.Invalidate(); pnlDesen.Visible = false; label6.Visible = false; switch (cbox.SelectedIndex) { case 0: label4.Text = "X2 ="; label5.Text = "Y2 ="; label5.Visible = true; tb4.Visible = true; label7.Visible = false; tb5.Visible = false; cbox_opt = 0; break; case 1: label4.Text = "R ="; label5.Visible = false; tb4.Visible = false; label7.Visible = false; tb5.Visible = false; cbox_opt = 1; break; case 2: label4.Text = " r = "; label5.Text = " R = "; tb4.Visible = true; label5.Visible = true;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
/*
label7.Visible = false; tb5.Visible = false; cbox_opt = 2; break; case 3: label4.Text = " r = "; label5.Text = " R = "; tb4.Visible = true; label5.Visible = true; label7.Visible = true; tb5.Visible = true; cbox_opt = 3; break; */
} } private void button2_Click(object sender, EventArgs e) { pnlDesen.Visible = false; pnlDesen.Invalidate(); label6.Visible = false; tb1.Text tb2.Text tb3.Text tb4.Text tb5.Text
= = = = =
""; ""; ""; ""; "";
} private void gbox2_Enter(object sender, EventArgs e) { } private void btn1_Click(object sender, EventArgs e) { label6.Visible = true; pnlDesen.Visible = true; pnlDesen.Invalidate(); } private void pnlDesen_Paint(object sender, PaintEventArgs e) { Graphics grafics = e.Graphics; // daca nu avem coordonatele introduse nu avem ce desena si iesim din event-ul de desenare al panalului int xflag = 1; if (cbox_opt == 10) return; else switch (cbox_opt) {
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada case 0 : //desenam dreapta // variabile locale folosite in algoritm int x1, y1, x2, y2, a, b, dl1, dl2, g, nxt, nyt; double iXB, iYB, ixa2, iya2,ixb2,iyb2,ixaya ,ixbyb,ila2, ila4 ,ilb2 , ilb4; double iA, iB, iC, iD, iDx, iDy, iSigma, iXp1, temp,iYm1,iYp1; double pi; float iXA, iYA;
try { // x1 y1 x2 y2
se scot coordonatele = Int32.Parse(tb1.Text); = Int32.Parse(tb2.Text); = Int32.Parse(tb3.Text); = Int32.Parse(tb4.Text);
} catch (FormatException) { //datele introduse nu sunt valide( se face verificarea datelor) MessageBox.Show("Invalid number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //se deseneaza coordonatele introduse grafics.FillRectangle(Brushes.Red, x1, y1, 6, 6); grafics.FillRectangle(Brushes.Red, x2, y2, 6, 6); // se calculeaza modulul diferentei dintre coordonate a = Math.Abs(y2 - y1); b = Math.Abs(x2 - x1); if (a <= b) { g = 2 * dl1 = 2 dl2 = 2 } else { g = 2 * dl1 = 2 dl2 = 2 }
a - b; * (a - b); * a;
b - a; * (b - a); * b;
nxt = x2 < x1 ? -1 : 1; nyt = y2 < y1 ? -1 : 1; if (a < b) { for (int i = 0; i < b; i++)
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada { if (g > 0) { g += dl1; x1 += nxt; y1 += nyt; } else { g += dl2; x1 += nxt; } //se deseneza pixelul la coordonatele calculate prin algoritm grafics.FillRectangle(Brushes.BlueViolet, x1, y1, 3, 3); } } else { for (int i = 0; i < a; i++) { if (g > 0) { g += dl1; y1 += nyt; x1 += nxt; } else { g += dl2; y1 += nyt; } //se deseneza pixelul la coordonatele calculate prin algoritm grafics.FillRectangle(Brushes.BlueViolet, x1, y1, 3, 3); } } break; case 1: // desenam cercul //variabile locale folosite in algoritm int xc, yc, R, x, y, p; try { //se scot coordonatele si raza xc = Int32.Parse(tb1.Text); yc = Int32.Parse(tb2.Text); R = Int32.Parse(tb3.Text); } catch (FormatException) { //datele introduse nu sunt valide //mesaj de eroare
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada MessageBox.Show("Invalid number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // iesim din event deoarece nu se poate desena cercul deoarece datele nu sunt valide return; } //se deseneaza centrul cercului grafics.FillRectangle(Brushes.Red, xc, yc, 6, 6); x = -1; y = R; p = (5 - R * 4) / 4; while (x <= y) { x++; if (p < 0) p = p + 2 * x + 1; else { y--; p = p + 2 * (x - y) + 1; } if (x == 0) { // se deseneaza pixeli simetrici la coordonatele calculate conform algoritmului grafics.FillRectangle(Brushes.BlueViolet, yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, yc - y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, y, yc, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, y, yc, 3, 3); } if (x == y) { grafics.FillRectangle(Brushes.BlueViolet, x, yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, x, yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, x, yc - y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, x, yc - y, 3, 3); } if (x < y) { grafics.FillRectangle(Brushes.BlueViolet, x, yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, x, yc + y, 3, 3);
xc, xc, xc + xc -
xc + xc xc + xc -
xc + xc -
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada grafics.FillRectangle(Brushes.BlueViolet, xc + x, yc - y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc x, yc - y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc + y, yc + x, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc y, yc + x, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc + y, yc - x, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc y, yc - x, 3, 3); } } break; case 2:
// desenam elipsa
int r, R2, r2, s, t; try { //se scot coordonatele centrului si razele xc = Int32.Parse(tb1.Text); yc = Int32.Parse(tb2.Text); r = Int32.Parse(tb3.Text); R = Int32.Parse(tb4.Text); } catch (FormatException) { //datele introduse nu sunt valide //se arunca un mesaj de eroare MessageBox.Show("Invalid number", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //se desenaza centrul elipsei grafics.FillRectangle(Brushes.Red, xc, yc, 6, 6); R2 = R r2 = r x = 0; y = r; s = R2 t = r2
* R; * r; * (1 - 2 * r) + 2 * r2; - 2 * R2 * (2 * r - 1);
//se deseneaza cei patru pixeli simetrici dupa r grafics.FillRectangle(Brushes.BlueViolet, xc + x, yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc - x, yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc - x, yc y, 3, 3);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada grafics.FillRectangle(Brushes.BlueViolet, xc + x, yc y, 3, 3); do { if (s < 0) { s = s + t = t + x++; } else if (t < { s =
2 * r2 * (2 * x + 3); 4 * r2 * (x + 1);
0) s + 2 * r2 * (2 * x + 3) - 4 * R2 * (y
- 1); t = t + 4 * r2 * (x + 1) - 2 * R2 * (2 * y - 3); x++; y--; } else { s = s - 4 * R2 * (y - 1); t = t - 2 * R2 * (2 * y - 3); y--; } //se deseneaza ce patru pixeli simetrici la coordonatele nou calculate grafics.FillRectangle(Brushes.BlueViolet, xc yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc yc + y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc yc - y, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, xc yc - y, 3, 3);
+ x, - x, - x, + x,
} while (y != 0); break; /*
case 3:
//se scot coordonatele; int iXC = Int32.Parse(tb1.Text); int iYC = Int32.Parse(tb2.Text); int A = Int32.Parse(tb3.Text); int B = Int32.Parse(tb4.Text); double angle = Double.Parse(tb5.Text); //se desenaza centrul elipsei grafics.FillRectangle(Brushes.Red, iXC, iYC, 6, 6);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada pi=3.1415926 ; if (angle < pi/2)
xflag=1 ;
else if (angle>pi/2 && angle
=pi && angle < pi*1.5) { angle=angle-pi; xflag=1; } else if (angle >= pi * 1.5 && angle < pi * 2) { angle = angle - pi; temp = angle - pi / 2; angle = pi / 2 - temp; xflag = -1; } iXA=(float)Math.Cos(angle)*A iYA=(float)Math.Sin(angle)*A iXB=Math.Cos(angle+(pi/2))*B iYB=Math.Sin(angle+(pi/2))*B ixa2=iXA*iXA ; iya2=iYA*iYA ; ixb2=iXB*iXB ; iyb2=iYB*iYB ; ixaya=iXA*iYA ; ixbyb=iXB*iYB ; ila2=ixa2+iya2 ; ila4=ila2*ila2 ; ilb2=ixb2+iyb2 ; ilb4=ilb2*ilb2 ; iA=ixa2*ilb4+ixb2*ila4 ; iB=ixaya*ilb4+ixbyb*ila4; iC=iya2*ilb4+iyb2*ila4 ; iD = ila4 * ilb4;
//
float iX, iY; double iym1 ,iyp1 ; if (iYA <= iXA) // start AT (-xA,-yA) { iX = -iXA; iY = -iYA; iDx = -(iB * iXA + iC * iYA); iDy = iA * iXA + iB * iYA;
; ; ; ;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada // arc FROM (-xA,-yA) TO point (x0,y0) where dx/dy = 0 while (iDx <= 0) { grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iY++; iSigma = iA * iX * iX + 2 * iB * iX * iY + iC * iY * iY - iD; if (iSigma < 0) { iDx = iDx - iB; iDy = iDy + iA; iX--; } iDx = iDx + iC; iDy = iDy - iB; } //' arc FROM (x0,y0) TO point (x1,y1) where dy/dx = 1 while (iDx <= iDy) { grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iY++; iXp1 = iX + 1; iSigma = iA * iXp1 * iXp1 + 2 * iB * iXp1 * iY + iC * iY * iY - iD; if (iSigma >= 0) { iDx = iDx + iB; iDy = iDy - iA; iX = (float)iXp1; } iDx = iDx + iC; iDy = iDy - iB; } //' arc FROM (x1,y1) TO point (x2,y2) where dy/dx = 0 while (iDy >= 0) { grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iX++; iSigma = iA * iX * iX + 2 * iB * iX * iY + iC * iY * iY - iD; if (iSigma < 0) { iDx = iDx + iC; iDy = iDy - iB; iY++; } iDx = iDx + iB; iDy = iDy - iA; } //' arc FROM (x2,y2) TO point (x3,y3) where dy/dx = while (iDy >= -iDx) { grafics.FillRectangle(Brushes.BlueViolet, iXC + * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC * xflag, iYC - iY, 3, 3); iX++; iYm1 = iY - 1; iSigma = iA * iX * iX + 2 * iB * iX * iYm1 + iC iYm1 * iYm1 - iD;
-1 iX iX
*
if (iSigma >= 0) { iDx = iDx - iC; iDy = iDy + iB; iY = (float)iYm1; } iDx = iDx + iB; iDy = iDy - iA; } //' arc FROM (x3,y3) TO (xa,ya) while (iY >= iYA) { grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iY--; iSigma = iA * iX * iX + 2 * iB * iX * iY + iC * iY * iY - iD; if (iSigma < 0) { iDx = iDx + iB; iDy = iDy - iA; iX++; } iDx = iDx - iC;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada iDy = iDy + iB; }
//' start AT (-xa,-ya) iX = -iXA; iY = -iYA; iDx = -(iB * iXA + iC * iYA); iDy = iA * iXA + iB * iYA; //' arc FROM (-xa,-ya) TO point (x0,y0) where dy/dx = -1 while (-iDx >= iDy) { grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iX--; iYp1 = iY + 1; iSigma = iA * iX * iX + 2 * iB * iX * iYp1 + iC * iYp1 * iYp1 - iD; if (iSigma >= 0) { iDx = iDx + iC; iDy = iDy - iB; iY = (float)iYp1; } iDx = iDx - iB; iDy = iDy + iA; } //' arc FROM (x0,y0) TO point (x1,y1) where dx/dy while (iDx <= 0) { grafics.FillRectangle(Brushes.BlueViolet, iXC * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC * xflag, iYC - iY, 3, 3); iY++; iSigma = iA * iX * iX + 2 * iB * iX * iY + iC * iY - iD; if (iSigma < 0) { iDx = iDx - iB; iDy = iDy + iA; iX--; } iDx = iDx + iC; iDy = iDy - iB; }
= 0 + iX - iX * iY
//' arc FROM (x1,y1) TO point (x2,y2) where dy/dx = 1 while (iDx <= iDy) {
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iY++; iXp1 = iX + 1; iSigma = iA * iXp1 * iXp1 + 2 * iB * iXp1 * iY + iC * iY * iY - iD; if (iSigma >= 0) { iDx = iDx + iB; iDy = iDy - iA; iX = (float)iXp1; } iDx = iDx + iC; iDy = iDy - iB; } //' arc FROM (x2,y2) TO point (x3,y3) where dy/dx while (iDy >= 0) { grafics.FillRectangle(Brushes.BlueViolet, iXC * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC * xflag, iYC - iY, 3, 3); iX++; iSigma = iA * iX * iX + 2 * iB * iX * iY + iC * iY - iD; if (iSigma < 0) { iDx = iDx + iC; iDy = iDy - iB; iY++; } iDx = iDx + iB; iDy = iDy - iA; }
= 0 + iX - iX * iY
//' arc FROM (x3,y3) TO (xa,ya) while (iX <= iXA) { grafics.FillRectangle(Brushes.BlueViolet, iXC + iX * xflag, iYC + iY, 3, 3); grafics.FillRectangle(Brushes.BlueViolet, iXC - iX * xflag, iYC - iY, 3, 3); iX++; iYm1 = iY - 1; iSigma = iA * iX * iX + 2 * iB * iX * iYm1 + iC * iYm1 * iYm1 - iD; if (iSigma >= 0) { iDx = iDx - iC; iDy = iDy + iB; iY = (float)iYm1; } iDx = iDx + iB; iDy = iDy - iA;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada } } break;*/ } } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { } } }
PROIECT – Linii poligonale aproximate prin Curbe Bezier Nota: Codul Visual Studio (Visual
C++); Visual Studio .NET 2003
Autor: Ciutu Calin, student Facultatea de Matematica si Informatica, Universitatea din Bucuresti -Utilizeaza algoritmul pentru Curbe Bezier
Programul ofera o fereastra pentru aplicatie: un meniu in partea dreapta (Control Panel) si o zona pentru trasare in partea centrala. Folosind mouse-ul prin click-stanga se indica punctele liniei poligonale. Programul traseaza linia introdusa si realizeaza aproximarea trasand linii de diverse culori conform algoritmului de aproximare. Coordonatele punctelor indicate apar in lista „Puncte introduse”din „Control Panel”. In final, curba optinuta este trasata cu culoarea rosie. Butonul „Sterge” elimina desenarea din zona de trasare pentru a realiza o noua trasare. Main.cs using System; using System.Windows.Forms; using System.Collections.Generic; namespace bezier1 { class MainClass { [STAThread] public static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
MainForm.cs
using using using using using using using
System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Text; System.Windows.Forms;
namespace bezier1 { public partial class MainForm : Form { const int max_points = 10; const int max_aprox_points = 100; const int numberOfPoints = 40; const double dt = 1.0 / (numberOfPoints - 1); Point[] cp = new Point[max_points]; Point[] curve = new Point[max_aprox_points]; Color[] colors = new Color[max_points];
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada int[] comb = new int[max_points]; int N; int current_pos; bool stop = true; public MainForm() { InitializeComponent(); SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.DoubleBuffer, true); listBox1.Items.Clear(); colors[0] = Color.MediumBlue; colors[1] = Color.SeaGreen; colors[2] = Color.Maroon; colors[3] = Color.Yellow; colors[4] = Color.Tomato; colors[5] = Color.OrangeRed; colors[6] = Color.Sienna; colors[7] = Color.Turquoise; colors[8] = Color.Violet; colors[9] = Color.Tan; } private void MainForm_Load(object sender, EventArgs e) { Invalidate(); } private void button1_Click(object sender, EventArgs e) { listBox1.Items.Clear(); stop = true; Invalidate(); } private void MainForm_MouseClick(object sender, MouseEventArgs e) { if (listBox1.Items.Count >= max_points || e.X < 2 || e.X > 515 || e.Y < 2 || e.Y > 450) return; listBox1.Items.Add(new Point(e.X, e.Y)); cp[listBox1.Items.Count - 1].X = e.X; cp[listBox1.Items.Count - 1].Y = e.Y; for (int i = listBox1.Items.Count; i < max_points; i++) { cp[i].X = e.X; cp[i].Y = e.Y; } N = listBox1.Items.Count - 1; PrepareValues(); button1.Enabled = false;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada current_pos = 0; stop = false; timer1.Enabled = true; } private void MainForm_Paint(object sender, PaintEventArgs e) { Graphics grfx = e.Graphics; Pen pen = new Pen(ForeColor); double t = (current_pos - 1) * dt; int i, j; Point[] prev = new Point[max_points]; Point[] curr = new Point[max_points]; if (listBox1.Items.Count == 0) return; for (i = 0; i < listBox1.Items.Count; i++) grfx.DrawRectangle(pen, cp[i].X-2, cp[i].Y-2, 4, 4); grfx.DrawLines(pen, cp); for (i = 0; i < listBox1.Items.Count; i++) prev[i] = cp[i]; for (i = 1; i < listBox1.Items.Count - 1; i++) { pen.Color = colors[i - 1]; for (j = 1; j <= listBox1.Items.Count - i; j++) { curr[j - 1].X = (int)((prev[j].X - prev[j - 1].X) * t + prev[j - 1].X); curr[j - 1].Y = (int)((prev[j].Y - prev[j - 1].Y) * t + prev[j - 1].Y); } for (j = listBox1.Items.Count - i ; j < max_points; j++) curr[j] = curr[listBox1.Items.Count - i - 1]; for (j = 0; j < listBox1.Items.Count - i; j++) grfx.DrawEllipse(pen, curr[j].X - 2, curr[j].Y - 2, 4, 4); grfx.DrawLines(pen, curr); for (j = 0; j < listBox1.Items.Count - i; j++) prev[j] = curr[j]; } if (stop) { pen.Color = ForeColor; grfx.DrawLines(pen, cp); for (i = 0; i < listBox1.Items.Count; i++)
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada grfx.DrawRectangle(pen, cp[i].X - 2, cp[i].Y - 2, 4, 4); } pen.Color = Color.Red; grfx.DrawLines(pen, curve); } private int Fact(int n) { int i, rez = 1; for (i = 1; i <= n; i++) rez *= i; return rez; } private void PrepareValues() { int i, numitor, numarator; numitor = numarator = Fact(N); comb[0] = 1; for (i = 1; i <= N; i++) { numitor = (numitor * i) / (N - i + 1); comb[i] = numarator / numitor; } } private Point GetPointOnCurve(double t) { double[] tpow = new double[max_points]; double[] _tpow = new double[max_points]; int i; Point result; result = new Point(0, 0); tpow[0] = _tpow[0] = 1; for (i = 1; i <= N; i++) { tpow[i] = tpow[i - 1] * t; _tpow[i] = _tpow[i - 1] * (1 - t); } for (i = 0; i <= N; i++) { result.X = (int)((double)result.X + ((double)comb[i] * (double)cp[i].X * _tpow[N - i] * tpow[i])); result.Y = (int)((double)result.Y + ((double)comb[i] * (double)cp[i].Y * _tpow[N - i] * tpow[i])); } return result; }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada private void timer1_Tick(object sender, EventArgs e) { curve[current_pos] = GetPointOnCurve(current_pos * dt); for (int j = current_pos + 1; j < max_aprox_points; j++) curve[j] = curve[current_pos]; current_pos++; if (current_pos == numberOfPoints) { button1.Enabled = true; timer1.Enabled = false; stop = true; } Invalidate(); } } }