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 itkShapedNeighborhoodIterator_h 19 #define itkShapedNeighborhoodIterator_h 20 21 #include <vector> 22 #include <list> 23 #include "itkConstShapedNeighborhoodIterator.h" 24 25 namespace itk 26 { 27 /** \class ShapedNeighborhoodIterator 28 * 29 * \brief A neighborhood iterator which can take on an arbitrary shape. 30 * 31 * \par General Information 32 * The ShapedNeighborhoodIterator is a refinement of NeighborhoodIterator which 33 * allows the user to specify which of the neighborhood elements are active and 34 * which will be ignored. This is useful for applications which only need to 35 * work with a subset of the neighborhood around a pixel such as morphological 36 * operations or cellular automata. This iterator can also be used, for 37 * example, to specify "cross-shaped" neighborhood where only elements along a 38 * spatial axes are significant. 39 * 40 * \par Constructing a shaped neighborhood iterator 41 * A shaped neighborhood iterator is constructed by constructing a list of 42 * active neighbor locations. The list is called the ActiveIndexList. The 43 * methods ActivateOffset, DeactivateOffset, and ClearActiveList are used to 44 * construct the ActiveIndexList. The argument to Activate/DeactivateOffset is 45 * an itk::Offset which represents the ND spatial offset from the center of the 46 * neighborhood. For example, to activate the center pixel in the neighborhood, 47 * you would do the following: 48 * 49 \code 50 using ImageType = Image<float, 3>; 51 ShapedNeighborhoodIterator<ImageType> it(radius, image, region); 52 ShapedNeighborhoodIterator<ImageType>::OffsetType offset = {{0,0,0}}; 53 it.ActivateOffset(offset); 54 \endcode 55 * 56 * where radius, image, and region are as described in NeighborhoodIterator. 57 * 58 * Once a neighborhood location has been activated, iteration (operator++, 59 * operator--, operator+=, operator-=) will update the value at the active 60 * location. Note that values at inactive locations will NOT be valid if 61 * queried. 62 * 63 * \par Accessing elements in a shaped neighborhood. 64 * To access the value at an active neighborhood location, you can use the 65 * standard GetPixel, SetPixel methods. SetPixel is not defined for 66 * ConstShapedNeighborhoodIterator. The class will not complain if you 67 * attempt to access a value at a non-active location, but be aware that the 68 * result will be undefined. Error checking is not done in this case for the 69 * sake of efficiency. 70 * 71 * A second way to access active shaped neighborhood values is through a 72 * ShapedNeighborhoodIterator::Iterator or 73 * ConstShapedNeighborhoodIterator::ConstIterator. The following example 74 * demonstrates the use of these iterators. 75 * 76 \code 77 using ImageType = Image<float, 3>; 78 ShapedNeighborhoodIterator<ImageType> it(radius, image, region); 79 . 80 . 81 . 82 it.ActivateOffset(offset1); 83 it.ActivateOffset(offset2); 84 it.ActivateOffset(offset3); 85 etc.. 86 . 87 . 88 . 89 ShapedNeighborhoodIterator<ImageType>::Iterator i; 90 for (i = it.Begin(); ! i.IsAtEnd(); i++) 91 { i.Set(i.Get() + 1.0); } 92 \\ you may also use i != i.End(), but IsAtEnd() may be slightly faster. 93 \endcode 94 * 95 * You can also iterate backward through the neighbohood active list. 96 * 97 \code 98 i = it.End(); 99 i--; 100 while (i != it.Begin()) 101 { 102 i.Set(i.Get() + 1.0); 103 i--; 104 } 105 i.Set(i.Get() + 1.0); 106 \endcode 107 * 108 * The Get() Set() syntax was chosen versus defining operator* for these 109 * iterators because lvalue vs. rvalue context information is needed to 110 * determine whether bounds checking must take place. 111 * 112 * \sa Neighborhood 113 * 114 * \par MORE INFORMATION 115 * For a complete description of the ITK Image Iterators and their API, please 116 * see the Iterators chapter in the ITK Software Guide. The ITK Software Guide 117 * is available in print and as a free .pdf download from https://www.itk.org. 118 * 119 * \ingroup ImageIterators 120 * 121 * \sa ImageConstIterator \sa ConditionalConstIterator 122 * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator 123 * \sa ConstSliceIterator \sa CorrespondenceDataStructureIterator 124 * \sa FloodFilledFunctionConditionalConstIterator 125 * \sa FloodFilledImageFunctionConditionalConstIterator 126 * \sa FloodFilledImageFunctionConditionalIterator 127 * \sa FloodFilledSpatialFunctionConditionalConstIterator 128 * \sa FloodFilledSpatialFunctionConditionalIterator 129 * \sa ImageConstIterator \sa ImageConstIteratorWithIndex 130 * \sa ImageIterator \sa ImageIteratorWithIndex 131 * \sa ImageLinearConstIteratorWithIndex \sa ImageLinearIteratorWithIndex 132 * \sa ImageRandomConstIteratorWithIndex \sa ImageRandomIteratorWithIndex 133 * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex 134 * \sa ImageRegionExclusionConstIteratorWithIndex 135 * \sa ImageRegionExclusionIteratorWithIndex 136 * \sa ImageRegionIterator \sa ImageRegionIteratorWithIndex 137 * \sa ImageRegionReverseConstIterator \sa ImageRegionReverseIterator 138 * \sa ImageReverseConstIterator \sa ImageReverseIterator 139 * \sa ImageSliceConstIteratorWithIndex \sa ImageSliceIteratorWithIndex 140 * \sa NeighborhoodIterator \sa PathConstIterator \sa PathIterator 141 * \sa ShapedNeighborhoodIterator \sa SliceIterator 142 * \sa ImageConstIteratorWithIndex 143 * \ingroup ITKCommon 144 * 145 * \wiki 146 * \wikiexample{Iterators/ShapedNeighborhoodIterator_Manual,Iterate over a region of an image with a shaped neighborhood} 147 * \wikiexample{Iterators/ShapedNeighborhoodIterator,Iterate over a region of an image with a shaped neighborhood} 148 * \endwiki 149 */ 150 template< typename TImage, 151 typename TBoundaryCondition = ZeroFluxNeumannBoundaryCondition< TImage > 152 > 153 class ITK_TEMPLATE_EXPORT ShapedNeighborhoodIterator: 154 public ConstShapedNeighborhoodIterator< TImage, 155 TBoundaryCondition > 156 { 157 public: 158 /** Extract image type information. */ 159 using InternalPixelType = typename TImage::InternalPixelType; 160 using PixelType = typename TImage::PixelType; 161 162 /** Save the image dimension. */ 163 static constexpr unsigned int Dimension = TImage::ImageDimension; 164 165 /** Standard class type aliases. */ 166 using Self = ShapedNeighborhoodIterator; 167 using Superclass = ConstShapedNeighborhoodIterator< TImage, 168 TBoundaryCondition>; 169 170 /** Inherit type alias from superclass */ 171 using OffsetType = typename Superclass::OffsetType; 172 using OffsetValueType = typename OffsetType::OffsetValueType; 173 using RadiusType = typename Superclass::RadiusType; 174 using SizeType = typename Superclass::SizeType; 175 using SizeValueType = typename Superclass::SizeValueType; 176 using ConstIterator = typename Superclass::ConstIterator; 177 using IndexListType = typename Superclass::IndexListType; 178 using BoundaryConditionType = typename Superclass::BoundaryConditionType; 179 using ImageBoundaryConditionPointerType = typename Superclass::ImageBoundaryConditionPointerType; 180 using NeighborhoodType = typename Superclass::NeighborhoodType; 181 using IndexType = typename Superclass::IndexType; 182 using ImageType = typename Superclass::ImageType; 183 using RegionType = typename Superclass::RegionType; 184 using IndexValueType = typename Superclass::IndexValueType; 185 186 /** An iterator for the ShapedNeighborhood classes. */ 187 struct Iterator:public ConstIterator { 188 Iterator() = default; IteratorIterator189 Iterator(Self *s) : 190 ConstIterator(s) {} 191 192 ~Iterator() ITK_ITERATOR_OVERRIDE = default; 193 Iterator & operator=(const Iterator & o) 194 { 195 ConstIterator::operator=(o); 196 return *this; 197 } 198 199 // Promote to public SetIterator200 void Set(const PixelType & v) const 201 { ConstIterator::ProtectedSet(v); } 202 protected: 203 204 friend Self; 205 IteratorIterator206 Iterator( const Self *s, const typename IndexListType::const_iterator &li ) 207 : ConstIterator(s,li) { } 208 209 }; 210 211 /** Default constructor */ 212 ShapedNeighborhoodIterator() = default; 213 214 /** Virtual destructor */ 215 ~ShapedNeighborhoodIterator() override = default; 216 217 /** Constructor which establishes the region size, neighborhood, and image 218 * over which to walk. */ ShapedNeighborhoodIterator(const SizeType & radius,const ImageType * ptr,const RegionType & region)219 ShapedNeighborhoodIterator(const SizeType & radius, 220 const ImageType *ptr, 221 const RegionType & region 222 ):Superclass(radius, const_cast< ImageType * >( ptr ), 223 region) 224 { 225 } 226 227 // Expose the following methods from the superclass. This is a restricted 228 // subset of the methods available for NeighborhoodIterator. 229 using Superclass::SetPixel; 230 using Superclass::SetCenterPixel; 231 232 233 /** Assignment operator */ 234 Self & operator=(const Self & orig) 235 { 236 Superclass::operator=(orig); 237 return *this; 238 } 239 240 /** Standard itk print method */ 241 void PrintSelf(std::ostream &, Indent) const override; 242 243 /** Returns a const iterator for the neighborhood which points to the first 244 * pixel in the neighborhood. */ Begin()245 Iterator Begin() { return Iterator(this, this->m_ActiveIndexList.begin()); } End()246 Iterator End() { return Iterator(this, this->m_ActiveIndexList.end()); } 247 248 using Superclass::Begin; 249 using Superclass::End; 250 251 protected: 252 253 friend Superclass; 254 255 /** Copy constructor */ 256 ShapedNeighborhoodIterator(const ShapedNeighborhoodIterator & o) = delete; 257 258 using NeighborIndexType = typename Superclass::NeighborIndexType; 259 260 }; 261 } // namespace itk 262 263 #ifndef ITK_MANUAL_INSTANTIATION 264 #include "itkShapedNeighborhoodIterator.hxx" 265 #endif 266 267 #endif 268