Fawkes API  Fawkes Development Version
beams.cpp
1 
2 /***************************************************************************
3  * beams.cpp - Scanline model implementation: beams
4  *
5  * Created: Tue Apr 17 21:09:46 2007
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <core/exception.h>
25 #include <fvmodels/scanlines/beams.h>
26 
27 #include <cmath>
28 
29 using fawkes::upoint_t;
30 
31 namespace firevision {
32 #if 0 /* just to make Emacs auto-indent happy */
33 }
34 #endif
35 
36 /** @class ScanlineBeams <fvmodels/scanlines/beams.h>
37  * Raytraced beams scanline model.
38  * This model uses a defined number of beams shot from the bottom of the image
39  * towards the top using Bresenham. With this you can have kind of a radar-like
40  * scanline model. Additionally the starting points at the bottom can be
41  * distributed over the full width of the image which alles for a scan aligned
42  * to the image.
43  *
44  * To ease the calculation of the finished state the very last point is traversed
45  * twice.
46  *
47  * @author Tim Niemueller
48  */
49 
50 /** Construtor.
51  * @param image_width image width
52  * @param image_height image height
53  * @param start_x x coordinate of the starting point, ignored if distributed (see below)
54  * @param start_y y coordinate of the starting point, this is the lowest points of the
55  * the lines and should thus be close to the bottom of the image
56  * @param stop_y Y coordinate for stopping the traversal
57  * @param offset_y number of pixel to advance in Y-direction per iteration
58  * @param distribute_start_x set to true, to distribute the start x coordinates
59  * equidistant over the whole width of the image.
60  * @param angle_from angle to start the scan at, a straight vertical line means
61  * zero rad, clock-wise positive, in radians
62  * @param angle_range the range to use to distribute the beams, clockwise positive,
63  * in radians
64  * @param num_beams number of beams to use
65  * @exception Exception thrown if parameters are out of bounds
66  */
67 ScanlineBeams::ScanlineBeams(unsigned int image_width, unsigned int image_height,
68  unsigned int start_x, unsigned int start_y,
69  unsigned int stop_y, unsigned int offset_y,
70  bool distribute_start_x,
71  float angle_from, float angle_range,
72  unsigned int num_beams)
73 {
74  if ( start_y < stop_y ) throw fawkes::Exception("start_y < stop_y");
75  if ( (stop_y > image_height) || (start_y > image_height) ) {
76  throw fawkes::Exception("(stop_y > height) || (start_y > height)");
77  }
78 
79  this->start_x = start_x;
80  this->start_y = start_y;
81  this->angle_from = angle_from;
82  this->angle_range = angle_range;
83  this->num_beams = num_beams;
84  this->stop_y = stop_y;
85  this->offset_y = offset_y;
86  this->image_width = image_width;
87  this->image_height = image_height;
88  this->distribute_start_x = distribute_start_x;
89 
90  reset();
91 }
92 
93 
96 {
97  return coord;
98 }
99 
100 upoint_t*
102 {
103  return &coord;
104 }
105 
106 
107 bool
109 {
110  return _finished;
111 }
112 
113 
114 void
115 ScanlineBeams::advance()
116 {
117 
118  while ( ! _finished && (first_beam < last_beam) ) {
119 
120  unsigned int x_start = beam_current_pos[next_beam].x;
121  unsigned int y_start = beam_current_pos[next_beam].y;
122 
123  unsigned int x_end = beam_end_pos[next_beam].x;
124  unsigned int y_end = beam_end_pos[next_beam].y;
125 
126  int x, y, dist, xerr, yerr, dx, dy, incx, incy;
127 
128  // calculate distance in both directions
129  dx = x_end - x_start;
130  dy = y_end - y_start;
131 
132  // Calculate sign of the increment
133  if(dx < 0) {
134  incx = -1;
135  dx = -dx;
136  } else {
137  incx = dx ? 1 : 0;
138  }
139 
140  if(dy < 0) {
141  incy = -1;
142  dy = -dy;
143  } else {
144  incy = dy ? 1 : 0;
145  }
146 
147  // check which distance is larger
148  dist = (dx > dy) ? dx : dy;
149 
150  // Initialize for loops
151  x = x_start;
152  y = y_start;
153  xerr = dx;
154  yerr = dy;
155 
156  /* Calculate and draw pixels */
157  unsigned int offset = 0;
158  while ( (x >= 0) && ((unsigned int )x < image_width) && ((unsigned int)y > stop_y) &&
159  (offset < offset_y) ) {
160  ++offset;
161 
162  xerr += dx;
163  yerr += dy;
164 
165  if(xerr > dist) {
166  xerr -= dist;
167  x += incx;
168  }
169 
170  if(yerr>dist) {
171  yerr -= dist;
172  y += incy;
173  }
174  }
175  if ( (y < 0) || (unsigned int)y <= stop_y ) {
176  _finished = true;
177  break;
178  }
179  if ( x < 0 ) {
180  first_beam = ++next_beam;
181  continue;
182  }
183  if ( (unsigned int)x > image_width ) {
184  last_beam = next_beam - 1;
185  next_beam = first_beam;
186  continue;
187  }
188 
189  coord.x = x;
190  coord.y = y;
191 
192  beam_current_pos[next_beam] = coord;
193 
194  if ( next_beam < last_beam) {
195  ++next_beam;
196  } else {
197  next_beam = first_beam;
198  }
199  break;
200  }
201 
202 }
203 
204 
205 upoint_t *
207 {
208  advance();
209  return &coord;
210 }
211 
212 
213 upoint_t *
215 {
216  tmp_coord.x = coord.x;
217  tmp_coord.y = coord.y;
218  advance();
219  return &tmp_coord;
220 }
221 
222 
223 void
225 {
226  _finished = false;
227 
228  beam_current_pos.clear();
229  if ( distribute_start_x ) {
230  unsigned int offset_start_x = image_width / (num_beams - 1);
231  for (unsigned int i = 0; i < num_beams; ++i) {
232  coord.x = i * offset_start_x;
233  coord.y = start_y;
234  beam_current_pos.push_back(coord);
235  }
236  coord.x = beam_current_pos[0].x;
237  coord.y = beam_current_pos[0].y;
238  } else {
239  coord.x = start_x;
240  coord.y = start_y;
241  beam_current_pos.resize( num_beams, coord );
242  }
243 
244 
245  beam_end_pos.clear();
246  next_beam = 0;
247  float angle_between_beams = angle_range / num_beams;
248  for (unsigned int i = 0; i < num_beams; ++i) {
249  float diff_y = beam_current_pos[i].y - stop_y;
250  float diff_x = diff_y * tan( angle_from + (float)i * angle_between_beams );
251  upoint_t end_point;
252  end_point.y = stop_y;
253  end_point.x = (int)roundf(diff_x) + start_x;
254  beam_end_pos.push_back(end_point);
255  }
256  first_beam = 0;
257  last_beam = beam_end_pos.size() - 1;
258 }
259 
260 const char *
262 {
263  return "ScanlineModel::Beams";
264 }
265 
266 
267 unsigned int
269 {
270  return offset_y;
271 }
272 
273 } // end namespace firevision
bool finished()
Check if all desired points have been processed.
Definition: beams.cpp:108
ScanlineBeams(unsigned int image_width, unsigned int image_height, unsigned int start_x, unsigned int start_y, unsigned int stop_y, unsigned int offset_y, bool distribute_start_x, float angle_from, float angle_range, unsigned int num_beams)
Construtor.
Definition: beams.cpp:67
fawkes::upoint_t operator*()
Get the current coordinate.
Definition: beams.cpp:95
unsigned int y
y coordinate
Definition: types.h:36
unsigned int x
x coordinate
Definition: types.h:35
const char * get_name()
Get name of scanline model.
Definition: beams.cpp:261
unsigned int get_margin()
Get margin around points.
Definition: beams.cpp:268
Base class for exceptions in Fawkes.
Definition: exception.h:36
fawkes::upoint_t * operator++()
Postfix ++ operator.
Definition: beams.cpp:206
void reset()
Reset model.
Definition: beams.cpp:224
Point with cartesian coordinates as unsigned integers.
Definition: types.h:34
fawkes::upoint_t * operator->()
Get pointer to current point.
Definition: beams.cpp:101