1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkGenericCellTessellator.cxx
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 #include "vtkGenericCellTessellator.h"
16 #include "vtkObjectFactory.h"
17
18 #include "vtkPoints.h"
19 #include "vtkIdList.h"
20 #include "vtkGenericAdaptorCell.h"
21 #include "vtkPointData.h"
22 #include "vtkDoubleArray.h"
23 #include "vtkMergePoints.h"
24 #include "vtkCellArray.h"
25 #include "vtkCollection.h"
26 #include "vtkGenericSubdivisionErrorMetric.h"
27 #include "vtkGenericAttribute.h"
28 #include "vtkGenericAttributeCollection.h"
29 #include "vtkGenericCellIterator.h"
30
31
32 #include <cassert>
33
34 #include "vtkMath.h"
35
36 vtkCxxSetObjectMacro(vtkGenericCellTessellator, ErrorMetrics, vtkCollection);
37
38 //-----------------------------------------------------------------------------
39 // Create the tessellator helper with a default of 0.25 for threshold
vtkGenericCellTessellator()40 vtkGenericCellTessellator::vtkGenericCellTessellator()
41 {
42 this->ErrorMetrics = vtkCollection::New();
43 this->MaxErrorsCapacity = 0;
44 this->MaxErrors = 0;
45 this->Measurement = 0;
46 }
47
48 //-----------------------------------------------------------------------------
~vtkGenericCellTessellator()49 vtkGenericCellTessellator::~vtkGenericCellTessellator()
50 {
51 this->SetErrorMetrics( 0 );
52 delete[] this->MaxErrors;
53 }
54
55
56 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)57 void vtkGenericCellTessellator::PrintSelf(ostream& os, vtkIndent indent)
58 {
59 this->Superclass::PrintSelf(os,indent);
60
61 os << indent << "Measurement: " << this->Measurement << endl;
62 os << indent << "ErrorMetrics: " << this->ErrorMetrics << endl;
63 /* this->MaxErrorsCapacity */
64 /* this->MaxErrors */
65 }
66
67 //-----------------------------------------------------------------------------
68 // Description:
69 // Does the edge need to be subdivided according to at least one error
70 // metric? The edge is defined by its `leftPoint' and its `rightPoint'.
71 // `leftPoint', `midPoint' and `rightPoint' have to be initialized before
72 // calling RequiresEdgeSubdivision().
73 // Their format is global coordinates, parametric coordinates and
74 // point centered attributes: xyx rst abc de...
75 // `alpha' is the normalized abscissa of the midpoint along the edge.
76 // (close to 0 means close to the left point, close to 1 means close to the
77 // right point)
78 // \pre leftPoint_exists: leftPoint!=0
79 // \pre midPoint_exists: midPoint!=0
80 // \pre rightPoint_exists: rightPoint!=0
81 // \pre clamped_alpha: alpha>0 && alpha<1
82 // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint)
83 // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6
RequiresEdgeSubdivision(double * leftPoint,double * midPoint,double * rightPoint,double alpha)84 int vtkGenericCellTessellator::RequiresEdgeSubdivision(double *leftPoint,
85 double *midPoint,
86 double *rightPoint,
87 double alpha)
88 {
89 assert("pre: leftPoint_exists" && leftPoint!=0);
90 assert("pre: midPoint_exists" && midPoint!=0);
91 assert("pre: rightPoint_exists" && rightPoint!=0);
92 assert("pre: clamped_alpha" && alpha>0 && alpha<1);
93
94 int result = 0;
95 this->ErrorMetrics->InitTraversal();
96 vtkGenericSubdivisionErrorMetric *e =
97 static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
98
99 // Once we found at least one error metric that need subdivision,
100 // the subdivision has to be done and there is no need to check for other
101 // error metrics.
102 while(!result && e != 0 )
103 {
104 result = e->RequiresEdgeSubdivision(leftPoint,midPoint,rightPoint,alpha);
105 e = static_cast<vtkGenericSubdivisionErrorMetric *>
106 (this->ErrorMetrics->GetNextItemAsObject());
107 }
108
109 return result;
110 }
111
112 //-----------------------------------------------------------------------------
113 // Description:
114 // Update the max error of each error metric according to the error at the
115 // mid-point. The type of error depends on the state
116 // of the concrete error metric. For instance, it can return an absolute
117 // or relative error metric.
118 // See RequiresEdgeSubdivision() for a description of the arguments.
119 // \pre leftPoint_exists: leftPoint!=0
120 // \pre midPoint_exists: midPoint!=0
121 // \pre rightPoint_exists: rightPoint!=0
122 // \pre clamped_alpha: alpha>0 && alpha<1
123 // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint)
124 // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6
UpdateMaxError(double * leftPoint,double * midPoint,double * rightPoint,double alpha)125 void vtkGenericCellTessellator::UpdateMaxError(double *leftPoint,
126 double *midPoint,
127 double *rightPoint,
128 double alpha)
129 {
130 assert("pre: leftPoint_exists" && leftPoint!=0);
131 assert("pre: midPoint_exists" && midPoint!=0);
132 assert("pre: rightPoint_exists" && rightPoint!=0);
133 assert("pre: clamped_alpha" && alpha>0 && alpha<1);
134
135 this->ErrorMetrics->InitTraversal();
136 vtkGenericSubdivisionErrorMetric *e =
137 static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
138
139 // Once we found at least one error metric that need subdivision,
140 // the subdivision has to be done and there is no need to check for other
141 // error metrics.
142 for(int i = 0; e!=0; ++i)
143 {
144 double error = e->GetError(leftPoint,midPoint,rightPoint,alpha);
145 assert("check: positive_error" && error>=0);
146 if(error > this->MaxErrors[i])
147 {
148 this->MaxErrors[i] = error;
149 }
150 e = static_cast<vtkGenericSubdivisionErrorMetric *>
151 (this->ErrorMetrics->GetNextItemAsObject());
152 }
153 }
154
155 //-----------------------------------------------------------------------------
156 // Description:
157 // Init the error metric with the dataset. Should be called in each filter
158 // before any tessellation of any cell.
InitErrorMetrics(vtkGenericDataSet * ds)159 void vtkGenericCellTessellator::InitErrorMetrics(vtkGenericDataSet *ds)
160 {
161 this->Initialize(ds);
162 this->ErrorMetrics->InitTraversal();
163 vtkGenericSubdivisionErrorMetric *e =
164 static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
165
166 while(e!=0)
167 {
168 e->SetDataSet(ds);
169 e = static_cast<vtkGenericSubdivisionErrorMetric *>
170 (this->ErrorMetrics->GetNextItemAsObject());
171 }
172
173 if(this->Measurement)
174 {
175 this->ResetMaxErrors();
176 }
177 }
178
179 //-----------------------------------------------------------------------------
180 // Description:
181 // Reset the maximal error of each error metric. The purpose of the maximal
182 // error is to measure the quality of a fixed subdivision.
ResetMaxErrors()183 void vtkGenericCellTessellator::ResetMaxErrors()
184 {
185 int c = this->ErrorMetrics->GetNumberOfItems();
186
187 // Allocate the array.
188 if(c>this->MaxErrorsCapacity)
189 {
190 this->MaxErrorsCapacity = c;
191 delete [] this->MaxErrors;
192 this->MaxErrors = new double[this->MaxErrorsCapacity];
193 }
194
195 for(int i = 0; i<c; ++i)
196 {
197 this->MaxErrors[i] = 0;
198 }
199 }
200
201 //-----------------------------------------------------------------------------
202 // Description:
203 // Get the maximum error measured after the fixed subdivision.
204 // \pre errors_exists: errors!=0
205 // \pre valid_size: sizeof(errors)==GetErrorMetrics()->GetNumberOfItems()
GetMaxErrors(double * errors)206 void vtkGenericCellTessellator::GetMaxErrors(double *errors)
207 {
208 assert("pre: errors_exists" && errors!=0);
209
210 int c = this->ErrorMetrics->GetNumberOfItems();
211 for(int i = 0; i<c; ++i)
212 {
213 errors[i] = this->MaxErrors[i];
214 }
215 }
216
217 //-----------------------------------------------------------------------------
218 // Description:
219 // Send the current cell to error metrics. Should be called at the beginning
220 // of the implementation of Tessellate(), Triangulate()
221 // or TessellateFace()
222 // \pre cell_exists: cell!=0
SetGenericCell(vtkGenericAdaptorCell * cell)223 void vtkGenericCellTessellator::SetGenericCell(vtkGenericAdaptorCell *cell)
224 {
225 assert("pre: cell_exists" && cell!=0);
226
227 this->ErrorMetrics->InitTraversal();
228 vtkGenericSubdivisionErrorMetric *e=static_cast<vtkGenericSubdivisionErrorMetric *>(this->ErrorMetrics->GetNextItemAsObject());
229
230 while(e!=0)
231 {
232 e->SetGenericCell(cell);
233 e = static_cast<vtkGenericSubdivisionErrorMetric *>
234 (this->ErrorMetrics->GetNextItemAsObject());
235 }
236 }
237