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