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
31
32namespace 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 */
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
85{
86 return &coord;
87}
88
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
198upoint_t *
200{
201 memcpy(&tmp_coord, &coord, sizeof(upoint_t));
202 return &tmp_coord;
203}
204
205bool
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 */
214void
215ScanlineRadial::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
236void
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
280const char *
282{
283 return "ScanlineModel::Radial";
284}
285
286unsigned 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 */
298void
299ScanlineRadial::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 */
312void
313ScanlineRadial::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
fawkes::upoint_t * operator->()
Get pointer to current point.
Definition: radial.cpp:84
bool finished()
Check if all desired points have been processed.
Definition: radial.cpp:206
void reset()
Reset model.
Definition: radial.cpp:237
void set_center(unsigned int center_x, unsigned int center_y)
Set new center point.
Definition: radial.cpp:299
const char * get_name()
Get name of scanline model.
Definition: radial.cpp:281
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
unsigned int get_margin()
Get margin around points.
Definition: radial.cpp:287
void set_radius(unsigned int dead_radius, unsigned int max_radius)
Set new radius.
Definition: radial.cpp:313
fawkes::upoint_t operator*()
Get the current coordinate.
Definition: radial.cpp:78
fawkes::upoint_t * operator++()
Postfix ++ operator.
Definition: radial.cpp:90
Point with cartesian coordinates as unsigned integers.
Definition: types.h:35
unsigned int x
x coordinate
Definition: types.h:36
unsigned int y
y coordinate
Definition: types.h:37