1 // Computergraphik I
2 // Prof. Dr. Juergen Doellner
3 // Sommersemester 2001
4 //
5 // Rahmenprogramm fuer Aufgabenzettel 4
6
7 // Stephan Brumme, 702544
8 // last changes: May 19, 2001
9
10 #include "cgellipse.h"
11
12
13 CGEllipse::CGEllipse(int width, int height) : raster_(width,height) {
14 // Objektvariablen initialisieren
15 First_ = true;
16 }
17
18 void CGEllipse::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 CGEllipse::onDraw() {
29 // Colorbuffer loeschen
30 glClear(GL_COLOR_BUFFER_BIT);
31
32 // Zeichenen der Raster-Klasse
33 raster_.draw();
34
35 // Backbuffer anzeigen
36 swapBuffers();
37 }
38
39 void CGEllipse::onSize(unsigned int newWidth, unsigned int newHeight) {
40 // neue Fenstergröße speichern
41 winWidth_ = newWidth;
42 winHeight_ = newHeight;
43 glViewport(0, 0, newWidth - 1, newHeight - 1);
44 }
45
46 void CGEllipse::onButton(MouseButton button, MouseButtonEvent event, int x, int y) {
47 // Sichern der x und y Werte
48 // Anfang und Ende unterscheiden durch MouseButtonEvent:
49 // MouseButtonDown = Start
50 // MouseButtonUp = End
51
52 // Mausposition in Rasterkoordinaten umrechnen
53 x = (int)(0.5 + x / ((float)winWidth_ /(raster_.width()-1)));
54 y = (int)(0.5 + y / ((float)winHeight_/(raster_.height()-1)));
55
56 // Linienanfang
57 if (event == MouseButtonDown)
58 {
59 xBegin_ = x;
60 yBegin_ = y;
61 }
62
63 // Linienende
64 if (event == MouseButtonUp)
65 {
66 xEnd_ = x;
67 yEnd_ = y;
68 // Endpunkt steht fest, Linie darf gezeichnet werden
69 First_ = false;
70 }
71
72 // Raster löschen
73 raster_.clear();
74 // Linie im Raster zeichnen
75 if (!First_)
76 drawEllipse(xBegin_, yBegin_, xEnd_, yEnd_);
77
78 // Raster auf dem Bildschirm darstellen
79 onDraw();
80 }
81
82 void CGEllipse::onMove(MouseButton button, int x, int y) {
83 // Endpunkt ermitteln
84 onButton(button, MouseButtonUp, x, y);
85 }
86
87 void CGEllipse::drawEllipsePoints(int midx, int midy, int x, int y)
88 {
89 // zeichne in allen 4 Quadranten, beachte Verschiebung aus Ursprung heraus
90 raster_.setPixel(midx+x, midy+y);
91 raster_.setPixel(midx+x, midy-y);
92 raster_.setPixel(midx-x, midy+y);
93 raster_.setPixel(midx-x, midy-y);
94 }
95
96 void CGEllipse::drawEllipse(int x1, int y1, int x2, int y2) {
97 // Ellipsen Algorithmus
98 // Zeichnen mit der Raster-Klasse
99
100 // ändere ggf. Eckpunkte, sodass untere linke Ecke per x1/y1
101 // und obere rechte per x2/y2 definiert wird
102 if (x2 < x1)
103 {
104 int temp;
105
106 temp = x2;
107 x2 = x1;
108 x1 = temp;
109 }
110 if (y2 < y1)
111 {
112 int temp;
113
114 temp = y2;
115 y2 = y1;
116 y1 = temp;
117 }
118
119 // Ellipsenparameter
120 int A = (y2-y1) / 2;
121 int B = (x2-x1) / 2;
122 int A2= A*A;
123 int B2= B*B;
124
125 // verweigere zu kleine Ellipsen
126 if (A == 0 || B == 0)
127 return;
128
129 // Ellipsenmittelpunkt
130 int midX = x1+B;
131 int midY = y1+A;
132
133 // oben mittig beginnen
134 int x = 0;
135 int y = A;
136
137 // "Enden" der Ellipsen zeichnen
138 drawEllipsePoints(midX, midY, 0, A);
139
140 // Entscheidungsvariable für E/SE
141 int d1 = A2-A*B2+B2/4;
142
143 // Inkremente 1. und 2.Ordnung für x und y
144 int dX = A2*3;
145 int ddX = A2*2;
146 int dY = B2*(-2*A+2);
147 int ddY = 2*B2;
148
149 // solange in Region 1
150 while (dX < -dY || d1 < 0)
151 {
152
153 // nach Süden ?
154 if (d1 > 0)
155 {
156 d1 += dY;
157 dY += ddY;
158 y--;
159 }
160
161 // immer nach Osten
162 d1 += dX;
163 dX += ddX;
164 x++;
165
166 // alle 4 Quadranten zeichnen
167 drawEllipsePoints(midX, midY, x, y);
168 }
169
170
171 // Entscheidungsvariable für SE/S
172 int d2 = A2*x*x+A2*x + B2*(y-1)*(y-1) - A2*B2;
173
174 // Inkremente 1.Ordnung für x und y
175 dX = A2*(2*x+2);
176 dY = B2*(-2*y+3);
177 // Inkremente 2.Ordnung können unverändert aus Region 1 übernommen werden
178
179 // bis x-Achse errreicht
180 while (y > 0)
181 {
182 // nach Osten ?
183 if (d2 < 0)
184 {
185 d2 += dX;
186 dX += ddX;
187 x++;
188 }
189
190 // immer nach Süden
191 d2 += dY;
192 dY += ddY;
193 y--;
194
195 // alle 4 Quadranten zeichnen
196 drawEllipsePoints(midX, midY, x, y);
197 }
198 }
199
200 int main(int argc, char* argv[]) {
201 CGEllipse ellipse(81, 81);
202 ellipse.start(argc, argv, "CGEllipse, Stephan Brumme, 702544");
203 return(0);
204 }
205
206