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 itkCellInterface_h
19 #define itkCellInterface_h
20 
21 #include "itkObject.h"
22 #include <map>
23 #include "itkCellInterfaceVisitor.h"
24 #include "itkAutoPointer.h"
25 #include "itkArray.h"
26 
27 // Define a macro for CellInterface sub-classes to use
28 // to define the Accept and GetTopologyId virtuals used
29 // by the MultiVisitor class
30 #define itkCellVisitMacro(TopologyId)                                                                \
31   static int GetTopologyId()                                                                         \
32     {                                                                                                \
33     return TopologyId;                                                                               \
34     }                                                                                                \
35   virtual void Accept(CellIdentifier cellid, typename CellInterface< PixelType,                      \
36                       CellTraits >::MultiVisitor * mv) override                                  \
37     {                                                                                                \
38     typename CellInterfaceVisitor< PixelType, CellTraits >::Pointer v =                              \
39       mv->GetVisitor(TopologyId);                                                                    \
40     if ( v )                                                                                         \
41       {                                                                                              \
42       v->VisitFromCell(cellid, this);                                                                \
43       }                                                                                              \
44     }
45 
46 // Define a macro for the common type alias required by the
47 // classes deriving form CellInterface (included).
48 #define itkCellCommonTypedefs(celltype)                   \
49   using Self = celltype;                 \
50   using ConstSelfAutoPointer = AutoPointer< const Self >; \
51   using SelfAutoPointer = AutoPointer< Self >;      \
52   using RawPointer = Self *;           \
53   using ConstRawPointer = const Self *
54 
55 // Define a macro for the common type alias required by the
56 // classes deriving form CellInterface (excluded).
57 #define itkCellInheritedTypedefs(superclassArg)                             \
58   using Superclass = superclassArg;             \
59   using PixelType = typename Superclass::PixelType;              \
60   using CellType = typename Superclass::CellType;               \
61   using CellAutoPointer = typename Superclass::CellAutoPointer;        \
62   using CellConstAutoPointer = typename Superclass::CellConstAutoPointer;   \
63   using CellRawPointer = typename Superclass::CellRawPointer;         \
64   using CellConstRawPointer = typename Superclass::CellConstRawPointer;    \
65   using CellTraits = typename Superclass::CellTraits;             \
66   using CoordRepType = typename Superclass::CoordRepType;           \
67   using InterpolationWeightType = typename Superclass::InterpolationWeightType; \
68   using PointIdentifier = typename Superclass::PointIdentifier;       \
69   using PointIdIterator = typename Superclass::PointIdIterator;       \
70   using PointIdConstIterator = typename Superclass::PointIdConstIterator;  \
71   using CellIdentifier = typename Superclass::CellIdentifier;        \
72   using CellFeatureIdentifier = typename Superclass::CellFeatureIdentifier; \
73   using CellFeatureCount = typename Superclass::CellFeatureIdentifier;      \
74   using PointType = typename Superclass::PointType;             \
75   using VectorType = typename Superclass::VectorType;            \
76   using PointsContainer = typename Superclass::PointsContainer;       \
77   using UsingCellsContainer = typename Superclass::UsingCellsContainer;   \
78   using CellGeometry = typename Superclass::CellGeometry;          \
79   using ParametricCoordArrayType = typename Superclass::ParametricCoordArrayType; \
80   using ShapeFunctionsArrayType = typename Superclass::ShapeFunctionsArrayType; \
81   static constexpr unsigned int PointDimension = Superclass::PointDimension
82 
83 namespace itk
84 {
85 /** \class CellInterface
86  *  \brief An abstract interface for cells.
87  *
88  * Define an abstract interface for cells.  Actual cell types derive from
89  * this class.
90  *
91  * \tparam TPixelType The type stored with an entity (cell, point, or boundary).
92  * \tparam TCellTraits Type information for cell.
93  *
94  * \ingroup MeshObjects
95  * \ingroup ITKCommon
96  */
97 template<
98   typename TPixelType,
99   typename TCellTraits
100   >
101 class ITK_TEMPLATE_EXPORT CellInterface
102 {
103 public:
104   ITK_DISALLOW_COPY_AND_ASSIGN(CellInterface);
105 
106   /** Standard class type aliases. */
107   itkCellCommonTypedefs(CellInterface);
108 
109   /** Save the PixelType template parameter. */
110   using PixelType = TPixelType;
111 
112   /** Save the CellTraits template parameter. */
113   using CellTraits = TCellTraits;
114 
115   /** Save type information for this cell. */
116   using CoordRepType = typename CellTraits::CoordRepType;
117   using InterpolationWeightType = typename CellTraits::InterpolationWeightType;
118   using PointIdentifier = typename CellTraits::PointIdentifier;
119   using PointIdIterator = typename CellTraits::PointIdIterator;
120   using PointIdConstIterator = typename CellTraits::PointIdConstIterator;
121   using CellIdentifier = typename CellTraits::CellIdentifier;
122   using CellFeatureIdentifier = typename CellTraits::CellFeatureIdentifier;
123   using PointType = typename CellTraits::PointType;
124   using PointsContainer = typename CellTraits::PointsContainer;
125   using UsingCellsContainer = typename CellTraits::UsingCellsContainer;
126 
127   ///NOTE: it should normally be defined in the traits
128   using VectorType = typename PointType::VectorType;
129 
130   /** Save the dimension from the template parameters. */
131   static constexpr unsigned int PointDimension = CellTraits::PointDimension;
132 
133   /** An iterator through the UsingCellsContainer. */
134   using UsingCellsContainerIterator = typename UsingCellsContainer::iterator;
135 
136   /** Give this and all derived classes quick access to the base cell type. */
137   using CellType = CellInterface;
138   using CellAutoPointer = SelfAutoPointer;
139   using CellConstAutoPointer = ConstSelfAutoPointer;
140   using CellRawPointer = RawPointer;
141   using CellConstRawPointer = ConstRawPointer;
142 
143   /** A useful rename. */
144   using CellFeatureCount = CellFeatureIdentifier;
145 
146   /**  Cell Visitor interfaces */
147   enum CellGeometry { VERTEX_CELL = 0, LINE_CELL, TRIANGLE_CELL,
148                       QUADRILATERAL_CELL, POLYGON_CELL, TETRAHEDRON_CELL, HEXAHEDRON_CELL,
149                       QUADRATIC_EDGE_CELL, QUADRATIC_TRIANGLE_CELL,
150                       LAST_ITK_CELL, MAX_ITK_CELLS = 255 };
151 
152   /** Types needed to contour the cells */
153   using ParametricCoordArrayType = Array< CoordRepType >;
154   using ShapeFunctionsArrayType = Array< InterpolationWeightType >;
155 
156 //  static int GetNextUserCellId(); // never return > MAX_INTERFACE
157 
158   /** \class MultiVisitor
159    * \brief A visitor that can visit different cell types in a mesh.
160    * CellInterfaceVisitor instances can be registered for each
161    * type of cell that needs to be visited.
162    *
163    * \ingroup MeshAccess
164    * \ingroup ITKCommon
165    */
166   class MultiVisitor:public LightObject
167   {
168 public:
169     /**  Visitor type, because VisualC++ 6.0 does not like
170      *  Visitor being a nested type of CellInterfaceVisitor   */
171     using VisitorType = CellInterfaceVisitor< TPixelType, TCellTraits >;
172 
173     /** Standard class type aliases.   */
174     using Self = MultiVisitor;
175     using Pointer = SmartPointer< Self >;
176 
177     /** Method for creation through the object factory.   */
178     //itkNewMacro(Self);
New()179     static Pointer New() { Pointer smartPtr = new Self; smartPtr->UnRegister(); return smartPtr; }
180 
181     /** Run-time type information (and related methods).   */
182     itkTypeMacro(MultiVisitor, LightObject);
183 
184     /** Typedefs for the visitor class.   */
185     using VisitorPointer = typename VisitorType::Pointer;
186     using VisitorPointerValueType = typename std::map< int, VisitorPointer >::value_type;
187 
188 public:
GetVisitor(int id)189     VisitorType * GetVisitor(int id)
190     {
191       if ( id < LAST_ITK_CELL )
192         {
193         return m_Visitors[id];
194         }
195       else
196         {
197         auto pos = m_UserDefined.find(id);
198         if ( pos != m_UserDefined.end() )
199           {
200           return ( *pos ).second;
201           }
202         }
203       return nullptr;
204     }
205 
AddVisitor(VisitorType * v)206     void AddVisitor(VisitorType *v)
207     {
208       int id = v->GetCellTopologyId();
209 
210       if ( id < LAST_ITK_CELL )
211         {
212         m_Visitors[id] = v;
213         }
214       else
215         {
216         m_UserDefined.insert( VisitorPointerValueType(id, v) );
217         }
218     }
219 
220     ~MultiVisitor() override = default;
221 
222 protected:
223     VisitorPointer m_Visitors[LAST_ITK_CELL];      // fixed array set to the
224                                                    // size
225                                                    // from the enum
226     std::map< int, VisitorPointer > m_UserDefined; // user defined cell types
227                                                    // go here
228   };
229 
230   /** This must be implemented by all sub-classes of CellInterface */
231   virtual void Accept(CellIdentifier cellId, MultiVisitor *) = 0;
232 
233   /**  Return the type of the cell (one of the CellGeometry enums
234    *   listed above). */
235   virtual CellGeometry GetType() const = 0;
236 
237   /** Create a new copy of this cell.  This is provided so that a copy can
238    * be made without knowing the cell type. */
239   virtual void MakeCopy(CellAutoPointer &) const = 0;
240 
241   /** Get the topological dimension of this cell. */
242   virtual unsigned int GetDimension() const = 0;
243 
244   /** Get the interpolation order of the cell.  Usually linear. */
245   virtual unsigned int GetInterpolationOrder() const;
246 
247   /** Get the number of points required to define the cell. */
248   virtual unsigned int GetNumberOfPoints() const = 0;
249 
250   /** Get the number of boundary features of a given dimension on this cell. */
251   virtual CellFeatureCount GetNumberOfBoundaryFeatures(int dimension) const = 0;
252 
253   /** Get the boundary feature corresponding to the given dimension and Id. */
254   virtual bool GetBoundaryFeature(int dimension, CellFeatureIdentifier,
255                                   CellAutoPointer &) = 0;
256 
257   /** Get the point id list used by the cell in a form suitable to pass to
258    * SetPointIds(first) on another cell.  This is equivalent to
259    * PointIdsBegin() const. */
260   virtual PointIdConstIterator GetPointIds() const;
261 
262   /** Set the point id list used by the cell.  It is assumed that the given
263    * iterator can be incremented and safely de-referenced enough times to
264    * get all the point ids needed by the cell. */
265   virtual void SetPointIds(PointIdConstIterator first) = 0;
266 
267   /** Set the point id list used by the cell.  It is assumed that the range
268    * of iterators [first, last) contains the correct number of points needed to
269    * define the cell.  The position *last is NOT referenced, so it can safely
270    * be one beyond the end of an array or other container. */
271   virtual void SetPointIds(PointIdConstIterator first,
272                            PointIdConstIterator last) = 0;
273 
274   /** Set the point identifier for a given spot in the point list
275    *  for the cell. */
276   virtual void SetPointId(int localId, PointIdentifier) = 0;
277 
278   /** Get a begin iterator to the list of point identifiers used by the cell. */
279   virtual PointIdIterator PointIdsBegin() = 0;
280 
281   /** Get a const begin iterator to the list of point identifiers used
282    * by the cell. */
283   virtual PointIdConstIterator PointIdsBegin() const = 0;
284 
285   /** Get an end iterator to the list of point identifiers used by the cell. */
286   virtual PointIdIterator PointIdsEnd() = 0;
287 
288   /** Get a const end iterator to the list of point identifiers used
289    * by the cell. */
290   virtual PointIdConstIterator PointIdsEnd() const = 0;
291 
292   /** Get/Set the point id list used by the cell */
293   using PointIdentifierContainerType = itk::Array<PointIdentifier>;
294   PointIdentifierContainerType GetPointIdsContainer() const;
295   void SetPointIdsContainer( const PointIdentifierContainerType & );
296 
297   /** Given the parametric coordinates of a point in the cell
298    * (pCoords[CellDimension]), get the closest cell boundary feature of
299    * topological dimension CellDimension-1.  If the "inside" pointer is not
300    * nullptr, the flag is set to indicate whether the point is inside the cell. */
GetClosestBoundary(CoordRepType[],bool *,CellAutoPointer &)301   virtual bool GetClosestBoundary(CoordRepType[], bool *, CellAutoPointer &)
302   { return false; }
303 
304   /** Given the geometric coordinates of a point (coord[PointDimension]),
305    * return whether it is inside the cell.  Also perform the following
306    * calculations, if the corresponding result pointers are not nullptr:
307    *
308    *  - Find the closest point in or on the cell to the given point
309    *     (Returns through pointer to array: closestPoint[PointDimension]).
310    *
311    *  - Get the cell's parametric coordinates for the given point
312    *     (Returns through pointer to array: pCoords[CellDimension]).
313    *
314    *  - Get the square of the distance between the point and the cell
315    *     (this is the distance from the point to the closest point,
316    *      returned through "dist2" pointer).
317    *
318    *  - Get the interpolation weights for the cell
319    *     (Returns through pointer to array: weights[NumberOfPoints]). */
EvaluatePosition(CoordRepType *,PointsContainer *,CoordRepType *,CoordRepType[],double *,InterpolationWeightType *)320   virtual bool EvaluatePosition(CoordRepType *,
321                                 PointsContainer *,
322                                 CoordRepType *,
323                                 CoordRepType[],
324                                 double *,
325                                 InterpolationWeightType *)
326   { return bool(); }
327 
328   /** Given the parametric coordinates of a point in the cell
329    *  determine the value of its Shape Functions
330    *  returned through an itkArray<InterpolationWeightType>).  */
EvaluateShapeFunctions(const ParametricCoordArrayType &,ShapeFunctionsArrayType &)331   virtual void EvaluateShapeFunctions(
332     const ParametricCoordArrayType &,
333     ShapeFunctionsArrayType  &) const {}
334 
335   /** Intersect the cell with a line given by an origin (origin[PointDimension])
336    * and direction (direction[PointDimension]).  The intersection point
337    * found will be within the given tolerance of the real intersection.
338    * Get the following results if the corresponding pointers are not nullptr:
339    *
340    *  - The intersection point's geometric coordinates (returned through
341    *     pointer to array: coords[PointDimension]).
342    *
343    *  - The line's parametric coordinate of the intersection point
344    *     (returned through "t" pointer).
345    *
346    *  - The cell's parametric coordinates of the intersection point
347    *     (returned through pointer to array: pCoords[CellDimension]).
348    *
349    * Returns whether an intersection exists within the given tolerance. */
IntersectWithLine(CoordRepType[PointDimension],CoordRepType[PointDimension],CoordRepType,CoordRepType[PointDimension],CoordRepType *,CoordRepType[])350   virtual bool IntersectWithLine(CoordRepType[PointDimension],
351                                  CoordRepType[PointDimension],
352                                  CoordRepType,
353                                  CoordRepType[PointDimension],
354                                  CoordRepType *,
355                                  CoordRepType[]) { return bool(); }
356 
357   /** Compute cell bounding box and store in the user-provided array.
358    * Array is ordered (xmin, xmax,  ymin, ymax, ....).  A pointer to the
359    * array is returned for convenience.  This allows code like:
360    * "CoordRep* bounds = cell->GetBoundingBox(new CoordRep[6]);". */
GetBoundingBox(CoordRepType[PointDimension * 2])361   CoordRepType * GetBoundingBox(CoordRepType[PointDimension * 2]) { return nullptr; }
362 
363   /** Compute the square of the diagonal length of the bounding box. */
GetBoundingBoxDiagonalLength2()364   CoordRepType GetBoundingBoxDiagonalLength2() { return NumericTraits< CoordRepType >::ZeroValue(); }
365 
366   /** Intersect the given bounding box (bounds[PointDimension*2]) with a line
367    * given by an origin (origin[PointDimension]) and direction
368    * (direction[PointDimension]). Get the following results if the
369    * corresponding pointers are not nullptr:
370    *
371    *  - The intersection point's geometric coordinates (returned through
372    *     pointer to array: coords[PointDimension]).
373    *
374    *  - The line's parametric coordinate of the intersection point
375    *     (returned through "t" pointer).
376    *
377    * Returns whether an intersection exists. */
IntersectBoundingBoxWithLine(CoordRepType[PointDimension * 2],CoordRepType[PointDimension],CoordRepType[PointDimension],CoordRepType[PointDimension],CoordRepType *)378   virtual bool IntersectBoundingBoxWithLine(CoordRepType[PointDimension * 2],
379                                             CoordRepType[PointDimension],
380                                             CoordRepType[PointDimension],
381                                             CoordRepType[PointDimension],
382                                             CoordRepType *) { return bool(); }
383 
384   /** Interface to the boundary form of the cell to set/get UsingCells.
385    * See the boundary wrapper source for more information. */
386 
387   /** Returns true if the cell has been explicitly assigned as a
388    *  boundary, false otherwise. */
389   virtual bool IsExplicitBoundary();
390 
391   /**
392    * Register the fact that this cell is a part of the boundary of the
393    * cell \a cellId, by adding \a cellId to the UsingCellsContainer.
394    */
395   virtual void AddUsingCell(CellIdentifier cellId);
396 
397   /**
398    * Remove a cell from the UsingCellsContainer.
399    */
400   virtual void RemoveUsingCell(CellIdentifier cellId);
401 
402   /**
403    * Test if a cell is in the UsingCellsContainer.  A result of \c true
404    * indicates that this cell is part of the boundary of the cell \a
405    * cellId, assuming that boundary information has been recorded.
406    */
407   virtual bool IsUsingCell(CellIdentifier cellId);
408 
409   /**
410    * Get the number of cells in the UsingCellsContainer.
411    */
412   virtual unsigned int GetNumberOfUsingCells();
413 
414 #if !defined( ITK_WRAPPING_PARSER )
415   /**
416    * Get a begin iterator for the UsingCellsContainer.
417    */
418   virtual UsingCellsContainerIterator UsingCellsBegin();
419 
420   /**
421    * Get an end iterator for the UsingCellsContainer.
422    */
423   virtual UsingCellsContainerIterator UsingCellsEnd();
424 
425 #endif
426 
427   /** Standard part of every itk Object. */
428   itkTypeMacroNoParent(CellInterface);
429 
430 public:
431   CellInterface() = default;
432   virtual ~CellInterface() = default;
433   /** Cell internal utility routines. */
434 
435   /** Get the geometric position of a point. */
436 //  bool GetPointPosition(PointsContainer*, int localId, Point*)=0;
437 
438 protected:
439   /** Store the set of cells using this boundary. */
440   UsingCellsContainer m_UsingCells;
441 };
442 
443 /** \class CellTraitsInfo
444  * \brief A simple utility class to define the cell type inside a mesh type
445  * structure definition.  This just makes a copy of existing type information
446  * that is needed for a cell type template parameter.
447  *
448  * During a mesh type definition, after the appropriate types and values
449  * have been defined, just have the line:
450  \verbatim
451  using CellTraits = itkMakeCellTraitsMacro;
452  \endverbatim
453  *
454  * itkMakeCellTraitsMacro is a macro front-end to automatically fill in the
455  * template parameters for the CellTraitsInfo structure inside a mesh
456  * type structure definition.
457  *
458  * \ingroup MeshObjects
459  * \ingroup ITKCommon
460  */
461 template< int VPointDimension, typename TCoordRep,
462           typename TInterpolationWeight, typename TPointIdentifier,
463           typename TCellIdentifier, typename TCellFeatureIdentifier,
464           typename TPoint, typename TPointsContainer,
465           typename TUsingCellsContainer >
466 class ITK_TEMPLATE_EXPORT CellTraitsInfo
467 {
468 public:
469   static constexpr unsigned int PointDimension = VPointDimension;
470   using CoordRepType = TCoordRep;
471   using InterpolationWeightType = TInterpolationWeight;
472   using PointIdentifier = TPointIdentifier;
473   using CellIdentifier = TCellIdentifier;
474   using CellFeatureIdentifier = TCellFeatureIdentifier;
475   using PointType = TPoint;
476   using PointsContainer = TPointsContainer;
477   using UsingCellsContainer = TUsingCellsContainer;
478   using PointIdIterator = PointIdentifier *;
479 
480   using PointIdConstIterator = const PointIdentifier *;
481 };
482 
483 #define itkMakeCellTraitsMacro                                           \
484   CellTraitsInfo < Self::PointDimension, CoordRepType, \
485   InterpolationWeightType,                                               \
486   PointIdentifier, CellIdentifier, CellFeatureIdentifier,                \
487   PointType, PointsContainer, UsingCellsContainer >
488 } // end namespace itk
489 
490 #if !defined( ITK_WRAPPING_PARSER )
491 #ifndef ITK_MANUAL_INSTANTIATION
492 #include "itkCellInterface.hxx"
493 #endif
494 #endif
495 
496 #endif
497