1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkGenericCellTessellator.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 // .NAME vtkGenericCellTessellator - helper class to perform cell tessellation
16 // .SECTION Description
17 // vtkGenericCellTessellator is a helper class to perform adaptive tessellation
18 // of particular cell topologies. The major purpose for this class is to
19 // transform higher-order cell types (e.g., higher-order finite elements)
20 // into linear cells that can then be easily visualized by VTK. This class
21 // works in conjunction with the vtkGenericDataSet and vtkGenericAdaptorCell
22 // classes.
23 //
24 // This algorithm is based on edge subdivision. An error metric along each
25 // edge is evaluated, and if the error is greater than some tolerance, the
26 // edge is subdivided (as well as all connected 2D and 3D cells). The process
27 // repeats until the error metric is satisfied.
28 //
29 // A significant issue addressed by this algorithm is to insure face
30 // compatibility across neigboring cells. That is, diagonals due to face
31 // triangulation must match to insure that the mesh is compatible. The
32 // algorithm employs a precomputed table to accelerate the tessellation
33 // process. The table was generated with the help of vtkOrderedTriangulator;
34 // the basic idea is that the choice of diagonal is made by considering the
35 // relative value of the point ids.
36 
37 
38 #ifndef vtkGenericCellTessellator_h
39 #define vtkGenericCellTessellator_h
40 
41 #include "vtkCommonDataModelModule.h" // For export macro
42 #include "vtkObject.h"
43 
44 class vtkCellArray;
45 class vtkDoubleArray;
46 class vtkCollection;
47 class vtkGenericAttributeCollection;
48 class vtkGenericAdaptorCell;
49 class vtkGenericCellIterator;
50 class vtkPointData;
51 class vtkGenericDataSet;
52 
53 //-----------------------------------------------------------------------------
54 //
55 // The tessellation object
56 class VTKCOMMONDATAMODEL_EXPORT vtkGenericCellTessellator : public vtkObject
57 {
58 public:
59   vtkTypeMacro(vtkGenericCellTessellator,vtkObject);
60   void PrintSelf(ostream& os, vtkIndent indent);
61 
62   // Description:
63   // Tessellate a face of a 3D `cell'. The face is specified by the
64   // index value.
65   // The result is a set of smaller linear triangles in `cellArray' with
66   // `points' and point data `internalPd'.
67   // \pre cell_exists: cell!=0
68   // \pre valid_dimension: cell->GetDimension()==3
69   // \pre valid_index_range: (index>=0) && (index<cell->GetNumberOfBoundaries(2))
70   // \pre att_exists: att!=0
71   // \pre points_exists: points!=0
72   // \pre cellArray_exists: cellArray!=0
73   // \pre internalPd_exists: internalPd!=0
74   virtual void TessellateFace(vtkGenericAdaptorCell *cell,
75                               vtkGenericAttributeCollection *att,
76                               vtkIdType index,
77                               vtkDoubleArray *points,
78                               vtkCellArray *cellArray,
79                               vtkPointData *internalPd)=0;
80 
81   // Description:
82   // Tessellate a 3D `cell'. The result is a set of smaller linear
83   // tetrahedra in `cellArray' with `points' and point data `internalPd'.
84   // \pre cell_exists: cell!=0
85   // \pre valid_dimension: cell->GetDimension()==3
86   // \pre att_exists: att!=0
87   // \pre points_exists: points!=0
88   // \pre cellArray_exists: cellArray!=0
89   // \pre internalPd_exists: internalPd!=0
90   virtual void Tessellate(vtkGenericAdaptorCell *cell,
91                           vtkGenericAttributeCollection *att,
92                           vtkDoubleArray *points,
93                           vtkCellArray *cellArray,
94                           vtkPointData *internalPd )=0;
95 
96   // Description:
97   // Triangulate a 2D `cell'. The result is a set of smaller linear triangles
98   // in `cellArray' with `points' and point data `internalPd'.
99   // \pre cell_exists: cell!=0
100   // \pre valid_dimension: cell->GetDimension()==2
101   // \pre att_exists: att!=0
102   // \pre points_exists: points!=0
103   // \pre cellArray_exists: cellArray!=0
104   // \pre internalPd_exists: internalPd!=0
105   virtual void Triangulate(vtkGenericAdaptorCell *cell,
106                            vtkGenericAttributeCollection *att,
107                            vtkDoubleArray *points,
108                            vtkCellArray *cellArray,
109                            vtkPointData *internalPd)=0;
110 
111   // Description:
112   // Specify the list of error metrics used to decide if an edge has to be
113   // splitted or not. It is a collection of vtkGenericSubdivisionErrorMetric-s.
114   virtual void SetErrorMetrics(vtkCollection *someErrorMetrics);
115   vtkGetObjectMacro(ErrorMetrics,vtkCollection);
116 
117   // Description:
118   // Initialize the tessellator with a data set `ds'.
119   virtual void Initialize(vtkGenericDataSet *ds)=0;
120 
121   // Description:
122   // Init the error metric with the dataset. Should be called in each filter
123   // before any tessellation of any cell.
124   void InitErrorMetrics(vtkGenericDataSet *ds);
125 
126   // Description:
127   // If true, measure the quality of the fixed subdivision.
128   vtkGetMacro(Measurement,int);
129   vtkSetMacro(Measurement,int);
130 
131   // Description:
132   // Get the maximum error measured after the fixed subdivision.
133   // \pre errors_exists: errors!=0
134   // \pre valid_size: sizeof(errors)==GetErrorMetrics()->GetNumberOfItems()
135   void GetMaxErrors(double *errors);
136 
137 protected:
138   vtkGenericCellTessellator();
139   ~vtkGenericCellTessellator();
140 
141   // Description:
142   // Does the edge need to be subdivided according to at least one error
143   // metric? The edge is defined by its `leftPoint' and its `rightPoint'.
144   // `leftPoint', `midPoint' and `rightPoint' have to be initialized before
145   // calling RequiresEdgeSubdivision().
146   // Their format is global coordinates, parametric coordinates and
147   // point centered attributes: xyx rst abc de...
148   // `alpha' is the normalized abscissa of the midpoint along the edge.
149   // (close to 0 means close to the left point, close to 1 means close to the
150   // right point)
151   // \pre leftPoint_exists: leftPoint!=0
152   // \pre midPoint_exists: midPoint!=0
153   // \pre rightPoint_exists: rightPoint!=0
154   // \pre clamped_alpha: alpha>0 && alpha<1
155   // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint)
156   //          =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6
157   int RequiresEdgeSubdivision(double *left, double *mid, double *right,
158                               double alpha);
159 
160 
161   // Description:
162   // Update the max error of each error metric according to the error at the
163   // mid-point. The type of error depends on the state
164   // of the concrete error metric. For instance, it can return an absolute
165   // or relative error metric.
166   // See RequiresEdgeSubdivision() for a description of the arguments.
167   // \pre leftPoint_exists: leftPoint!=0
168   // \pre midPoint_exists: midPoint!=0
169   // \pre rightPoint_exists: rightPoint!=0
170   // \pre clamped_alpha: alpha>0 && alpha<1
171   // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint)
172   //          =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6
173   virtual void UpdateMaxError(double *leftPoint, double *midPoint,
174                               double *rightPoint, double alpha);
175 
176   // Description:
177   // Reset the maximal error of each error metric. The purpose of the maximal
178   // error is to measure the quality of a fixed subdivision.
179   void ResetMaxErrors();
180 
181   // Description:
182   // List of error metrics. Collection of vtkGenericSubdivisionErrorMetric
183   vtkCollection *ErrorMetrics;
184 
185   // Description:
186   // Send the current cell to error metrics. Should be called at the beginning
187   // of the implementation of Tessellate(), Triangulate()
188   // or TessellateFace()
189   // \pre cell_exists: cell!=0
190   void SetGenericCell(vtkGenericAdaptorCell *cell);
191 
192   vtkGenericDataSet *DataSet;
193 
194   int Measurement; // if true, measure the quality of the fixed subdivision.
195   double *MaxErrors; // max error for each error metric, for measuring the
196   // quality of a fixed subdivision.
197   int MaxErrorsCapacity;
198 
199 private:
200   vtkGenericCellTessellator(const vtkGenericCellTessellator&);  // Not implemented.
201   void operator=(const vtkGenericCellTessellator&);  // Not implemented.
202 };
203 
204 #endif
205