1 // Computergraphik I
2 // Prof. Dr. Juergen Doellner
3 // Sommersemester 2001
4 //
5 // Rahmenprogramm fuer Aufgabenzettel 3
6
7 // Stephan Brumme, 702544
8 // last changes: May 17, 2001
9
10 #include "cgmidpoint.h"
11
12
13 CGMidpoint::CGMidpoint(int width, int height) : raster_(width,height) {
14 // Objektvariablen initialisieren
15 First_ = true;
16 }
17
18 void CGMidpoint::onInit() {
19 // Hintergrundfarbe weiss
20 glClearColor(1, 0.9, 0.8, 1);
21
22 // ohne perspektivische Verzerrung, da nur 2D
23 glMatrixMode(GL_PROJECTION);
24 glLoadIdentity();
25 gluOrtho2D(0, raster_.width()-1, 0, raster_.height()-1);
26 }
27
28 void CGMidpoint::onDraw() {
29 // Colorbuffer loeschen
30 glClear(GL_COLOR_BUFFER_BIT);
31
32 // Zeichenen der Raster-Klasse
33 raster_.draw();
34
35 // Zeichenen einer roten Kontroll-Linie
36 // mit OpenGL
37
38 // erst durchführen, wenn ein Endpunkt feststeht
39 if (!First_)
40 {
41 // Umgebung sichern
42 glPushAttrib(GL_CURRENT_BIT);
43 // rote Linie
44 glColor3f(1.0, 0.0, 0.0);
45
46 // und Hilfslinie zeichnen
47 glBegin(GL_LINES);
48 glVertex2f(xBegin_, yBegin_);
49 glVertex2f(xEnd_ , yEnd_ );
50 glEnd();
51 // Umgebung wiederherstellen
52 glPopAttrib();
53 }
54
55 // Backbuffer anzeigen
56 swapBuffers();
57 }
58
59 void CGMidpoint::onSize(unsigned int newWidth, unsigned int newHeight) {
60 // neue Fenstergröße speichern
61 winWidth_ = newWidth;
62 winHeight_ = newHeight;
63 glViewport(0, 0, newWidth - 1, newHeight - 1);
64 }
65
66 void CGMidpoint::onButton(MouseButton button, MouseButtonEvent event, int x, int y) {
67 // Sichern der x und y Werte
68 // Anfang und Ende unterscheiden durch MousButtonEvent:
69 // MouseButtonDown = Start
70 // MouseButtonUp = End
71
72 // Mausposition in Rasterkoordinaten umrechnen
73 x = (int)(0.5 + x / ((float)winWidth_ /(raster_.width()-1)));
74 y = (int)(0.5 + y / ((float)winHeight_/(raster_.height()-1)));
75
76 // Linienanfang
77 if (event == MouseButtonDown)
78 {
79 xBegin_ = x;
80 yBegin_ = y;
81 }
82
83 // Linienende
84 if (event == MouseButtonUp)
85 {
86 xEnd_ = x;
87 yEnd_ = y;
88 // Endpunkt steht fest, Linie darf gezeichnet werden
89 First_ = false;
90 }
91
92 // Raster löschen
93 raster_.clear();
94 // Linie im Raster zeichnen
95 if (!First_)
96 drawLine(xBegin_, yBegin_, xEnd_, yEnd_);
97
98 // Raster auf dem Bildschirm darstellen
99 onDraw();
100 }
101
102 void CGMidpoint::onMove(MouseButton button, int x, int y) {
103 // Endpunkt ermitteln
104 onButton(button, MouseButtonUp, x, y);
105 }
106
107 void CGMidpoint::drawLine(int x1, int y1, int x2, int y2) {
108 // Bresenham Algorithmus
109 // Zeichnen mit der Raster-Klasse
110
111 // zeichne immer von links nach rechts, vertausche ggf. Eckpunkte
112 if (x2 < x1)
113 {
114 int temp;
115
116 temp = x2;
117 x2 = x1;
118 x1 = temp;
119
120 temp = y2;
121 y2 = y1;
122 y1 = temp;
123 }
124
125 // dx ist immer nicht-negativ (aufgrund des vorhergehendes Tausches von x1,x2)
126 int dx = x2 - x1;
127 // dy kann auch negativ sein ...
128 int dy = y2 - y1;
129
130 // berechne Steigung pro Iteration entlang der y-Achse
131 int ystep = 1;
132 if (dy < 0)
133 {
134 ystep = -1;
135 // ab jetzt ist dy immer nicht-negativ
136 dy = -dy;
137 }
138
139 // Steigung <= 1 ?
140 if (dy <= dx)
141 {
142 // Standardalgorithmus aus Vorlesung, lediglich y++ durch y += ystep ersetzt
143 int d = 2*dy - dx;
144 int dE = 2*dy;
145 int dNE= 2*(dy-dx);
146 int x = x1;
147 int y = y1;
148
149 raster_.setPixel(x,y);
150
151 while(x != x2)
152 {
153 if (d <= 0)
154 d += dE;
155 else
{
156 d += dNE;
157 y += ystep;
158 }
159 x++;
160
161 raster_.setPixel(x,y);
162 }
163 }
164 else
{
165 // alle x durch y ersetzt (und umgekehrt, auch dx und dy !),
166 // lediglich setPixel blieb jeweils unverändert
167 int d = 2*dx - dy;
168 int dNE= 2*dx;
169 int dN = 2*(dx-dy);
170 int x = x1;
171 int y = y1;
172
173 raster_.setPixel(x,y);
174
175 while(y != y2)
176 {
177 if (d <= 0)
178 d += dNE;
179 else
{
180 d += dN;
181 x++;
182 }
183 y += ystep;
184
185 raster_.setPixel(x,y);
186 }
187 }
188 }
189
190 int main(int argc, char* argv[]) {
191 CGMidpoint bresenham(30, 30);
192 bresenham.start(argc, argv, "CGMidpoint, Stephan Brumme, 702544");
193 return(0);
194 }
195
196