1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkSimpleCellTessellator.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 /** 16 * @class vtkSimpleCellTessellator 17 * @brief helper class to perform cell tessellation 18 * 19 * vtkSimpleCellTessellator is a helper class to perform adaptive tessellation 20 * of particular cell topologies. The major purpose for this class is to 21 * transform higher-order cell types (e.g., higher-order finite elements) 22 * into linear cells that can then be easily visualized by VTK. This class 23 * works in conjunction with the vtkGenericDataSet and vtkGenericAdaptorCell 24 * classes. 25 * 26 * This algorithm is based on edge subdivision. An error metric along each 27 * edge is evaluated, and if the error is greater than some tolerance, the 28 * edge is subdivided (as well as all connected 2D and 3D cells). The process 29 * repeats until the error metric is satisfied. Since the algorithm is based 30 * on edge subdivision it inherently avoid T-junctions. 31 * 32 * A significant issue addressed by this algorithm is to insure face 33 * compatibility across neigboring cells. That is, diagonals due to face 34 * triangulation must match to insure that the mesh is compatible. The 35 * algorithm employs a precomputed table to accelerate the tessellation 36 * process. The table was generated with the help of vtkOrderedTriangulator 37 * the basic idea is that the choice of diagonal is made only by considering the 38 * relative value of the point ids. 39 * 40 * @sa 41 * vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric vtkAttributesErrorMetric 42 * vtkGeometricErrorMetric vtkViewDependentErrorMetric 43 */ 44 45 #ifndef vtkSimpleCellTessellator_h 46 #define vtkSimpleCellTessellator_h 47 48 #include "vtkCommonDataModelModule.h" // For export macro 49 #include "vtkGenericCellTessellator.h" 50 51 class vtkTriangleTile; 52 class vtkTetraTile; 53 class vtkCellArray; 54 class vtkDoubleArray; 55 class vtkGenericEdgeTable; 56 class vtkGenericSubdivisionErrorMetric; 57 class vtkGenericAttributeCollection; 58 class vtkGenericAdaptorCell; 59 class vtkGenericCellIterator; 60 class vtkPointData; 61 class vtkOrderedTriangulator; 62 class vtkPolygon; 63 class vtkIdList; 64 65 //----------------------------------------------------------------------------- 66 // 67 // The tessellation object 68 class VTKCOMMONDATAMODEL_EXPORT vtkSimpleCellTessellator : public vtkGenericCellTessellator 69 { 70 public: 71 static vtkSimpleCellTessellator *New(); 72 vtkTypeMacro(vtkSimpleCellTessellator,vtkGenericCellTessellator); 73 void PrintSelf(ostream& os, vtkIndent indent) override; 74 75 //@{ 76 /** 77 * Get the higher order cell in order to access the evaluation function. 78 */ 79 vtkGetObjectMacro(GenericCell, vtkGenericAdaptorCell); 80 //@} 81 82 /** 83 * Tessellate a face of a 3D `cell'. The face is specified by the 84 * index value. 85 * The result is a set of smaller linear triangles in `cellArray' with 86 * `points' and point data `internalPd'. 87 * \pre cell_exists: cell!=0 88 * \pre valid_dimension: cell->GetDimension()==3 89 * \pre valid_index_range: (index>=0) && (index<cell->GetNumberOfBoundaries(2)) 90 * \pre att_exists: att!=0 91 * \pre points_exists: points!=0 92 * \pre cellArray_exists: cellArray!=0 93 * \pre internalPd_exists: internalPd!=0 94 */ 95 void TessellateFace(vtkGenericAdaptorCell *cell, 96 vtkGenericAttributeCollection *att, 97 vtkIdType index, 98 vtkDoubleArray *points, 99 vtkCellArray *cellArray, 100 vtkPointData *internalPd) override; 101 102 /** 103 * Tessellate a 3D `cell'. The result is a set of smaller linear 104 * tetrahedra in `cellArray' with `points' and point data `internalPd'. 105 * \pre cell_exists: cell!=0 106 * \pre valid_dimension: cell->GetDimension()==3 107 * \pre att_exists: att!=0 108 * \pre points_exists: points!=0 109 * \pre cellArray_exists: cellArray!=0 110 * \pre internalPd_exists: internalPd!=0 111 */ 112 void Tessellate(vtkGenericAdaptorCell *cell, 113 vtkGenericAttributeCollection *att, 114 vtkDoubleArray *points, 115 vtkCellArray *cellArray, 116 vtkPointData *internalPd ) override; 117 118 /** 119 * Triangulate a 2D `cell'. The result is a set of smaller linear triangles 120 * in `cellArray' with `points' and point data `internalPd'. 121 * \pre cell_exists: cell!=0 122 * \pre valid_dimension: cell->GetDimension()==2 123 * \pre att_exists: att!=0 124 * \pre points_exists: points!=0 125 * \pre cellArray_exists: cellArray!=0 126 * \pre internalPd_exists: internalPd!=0 127 */ 128 void Triangulate(vtkGenericAdaptorCell *cell, 129 vtkGenericAttributeCollection *att, 130 vtkDoubleArray *points, 131 vtkCellArray *cellArray, 132 vtkPointData *internalPd) override; 133 134 /** 135 * Reset the output for repeated use of this class. 136 */ 137 void Reset(); 138 139 140 /** 141 * Initialize the tessellator with a data set `ds'. 142 */ 143 void Initialize(vtkGenericDataSet *ds) override; 144 145 /** 146 * Return the number of fixed subdivisions. It is used to prevent from 147 * infinite loop in degenerated cases. For order 3 or higher, if the 148 * inflection point is exactly on the mid-point, error metric will not 149 * detect that a subdivision is required. 0 means no fixed subdivision: 150 * there will be only adaptive subdivisions. 151 152 * The algorithm first performs `GetFixedSubdivisions' non adaptive 153 * subdivisions followed by at most `GetMaxAdaptiveSubdivisions' adaptive 154 * subdivisions. Hence, there are at most `GetMaxSubdivisionLevel' 155 * subdivisions. 156 * \post positive_result: result>=0 && result<=GetMaxSubdivisionLevel() 157 */ 158 int GetFixedSubdivisions(); 159 160 /** 161 * Return the maximum level of subdivision. It is used to prevent from 162 * infinite loop in degenerated cases. For order 3 or higher, if the 163 * inflection point is exactly on the mid-point, error metric will not 164 * detect that a subdivision is required. 0 means no subdivision, 165 * neither fixed nor adaptive. 166 * \post positive_result: result>=GetFixedSubdivisions() 167 */ 168 int GetMaxSubdivisionLevel(); 169 170 /** 171 * Return the maximum number of adaptive subdivisions. 172 * \post valid_result: result==GetMaxSubdivisionLevel()-GetFixedSubdivisions() 173 */ 174 int GetMaxAdaptiveSubdivisions(); 175 176 /** 177 * Set the number of fixed subdivisions. See GetFixedSubdivisions() for 178 * more explanations. 179 * \pre positive_level: level>=0 && level<=GetMaxSubdivisionLevel() 180 * \post is_set: GetFixedSubdivisions()==level 181 */ 182 void SetFixedSubdivisions(int level); 183 184 /** 185 * Set the maximum level of subdivision. See GetMaxSubdivisionLevel() for 186 * more explanations. 187 * \pre positive_level: level>=GetFixedSubdivisions() 188 * \post is_set: level==GetMaxSubdivisionLevel() 189 */ 190 void SetMaxSubdivisionLevel(int level); 191 192 /** 193 * Set both the number of fixed subdivisions and the maximum level of 194 * subdivisions. See GetFixedSubdivisions(), GetMaxSubdivisionLevel() and 195 * GetMaxAdaptiveSubdivisions() for more explanations. 196 * \pre positive_fixed: fixed>=0 197 * \pre valid_range: fixed<=maxLevel 198 * \post fixed_is_set: fixed==GetFixedSubdivisions() 199 * \post maxLevel_is_set: maxLevel==GetMaxSubdivisionLevel() 200 */ 201 void SetSubdivisionLevels(int fixed, 202 int maxLevel); 203 204 205 protected: 206 vtkSimpleCellTessellator(); 207 ~vtkSimpleCellTessellator() override; 208 209 /** 210 * Extract point `pointId' from the edge table to the output point and output 211 * point data. 212 */ 213 void CopyPoint(vtkIdType pointId); 214 215 /** 216 * HashTable instead of vtkPointLocator 217 */ 218 vtkGenericEdgeTable *EdgeTable; 219 220 void InsertEdgesIntoEdgeTable( vtkTriangleTile &tri ); 221 void RemoveEdgesFromEdgeTable( vtkTriangleTile &tri ); 222 void InsertPointsIntoEdgeTable( vtkTriangleTile &tri ); 223 224 void InsertEdgesIntoEdgeTable( vtkTetraTile &tetra ); 225 void RemoveEdgesFromEdgeTable( vtkTetraTile &tetra ); 226 227 /** 228 * Initialize `root' with the sub-tetra defined by the `localIds' points on 229 * the complex cell, `ids' are the global ids over the mesh of those points. 230 * The sub-tetra is also defined by the ids of its edges and of its faces 231 * relative to the complex cell. -1 means that the edge or the face of the 232 * sub-tetra is not an original edge or face of the complex cell. 233 * \pre cell_exists: this->GenericCell!=0 234 * \pre localIds_exists: localIds!=0 235 * \pre localIds_size: sizeof(localIds)==4 236 * \pre ids_exists: ids!=0 237 * \pre ids_size: sizeof(ids)==4 238 * \pre edgeIds_exists: edgeIds!=0 239 * \pre edgeIds_size: sizeof(edgeIds)==6 240 * \pre faceIds_exists: faceIds!=0 241 * \pre faceIds_size: sizeof(faceIds)==4 242 */ 243 void InitTetraTile(vtkTetraTile &root, 244 vtkIdType *localIds, 245 vtkIdType *ids, 246 int *edgeIds, 247 int *faceIds); 248 249 /** 250 * Triangulate a triangle of `cell'. This triangle can be the top-level 251 * triangle if the cell is a triangle or a toplevel sub-triangle is the cell 252 * is a polygon, or a triangular face of a 3D cell or a top-level 253 * sub-triangle of a face of a 3D cell if the face is not a triangle. 254 * Arguments `localIds', `ids' and `edgeIds' have the same meaning than 255 * for InitTetraTile. 256 * \pre cell_exists: cell!=0 257 * \pre localIds_exists: localIds!=0 258 * \pre localIds_size: sizeof(localIds)==3 259 * \pre ids_exists: ids!=0 260 * \pre ids_size: sizeof(ids)==3 261 * \pre edgeIds_exists: edgeIds!=0 262 * \pre edgeIds_size: sizeof(edgeIds)==3 263 */ 264 void TriangulateTriangle(vtkGenericAdaptorCell *cell, 265 vtkIdType *localIds, 266 vtkIdType *ids, 267 int *edgeIds, 268 vtkGenericAttributeCollection *att, 269 vtkDoubleArray *points, 270 vtkCellArray *cellArray, 271 vtkPointData *internalPd); 272 273 /** 274 * To access the higher order cell from third party library 275 */ 276 vtkGenericAdaptorCell *GenericCell; 277 278 /** 279 * Allocate some memory if Scalars does not exists or is smaller than size. 280 * \pre positive_size: size>0 281 */ 282 void AllocateScalars(int size); 283 284 /** 285 * Scalar buffer used to save the interpolate values of the attributes 286 * The capacity is at least the number of components of the attribute 287 * collection ot the current cell. 288 */ 289 290 // Scalar buffer that stores the global coordinates, parametric coordinates, 291 // attributes at left, mid and right point. The format is: 292 // lxlylz lrlslt [lalb lcldle...] mxmymz mrmsmt [mamb mcmdme...] 293 // rxryrz rrrsrt [rarb rcrdre...] 294 // The ScalarsCapacity>=(6+attributeCollection->GetNumberOfComponents())*3 295 296 double *Scalars; 297 int ScalarsCapacity; 298 299 /** 300 * Number of double value to skip to go to the next point into Scalars array 301 * It is 6+attributeCollection->GetNumberOfComponents() 302 */ 303 int PointOffset; 304 305 /** 306 * Used to iterate over edges boundaries in GetNumberOfCellsUsingEdges() 307 */ 308 vtkGenericCellIterator *CellIterator; 309 310 /** 311 * To access the higher order field from third party library 312 */ 313 vtkGenericAttributeCollection *AttributeCollection; 314 315 //@{ 316 /** 317 * To avoid New/Delete 318 */ 319 vtkDoubleArray *TessellatePoints; //Allow to use GetPointer 320 vtkCellArray *TessellateCellArray; 321 vtkPointData *TessellatePointData; 322 //@} 323 324 int FindEdgeReferenceCount(double p1[3], double p2[3], 325 vtkIdType &e1, vtkIdType &e2); 326 327 int GetNumberOfCellsUsingFace( int faceId ); 328 int GetNumberOfCellsUsingEdge( int edgeId ); 329 330 /** 331 * Is the edge defined by vertices (`p1',`p2') in parametric coordinates on 332 * some edge of the original tetrahedron? If yes return on which edge it is, 333 * else return -1. 334 * \pre p1!=p2 335 * \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) 336 * \post valid_result: (result==-1) || ( result>=0 && result<=5 ) 337 */ 338 int IsEdgeOnFace(double p1[3], double p2[3]); 339 340 /** 341 * Return 1 if the parent of edge defined by vertices (`p1',`p2') in 342 * parametric coordinates, is an edge; 3 if there is no parent (the edge is 343 * inside). If the parent is an edge, return its id in `localId'. 344 * \pre p1!=p2 345 * \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) 346 * \post valid_result: (result==1)||(result==3) 347 */ 348 int FindEdgeParent2D(double p1[3], double p2[3], int &localId); 349 350 /** 351 * Return 1 if the parent of edge defined by vertices (`p1',`p2') in 352 * parametric coordinates, is an edge; 2 if the parent is a face, 3 if there 353 * is no parent (the edge is inside). If the parent is an edge or a face, 354 * return its id in `localId'. 355 * \pre p1!=p2 356 * \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) 357 * \post valid_result: result>=1 && result<=3 358 */ 359 int FindEdgeParent(double p1[3], double p2[3], int &localId); 360 361 /** 362 * Allocate some memory if PointIds does not exist or is smaller than size. 363 * \pre positive_size: size>0 364 */ 365 void AllocatePointIds(int size); 366 367 /** 368 * Are the faces `originalFace' and `face' equal? 369 * The result is independent from any order or orientation. 370 * \pre originalFace_exists: originalFace!=0 371 */ 372 int FacesAreEqual(int *originalFace, 373 int face[3]); 374 375 /** 376 * Number of points in the dataset to be tessellated. 377 */ 378 vtkIdType NumberOfPoints; 379 380 int FixedSubdivisions; 381 int MaxSubdivisionLevel; 382 int CurrentSubdivisionLevel; 383 384 /** 385 * For each edge (6) of the sub-tetra, there is the id of the original edge 386 * or -1 if the edge is not an original edge 387 */ 388 int *EdgeIds; 389 /** 390 * For each face (4) of the sub-tetra, there is the id of the original face 391 * or -1 if the face is not an original face 392 */ 393 int *FaceIds; 394 395 // The following variables are for complex cells. 396 397 // Used to create tetra from more complex cells, because the tessellator 398 // is supposed to deal with simplices only. 399 vtkOrderedTriangulator *Triangulator; 400 401 // Used to store the sub-tetra during the tessellation of complex 402 // cells. 403 vtkCellArray *Connectivity; 404 405 // Used to create triangles from a face of a complex cell. 406 vtkPolygon *Polygon; 407 408 // Used to store the sub-triangles during the tessellation of complex cells. 409 vtkIdList *TriangleIds; 410 411 vtkIdType *PointIds; 412 int PointIdsCapacity; 413 414 private: 415 vtkSimpleCellTessellator(const vtkSimpleCellTessellator&) = delete; 416 void operator=(const vtkSimpleCellTessellator&) = delete; 417 418 friend class vtkTetraTile; 419 friend class vtkTriangleTile; 420 421 }; 422 423 #endif 424