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