Fawkes API  Fawkes Development Version
radial.cpp
1 
2 /***************************************************************************
3  * radial.cpp - Implementation of the radial scanline model
4  *
5  * Created: Tue Jul 19 12:46:52 2005
6  * Copyright 2005 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 <fvmodels/scanlines/radial.h>
25 
26 #include <utils/system/console_colors.h>
27 
28 #include <cmath>
29 #include <cstring>
30 
31 using fawkes::upoint_t;
32 
33 namespace firevision {
34 #if 0 /* just to make Emacs auto-indent happy */
35 }
36 #endif
37 
38 /** @class ScanlineRadial <fvmodels/scanlines/radial.h>
39  * Radial scanlines.
40  * Uses circles to generate scanline points. A dead radius is ignored in the
41  * center of the image (for example for the camera itself in an omni-vision system).
42  * From there circles are used in radius_increment distances. On each circle points are
43  * generated in a distance of about step pixels. This is done up to a given maximum
44  * radius. If no maximum radius is supplied (max_radius=0) it is automatically
45  * calculated depending on the image size.
46  */
47 
48 /** Constructor.
49  * @param width image width
50  * @param height image height
51  * @param center_x radial center center x
52  * @param center_y radial center center y
53  * @param radius_increment radius increment
54  * @param step step
55  * @param max_radius maximum radius, if set to 0 will be calculated
56  * automatically depending on the image dimensions.
57  * @param dead_radius inner radius to ignore
58  */
59 ScanlineRadial::ScanlineRadial(unsigned int width, unsigned int height,
60  unsigned int center_x, unsigned int center_y,
61  unsigned int radius_increment,
62  unsigned int step,
63  unsigned int max_radius, unsigned int dead_radius
64  )
65 {
66  this->width = width;
67  this->height = height;
68  this->center_x = center_x;
69  this->center_y = center_y;
70  this->radius_increment = radius_increment;
71  this->step = step;
72  this->dead_radius = dead_radius;
73  this->max_radius = max_radius;
74  this->auto_max_radius = (max_radius == 0);
75 
76  reset();
77 }
78 
81 {
82  return coord;
83 }
84 
85 upoint_t*
87 {
88  return &coord;
89 }
90 
91 upoint_t *
93 {
94 
95  if ( done ) return &coord;
96 
97  bool ok = false;
98 
99  do {
100 
101  tmp_x = 0;
102  tmp_y = 0;
103 
104  if ( current_radius == 0 ) {
105  // Special case, after first reset
106  current_radius += radius_increment;
107  x = 0;
108  y = current_radius;
109  ok = true;
110  } else {
111 
112  if ( x < y ) {
113 
114  switch (sector) {
115  case 0:
116  tmp_x = x;
117  tmp_y = -y;
118  break;
119 
120  case 1:
121  tmp_x = y;
122  tmp_y = -x;
123  break;
124 
125  case 2:
126  tmp_x = y;
127  tmp_y = x;
128  break;
129 
130  case 3:
131  tmp_x = x;
132  tmp_y = y;
133  break;
134 
135  case 4:
136  tmp_x = -x;
137  tmp_y = y;
138  break;
139 
140  case 5:
141  tmp_x = -y;
142  tmp_y = x;
143  break;
144 
145  case 6:
146  tmp_x = -y;
147  tmp_y = -x;
148  break;
149 
150  case 7:
151  tmp_x = -x;
152  tmp_y = -y;
153  break;
154 
155  default:
156  tmp_x = 0;
157  tmp_y = 0;
158  break;
159 
160  }
161 
162  x += step;
163  y = (int)(sqrt( (float(current_radius * current_radius) - float(x * x)) ) + 0.5);
164 
165  ok = true;
166 
167  } else {
168  // cout << "x !< y" << endl;
169  if (sector == 7) {
170  // Need to go to next circle
171  current_radius += radius_increment;
172  x = 0;
173  y = current_radius;
174  sector = 0;
175  if (current_radius >= max_radius) { done = true; ok = true; }
176  } else {
177  sector += 1;
178  x = 0;
179  y = current_radius;
180  }
181  }
182 
183  }
184 
185  if ( (tmp_x < -(int)center_x) ||
186  (tmp_x > (int)(width - center_x)) ||
187  (tmp_y < -(int)center_y) ||
188  (tmp_y > (int)(height - center_y))
189  ) {
190  coord.x = 0;
191  coord.y = 0;
192  // out of image, not ok
193  ok = false;
194  //done = true;
195  } else {
196  coord.x = center_x + tmp_x;
197  coord.y = center_y + tmp_y;
198  }
199 
200  } while (! ok);
201 
202  return &coord;
203 }
204 
205 upoint_t *
207 {
208  memcpy(&tmp_coord, &coord, sizeof(upoint_t));
209  return &tmp_coord;
210 }
211 
212 bool
214 {
215  return done;
216 }
217 
218 
219 /** Do a simple sort of the given array, sorted descending, biggest first
220  * this sort is stable
221  */
222 void
223 ScanlineRadial::simpleBubbleSort(unsigned int array[], unsigned int num_elements)
224 {
225  bool modified = false;
226  unsigned int end = num_elements;
227  unsigned int tmp;
228  do {
229  modified = false;
230 
231  for (unsigned int i = 0; i < end-1; ++i) {
232  if ( array[i] < array[i+1] ) {
233  tmp = array[i];
234  array[i] = array[i+1];
235  array[i+1] = tmp;
236  end -= 1;
237  modified = true;
238  }
239  }
240 
241  } while ( modified );
242 }
243 
244 void
246 {
247  current_radius = radius_increment;
248  while (current_radius < dead_radius) {
249  current_radius += radius_increment;
250  }
251  x = 0;
252  y = current_radius;
253  sector = 0;
254 
255  coord.x = center_x;
256  coord.y = center_y;
257 
258  if ( auto_max_radius ) {
259  // Calculate distances to corners of image
260  unsigned int dists[4];
261  dists[0] = (unsigned int)sqrt( float(center_x * center_x) + float(center_y * center_y) );
262  dists[1] = (unsigned int)sqrt( float((width - center_x) * (width - center_x)) + float(center_y * center_y) );
263  dists[2] = (unsigned int)sqrt( float((width - center_x) * (width - center_x)) + float((height - center_y) * (height - center_y)) );
264  dists[3] = (unsigned int)sqrt( float(center_x * center_x) + float((height - center_y) * (height - center_y)) );
265 
266  // now the maximum corner distance is the maximum radius
267  simpleBubbleSort(dists, 4);
268  max_radius = dists[0] - 1;
269  }
270 
271  done = false;
272 
273  if (radius_increment > max_radius) {
274  // cout << msg_prefix << cred << "radius_increment > max_radius, resetting radius_increment to one!" << cnormal << endl;
275  radius_increment = 1;
276  }
277 
278  if (dead_radius > max_radius) {
279  // cout << msg_prefix << cred << "dead_radius > max_radius, resetting dead_radius to zero!" << cnormal << endl;
280  dead_radius = 0;
281  current_radius = radius_increment;
282  }
283 
284 }
285 
286 const char *
288 {
289  return "ScanlineModel::Radial";
290 }
291 
292 
293 unsigned int
295 {
296  return radius_increment;
297 }
298 
299 
300 /** Set new center point.
301  * Sets new center point to move around the scanlines in the image.
302  * Does an implicit reset().
303  * @param center_x x coordinate of the new center
304  * @param center_y y coordinate of the new center
305  */
306 void
307 ScanlineRadial::set_center(unsigned int center_x, unsigned int center_y)
308 {
309  this->center_x = center_x;
310  this->center_y = center_y;
311  reset();
312 }
313 
314 
315 /** Set new radius.
316  * Sets the new maximum and dead radius. Does an implicit reset().
317  * @param dead_radius new dead radius
318  * @param max_radius new maximum radius, if set to 0 this is automatically
319  * calculated depending on the image size.
320  */
321 void
322 ScanlineRadial::set_radius(unsigned int dead_radius, unsigned int max_radius)
323 {
324  this->max_radius = max_radius;
325  this->dead_radius = dead_radius;
326  this->auto_max_radius = (max_radius == 0);
327 
328  reset();
329 }
330 
331 } // end namespace firevision
fawkes::upoint_t operator*()
Get the current coordinate.
Definition: radial.cpp:80
fawkes::upoint_t * operator++()
Postfix ++ operator.
Definition: radial.cpp:92
unsigned int get_margin()
Get margin around points.
Definition: radial.cpp:294
unsigned int y
y coordinate
Definition: types.h:36
unsigned int x
x coordinate
Definition: types.h:35
void set_radius(unsigned int dead_radius, unsigned int max_radius)
Set new radius.
Definition: radial.cpp:322
const char * get_name()
Get name of scanline model.
Definition: radial.cpp:287
void set_center(unsigned int center_x, unsigned int center_y)
Set new center point.
Definition: radial.cpp:307
bool finished()
Check if all desired points have been processed.
Definition: radial.cpp:213
fawkes::upoint_t * operator->()
Get pointer to current point.
Definition: radial.cpp:86
void reset()
Reset model.
Definition: radial.cpp:245
Point with cartesian coordinates as unsigned integers.
Definition: types.h:34
ScanlineRadial(unsigned int width, unsigned int height, unsigned int center_x, unsigned int center_y, unsigned int radius_increment, unsigned int step, unsigned int max_radius=0, unsigned int dead_radius=0)
Constructor.
Definition: radial.cpp:59