This document was uploaded by user and they confirmed that they have the permission to share
it. If you are author or own the copyright of this book, please report to us by using this DMCA
report form. Report DMCA
Overview
Download & View Projects-3-computer Graphics & Virtual Reality (algorithms, Modeling, Programs) as PDF for free.
PROIECT – mini editor grafic Nota: Codul Visual Studio (Visual
C++); Visual Studio .NET 2003
Autor: Lucian Codita, sudent Facultatea de Matematica si Informatica, Universitatea din Bucuresti -Utilizeaza algoritmul Bresenham pentru trasarea liniei si cercului Program.cs using System; using System.Collections.Generic; using System.Windows.Forms; namespace Grafica { 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 } } }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada Form1.cs using using using using using using using using
namespace Grafica { public partial class Form1 : Form { private Bitmap buffer; // va contine figura ce se deseneaza la un moment dat; dupa ce am terminat, se va salva figura pe canvas private Bitmap canvas; // va contine imaginea finala private Graphics canvasGraphics; private Graphics bufferGraphics; private private private private
int int int int
Ax; // punctul de unde incep sa desenez Ay; Bx; // punctul unde termin de desenat By;
private Color color; //culoarea cu care se picteaza private Boolean drawMode = false; // desenez in momentul asta sau nu ? private String operation; // operatia ce se desfasoara public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { buffer = new Bitmap(400, 300, System.Drawing.Imaging.PixelFormat.Format24bppRgb); canvas = new Bitmap(400, 300, System.Drawing.Imaging.PixelFormat.Format24bppRgb); canvasGraphics = Graphics.FromImage(canvas); bufferGraphics = Graphics.FromImage(buffer); color = Color.DarkCyan; operation = "circle"; canvasGraphics.Clear(Color.White); bufferGraphics.Clear(Color.White); panel1.Cursor = Cursors.Cross; } private void panel1_MouseDown(object sender, MouseEventArgs e) { Ax = e.X; Ay = e.Y;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada drawMode = true; } private void panel1_MouseMove(object sender, MouseEventArgs e) { if (!drawMode) return; Bx = e.X; By = e.Y; bufferGraphics.Clear(Color.White); if (operation == "circle") drawCircle(); if (operation == "line") drawLine(); if (operation == "erase") erase(); if (operation == "brush") brush(); this.panel1.Invalidate(); // fortez redesenarea panel-ului } private void panel1_MouseUp(object sender, MouseEventArgs e) { drawMode = false; // salvez figura curenta pe poza principala (canvas) : ImageAttributes attr = new ImageAttributes(); attr.SetColorKey(Color.White, Color.White); Rectangle dstRect = new Rectangle(0, 0, buffer.Width, buffer.Height); canvasGraphics.DrawImage(buffer, dstRect, 0, 0, buffer.Width, buffer.Height, GraphicsUnit.Pixel, attr); bufferGraphics.Clear(Color.White); this.panel1.Invalidate(); } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics objGraphics = e.Graphics; // afisez mai intai poza principala : objGraphics.DrawImage(canvas, 0, 0); // fac bufferul (ce contine figura curenta) transparent si il afisez : ImageAttributes attr = new ImageAttributes(); attr.SetColorKey(Color.White, Color.White); Rectangle dstRect = new Rectangle(0, 0, buffer.Width, buffer.Height); objGraphics.DrawImage(buffer, dstRect, 0, 0, buffer.Width, buffer.Height, GraphicsUnit.Pixel, attr); } private void newToolStripMenuItem_Click(object sender, EventArgs e) { // sterg totul: canvasGraphics.Clear(Color.White); bufferGraphics.Clear(Color.White); this.panel1.Invalidate(); }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada /* * - functii grafice -----------------------------------*/ void drawCircle() { int radius = (int)Math.Round(Math.Sqrt((Bx - Ax) * (Bx Ax) + (By - Ay) * (By - Ay))); Bitmap bm = new Bitmap(1, 1); bm.SetPixel(0, 0, color); int D = 1 - radius; int x = 0; int y = radius; int i = 0; while (x <= y) { ++i; x++; if (D < 0) { D += 2 * x + 3; } else { y--; D += 2 * (x - y) + 5; } bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm, bufferGraphics.DrawImage(bm,
Ax Ax Ax Ax Ax Ax Ax Ax
+ + + + -
x, y, y, x, x, x, y, y,
Ay Ay Ay Ay Ay Ay Ay Ay
+ + + +
y); x); x); y); y); y); x); x);
} } void drawLine() // algoritmul bresenham { Bitmap bm = new Bitmap(1, 1); bm.SetPixel(0, 0, color); int x0 = Ax; int y0 = Ay; int x1 = Bx; int y1 = By; bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); if (steep) // daca panta dreptei e mai mare ca 1 inversez coordonatele x si y { swap(ref x0, ref y0); swap(ref x1, ref y1); } if (x0 > x1) // daca linia se indreapta spre stanga inversez capetele { swap(ref x0, ref x1);
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada swap(ref y0, ref y1); } int deltax = x1 - x0; int deltay = Math.Abs(y1 - y0); int error = -deltax / 2; int ystep; int y = y0; if (y0 < y1) // daca linia se indreapta in sus adaug -1 variabilei y la fiecare pas ystep = 1; else ystep = -1; for (int x = x0; x<= x1; x++) { if (steep) bufferGraphics.DrawImage(bm, y, x); else bufferGraphics.DrawImage(bm, x, y); error = error + deltay; if (error >= 0) { y = y + ystep; error = error - deltax; } } } void erase() { Bitmap bm = new Bitmap(20, 20); Graphics objGraphics = Graphics.FromImage(bm); objGraphics.Clear(Color.White); canvasGraphics.DrawImage(bm, Bx, By); } void brush() { Bitmap bm = new Bitmap(5, 5); Graphics objGraphics = Graphics.FromImage(bm); objGraphics.Clear(color); canvasGraphics.DrawImage(bm, Bx, By); } private void button15_Click(object sender, EventArgs e) { info.BackColor = this.color = button15.BackColor; } private void button2_Click(object sender, EventArgs e) { info.BackColor = this.color = button2.BackColor; } private void button3_Click(object sender, EventArgs e) { info.BackColor = this.color = button3.BackColor; } private void button4_Click(object sender, EventArgs e) { info.BackColor = this.color = button4.BackColor;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada private { int y = x = }
void swap(ref int x, ref int y) a = y; x; a;
private void button16_Click(object sender, EventArgs e) { operation = "circle"; } private void button18_Click(object sender, EventArgs e) { operation = "line"; } private void button19_Click(object sender, EventArgs e) { operation = "erase"; } private void button20_Click(object sender, EventArgs e) { operation = "brush"; } private void newToolStripMenuItem1_Click(object sender, EventArgs e) { canvasGraphics.Clear(Color.White); bufferGraphics.Clear(Color.White); panel1.Invalidate(); } private void exitToolStripMenuItem1_Click(object sender, EventArgs e) { this.Close(); } } // un panel special, ce nu clipeste atunci cand se deseneaza pe el public class NewPanel : System.Windows.Forms.Panel { public NewPanel() { this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.UpdateStyles(); } } }
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
PROIECT – aplicatie privind aria uni poligon oarecare Nota: Codul Visual Studio (Visual
C++); Visual Studio .NET 2003
Într-un sistem cartezian de axe XOY, considerăm un domeniu ce este determinat de o linie poligonală oarecare şi închisă P = P1P2 ... Pn , unde punctele Pi (xi , yi ), i= 1…n sunt determinate de coordonatele carteziene (xi , yi ), i= 1…n . Aria domeniului este data de urmatoarea formula:
Ca exemplu, prezentăm în figura de mai jos un domeniu oarecare determinat de 11 puncte date prin coordonate carteziene. Valoarea absolută din formula de mai sus este necesară, deoarece introducerea coordonatelor punctelor ce determină domeniu poate fi în sens trigonometric sau în sens invers celui trigonometric, aşa cum este în figura de mai jos.
Programul va afisa fereastra prezentata mai jos (Height = 300, Width = 450) si care ofera un meniu in partea inferioara, format din butoane pentru actiuni utile pentru aplicatie: - stergerea tuturor elementelor din zona de editare • Erase all (New) • Load from file - incarcarea unui fisier deja creat - salvarea coordonetelor punctelor intr-un fisier • Save to a file • Edit – modificarea / editarea punctelor deja introduse • Compute Area – activ (se va calcula aria domeniului poligonal) dupa introducerea in zona de editare a punctelor poligonului
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada
Erase Load from file Save to a file Introducerea punctelor se face folosind mouse-ul prin actiunea de click-stanga in zona de editare, fiecare punct fiid numerotat si colorat cu verde (punctul initial fiind colorat cu albastru). Ultimul punt trebuie sa fie obtinut prin click-stanga pe primul introdus in scopul inchiderii domeniului poligonal. Dupa obtinerea poligonului dorit se pot face modificari ale coordonatelor punctelor prin click-stanga pe punct si „tragere” in zona dorita.
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada EXEMPLU:
Calculul ariei Program.cs using System; using System.Collections.Generic; using System.Windows.Forms; namespace PolygonalArea { static class Program { /// <summary> /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault( false ); Application.Run( new Form1() ); } } } Form1.cs using using using using
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada internal struct Edge { public int v1, v2; public Edge( int v1, int v2 ) { this.v1 = v1; this.v2 = v2; } } public enum graphicAreaMode { Graph, Polygon, Count } public enum graphicAreaStatus { Place, Edit, Compute, Count } public partial class graphicArea : UserControl { private List v = new List(); private List<Edge> e = new List<Edge>(); graphicAreaMode mode; internal bool closingASAP = false; public graphicArea( graphicAreaMode mode ) { this.mode = mode; InitializeComponent(); cmdAction.Text = actionName; cmdAction.Enabled = chkEdit.Checked = false; picBox.Image = new Bitmap( picBox.Width, picBox.Height, PixelFormat.Format32bppPArgb ); tooltips.SetToolTip( cmdNew, "Erase all (New)" ); tooltips.SetToolTip( cmdLoad, "Load from file" ); tooltips.SetToolTip( cmdSave, "Save to a file" ); } public graphicAreaStatus status() { if( !chkEdit.Checked ) return graphicAreaStatus.Place; return graphicAreaStatus.Edit; //to-do: other statuses? } private Point startedAt; private Label editing = null;
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada private void picBox_MouseDown( object sender, MouseEventArgs e ) { if( ( chkEdit.Checked ) && ( editing != null ) ) { editing.BackColor = Color.LightGreen; editing = null; } startedAt = e.Location; } private void vertex_MouseDown( object sender, MouseEventArgs e ) { if( chkEdit.Checked ) { editing = ( Label )sender; editing.BackColor = Color.Yellow; } startedAt = ( ( Label )sender ).Location; startedAt.Offset( e.Location ); //updates the global variable } private /*const*/ int RADIUS = 10; private List getTouchyPoints( int x, int y ) { return getTouchyPoints( x, y, -1 ); } private List getTouchyPoints( int x, int y, int excluding ) { List result = new List(); int minDist = 7 * RADIUS / 2; for( int i = 0; i < v.Count; i++ ) if( i != excluding ) if( distance( x, y, v[ i ].X, v[ i ].Y ) < minDist ) result.Add( i ); return result; } private double distance( int x1, int y1, int x2, int y2 ) { return Math.Sqrt( ( ( x1 - x2 ) * ( x1 - x2 ) ) + ( ( y1 - y2 ) * ( y1 - y2 ) ) ); } private double getDistance( Point p1, Point p2 ) { return distance( p1.X, p1.Y, p2.X, p2.Y ); } private Label makeVertex( int x, int y, string tag ) { return makeVertex( x, y, tag, Color.LightGreen );
Conf. Dr. Marin Vlada, Universitatea din Bucuresti
www.ad-astra.ro/marinvlada } private Label makeVertex( int x, int y, string tag, Color c ) { Label vertex = new Label(); vertex.BackColor = c; vertex.Height = vertex.Width = 2 * RADIUS; vertex.Location = new Point( x - RADIUS, y - RADIUS ); vertex.Tag = tag; //todo: use a flag to set if the number is shown or not vertex.TextAlign = ContentAlignment.MiddleCenter; vertex.Text = tag; //shape GraphicsPath path = new GraphicsPath(); //System.Drawing.Drawing2D path.AddEllipse( 0, 0, 2 * RADIUS, 2 * RADIUS ); vertex.Region = new Region( path ); //event handlers vertex.MouseDown += new MouseEventHandler( vertex_MouseDown ); vertex.MouseUp += new MouseEventHandler( vertex_MouseUp ); vertex.MouseMove += new MouseEventHandler( vertex_MouseMove ); //the end return vertex; } private void makeLine( int p ) { makeLine( p, p + 1, Pens.Black ); } private void makeLines( int point, Pen pen ) { if( point < 0 ) return; int max = v.Count - 1; if( point > 0 ) makeLine( point - 1, point, pen ); else makeLine( max, 0, pen ); if( point < max ) makeLine( point, point + 1, pen ); else makeLine( max, 0, pen ); } private void makeLine( int p1, int p2, Pen pen ) { //Pen p = new Pen( Color.Black, 1 ); //Graphics g = picBox.CreateGraphics(); //g.DrawLine( p, v[ p1 ], v[ p2 ] ); //g.Dispose(); //p.Dispose();
Conf. Dr. Marin Vlada, Universitatea din Bucuresti