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 itkChainCodePath_h 19 #define itkChainCodePath_h 20 21 #include "itkPath.h" 22 #include "itkOffset.h" 23 #include "itkObjectFactory.h" 24 25 #include <vector> 26 27 namespace itk 28 { 29 /** \class ChainCodePath 30 * \brief Represent a path as a sequence of connected image index offsets 31 * 32 * This class is intended to represent sequences of connected indices in an 33 * image. It does so by storing the offset of each index from its immediately 34 * preceding, connected, index. The only image index stored directly is that 35 * of the first index. ChainCodePath maps a 1D integer input (step number) to 36 * an ND integer output (either an offset or an image index, depending on 37 * whether Evaluate or EvaluateToIndex is called). 38 * 39 * \sa ChainCodePath2D 40 * \sa ParametricPath 41 * \sa Path 42 * \sa Index 43 * \sa Offset 44 * 45 * \ingroup PathObjects 46 * \ingroup ITKPath 47 */ 48 template< unsigned int VDimension > 49 class ITK_TEMPLATE_EXPORT ChainCodePath:public 50 Path< unsigned int, Offset< VDimension >, VDimension > 51 { 52 public: 53 ITK_DISALLOW_COPY_AND_ASSIGN(ChainCodePath); 54 55 /** Dimension underlying input image. */ 56 static constexpr unsigned int Dimension = VDimension; 57 58 /** Standard class type aliases. */ 59 using Self = ChainCodePath< VDimension >; 60 using Superclass = Path< unsigned int, Offset< VDimension >, VDimension >; 61 62 using Pointer = SmartPointer< Self >; 63 using ConstPointer = SmartPointer< const Self >; 64 65 /** Run-time type information (and related methods). */ 66 itkTypeMacro(ChainCodePath, Path); 67 68 /** OutputType type alias support */ 69 using OutputType = typename Superclass::OutputType; 70 using InputType = typename Superclass::InputType; 71 72 /** The output type of this function is an Index */ 73 using OffsetType = OutputType; 74 using IndexType = Index< VDimension >; 75 76 using ChainCodeType = std::vector< OffsetType >; 77 78 using ChainCodeSizeType = typename ChainCodeType::size_type; 79 80 // Functions inherited from Path 81 82 /** Evaluate the chaincode for the offset at the specified path-position. */ Evaluate(const InputType & input)83 OutputType Evaluate(const InputType & input) const override 84 { 85 return m_Chain[input]; 86 } 87 88 /** Like Evaluate(), but returns the index at the specified path-position. */ 89 IndexType EvaluateToIndex(const InputType & input) const override; 90 91 /** Increment the input variable passed by reference and then return the 92 * offset stored at the new path-position. If the chaincode is unable to be 93 * incremented, input is not changed and an offset of zero is returned, which 94 * may be used to check for the end of the chain code. */ 95 OffsetType IncrementInput(InputType & input) const override; 96 97 /** Where does the path end (what is the last valid input value)? */ EndOfInput()98 InputType EndOfInput() const override 99 { 100 return static_cast<InputType>(NumberOfSteps()); // 0 is before the first step, 1 is after it 101 } 102 103 /** New() method for dynamic construction */ 104 itkNewMacro(Self); 105 106 /** Set/Get the index associated with the initial position of the path */ 107 itkSetMacro(Start, IndexType); 108 itkGetConstReferenceMacro(Start, IndexType); 109 110 /** Insert a new step into the chaincode at a specified position */ InsertStep(InputType position,OffsetType step)111 virtual inline void InsertStep(InputType position, OffsetType step) 112 { 113 m_Chain.insert(m_Chain.begin() + position, step); 114 this->Modified(); 115 } 116 117 /** Change the direction of a step in the chaincode */ ChangeStep(InputType position,OffsetType step)118 virtual inline void ChangeStep(InputType position, OffsetType step) 119 { 120 m_Chain[position] = step; 121 this->Modified(); 122 } 123 124 /** Remove all steps from the chain code */ Clear()125 virtual inline void Clear() 126 { 127 m_Chain.clear(); 128 this->Modified(); 129 } 130 131 /** How many steps in the chaincode? */ NumberOfSteps()132 virtual inline ChainCodeSizeType NumberOfSteps() const 133 { 134 return m_Chain.size(); 135 } 136 137 /** Needed for Pipelining */ Initialize()138 void Initialize() override 139 { 140 m_Start = this->GetZeroIndex(); 141 this->Clear(); 142 } 143 144 protected: 145 ChainCodePath(); 146 ~ChainCodePath() override = default; 147 void PrintSelf(std::ostream & os, Indent indent) const override; 148 149 private: 150 IndexType m_Start; // origin image index for the path 151 ChainCodeType m_Chain; // the chain code (vector of offsets) 152 }; 153 } // end namespace itk 154 155 #ifndef ITK_MANUAL_INSTANTIATION 156 #include "itkChainCodePath.hxx" 157 #endif 158 159 #endif 160