line_grid.cpp

00001
00002 /***************************************************************************
00003  *  line_grid.cpp - Implementation of the line grid scanline model
00004  *
00005  *  Generated: Wed Mar 25 17:31:00 2009
00006  *  Copyright  2009 Christof Rath <c.rath@student.tugraz.at>
00007  *
00008  ****************************************************************************/
00009
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023
00024 #include "line_grid.h"
00025
00026 #include <fvutils/base/roi.h>
00027 #include <fvutils/draw/drawer.h>
00028 #include <core/exceptions/software.h>
00029
00030 #include <cstring>
00031
00032 using fawkes::point_t;
00033 
00034 /** @class ScanlineLineGrid line_grid.h <models/scanlines/line_grid.h>
00035  * Grid of scan lines.
00036  * A grid of scan lines (i.e. horizontal and/or vertical lines) instead of only
00037  * points on the grid crossings.
00038  * The behavior of the ScanlineGrid (grid.h) class can be modeled if offset_hor
00039  * is set to the same value as offset_x in the Grid class, offset_ver = 0 and
00040  * gap is set to offset_y - 1. The advantage of doing this is a performance gain
00041  * as the LineGrid is pre-calculated and getting the next point is only an
00042  * iterator increment.
00043  */
00044 
00045 /** Constructor.
00046  * @param width Width of grid (most likely equal to image_width)
00047  * @param height Height of grid (most likely equal to image_height)
00048  * @param offset_hor Offset between horizontal lines (set to 0 to get only vertical lines)
00049  * @param offset_ver Offset between vertical lines (set to 0 to get only horizontal lines)
00050  * @param roi The grid will only be calculated within the roi (if NULL the grid gets
00051  *            calculated over the complete width/height).
00052  *            The provided object will be deleted by ScanlineLineGrid!
00053  * @param gap Gap between two points on the line
00054  */
00055 ScanlineLineGrid::ScanlineLineGrid(unsigned int width, unsigned int height,
00056                            unsigned int offset_hor, unsigned int offset_ver,
00057                            ROI* roi, unsigned int gap)
00058 {
00059   __roi = NULL;
00060   __next_pixel = gap + 1;
00061   set_grid_params(width, height,
00062                 offset_hor, offset_ver, roi);
00063   //reset is done in set_grid_params ()
00064 }
00065 
00066 /** Destructor
00067  */
00068 ScanlineLineGrid::~ScanlineLineGrid()
00069 {
00070   delete __roi;
00071 }
00072
00073 point_t
00074 ScanlineLineGrid::operator*()
00075 {
00076   return *__cur;
00077 }
00078
00079 point_t*
00080 ScanlineLineGrid::operator->()
00081 {
00082   return &*__cur;
00083 }
00084
00085 void
00086 ScanlineLineGrid::calc_coords()
00087 {
00088   __point_list.clear();
00089   bool more_to_come = true;
00090   point_t coord;
00091   unsigned int next_px;
00092
00093   if (__offset_hor > 0) //horizontal lines
00094   {
00095     more_to_come = true;
00096     next_px = std::min(__next_pixel, __offset_ver ? __offset_ver : __width);
00097     coord.x = __roi->start.x;
00098     coord.y = __roi->start.y + ((__roi->height - 1) % __offset_hor) / 2; //Center the horizontal lines in the image
00099     __point_list.push_back(coord);
00100
00101     while (more_to_come) {
00102       if (coord.x < (__roi->image_width - next_px))
00103       {
00104         coord.x += next_px;
00105       }
00106       else
00107       {
00108         if (coord.y < (__roi->image_height - __offset_hor))
00109         {
00110           coord.x = __roi->start.x;
00111           coord.y += __offset_hor;
00112         }
00113         else
00114         {
00115           more_to_come = false;
00116         }
00117       }
00118
00119       if (more_to_come) __point_list.push_back(coord);
00120     }
00121   }
00122
00123   if (__offset_ver > 0) //vertical lines
00124   {
00125     more_to_come = true;
00126     next_px = std::min(__next_pixel, __offset_hor ? __offset_hor : __height);
00127     coord.x = __roi->start.x + ((__roi->width - 1) % __offset_ver) / 2; //Center the vertical lines in the image
00128     coord.y = __roi->start.y;
00129     __point_list.push_back(coord);
00130
00131     while (more_to_come) {
00132       if (coord.y < (__roi->image_height - next_px))
00133       {
00134         coord.y += next_px;
00135       }
00136       else
00137       {
00138         if (coord.x < (__roi->image_width - __offset_ver))
00139         {
00140           coord.x += __offset_ver;
00141           coord.y = __roi->start.y;
00142         }
00143         else
00144         {
00145           more_to_come = false;
00146         }
00147       }
00148
00149       if (more_to_come) __point_list.push_back(coord);
00150     }
00151   }
00152
00153   reset();
00154 }
00155
00156 point_t *
00157 ScanlineLineGrid::operator++()
00158 {
00159   if (__cur != __point_list.end()) ++__cur;
00160   return __cur != __point_list.end() ? &*__cur : &__point_list.back();
00161 }
00162
00163 point_t *
00164 ScanlineLineGrid::operator++(int)
00165 {
00166   if (__cur != __point_list.end()) {
00167     point_t *res = &*__cur++;
00168     return res;
00169   }
00170   else return &__point_list.back();
00171 }
00172
00173 bool
00174 ScanlineLineGrid::finished()
00175 {
00176   return __cur == __point_list.end();
00177 }
00178
00179 void
00180 ScanlineLineGrid::reset()
00181 {
00182   __cur = __point_list.begin();
00183 }
00184
00185 const char *
00186 ScanlineLineGrid::get_name()
00187 {
00188   return "ScanlineModel::LineGrid";
00189 }
00190
00191
00192 unsigned int
00193 ScanlineLineGrid::get_margin()
00194 {
00195   return std::max(__offset_ver, __offset_hor);
00196 }
00197
00198
00199 void
00200 ScanlineLineGrid::set_robot_pose(float x, float y, float ori)
00201 {
00202   // ignored
00203 }
00204
00205
00206 void
00207 ScanlineLineGrid::set_pan_tilt(float pan, float tilt)
00208 {
00209   // ignored
00210 }
00211
00212 
00213 /** Sets the dimensions of the grid.
00214  * Set width and height of scanline grid. Implicitly resets the grid.
00215  *
00216  * @param width Width of grid (most likely equal to image_width)
00217  * @param height Height of grid (most likely equal to image_height)
00218  * @param roi The grid will only be calculated within the roi (if NULL the grid gets
00219  *            calculated over the complete width/height).
00220  *            The provided object will be deleted by ScanlineLineGrid!
00221  */
00222 void
00223 ScanlineLineGrid::set_dimensions(unsigned int width, unsigned int height, ROI* roi)
00224 {
00225   __width  = width;
00226   __height = height;
00227
00228   set_roi(roi);
00229 }
00230 
00231 /** Sets the region-of-interest.
00232  * @param roi The grid will only be calculated within the roi (if NULL the grid gets
00233  *            calculated over the complete width/height).
00234  *            The provided object will be deleted by ScanlineLineGrid!
00235  */
00236 void
00237 ScanlineLineGrid::set_roi(ROI* roi)
00238 {
00239   delete __roi;
00240
00241   if (!roi) __roi = new ROI(0, 0, __width, __height, __width, __height);
00242   else
00243   {
00244     __roi = roi;
00245     //Use roi image width/height as grid boundary
00246     __roi->set_image_width(__roi->start.x + __roi->width);
00247     __roi->set_image_height(__roi->start.y + __roi->height);
00248
00249     if (__roi->image_width > __width)
00250       throw fawkes::OutOfBoundsException("ScanlineLineGrid: ROI is out of grid bounds!", __roi->image_width, 0, __width);
00251     if (__roi->image_height > __height)
00252       throw fawkes::OutOfBoundsException("ScanlineLineGrid: ROI is out of grid bounds!", __roi->image_height, 0, __height);
00253   }
00254
00255   calc_coords();
00256 }
00257 
00258 /** Sets offset.
00259  * Set horizontal and vertical offset by which the pointer in the grid is advanced.
00260  * This function implicitly resets the grid.
00261  *
00262  * @param offset_hor Offset between horizontal lines (set to 0 to get only vertical lines)
00263  * @param offset_ver Offset between vertical lines (set to 0 to get only horizontal lines)
00264  */
00265 void
00266 ScanlineLineGrid::set_offset(unsigned int offset_hor, unsigned int offset_ver)
00267 {
00268   __offset_hor = offset_hor;
00269   __offset_ver = offset_ver;
00270
00271   calc_coords();
00272 }
00273
00274 
00275 /** Set all grid parameters.
00276  * Set width, height, horizontal and vertical offset by which the pointer in the
00277  * grid is advanced.
00278  * Implicitly resets the grid.
00279  *
00280  * @param width Width of grid (most likely equal to image_width)
00281  * @param height Height of grid (most likely equal to image_height)
00282  * @param offset_hor Offset between horizontal lines (set to 0 to get only vertical lines)
00283  * @param offset_ver Offset between vertical lines (set to 0 to get only horizontal lines)
00284  * @param roi The grid will only be calculated within the roi (if NULL the grid gets
00285  *            calculated over the complete width/height).
00286  *            The provided object will be deleted by ScanlineLineGrid!
00287  */
00288 void
00289 ScanlineLineGrid::set_grid_params(unsigned int width, unsigned int height,
00290                             unsigned int offset_hor, unsigned int offset_ver,
00291                             ROI* roi)
00292 {
00293   __offset_hor = offset_hor;
00294   __offset_ver = offset_ver;
00295
00296   set_dimensions(width, height, roi);
00297 }