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