// Computergraphik I // Prof. Dr. Juergen Doellner // Sommersemester 2001 // // Rahmenprogramm fuer Aufgabenzettel 3 // Stephan Brumme, 702544 // last changes: May 17, 2001 #include "cgmidpoint.h" CGMidpoint::CGMidpoint(int width, int height) : raster_(width,height) { // Objektvariablen initialisieren First_ = true; } void CGMidpoint::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 CGMidpoint::onDraw() { // Colorbuffer loeschen glClear(GL_COLOR_BUFFER_BIT); // Zeichenen der Raster-Klasse raster_.draw(); // Zeichenen einer roten Kontroll-Linie // mit OpenGL // erst durchführen, wenn ein Endpunkt feststeht if (!First_) { // Umgebung sichern glPushAttrib(GL_CURRENT_BIT); // rote Linie glColor3f(1.0, 0.0, 0.0); // und Hilfslinie zeichnen glBegin(GL_LINES); glVertex2f(xBegin_, yBegin_); glVertex2f(xEnd_ , yEnd_ ); glEnd(); // Umgebung wiederherstellen glPopAttrib(); } // Backbuffer anzeigen swapBuffers(); } void CGMidpoint::onSize(unsigned int newWidth, unsigned int newHeight) { // neue Fenstergröße speichern winWidth_ = newWidth; winHeight_ = newHeight; glViewport(0, 0, newWidth - 1, newHeight - 1); } void CGMidpoint::onButton(MouseButton button, MouseButtonEvent event, int x, int y) { // Sichern der x und y Werte // Anfang und Ende unterscheiden durch MousButtonEvent: // 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_) drawLine(xBegin_, yBegin_, xEnd_, yEnd_); // Raster auf dem Bildschirm darstellen onDraw(); } void CGMidpoint::onMove(MouseButton button, int x, int y) { // Endpunkt ermitteln onButton(button, MouseButtonUp, x, y); } void CGMidpoint::drawLine(int x1, int y1, int x2, int y2) { // Bresenham Algorithmus // Zeichnen mit der Raster-Klasse // zeichne immer von links nach rechts, vertausche ggf. Eckpunkte if (x2 < x1) { int temp; temp = x2; x2 = x1; x1 = temp; temp = y2; y2 = y1; y1 = temp; } // dx ist immer nicht-negativ (aufgrund des vorhergehendes Tausches von x1,x2) int dx = x2 - x1; // dy kann auch negativ sein ... int dy = y2 - y1; // berechne Steigung pro Iteration entlang der y-Achse int ystep = 1; if (dy < 0) { ystep = -1; // ab jetzt ist dy immer nicht-negativ dy = -dy; } // Steigung <= 1 ? if (dy <= dx) { // Standardalgorithmus aus Vorlesung, lediglich y++ durch y += ystep ersetzt int d = 2*dy - dx; int dE = 2*dy; int dNE= 2*(dy-dx); int x = x1; int y = y1; raster_.setPixel(x,y); while(x != x2) { if (d <= 0) d += dE; else { d += dNE; y += ystep; } x++; raster_.setPixel(x,y); } } else { // alle x durch y ersetzt (und umgekehrt, auch dx und dy !), // lediglich setPixel blieb jeweils unverändert int d = 2*dx - dy; int dNE= 2*dx; int dN = 2*(dx-dy); int x = x1; int y = y1; raster_.setPixel(x,y); while(y != y2) { if (d <= 0) d += dNE; else { d += dN; x++; } y += ystep; raster_.setPixel(x,y); } } } int main(int argc, char* argv[]) { CGMidpoint bresenham(30, 30); bresenham.start(argc, argv, "CGMidpoint, Stephan Brumme, 702544"); return(0); }