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