Sunteți pe pagina 1din 43

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.
/// </summary>
[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 System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using 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 = x1 = Int32.Parse(txtX1.Text);
y1i = y1 = Int32.Parse(txtY1.Text);
x2i = x2 = Int32.Parse(textBox3.Text);
y2i = y2 = 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 f = 1 - r;
int ddF_x = 0;
int ddF_y = -2 * r;
int x = 0;
int 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, x1 *
10, (y1 + r) * 10, 10, 10);
if (y1 - r >= 0) grfx.FillRectangle(Brushes.Black, x1 *
10, (y1 - r) * 10, 10, 10);
if (x1 + r < 50) grfx.FillRectangle(Brushes.Black, (x1
+ r) * 10, y1 * 10, 10, 10);
if (x1 - r >= 0) grfx.FillRectangle(Brushes.Black, (x1
- 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 >= 0 && y1
+ y < 50) grfx.FillRectangle(Brushes.Black, (x1 + x)*10, (y1 +
y)*10,10,10);
if (x1 - x >= 0 && x1 - x < 50 && y1 + y >= 0 && y1
+ y < 50) grfx.FillRectangle(Brushes.Black, (x1 - x)*10, (y1 +
y)*10,10,10);
if (x1 + x >= 0 && x1 + x < 50 && y1 - y >= 0 && y1
- y < 50) grfx.FillRectangle(Brushes.Black, (x1 + x)*10, (y1 -
y)*10,10,10);
if (x1 - x >= 0 && x1 - x < 50 && y1 - y >= 0 && y1
- y < 50) grfx.FillRectangle(Brushes.Black, (x1 - x)*10, (y1 -
y)*10,10,10);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
if (x1 + y >= 0 && x1 + y < 50 && y1 + x >= 0 && y1
+ x < 50) grfx.FillRectangle(Brushes.Black, (x1 + y)*10, (y1 +
x)*10,10,10);
if (x1 - y >= 0 && x1 - y < 50 && y1 + x >= 0 && y1
+ x < 50) grfx.FillRectangle(Brushes.Black, (x1 - y)*10, (y1 +
x)*10,10,10);
if (x1 + y >= 0 && x1 + y < 50 && y1 - x >= 0 && y1
- x < 50) grfx.FillRectangle(Brushes.Black, (x1 + y)*10, (y1 -
x)*10,10,10);
if (x1 - y >= 0 && x1 - y < 50 && y1 - x >= 0 && y1
- x < 50) grfx.FillRectangle(Brushes.Black, (x1 - y) * 10, (y1 - x) *
10, 10, 10);

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;

while (stopX >= stopY) //primul set de puncte


{
//se deseneaza cate un punct in fiecare cadran
grfx.FillRectangle(Brushes.Black, (x1 + x) * 10,
(y1 + y) * 10, 10, 10);
grfx.FillRectangle(Brushes.Black, (x1 - x) * 10,
(y1 + y) * 10, 10, 10);
grfx.FillRectangle(Brushes.Black, (x1 - x) * 10,
(y1 - y) * 10, 10, 10);
grfx.FillRectangle(Brushes.Black, (x1 + x) * 10,
(y1 - y) * 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 = R * R;
yChange = r * r * (1 - 2 * R);
error = 0;
stopX = 0;
stopY = dAPatrat * R;

// al doilea set de puncte


while(stopX <= stopY)
{
//se deseneaza cate un punct in fiecare cadran
grfx.FillRectangle(Brushes.Black, (x1 + x) * 10,
(y1 + y) * 10, 10, 10);
grfx.FillRectangle(Brushes.Black, (x1 - x) * 10,
(y1 + y) * 10, 10, 10);
grfx.FillRectangle(Brushes.Black, (x1 - x) * 10,
(y1 - y) * 10, 10, 10);
grfx.FillRectangle(Brushes.Black, (x1 + x) * 10,
(y1 - y) * 10, 10, 10);

x++;
stopX += dBPatrat;
error += xChange;
xChange += dBPatrat;
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.
/// </summary>
[STAThread]
static void Main()
{

Application.EnableVisualStyles(
);

Application.SetCompatibleTextRe
nderingDefault(false);
Application.Run(new
FormBresenham());
}
}
}

FormBresenham.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Bersenham
{
/// <summary>
/// Clasa pentru a desena linie, cerc si elipsa cu algoritmul lui
Bresenham
/// </summary>
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
/// </summary>
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
/// </summary>
/// <param name="sender">Obiectul care a facut apelul</param>
/// <param name="e">Eveniment de tip EventArgs</param>
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
/// </summary>
/// <param name="sender">Obiectul care a facut apelul</param>
/// <param name="e">Eveniment de tip MouseEventArgs</param>
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 - x_2);
dy = Math.Abs(y_1 - y_2);
twodx = 2 * dx;
p = twodx - dy;
twodxdy = 2 * (dx - dy);
y = y_1; // Dummy initialization
yend = y_2; // Ditto
x = x_1;

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; // Change in x


deltay = y2 - y1; // 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.
/// </summary>
[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 System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using 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
{
// se scot coordonatele
x1 = Int32.Parse(tb1.Text);
y1 = Int32.Parse(tb2.Text);
x2 = Int32.Parse(tb3.Text);
y2 = 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 * a - b;
dl1 = 2 * (a - b);
dl2 = 2 * a;
}
else
{
g = 2 * b - a;
dl1 = 2 * (b - a);
dl2 = 2 * 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, xc,
yc + y, 3, 3);
grafics.FillRectangle(Brushes.BlueViolet, xc,
yc - y, 3, 3);
grafics.FillRectangle(Brushes.BlueViolet, xc +
y, yc, 3, 3);
grafics.FillRectangle(Brushes.BlueViolet, xc -
y, yc, 3, 3);
}
if (x == y)
{
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);
grafics.FillRectangle(Brushes.BlueViolet, xc -
x, yc - y, 3, 3);
}
if (x < y)
{
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);
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 * R;
r2 = r * r;
x = 0;
y = r;
s = R2 * (1 - 2 * r) + 2 * r2;
t = 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 + 2 * r2 * (2 * x + 3);
t = t + 4 * r2 * (x + 1);
x++;
}
else
if (t < 0)
{
s = 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 + 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);
grafics.FillRectangle(Brushes.BlueViolet, xc + x,
yc - y, 3, 3);

}
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)


{
temp=angle-pi/2;
angle=pi/2-temp ;
xflag=-1 ;
}
else if (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 = -1


while (iDy >= -iDx)
{
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;
}

//' 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 = 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 (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 = 0


while (iDy >= 0)
{
grafics.FillRectangle(Brushes.BlueViolet, iXC + iX
* xflag, iYC + iY, 3, 3);
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 (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 System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using 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();
}
}
}

S-ar putea să vă placă și