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