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