beams.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 <core/exception.h>
00025 #include <models/scanlines/beams.h>
00026
00027 #include <cmath>
00028
00029 using fawkes::point_t;
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 ScanlineBeams::ScanlineBeams(unsigned int image_width, unsigned int image_height,
00063 unsigned int start_x, unsigned int start_y,
00064 unsigned int stop_y, unsigned int offset_y,
00065 bool distribute_start_x,
00066 float angle_from, float angle_range,
00067 unsigned int num_beams)
00068 {
00069 if ( start_y < stop_y ) throw fawkes::Exception("start_y < stop_y");
00070 if ( (stop_y > image_height) || (start_y > image_height) ) {
00071 throw fawkes::Exception("(stop_y > height) || (start_y > height)");
00072 }
00073
00074 this->start_x = start_x;
00075 this->start_y = start_y;
00076 this->angle_from = angle_from;
00077 this->angle_range = angle_range;
00078 this->num_beams = num_beams;
00079 this->stop_y = stop_y;
00080 this->offset_y = offset_y;
00081 this->image_width = image_width;
00082 this->image_height = image_height;
00083 this->distribute_start_x = distribute_start_x;
00084
00085 reset();
00086 }
00087
00088
00089 point_t
00090 ScanlineBeams::operator*()
00091 {
00092 return coord;
00093 }
00094
00095 point_t*
00096 ScanlineBeams::operator->()
00097 {
00098 return &coord;
00099 }
00100
00101
00102 bool
00103 ScanlineBeams::finished()
00104 {
00105 return _finished;
00106 }
00107
00108
00109 void
00110 ScanlineBeams::advance()
00111 {
00112
00113 while ( ! _finished && (first_beam < last_beam) ) {
00114
00115 unsigned int x_start = beam_current_pos[next_beam].x;
00116 unsigned int y_start = beam_current_pos[next_beam].y;
00117
00118 unsigned int x_end = beam_end_pos[next_beam].x;
00119 unsigned int y_end = beam_end_pos[next_beam].y;
00120
00121 int x, y, dist, xerr, yerr, dx, dy, incx, incy;
00122
00123
00124 dx = x_end - x_start;
00125 dy = y_end - y_start;
00126
00127
00128 if(dx < 0) {
00129 incx = -1;
00130 dx = -dx;
00131 } else {
00132 incx = dx ? 1 : 0;
00133 }
00134
00135 if(dy < 0) {
00136 incy = -1;
00137 dy = -dy;
00138 } else {
00139 incy = dy ? 1 : 0;
00140 }
00141
00142
00143 dist = (dx > dy) ? dx : dy;
00144
00145
00146 x = x_start;
00147 y = y_start;
00148 xerr = dx;
00149 yerr = dy;
00150
00151
00152 unsigned int offset = 0;
00153 while ( (x >= 0) && ((unsigned int )x < image_width) && ((unsigned int)y > stop_y) &&
00154 (offset < offset_y) ) {
00155 ++offset;
00156
00157 xerr += dx;
00158 yerr += dy;
00159
00160 if(xerr > dist) {
00161 xerr -= dist;
00162 x += incx;
00163 }
00164
00165 if(yerr>dist) {
00166 yerr -= dist;
00167 y += incy;
00168 }
00169 }
00170 if ( (y < 0) || (unsigned int)y <= stop_y ) {
00171 _finished = true;
00172 break;
00173 }
00174 if ( x < 0 ) {
00175 first_beam = ++next_beam;
00176 continue;
00177 }
00178 if ( (unsigned int)x > image_width ) {
00179 last_beam = next_beam - 1;
00180 next_beam = first_beam;
00181 continue;
00182 }
00183
00184 coord.x = x;
00185 coord.y = y;
00186
00187 beam_current_pos[next_beam] = coord;
00188
00189 if ( next_beam < last_beam) {
00190 ++next_beam;
00191 } else {
00192 next_beam = first_beam;
00193 }
00194 break;
00195 }
00196
00197 }
00198
00199
00200 point_t *
00201 ScanlineBeams::operator++()
00202 {
00203 advance();
00204 return &coord;
00205 }
00206
00207
00208 point_t *
00209 ScanlineBeams::operator++(int i)
00210 {
00211 tmp_coord.x = coord.x;
00212 tmp_coord.y = coord.y;
00213 advance();
00214 return &tmp_coord;
00215 }
00216
00217
00218 void
00219 ScanlineBeams::reset()
00220 {
00221 _finished = false;
00222
00223 beam_current_pos.clear();
00224 if ( distribute_start_x ) {
00225 unsigned int offset_start_x = image_width / (num_beams - 1);
00226 for (unsigned int i = 0; i < num_beams; ++i) {
00227 coord.x = i * offset_start_x;
00228 coord.y = start_y;
00229 beam_current_pos.push_back(coord);
00230 }
00231 coord.x = beam_current_pos[0].x;
00232 coord.y = beam_current_pos[0].y;
00233 } else {
00234 coord.x = start_x;
00235 coord.y = start_y;
00236 beam_current_pos.resize( num_beams, coord );
00237 }
00238
00239
00240 beam_end_pos.clear();
00241 next_beam = 0;
00242 float angle_between_beams = angle_range / num_beams;
00243 for (unsigned int i = 0; i < num_beams; ++i) {
00244 float diff_y = beam_current_pos[i].y - stop_y;
00245 float diff_x = diff_y * tan( angle_from + (float)i * angle_between_beams );
00246 point_t end_point;
00247 end_point.y = stop_y;
00248 end_point.x = (int)roundf(diff_x) + start_x;
00249 beam_end_pos.push_back(end_point);
00250 }
00251 first_beam = 0;
00252 last_beam = beam_end_pos.size() - 1;
00253 }
00254
00255 const char *
00256 ScanlineBeams::get_name()
00257 {
00258 return "ScanlineModel::Beams";
00259 }
00260
00261
00262 unsigned int
00263 ScanlineBeams::get_margin()
00264 {
00265 return offset_y;
00266 }