radial.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <models/scanlines/radial.h>
00025
00026 #include <utils/system/console_colors.h>
00027
00028 #include <cmath>
00029 #include <cstring>
00030
00031 using fawkes::point_t;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 ScanlineRadial::ScanlineRadial(unsigned int width, unsigned int height,
00055 unsigned int center_x, unsigned int center_y,
00056 unsigned int radius_increment,
00057 unsigned int step,
00058 unsigned int max_radius, unsigned int dead_radius
00059 )
00060 {
00061 this->width = width;
00062 this->height = height;
00063 this->center_x = center_x;
00064 this->center_y = center_y;
00065 this->radius_increment = radius_increment;
00066 this->step = step;
00067 this->dead_radius = dead_radius;
00068 this->max_radius = max_radius;
00069 this->auto_max_radius = (max_radius == 0);
00070
00071 reset();
00072 }
00073
00074 point_t
00075 ScanlineRadial::operator*()
00076 {
00077 return coord;
00078 }
00079
00080 point_t*
00081 ScanlineRadial::operator->()
00082 {
00083 return &coord;
00084 }
00085
00086 point_t *
00087 ScanlineRadial::operator++()
00088 {
00089
00090 if ( done ) return &coord;
00091
00092 bool ok = false;
00093
00094 do {
00095
00096 tmp_x = 0;
00097 tmp_y = 0;
00098
00099 if ( current_radius == 0 ) {
00100
00101 current_radius += radius_increment;
00102 x = 0;
00103 y = current_radius;
00104 ok = true;
00105 } else {
00106
00107 if ( x < y ) {
00108
00109 switch (sector) {
00110 case 0:
00111 tmp_x = x;
00112 tmp_y = -y;
00113 break;
00114
00115 case 1:
00116 tmp_x = y;
00117 tmp_y = -x;
00118 break;
00119
00120 case 2:
00121 tmp_x = y;
00122 tmp_y = x;
00123 break;
00124
00125 case 3:
00126 tmp_x = x;
00127 tmp_y = y;
00128 break;
00129
00130 case 4:
00131 tmp_x = -x;
00132 tmp_y = y;
00133 break;
00134
00135 case 5:
00136 tmp_x = -y;
00137 tmp_y = x;
00138 break;
00139
00140 case 6:
00141 tmp_x = -y;
00142 tmp_y = -x;
00143 break;
00144
00145 case 7:
00146 tmp_x = -x;
00147 tmp_y = -y;
00148 break;
00149
00150 default:
00151 tmp_x = 0;
00152 tmp_y = 0;
00153 break;
00154
00155 }
00156
00157 x += step;
00158 y = (int)(sqrt( (float(current_radius * current_radius) - float(x * x)) ) + 0.5);
00159
00160 ok = true;
00161
00162 } else {
00163
00164 if (sector == 7) {
00165
00166 current_radius += radius_increment;
00167 x = 0;
00168 y = current_radius;
00169 sector = 0;
00170 if (current_radius >= max_radius) { done = true; ok = true; }
00171 } else {
00172 sector += 1;
00173 x = 0;
00174 y = current_radius;
00175 }
00176 }
00177
00178 }
00179
00180 if ( (tmp_x < -(int)center_x) ||
00181 (tmp_x > (int)(width - center_x)) ||
00182 (tmp_y < -(int)center_y) ||
00183 (tmp_y > (int)(height - center_y))
00184 ) {
00185 coord.x = 0;
00186 coord.y = 0;
00187
00188 ok = false;
00189
00190 } else {
00191 coord.x = center_x + tmp_x;
00192 coord.y = center_y + tmp_y;
00193 }
00194
00195 } while (! ok);
00196
00197 return &coord;
00198 }
00199
00200 point_t *
00201 ScanlineRadial::operator++(int)
00202 {
00203 memcpy(&tmp_coord, &coord, sizeof(point_t));
00204 return &tmp_coord;
00205 }
00206
00207 bool
00208 ScanlineRadial::finished()
00209 {
00210 return done;
00211 }
00212
00213
00214
00215
00216
00217 void
00218 ScanlineRadial::simpleBubbleSort(unsigned int array[], unsigned int num_elements)
00219 {
00220 bool modified = false;
00221 unsigned int end = num_elements;
00222 unsigned int tmp;
00223 do {
00224 modified = false;
00225
00226 for (unsigned int i = 0; i < end-1; ++i) {
00227 if ( array[i] < array[i+1] ) {
00228 tmp = array[i];
00229 array[i] = array[i+1];
00230 array[i+1] = tmp;
00231 end -= 1;
00232 modified = true;
00233 }
00234 }
00235
00236 } while ( modified );
00237 }
00238
00239 void
00240 ScanlineRadial::reset()
00241 {
00242 current_radius = radius_increment;
00243 while (current_radius < dead_radius) {
00244 current_radius += radius_increment;
00245 }
00246 x = 0;
00247 y = current_radius;
00248 sector = 0;
00249
00250 coord.x = center_x;
00251 coord.y = center_y;
00252
00253 if ( auto_max_radius ) {
00254
00255 unsigned int dists[4];
00256 dists[0] = (unsigned int)sqrt( float(center_x * center_x) + float(center_y * center_y) );
00257 dists[1] = (unsigned int)sqrt( float((width - center_x) * (width - center_x)) + float(center_y * center_y) );
00258 dists[2] = (unsigned int)sqrt( float((width - center_x) * (width - center_x)) + float((height - center_y) * (height - center_y)) );
00259 dists[3] = (unsigned int)sqrt( float(center_x * center_x) + float((height - center_y) * (height - center_y)) );
00260
00261
00262 simpleBubbleSort(dists, 4);
00263 max_radius = dists[0] - 1;
00264 }
00265
00266 done = false;
00267
00268 if (radius_increment > max_radius) {
00269
00270 radius_increment = 1;
00271 }
00272
00273 if (dead_radius > max_radius) {
00274
00275 dead_radius = 0;
00276 current_radius = radius_increment;
00277 }
00278
00279 }
00280
00281 const char *
00282 ScanlineRadial::get_name()
00283 {
00284 return "ScanlineModel::Radial";
00285 }
00286
00287
00288 unsigned int
00289 ScanlineRadial::get_margin()
00290 {
00291 return radius_increment;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301 void
00302 ScanlineRadial::set_center(unsigned int center_x, unsigned int center_y)
00303 {
00304 this->center_x = center_x;
00305 this->center_y = center_y;
00306 reset();
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316 void
00317 ScanlineRadial::set_radius(unsigned int dead_radius, unsigned int max_radius)
00318 {
00319 this->max_radius = 0;
00320 this->dead_radius = dead_radius;
00321 this->auto_max_radius = (max_radius == 0);
00322
00323 reset();
00324 }