00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2009 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef BITMASKITERATOR_H 00011 #define BITMASKITERATOR_H 00012 00013 #include "LocationType.h" 00014 00015 class BitMask; 00016 class RasterElement; 00017 00018 /** 00019 * Traverses selected pixels within a BitMask. 00020 * This class provides a convenient way to traverse the selected pixels within a 00021 * given area of a BitMask object. The BitMaskIterator extents can be set to either 00022 * custom values or the extents of a RasterElement. 00023 * \image html BitMaskIterator.JPG 00024 * \image html BitMaskIteratorExample1.jpg 00025 * \image html BitMaskIteratorExample2.jpg 00026 * 00027 * The iterator incorporates the outside flag of the BitMask when determining 00028 * whether a pixel is selected. The getPixel(int,int) const method is provided to 00029 * query the selected state of any pixel within the extents. A call to getPixel() for 00030 * pixel locations outside the extents of the BitMasKIterator will return false. 00031 * 00032 * \image html BitMaskIteratorExample3.jpg 00033 * \image html BitMaskIteratorExample4.jpg 00034 * 00035 * This class is intended to be used in place of directly traversing the 00036 * BitMask. 00037 * 00038 * @warning The iterator does not assume ownership over the BitMask. It is 00039 * intended to be used in place of directly traversing the BitMask. 00040 * Also for efficiency purposes, this class assumes that the BitMask 00041 * is valid (i.e. not deleted) throughout the lifetime of the 00042 * iterator. 00043 */ 00044 class BitMaskIterator 00045 { 00046 public: 00047 /** 00048 * Constructs a BitMaskIterator with given extents. 00049 * 00050 * All parameters are zero-based and inclusive. Upon construction, the iterator's pixel 00051 * location is set to the first selected pixel within the iterator's bounding box (the 00052 * intersection of the iterator extents and the BitMask minimal bounding box). If no pixels within 00053 * the iterator's bounding box are selected, the pixel location is set to (-1, -1), which is 00054 * equivalent to BitMaskIterator::end(). 00055 * 00056 * @param pBitMask 00057 * The BitMask to traverse. \c NULL is a valid value for the BitMask. 00058 * Use of a \c NULL BitMask allows algorithms to be designed with 00059 * a single code path, e.g., BitMaskIterator bit(pAoi, 0, 0, 100, 100) where pAoi can be 00060 * NULL or a valid pointer. 00061 * @param x1 00062 * The first column of the area over which the iterator may operate. The intersection between 00063 * this area and the BitMask determines the area to be traversed. This 00064 * value must be non-negative and less than or equal to the maximum value that the int 00065 * type will support on the platform. This is enforced by setting 00066 * larger values to that maximum value. 00067 * @param y1 00068 * The first row of the area over which the iterator may operate. The intersection between 00069 * this area and the BitMask determines the area to be traversed. This 00070 * value must be non-negative and less than or equal to the maximum value that the int 00071 * type will support on the platform. This is enforced by setting 00072 * larger values to that maximum value. 00073 * @param x2 00074 * The last column of the area over which the iterator may operate. The intersection between 00075 * this area and the BitMask determines the area to be traversed. This 00076 * value must be non-negative and less than or equal to the maximum value that the int 00077 * type will support on the platform. This is enforced by setting 00078 * larger values to that maximum value. 00079 * @param y2 00080 * The last row of the area over which the iterator may operate. The intersection between 00081 * this area and the BitMask determines the area to be traversed. This 00082 * value must be non-negative and less than or equal to the maximum value that the int 00083 * type will support on the platform. This is enforced by setting 00084 * larger values to that maximum value. 00085 */ 00086 BitMaskIterator(const BitMask* pBitMask, unsigned int x1, unsigned int y1, 00087 unsigned int x2, unsigned int y2); 00088 00089 /** 00090 * Constructs a BitMaskIterator using the extents from a given RasterElement. 00091 * 00092 * Upon construction, the iterator's pixel location is set to the first selected pixel within 00093 * the iterator's bounding box (the intersection of the iterator extents and the BitMask minimal 00094 * bounding box). If no pixels within the iterator's bounding box are selected, the pixel location 00095 * is set to (-1, -1), which is equivalent to BitMaskIterator::end(). 00096 * 00097 * @param pBitMask 00098 * The BitMask to traverse. \c NULL is a valid value for the BitMask. 00099 * Use of a \c NULL BitMask allows algorithms to be designed with 00100 * a single code path, e.g., BitMaskIterator bit(pAoi, pRaster) where pAoi can be NULL or a valid pointer. 00101 * @param pRasterElement 00102 * The RasterElement supplying the extents that will define the area over which the iterator may operate. 00103 * The extents are defined by the number of rows and columns in the 00104 * RasterElement, i.e., (0, 0) to (num cols - 1, num rows - 1). %Any offset to other elements is ignored. 00105 */ 00106 BitMaskIterator(const BitMask* pBitMask, const RasterElement* pRasterElement); 00107 00108 /** 00109 * Resets the pixel location to the first pixel. 00110 * 00111 * This method re-initializes the state of the BitMaskIterator to point at 00112 * the first selected pixel of the BitMask within the extents provided when 00113 * the iterator was constructed (the iterator's bounding box). 00114 * 00115 * @see nextPixel() 00116 */ 00117 void firstPixel(); 00118 00119 /** 00120 * Gets the number of selected pixels. 00121 * 00122 * To get the number of selected pixels, this method must iterate over the 00123 * entire extents, which may be slow based on the size of the extents. After 00124 * this method is called once, the selected pixel count is stored internally, 00125 * so subsequent calls to getCount() are much faster. 00126 * 00127 * @return Returns the number of selected pixels within the extents. 00128 */ 00129 int getCount() const; 00130 00131 /** 00132 * Queries whether a given pixel is selected. 00133 * 00134 * @param col 00135 * The zero-based column number of the pixel to query. 00136 * @param row 00137 * The zero-based row number of the pixel to query. 00138 * 00139 * @return Returns \c true if the given pixel is selected or if the BitMask is \c NULL 00140 * and the pixel is contained within the iterator's extents; otherwise returns \c false. 00141 * Also returns \c false if the given pixel is outside the iterator's extents. 00142 * 00143 * @see getPixelLocation() 00144 */ 00145 bool getPixel(int col, int row) const; 00146 00147 /** 00148 * Gets the current pixel location. 00149 * 00150 * @param pixelLocation 00151 * Populated with the current pixel location. When an iterator is 00152 * constructed, its pixel location is the first selected pixel. If 00153 * no pixels are selected, the pixel location is (-1, -1), 00154 * which is equivalent to BitMaskIterator::end(). 00155 */ 00156 void getPixelLocation(LocationType& pixelLocation) const; 00157 00158 /** 00159 * Gets the bounding box over which the iterator iterates. 00160 * 00161 * If the outside flag in the underlying BitMask is on, this method populates 00162 * the given parameters with the iterator extents set in the constructor. All 00163 * parameter values are zero-based and inclusive. 00164 * 00165 * @param x1 00166 * The starting column for iteration. 00167 * @param y1 00168 * The starting row for iteration. 00169 * @param x2 00170 * The ending column for iteration. 00171 * @param y2 00172 * The ending row for iteration. 00173 * 00174 * @see getNumSelectedRows() getNumSelectedColumns() 00175 */ 00176 void getBoundingBox(int& x1, int& y1, int& x2, int& y2) const; 00177 00178 /** 00179 * Advances the pixel location to the next selected pixel. 00180 * 00181 * If there are no more selected pixels within the extents, the state of the 00182 * iterator is equivalent to BitMaskIterator::end(). 00183 * 00184 * @see operator++(), operator++(int) 00185 */ 00186 void nextPixel(); 00187 00188 /** 00189 * Advances the pixel location to the next selected pixel. This overloads the prefix increment operator. 00190 * 00191 * @return Returns \c true if the iterator advanced to the next selected 00192 * pixel or the BitMask is \c NULL and the pixel is contained within the extents of the iterator. 00193 * If there are no more selected pixels within the iterator extents, the state of the 00194 * iterator is equivalent to BitMaskIterator::end() and \c false is returned. 00195 * 00196 * @see nextPixel(), operator++(int) 00197 */ 00198 bool operator++(); 00199 00200 /** 00201 * Advances the pixel location to the next selected pixel. This overloads the postfix increment operator. 00202 * A dummy parameter is used to differentiate between the signatures of the postfix (var++) operator 00203 * and the prefix (++var) operator. 00204 * 00205 * @return Returns \c true if the iterator advanced to the next selected 00206 * pixel or the BitMask is \c NULL and the pixel is contained within the extents of the iterator. 00207 * If there are no more selected pixels within the iterator extents, the state of the 00208 * iterator is equivalent to BitMaskIterator::end() and \c false is returned. 00209 * 00210 * @see nextPixel(), operator++() 00211 */ 00212 bool operator++(int); 00213 00214 /** 00215 * Creates an iterator that is ready to start traversing the BitMask. 00216 * 00217 * @return Returns a valid iterator with the conditions set to the initial 00218 * conditions of this iterator. 00219 */ 00220 BitMaskIterator begin(); 00221 00222 /** 00223 * Creates an iterator that has finished traversing the BitMask. 00224 * 00225 * @return Returns an invalid iterator with invalid conditions to represent an iterator 00226 * that has finished traversing the BitMask. 00227 */ 00228 BitMaskIterator end(); 00229 00230 /** 00231 * Gets the number of rows contained within the intersection of the iterator extents and the minimal 00232 * bounding box for the BitMask selected pixels. If the BitMask Outside flag is set, this will be equal 00233 * to the number of rows in the iterator extents. 00234 * 00235 * @return Returns the number of rows spanning the range of the BitMaskIterator bounding box. 00236 * 00237 * @see getBoundingBox() 00238 */ 00239 int getNumSelectedRows() const; 00240 00241 /** 00242 * Gets the number of columns contained within the intersection of the iterator extents and the minimal 00243 * bounding box for the BitMask selected pixels. If the BitMask Outside flag is set, this will be equal 00244 * to the number of columns in the iterator extents. 00245 * 00246 * @return Returns the number of columns spanning the range of the BitMaskIterator bounding box. 00247 * 00248 * @see getBoundingBox() 00249 */ 00250 int getNumSelectedColumns() const; 00251 00252 /** 00253 * Gets the distance in pixels from the beginning of the iterator extents to the start of the iterator bounding box. 00254 * For an unrotated, rectangular BitMap, it will be the distance between the beginning of the iterator extents 00255 * and the first selected pixel in the BitMask. 00256 * 00257 * @return Returns the offset in (column, row) coordinates from the beginning of the iterator 00258 * extents to the start of the iterator bounding box. A default constructed 00259 * LocationType indicating no offset is returned in the following cases: 00260 * - The BitMask is \c NULL. 00261 * - The method BitMask::isOutsideSelected() returns \c true. 00262 * 00263 * @see getBoundingBox() 00264 */ 00265 LocationType getOffset() const; 00266 00267 /** 00268 * Determines if the iterator will iterate over every every pixel within the iterator extents, i.e., every pixel 00269 * within the iterator extends is selected. 00270 * 00271 * @return Returns \c true if every pixel within the iterator extents is selected; otherwise 00272 * returns \c false. 00273 * 00274 * @see getBoundingBox() 00275 */ 00276 bool useAllPixels() const; 00277 00278 /** 00279 * Queries whether the current pixel is selected. 00280 * 00281 * @return Returns \c true if the current pixel is selected or the BitMask is \c NULL 00282 * and the pixel is contained within the iterator extents; otherwise returns \c false. 00283 * 00284 * @see getPixel(int,int) const 00285 */ 00286 bool operator*() const; 00287 00288 /** 00289 * Compares the position of this iterator with that of another. 00290 * 00291 * @param other 00292 * The iterator with which to compare its position. 00293 * 00294 * @return Returns \c true if the position of the given iterator matches 00295 * the position of this iterator; otherwise returns \c false. 00296 * 00297 * @see operator!=() 00298 */ 00299 bool operator==(const BitMaskIterator& other) const; 00300 00301 /** 00302 * Compares the position of this iterator with that of another. 00303 * 00304 * @param other 00305 * The iterator with which to compare its position. 00306 * 00307 * @return Returns \c true if the position of the given iterator does not 00308 * match the position of this iterator; otherwise returns \c false. 00309 * 00310 * @see operator==() 00311 */ 00312 bool operator!=(const BitMaskIterator& other) const; 00313 00314 /** 00315 * Gets the number of rows contained within the full extents of the iterator. This method just returns 00316 * either the number of rows in the extents passed to the constructor or the number of rows in the 00317 * raster element passed to the constructor. It should not be used in iterating over the BitMask passed 00318 * to the constructor. Use getNumSelectedRows() instead. 00319 * 00320 * @return Returns the number of rows within the iterator extents. 00321 * 00322 * @see getNumSelectedRows(), getNumSelectedColumns() 00323 */ 00324 int getNumRows() const; 00325 00326 /** 00327 * Gets the number of columns contained within the full extents of the iterator. This method just returns 00328 * either the number of columns in the extents passed to the constructor or the number of columns in the 00329 * raster element passed to the constructor. It should not be used in iterating over the BitMask passed 00330 * to the constructor. Use getNumSelectedColumns() instead. 00331 * 00332 * @return Returns the number of columns within the iterator extents. 00333 * 00334 * @see getNumSelectedRows(), getNumSelectedColumns() 00335 */ 00336 int getNumColumns() const; 00337 00338 /** 00339 * Gets the starting row in pixel coordinates of the bounding box over which the iterator iterates. 00340 * 00341 * @return Returns the starting row for iteration. This will be the number in pixel 00342 * coordinates of the first row in the iterator bounding box if the Outside flag in 00343 * the underlying BitMask is off. If the Outside flag is on, this method returns 00344 * the number of the first row in the full extents of the iterator. 00345 * The return value is zero-based and inclusive. 00346 * 00347 * @see getBoundingBox(), getBoundingBoxStartColumn() 00348 */ 00349 int getBoundingBoxStartRow() const; 00350 00351 /** 00352 * Gets the starting column in pixel coordinates of the bounding box over which the iterator iterates. 00353 * 00354 * @return Returns the starting column for iteration. This will be the number in pixel 00355 * coordinates of the first column in the iterator bounding box if the Outside flag in 00356 * the underlying BitMask is off. If the Outside flag is on, this method returns 00357 * the number of the first column in the full extents of the iterator. 00358 * The return value is zero-based and inclusive. 00359 * 00360 * @see getBoundingBox(), getBoundingBoxStartRow() 00361 */ 00362 int getBoundingBoxStartColumn() const; 00363 00364 /** 00365 * Gets the ending row in pixel coordinates of the bounding box over which the iterator iterates. 00366 * 00367 * @return Returns the ending row for iteration. This will be the number in pixel 00368 * coordinates of the last row in the iterator bounding box if the Outside flag in 00369 * the underlying BitMask is off. If the Outside flag is on, this method returns 00370 * the number of the last row in the full extents of the iterator. 00371 * The return value is zero-based and inclusive. 00372 * 00373 * @see getBoundingBox(), getBoundingBoxEndColumn() 00374 */ 00375 int getBoundingBoxEndRow() const; 00376 00377 /** 00378 * Gets the ending column in pixel coordinates of the bounding box over which the iterator iterates. 00379 * 00380 * @return Returns the ending column for iteration. This will be the number in pixel 00381 * coordinates of the last column in the iterator bounding box if the Outside flag in 00382 * the underlying BitMask is off. If the Outside flag is on, this method returns 00383 * the number of the last column in the full extents of the iterator. 00384 * The return value is zero-based and inclusive. 00385 * 00386 * @see getBoundingBox(), getBoundingBoxEndRow() 00387 */ 00388 int getBoundingBoxEndColumn() const; 00389 00390 /** 00391 * Gets the distance in pixels from the beginning of the iterator extents to the first row in 00392 * the iterator bounding box. 00393 * 00394 * @return Returns the offset in row coordinates from the beginning of the 00395 * iterator extents to the first row in the iterator bounding box. A value of zero 00396 * indicating no offset is returned in the following cases: 00397 * - The BitMask is \c NULL. 00398 * - The method BitMask::isOutsideSelected() returns \c true. 00399 * 00400 * @see getOffset(), getColumnOffset() 00401 */ 00402 int getRowOffset() const; 00403 00404 /** 00405 * Gets the distance in pixels from the beginning of the iterator extents to the first column 00406 * in the iterator bounding box. 00407 * 00408 * @return Returns the offset in column coordinates from the beginning of the 00409 * iterator extents to the first column in the iterator bounding box. A value of zero 00410 * indicating no offset is returned in the following cases: 00411 * - The BitMask is \c NULL. 00412 * - The method BitMask::isOutsideSelected() returns \c true. 00413 * 00414 * @see getOffset(), getRowOffset() 00415 */ 00416 int getColumnOffset() const; 00417 00418 /** 00419 * Gets the row of the current pixel. 00420 * 00421 * @return Returns the row of the current pixel location. When an iterator is 00422 * constructed, its pixel row location is the row of the first selected 00423 * pixel. If no pixels are selected, the pixel row and column are -1, 00424 * which is equivalent to BitMaskIterator::end(). 00425 * 00426 * @see getPixelColumnLocation() 00427 */ 00428 int getPixelRowLocation() const; 00429 00430 /** 00431 * Gets the column of the current pixel. 00432 * 00433 * @return Returns the column of the current pixel location. When an iterator is 00434 * constructed, its pixel column location is the column of the first selected 00435 * pixel. If no pixels are selected, the pixel row and column are -1, 00436 * which is equivalent to BitMaskIterator::end(). 00437 * 00438 * @see getPixelRowLocation() 00439 */ 00440 int getPixelColumnLocation() const; 00441 00442 private: 00443 BitMaskIterator(BitMaskIterator, bool); 00444 bool getPixel() const; 00445 void computeCount(); 00446 00447 const BitMask* mpBitMask; 00448 int mX1; 00449 int mY1; 00450 int mX2; 00451 int mY2; 00452 int mCurrentPixelX; // Begin state = first selected pixel, end state = -1 00453 int mCurrentPixelY; // Begin state = first selected pixel, end state = -1 00454 int mFirstPixelX; 00455 int mFirstPixelY; 00456 unsigned int mCurrentPixelCount; 00457 int mPixelCount; 00458 int mMinX; 00459 int mMinY; 00460 int mMaxX; 00461 int mMaxY; 00462 }; 00463 00464 #endif