// Computergraphik I // Prof. Dr. Juergen Doellner // Sommersemester 2001 // // Rahmenprogramm fuer Aufgabenzettel 4 // Stephan Brumme, 702544 // last changes: May 19, 2001 #include "cgellipse.h" CGEllipse::CGEllipse(int width, int height) : raster_(width,height) { // Objektvariablen initialisieren First_ = true; } void CGEllipse::onInit() { // Hintergrundfarbe weiss glClearColor(1, 0.9, 0.8, 1); // ohne perspektivische Verzerrung, da nur 2D glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, raster_.width()-1, 0, raster_.height()-1); } void CGEllipse::onDraw() { // Colorbuffer loeschen glClear(GL_COLOR_BUFFER_BIT); // Zeichenen der Raster-Klasse raster_.draw(); // Backbuffer anzeigen swapBuffers(); } void CGEllipse::onSize(unsigned int newWidth, unsigned int newHeight) { // neue Fenstergröße speichern winWidth_ = newWidth; winHeight_ = newHeight; glViewport(0, 0, newWidth - 1, newHeight - 1); } void CGEllipse::onButton(MouseButton button, MouseButtonEvent event, int x, int y) { // Sichern der x und y Werte // Anfang und Ende unterscheiden durch MouseButtonEvent: // MouseButtonDown = Start // MouseButtonUp = End // Mausposition in Rasterkoordinaten umrechnen x = (int)(0.5 + x / ((float)winWidth_ /(raster_.width()-1))); y = (int)(0.5 + y / ((float)winHeight_/(raster_.height()-1))); // Linienanfang if (event == MouseButtonDown) { xBegin_ = x; yBegin_ = y; } // Linienende if (event == MouseButtonUp) { xEnd_ = x; yEnd_ = y; // Endpunkt steht fest, Linie darf gezeichnet werden First_ = false; } // Raster löschen raster_.clear(); // Linie im Raster zeichnen if (!First_) drawEllipse(xBegin_, yBegin_, xEnd_, yEnd_); // Raster auf dem Bildschirm darstellen onDraw(); } void CGEllipse::onMove(MouseButton button, int x, int y) { // Endpunkt ermitteln onButton(button, MouseButtonUp, x, y); } void CGEllipse::drawEllipsePoints(int midx, int midy, int x, int y) { // zeichne in allen 4 Quadranten, beachte Verschiebung aus Ursprung heraus raster_.setPixel(midx+x, midy+y); raster_.setPixel(midx+x, midy-y); raster_.setPixel(midx-x, midy+y); raster_.setPixel(midx-x, midy-y); } void CGEllipse::drawEllipse(int x1, int y1, int x2, int y2) { // Ellipsen Algorithmus // Zeichnen mit der Raster-Klasse // ändere ggf. Eckpunkte, sodass untere linke Ecke per x1/y1 // und obere rechte per x2/y2 definiert wird if (x2 < x1) { int temp; temp = x2; x2 = x1; x1 = temp; } if (y2 < y1) { int temp; temp = y2; y2 = y1; y1 = temp; } // Ellipsenparameter int A = (y2-y1) / 2; int B = (x2-x1) / 2; int A2= A*A; int B2= B*B; // verweigere zu kleine Ellipsen if (A == 0 || B == 0) return; // Ellipsenmittelpunkt int midX = x1+B; int midY = y1+A; // oben mittig beginnen int x = 0; int y = A; // "Enden" der Ellipsen zeichnen drawEllipsePoints(midX, midY, 0, A); // Entscheidungsvariable für E/SE int d1 = A2-A*B2+B2/4; // Inkremente 1. und 2.Ordnung für x und y int dX = A2*3; int ddX = A2*2; int dY = B2*(-2*A+2); int ddY = 2*B2; // solange in Region 1 while (dX < -dY || d1 < 0) { // nach Süden ? if (d1 > 0) { d1 += dY; dY += ddY; y--; } // immer nach Osten d1 += dX; dX += ddX; x++; // alle 4 Quadranten zeichnen drawEllipsePoints(midX, midY, x, y); } // Entscheidungsvariable für SE/S int d2 = A2*x*x+A2*x + B2*(y-1)*(y-1) - A2*B2; // Inkremente 1.Ordnung für x und y dX = A2*(2*x+2); dY = B2*(-2*y+3); // Inkremente 2.Ordnung können unverändert aus Region 1 übernommen werden // bis x-Achse errreicht while (y > 0) { // nach Osten ? if (d2 < 0) { d2 += dX; dX += ddX; x++; } // immer nach Süden d2 += dY; dY += ddY; y--; // alle 4 Quadranten zeichnen drawEllipsePoints(midX, midY, x, y); } } int main(int argc, char* argv[]) { CGEllipse ellipse(81, 81); ellipse.start(argc, argv, "CGEllipse, Stephan Brumme, 702544"); return(0); }