1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 #ifndef itkConstNeighborhoodIteratorWithOnlyIndex_h 19 #define itkConstNeighborhoodIteratorWithOnlyIndex_h 20 21 #include <vector> 22 #include <cstring> 23 #include <iostream> 24 #include "itkImage.h" 25 #include "itkNeighborhood.h" 26 #include "itkMacro.h" 27 28 namespace itk 29 { 30 /** \class ConstNeighborhoodIteratorWithOnlyIndex 31 * 32 * \brief Index-only version of ConstNeighborhoodIterator, defining iteration of a local 33 * N-dimensional neighborhood of indecies across an itk::Image or itk::ImageBase. 34 * 35 * ConstNeighborhoodIteratorWithOnlyIndex implements the index-only methods of 36 * NeighborhoodIterator. No image data is accessed, so this iterator can be used 37 * with type itk::ImageBase. It serves as a base class from which other iterators 38 * can be derived. See NeighborhoodIterator for more complete information. 39 * 40 * The parent class itk::Neighborhood is declared with 'char' as its first 41 * template parameter, because the pixel type is not used in this class. 42 * 43 * \ingroup ImageIterators 44 * 45 * Other index-only iterators: 46 * 47 * \sa ImageConstIteratorWithOnlyIndex 48 * \sa ConstNeighborhoodIteratorWithOnlyIndex 49 * 50 * Other iterators: 51 * 52 * \sa ImageIterator \sa NeighborhoodIterator 53 * 54 * \sa Neighborhood 55 * 56 * \ingroup ITKCommon 57 * 58 */ 59 template< typename TImage > 60 class ITK_TEMPLATE_EXPORT ConstNeighborhoodIteratorWithOnlyIndex: 61 public Neighborhood< char, TImage::ImageDimension > 62 { 63 public: 64 65 /** Type used to refer to space dimensions */ 66 using DimensionValueType = unsigned int; 67 68 /** Save the image dimension. */ 69 static constexpr DimensionValueType Dimension = TImage::ImageDimension; 70 71 using DummyNeighborhoodPixelType = char; 72 73 /** Standard class type aliases. */ 74 using Self = ConstNeighborhoodIteratorWithOnlyIndex; 75 using Superclass = Neighborhood< DummyNeighborhoodPixelType, Self::Dimension >; 76 77 /** Inherit type alias from superclass */ 78 using OffsetType = typename Superclass::OffsetType; 79 using RadiusType = typename Superclass::RadiusType; 80 using SizeType = typename Superclass::SizeType; 81 using Iterator = typename Superclass::Iterator; 82 using ConstIterator = typename Superclass::ConstIterator; 83 84 /** Typedef support for common objects */ 85 using ImageType = TImage; 86 using RegionType = typename TImage::RegionType; 87 using IndexType = Index< Self::Dimension >; 88 using NeighborhoodType = Neighborhood< DummyNeighborhoodPixelType, Self::Dimension >; 89 90 /** Type used to refer to the elements in the list of neighbor pixels. */ 91 using NeighborIndexType = typename NeighborhoodType::NeighborIndexType; 92 93 /** Default constructor */ 94 ConstNeighborhoodIteratorWithOnlyIndex(); 95 96 /** Virtual destructor */ 97 ~ConstNeighborhoodIteratorWithOnlyIndex() override = default; 98 99 /** Copy constructor */ 100 ConstNeighborhoodIteratorWithOnlyIndex(const ConstNeighborhoodIteratorWithOnlyIndex &); 101 102 /** Constructor which establishes the region size, neighborhood, and image 103 * over which to walk. */ 104 ConstNeighborhoodIteratorWithOnlyIndex(const SizeType & radius, const ImageType *ptr, const RegionType & region); 105 106 /** Assignment operator */ 107 Self & operator=(const Self & orig); 108 109 /** Standard itk print method */ 110 void PrintSelf(std::ostream &, Indent) const override; 111 112 /** Computes the internal, N-d offset of a pixel array position n from 113 * (0,0, ..., 0) in the "upper-left" corner of the neighborhood. */ 114 OffsetType ComputeInternalIndex(NeighborIndexType n) const; 115 116 /** Returns the array of upper loop bounds used during iteration. */ GetBound()117 IndexType GetBound() const 118 { 119 return m_Bound; 120 } 121 122 /** Returns the loop bound used to define the edge of a single 123 * dimension in the itk::Image region. */ GetBound(NeighborIndexType n)124 IndexValueType GetBound(NeighborIndexType n) const 125 { 126 return m_Bound[n]; 127 } 128 129 /** Returns a smartpointer to the image on which this iterator operates. */ GetImagePointer()130 const ImageType * GetImagePointer() const 131 { 132 return m_ConstImage; 133 } 134 135 /** Returns the N-dimensional index of the iterator's position in 136 * the image. */ GetIndex()137 ITK_ITERATOR_VIRTUAL IndexType GetIndex() const ITK_ITERATOR_FINAL 138 { 139 return m_Loop; 140 } 141 142 /** Returns the image index for neighbor pixel at offset o from the center of 143 the neighborhood. */ GetIndex(const OffsetType & o)144 ITK_ITERATOR_VIRTUAL IndexType GetIndex(const OffsetType & o) const ITK_ITERATOR_FINAL 145 { 146 return ( this->GetIndex() + o ); 147 } 148 149 /** Returns the image index for neighbor pixel at index i in the 150 neighborhood. */ GetIndex(NeighborIndexType i)151 ITK_ITERATOR_VIRTUAL IndexType GetIndex(NeighborIndexType i) const ITK_ITERATOR_FINAL 152 { 153 return ( this->GetIndex() + this->GetOffset(i) ); 154 } 155 156 /** Returns the region of iteration. */ GetRegion()157 RegionType GetRegion() const 158 { 159 return m_Region; 160 } 161 162 /** Returns the N-dimensional starting index of the iterator's position on 163 * the image. */ GetBeginIndex()164 IndexType GetBeginIndex() const 165 { 166 return m_BeginIndex; 167 } 168 169 /** Returns a bounding box for the region spanned by this neighborhood 170 represented by an itk::ImageRegion */ 171 RegionType GetBoundingBoxAsImageRegion() const; 172 173 /** Method for rewinding the iterator to its beginning image index. */ 174 ITK_ITERATOR_VIRTUAL void GoToBegin() ITK_ITERATOR_FINAL; 175 176 /** Method for sending the iterator to one past the last index in its 177 * region. */ 178 ITK_ITERATOR_VIRTUAL void GoToEnd() ITK_ITERATOR_FINAL; 179 180 /** Initializes the iterator to walk a particular image and a particular 181 * region of that image. */ 182 ITK_ITERATOR_VIRTUAL void Initialize(const SizeType & radius, const ImageType *ptr, const RegionType & region) ITK_ITERATOR_FINAL; 183 184 /** Virtual method for determining whether the iterator is at the 185 * beginning of its iteration region. */ IsAtBegin()186 ITK_ITERATOR_VIRTUAL bool IsAtBegin() const ITK_ITERATOR_FINAL 187 { 188 return ( this->GetIndex() == m_BeginIndex ); 189 } 190 191 /** Virtual method for determining whether the iterator has reached the 192 * end of its iteration region. */ 193 ITK_ITERATOR_VIRTUAL bool IsAtEnd() const ITK_ITERATOR_FINAL; 194 195 /** Increments the pointers in the ConstNeighborhoodIteratorWithOnlyIndex, 196 * wraps across boundaries automatically, accounting for 197 * the disparity in the buffer size and the region size of the 198 * image. */ 199 Self & operator++(); 200 201 /** Decrements the pointers in the ConstNeighborhoodIteratorWithOnlyIndex, 202 * wraps across boundaries automatically, accounting for 203 * the disparity in the buffer size and the region size of the 204 * image. */ 205 Self & operator--(); 206 207 /** Returns a boolean == comparison of the current location/index 208 * of two ConstNeighborhoodIteratorWithOnlyIndexs of like 209 * dimensionality. The radii of the iterators are ignored. */ 210 bool operator==(const Self & it) const 211 { 212 return it.GetIndex() == this->GetIndex(); 213 } 214 215 /** Returns a boolean != comparison of the current location/index 216 * of two ConstNeighborhoodIteratorWithOnlyIndexs of like 217 * dimensionality. The radii of the iterators are ignored. */ 218 bool operator!=(const Self & it) const 219 { 220 return it.GetIndex() != this->GetIndex(); 221 } 222 223 /** Returns a boolean < comparison of the current location/index of 224 * two ConstNeighborhoodIteratorWithOnlyIndexs 225 * of like dimensionality. The radii of the iterators are ignored. 226 * The comparison progresses by dimension starting from the 227 * greatest. */ 228 bool operator<(const Self & it) const; 229 230 /** Returns a boolean <= comparison of the current location/index of 231 * two ConstNeighborhoodIteratorWithOnlyIndexs 232 * of like dimensionality. The radii of the iterators are ignored. 233 * The comparison progresses by dimension starting from the 234 * greatest. */ 235 bool operator<=(const Self & it) const; 236 237 /** Returns a boolean > comparison of the current location/index of 238 * two ConstNeighborhoodIteratorWithOnlyIndexs 239 * of like dimensionality. The radii of the iterators are ignored. 240 * The comparison progresses by dimension starting from the 241 * greatest. */ 242 bool operator>(const Self & it) const; 243 244 /** Returns a boolean >= comparison of the current location/index of 245 * two ConstNeighborhoodIteratorWithOnlyIndexs 246 * of like dimensionality. The radii of the iterators are ignored. 247 * The comparison progresses by dimension starting from the 248 * greatest. */ 249 bool operator>=(const Self & it) const; 250 251 /** This method positions the iterator at an indexed location in the 252 * image. SetLocation should _NOT_ be used to update the position of the 253 * iterator during iteration, only for initializing it to a position 254 * prior to iteration. This method is not optimized for speed. */ SetLocation(const IndexType & position)255 void SetLocation(const IndexType & position) 256 { 257 this->SetLoop(position); 258 } 259 260 /** Addition of an itk::Offset. Note that this method does not do any bounds 261 * checking. Adding an offset that moves the iterator out of its assigned 262 * region will produce undefined results. */ 263 Self & operator+=(const OffsetType &); 264 265 /** Subtraction of an itk::Offset. Note that this method does not do any 266 * bounds checking. Subtracting an offset that moves the iterator out 267 * of its assigned region will produce undefined results. */ 268 Self & operator-=(const OffsetType &); 269 270 /** Distance between two iterators */ 271 OffsetType operator-(const Self & b) 272 { 273 return m_Loop - b.m_Loop; 274 } 275 276 /** Returns false if the iterator overlaps region boundaries, true 277 * otherwise. Also updates an internal boolean array indicating 278 * which of the iterator's faces are out of bounds. */ 279 bool InBounds() const; 280 281 /** Returns true if the neighborhood index is within region boundaries, 282 * false otherwise. 283 * If false, then internalIndex and offset are calculated. Otherwise their 284 * values are left unchanged. 285 * Also updates an internal boolean array indicating 286 * which of the iterator's faces are out of bounds. 287 * \param n - linear neighborhood index. 288 * \param internalIndex - calculated for index \c n only when the neighborhood is not 289 * completely within region boundaries. 290 * \param offset - per-dimension offsets for index n to nearest boundary index, 291 * calculate only when the neighborhood is not completely within region boundaries. */ 292 bool IndexInBounds(const NeighborIndexType n, OffsetType & internalIndex, OffsetType & offset ) const; 293 294 /** */ NeedToUseBoundaryConditionOn()295 void NeedToUseBoundaryConditionOn() 296 { 297 this->SetNeedToUseBoundaryCondition(true); 298 } 299 NeedToUseBoundaryConditionOff()300 void NeedToUseBoundaryConditionOff() 301 { 302 this->SetNeedToUseBoundaryCondition(false); 303 } 304 SetNeedToUseBoundaryCondition(bool b)305 void SetNeedToUseBoundaryCondition(bool b) 306 { 307 m_NeedToUseBoundaryCondition = b; 308 } 309 GetNeedToUseBoundaryCondition()310 bool GetNeedToUseBoundaryCondition() const 311 { 312 return m_NeedToUseBoundaryCondition; 313 } 314 315 protected: 316 317 /** Default method for setting the coordinate location of the iterator. 318 * Loop indices correspond to the actual Image region index. */ SetLoop(const IndexType & p)319 ITK_ITERATOR_VIRTUAL void SetLoop(const IndexType & p) ITK_ITERATOR_FINAL 320 { 321 m_Loop = p; m_IsInBoundsValid = false; 322 } 323 324 /** Virtual method for setting internal loop boundaries. This 325 * method must be defined in each subclass because 326 * each subclass may handle loop boundaries differently. */ 327 ITK_ITERATOR_VIRTUAL void SetBound(const SizeType &) ITK_ITERATOR_FINAL; 328 329 /** Default method for setting the first index of the 330 * iteration region. */ SetBeginIndex(const IndexType & start)331 ITK_ITERATOR_VIRTUAL void SetBeginIndex(const IndexType & start) ITK_ITERATOR_FINAL 332 { 333 m_BeginIndex = start; 334 } 335 336 /** Default method for setting the last index of the 337 * iteration region. */ 338 ITK_ITERATOR_VIRTUAL void SetEndIndex() ITK_ITERATOR_FINAL; 339 340 /** The starting index for iteration within the itk::Image region 341 * on which this ConstNeighborhoodIteratorWithOnlyIndex is defined. */ 342 IndexType m_BeginIndex; 343 344 /** An array of upper looping boundaries used during iteration. */ 345 IndexType m_Bound; 346 347 /** The image on which iteration is defined. */ 348 typename ImageType::ConstPointer m_ConstImage; 349 350 /** The end index for iteration within the itk::Image region 351 * on which this ConstNeighborhoodIteratorWithOnlyIndex is defined. */ 352 IndexType m_EndIndex; 353 354 /** Array of loop counters used during iteration. */ 355 IndexType m_Loop; 356 357 /** The region over which iteration is defined. */ 358 RegionType m_Region; 359 360 /** Denotes which of the iterators dimensional sides spill outside 361 * region of interest boundaries. */ 362 mutable bool m_InBounds[Dimension]; 363 364 /** Denotes if iterator is entirely within bounds */ 365 mutable bool m_IsInBounds; 366 367 /** Is the m_InBounds and m_IsInBounds variables up to date? Set to 368 * false whenever the iterator is repositioned. Set to true within 369 * InBounds(). */ 370 mutable bool m_IsInBoundsValid; 371 372 /** Lower threshold of in-bounds loop counter values. */ 373 IndexType m_InnerBoundsLow; 374 375 /** Upper threshold of in-bounds loop counter values. */ 376 IndexType m_InnerBoundsHigh; 377 378 /** Does the specified region need to worry about boundary conditions? */ 379 bool m_NeedToUseBoundaryCondition; 380 }; 381 382 template< typename TImage > 383 inline ConstNeighborhoodIteratorWithOnlyIndex< TImage > 384 operator+(const ConstNeighborhoodIteratorWithOnlyIndex< TImage > & it, 385 const typename ConstNeighborhoodIteratorWithOnlyIndex< TImage > 386 ::OffsetType & ind) 387 { 388 ConstNeighborhoodIteratorWithOnlyIndex< TImage > ret; 389 ret = it; 390 ret += ind; 391 return ret; 392 } 393 394 template< typename TImage > 395 inline ConstNeighborhoodIteratorWithOnlyIndex< TImage > 396 operator+(const typename ConstNeighborhoodIteratorWithOnlyIndex< TImage > 397 ::OffsetType & ind, 398 const ConstNeighborhoodIteratorWithOnlyIndex< TImage > & it) 399 { return ( it + ind ); } 400 401 template< typename TImage > 402 inline ConstNeighborhoodIteratorWithOnlyIndex< TImage > 403 operator-(const ConstNeighborhoodIteratorWithOnlyIndex< TImage > & it, 404 const typename ConstNeighborhoodIteratorWithOnlyIndex< TImage > 405 ::OffsetType & ind) 406 { 407 ConstNeighborhoodIteratorWithOnlyIndex< TImage > ret; 408 ret = it; 409 ret -= ind; 410 return ret; 411 } 412 } // namespace itk 413 414 #ifndef ITK_MANUAL_INSTANTIATION 415 #include "itkConstNeighborhoodIteratorWithOnlyIndex.hxx" 416 #endif 417 418 #endif 419