/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkSimpleCellTessellator.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkSimpleCellTessellator - helper class to perform cell tessellation // .SECTION Description // vtkSimpleCellTessellator is a helper class to perform adaptive tessellation // of particular cell topologies. The major purpose for this class is to // transform higher-order cell types (e.g., higher-order finite elements) // into linear cells that can then be easily visualized by VTK. This class // works in conjunction with the vtkGenericDataSet and vtkGenericAdaptorCell // classes. // // This algorithm is based on edge subdivision. An error metric along each // edge is evaluated, and if the error is greater than some tolerance, the // edge is subdivided (as well as all connected 2D and 3D cells). The process // repeats until the error metric is satisfied. Since the algorithm is based // on edge subdivision it inherently avoid T-junctions. // // A significant issue addressed by this algorithm is to insure face // compatibility across neigboring cells. That is, diagonals due to face // triangulation must match to insure that the mesh is compatible. The // algorithm employs a precomputed table to accelerate the tessellation // process. The table was generated with the help of vtkOrderedTriangulator // the basic idea is that the choice of diagonal is made only by considering the // relative value of the point ids. // // .SECTION See Also // vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric vtkAttributesErrorMetric // vtkGeometricErrorMetric vtkViewDependentErrorMetric #ifndef __vtkSimpleCellTessellator_h #define __vtkSimpleCellTessellator_h #include "vtkGenericCellTessellator.h" class vtkTriangleTile; class vtkTetraTile; class vtkCellArray; class vtkDoubleArray; class vtkGenericEdgeTable; class vtkGenericSubdivisionErrorMetric; class vtkGenericAttributeCollection; class vtkGenericAdaptorCell; class vtkGenericCellIterator; class vtkPointData; class vtkOrderedTriangulator; class vtkPolygon; class vtkIdList; //----------------------------------------------------------------------------- // // The tessellation object class VTK_FILTERING_EXPORT vtkSimpleCellTessellator : public vtkGenericCellTessellator { public: static vtkSimpleCellTessellator *New(); vtkTypeRevisionMacro(vtkSimpleCellTessellator,vtkGenericCellTessellator); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the higher order cell in order to access the evaluation function. vtkGetObjectMacro(GenericCell, vtkGenericAdaptorCell); // Description: // Tessellate a face of a 3D `cell'. The face is specified by the // index value. // The result is a set of smaller linear triangles in `cellArray' with // `points' and point data `internalPd'. // \pre cell_exists: cell!=0 // \pre valid_dimension: cell->GetDimension()==3 // \pre valid_index_range: (index>=0) && (indexGetNumberOfBoundaries(2)) // \pre att_exists: att!=0 // \pre points_exists: points!=0 // \pre cellArray_exists: cellArray!=0 // \pre internalPd_exists: internalPd!=0 void TessellateFace(vtkGenericAdaptorCell *cell, vtkGenericAttributeCollection *att, vtkIdType index, vtkDoubleArray *points, vtkCellArray *cellArray, vtkPointData *internalPd); // Description: // Tessellate a 3D `cell'. The result is a set of smaller linear // tetrahedra in `cellArray' with `points' and point data `internalPd'. // \pre cell_exists: cell!=0 // \pre valid_dimension: cell->GetDimension()==3 // \pre att_exists: att!=0 // \pre points_exists: points!=0 // \pre cellArray_exists: cellArray!=0 // \pre internalPd_exists: internalPd!=0 void Tessellate(vtkGenericAdaptorCell *cell, vtkGenericAttributeCollection *att, vtkDoubleArray *points, vtkCellArray *cellArray, vtkPointData *internalPd ); // Description: // Triangulate a 2D `cell'. The result is a set of smaller linear triangles // in `cellArray' with `points' and point data `internalPd'. // \pre cell_exists: cell!=0 // \pre valid_dimension: cell->GetDimension()==2 // \pre att_exists: att!=0 // \pre points_exists: points!=0 // \pre cellArray_exists: cellArray!=0 // \pre internalPd_exists: internalPd!=0 void Triangulate(vtkGenericAdaptorCell *cell, vtkGenericAttributeCollection *att, vtkDoubleArray *points, vtkCellArray *cellArray, vtkPointData *internalPd); // Description: // Reset the output for repeated use of this class. void Reset(); // Description: // Initialize the tessellator with a data set `ds'. void Initialize(vtkGenericDataSet *ds); // Description: // Return the number of fixed subdivisions. It is used to prevent from // infinite loop in degenerated cases. For order 3 or higher, if the // inflection point is exactly on the mid-point, error metric will not // detect that a subdivision is required. 0 means no fixed subdivision: // there will be only adaptive subdivisions. // // The algorithm first performs `GetFixedSubdivisions' non adaptive // subdivisions followed by at most `GetMaxAdaptiveSubdivisions' adaptive // subdivisions. Hence, there are at most `GetMaxSubdivisionLevel' // subdivisions. // \post positive_result: result>=0 && result<=GetMaxSubdivisionLevel() int GetFixedSubdivisions(); // Description: // Return the maximum level of subdivision. It is used to prevent from // infinite loop in degenerated cases. For order 3 or higher, if the // inflection point is exactly on the mid-point, error metric will not // detect that a subdivision is required. 0 means no subdivision, // neither fixed nor adaptive. // \post positive_result: result>=GetFixedSubdivisions() int GetMaxSubdivisionLevel(); // Description: // Return the maximum number of adaptive subdivisions. // \post valid_result: result==GetMaxSubdivisionLevel()-GetFixedSubdivisions() int GetMaxAdaptiveSubdivisions(); // Description: // Set the number of fixed subdivisions. See GetFixedSubdivisions() for // more explanations. // \pre positive_level: level>=0 && level<=GetMaxSubdivisionLevel() // \post is_set: GetFixedSubdivisions()==level void SetFixedSubdivisions(int level); // Description: // Set the maximum level of subdivision. See GetMaxSubdivisionLevel() for // more explanations. // \pre positive_level: level>=GetFixedSubdivisions() // \post is_set: level==GetMaxSubdivisionLevel() void SetMaxSubdivisionLevel(int level); // Description: // Set both the number of fixed subdivisions and the maximum level of // subdivisions. See GetFixedSubdivisions(), GetMaxSubdivisionLevel() and // GetMaxAdaptiveSubdivisions() for more explanations. // \pre positive_fixed: fixed>=0 // \pre valid_range: fixed<=maxLevel // \post fixed_is_set: fixed==GetFixedSubdivisions() // \post maxLevel_is_set: maxLevel==GetMaxSubdivisionLevel() void SetSubdivisionLevels(int fixed, int maxLevel); protected: vtkSimpleCellTessellator(); ~vtkSimpleCellTessellator(); // Description: // Extract point `pointId' from the edge table to the output point and output // point data. void CopyPoint(vtkIdType pointId); // Description: //HashTable instead of vtkPointLocator vtkGenericEdgeTable *EdgeTable; void InsertEdgesIntoEdgeTable( vtkTriangleTile &tri ); void RemoveEdgesFromEdgeTable( vtkTriangleTile &tri ); void InsertPointsIntoEdgeTable( vtkTriangleTile &tri ); void InsertEdgesIntoEdgeTable( vtkTetraTile &tetra ); void RemoveEdgesFromEdgeTable( vtkTetraTile &tetra ); // Description: // Initialize `root' with the sub-tetra defined by the `localIds' points on // the complex cell, `ids' are the global ids over the mesh of those points. // The sub-tetra is also defined by the ids of its edges and of its faces // relative to the complex cell. -1 means that the edge or the face of the // sub-tetra is not an original edge or face of the complex cell. // \pre cell_exists: this->GenericCell!=0 // \pre localIds_exists: localIds!=0 // \pre localIds_size: sizeof(localIds)==4 // \pre ids_exists: ids!=0 // \pre ids_size: sizeof(ids)==4 // \pre edgeIds_exists: edgeIds!=0 // \pre edgeIds_size: sizeof(edgeIds)==6 // \pre faceIds_exists: faceIds!=0 // \pre faceIds_size: sizeof(faceIds)==4 void InitTetraTile(vtkTetraTile &root, vtkIdType *localIds, vtkIdType *ids, int *edgeIds, int *faceIds); // Description: // Triangulate a triangle of `cell'. This triangle can be the top-level // triangle if the cell is a triangle or a toplevel sub-triangle is the cell // is a polygon, or a triangular face of a 3D cell or a top-level // sub-triangle of a face of a 3D cell if the face is not a triangle. // Arguments `localIds', `ids' and `edgeIds' have the same meaning than // for InitTetraTile. // \pre cell_exists: cell!=0 // \pre localIds_exists: localIds!=0 // \pre localIds_size: sizeof(localIds)==3 // \pre ids_exists: ids!=0 // \pre ids_size: sizeof(ids)==3 // \pre edgeIds_exists: edgeIds!=0 // \pre edgeIds_size: sizeof(edgeIds)==3 void TriangulateTriangle(vtkGenericAdaptorCell *cell, vtkIdType *localIds, vtkIdType *ids, int *edgeIds, vtkGenericAttributeCollection *att, vtkDoubleArray *points, vtkCellArray *cellArray, vtkPointData *internalPd); // Description: // To access the higher order cell from third party library vtkGenericAdaptorCell *GenericCell; // Description: // Allocate some memory if Scalars does not exists or is smaller than size. // \pre positive_size: size>0 void AllocateScalars(int size); // Description: // Scalar buffer used to save the interpolate values of the attributes // The capacity is at least the number of components of the attribute // collection ot the current cell. // Scalar buffer that stores the global coordinates, parametric coordinates, // attributes at left, mid and right point. The format is: // lxlylz lrlslt [lalb lcldle...] mxmymz mrmsmt [mamb mcmdme...] // rxryrz rrrsrt [rarb rcrdre...] // The ScalarsCapacity>=(6+attributeCollection->GetNumberOfComponents())*3 double *Scalars; int ScalarsCapacity; // Description: // Number of double value to skip to go to the next point into Scalars array // It is 6+attributeCollection->GetNumberOfComponents() int PointOffset; // Description: // Used to iterate over edges boundaries in GetNumberOfCellsUsingEdges() vtkGenericCellIterator *CellIterator; // Description: // To access the higher order field from third party library vtkGenericAttributeCollection *AttributeCollection; // Description: // To avoid New/Delete vtkDoubleArray *TessellatePoints; //Allow to use GetPointer vtkCellArray *TessellateCellArray; vtkPointData *TessellatePointData; int FindEdgeReferenceCount(double p1[3], double p2[3], vtkIdType &e1, vtkIdType &e2); int GetNumberOfCellsUsingFace( int faceId ); int GetNumberOfCellsUsingEdge( int edgeId ); // Description: // Is the edge defined by vertices (`p1',`p2') in parametric coordinates on // some edge of the original tetrahedron? If yes return on which edge it is, // else return -1. // \pre p1!=p2 // \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) // \post valid_result: (result==-1) || ( result>=0 && result<=5 ) int IsEdgeOnFace(double p1[3], double p2[3]); // Description: // Return 1 if the parent of edge defined by vertices (`p1',`p2') in // parametric coordinates, is an edge; 3 if there is no parent (the edge is // inside). If the parent is an edge, return its id in `localId'. // \pre p1!=p2 // \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) // \post valid_result: (result==1)||(result==3) int FindEdgeParent2D(double p1[3], double p2[3], int &localId); // Description: // Return 1 if the parent of edge defined by vertices (`p1',`p2') in // parametric coordinates, is an edge; 2 if the parent is a face, 3 if there // is no parent (the edge is inside). If the parent is an edge or a face, // return its id in `localId'. // \pre p1!=p2 // \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) // \post valid_result: result>=1 && result<=3 int FindEdgeParent(double p1[3], double p2[3], int &localId); // Description: // Allocate some memory if PointIds does not exist or is smaller than size. // \pre positive_size: size>0 void AllocatePointIds(int size); // Description: // Are the faces `originalFace' and `face' equal? // The result is independent from any order or orientation. // \pre originalFace_exists: originalFace!=0 int FacesAreEqual(int *originalFace, int face[3]); // Description: // Dataset to be tessellated. vtkGenericDataSet *DataSet; // Description: // Number of points in the dataset to be tessellated. vtkIdType NumberOfPoints; int FixedSubdivisions; int MaxSubdivisionLevel; int CurrentSubdivisionLevel; // Description: // For each edge (6) of the sub-tetra, there is the id of the original edge // or -1 if the edge is not an original edge int *EdgeIds; // Description: // For each face (4) of the sub-tetra, there is the id of the original face // or -1 if the face is not an original face int *FaceIds; // The following variables are for complex cells. // Used to create tetra from more complex cells, because the tessellator // is supposed to deal with simplices only. vtkOrderedTriangulator *Triangulator; // Used to store the sub-tetra during the tessellation of complex // cells. vtkCellArray *Connectivity; // Used to create triangles from a face of a complex cell. vtkPolygon *Polygon; // Used to store the sub-triangles during the tessellation of complex cells. vtkIdList *TriangleIds; vtkIdType *PointIds; int PointIdsCapacity; private: vtkSimpleCellTessellator(const vtkSimpleCellTessellator&); // Not implemented. void operator=(const vtkSimpleCellTessellator&); // Not implemented. //BTX friend class vtkTetraTile; friend class vtkTriangleTile; //ETX }; #endif