1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkAttributesErrorMetric.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 "vtkAttributesErrorMetric.h"
16
17 #include "vtkGenericAdaptorCell.h"
18 #include "vtkGenericAttribute.h"
19 #include "vtkGenericAttributeCollection.h"
20 #include "vtkGenericDataSet.h"
21 #include "vtkObjectFactory.h"
22 #include <cassert>
23 #include <cmath>
24
25 vtkStandardNewMacro(vtkAttributesErrorMetric);
26
27 //------------------------------------------------------------------------------
vtkAttributesErrorMetric()28 vtkAttributesErrorMetric::vtkAttributesErrorMetric()
29 {
30 this->AttributeTolerance = 0.1; // arbitrary
31 this->AbsoluteAttributeTolerance = 0.1; // arbitrary
32 this->SquareAbsoluteAttributeTolerance =
33 this->AbsoluteAttributeTolerance * this->AbsoluteAttributeTolerance;
34 this->Range = 0;
35 this->DefinedByAbsolute = 1;
36 }
37
38 //------------------------------------------------------------------------------
39 vtkAttributesErrorMetric::~vtkAttributesErrorMetric() = default;
40
41 //------------------------------------------------------------------------------
42 // Description:
43 // Set the absolute attribute accuracy to `value'. See
44 // GetAbsoluteAttributeTolerance() for details.
45 // \pre valid_range_value: value>0
SetAbsoluteAttributeTolerance(double value)46 void vtkAttributesErrorMetric::SetAbsoluteAttributeTolerance(double value)
47 {
48 assert("pre: valid_range_value" && value > 0);
49 if (this->AbsoluteAttributeTolerance != value || !this->DefinedByAbsolute)
50 {
51 this->AbsoluteAttributeTolerance = value;
52 this->SquareAbsoluteAttributeTolerance =
53 this->AbsoluteAttributeTolerance * this->AbsoluteAttributeTolerance;
54 this->Range = 0;
55 this->DefinedByAbsolute = 1;
56 this->Modified();
57 }
58 }
59
60 //------------------------------------------------------------------------------
61 // Description:
62 // Set the relative attribute accuracy to `value'. See
63 // GetAttributeTolerance() for details.
64 // \pre valid_range_value: value>0 && value<1
SetAttributeTolerance(double value)65 void vtkAttributesErrorMetric::SetAttributeTolerance(double value)
66 {
67 assert("pre: valid_range_value" && value > 0 && value < 1);
68 if (this->AttributeTolerance != value || this->DefinedByAbsolute)
69 {
70 this->AttributeTolerance = value;
71 this->DefinedByAbsolute = 0;
72 this->Modified();
73 }
74 }
75
76 //------------------------------------------------------------------------------
RequiresEdgeSubdivision(double * leftPoint,double * midPoint,double * rightPoint,double alpha)77 int vtkAttributesErrorMetric::RequiresEdgeSubdivision(
78 double* leftPoint, double* midPoint, double* rightPoint, double alpha)
79 {
80 assert("pre: leftPoint_exists" && leftPoint != nullptr);
81 assert("pre: midPoint_exists" && midPoint != nullptr);
82 assert("pre: rightPoint_exists" && rightPoint != nullptr);
83 assert("pre: clamped_alpha" && alpha > 0 && alpha < 1);
84
85 int result;
86 double ae;
87 vtkGenericAttributeCollection* ac;
88
89 this->ComputeSquareAbsoluteAttributeTolerance();
90
91 const int ATTRIBUTE_OFFSET = 6;
92
93 ac = this->DataSet->GetAttributes();
94 vtkGenericAttribute* a = ac->GetAttribute(ac->GetActiveAttribute());
95
96 if (this->GenericCell->IsAttributeLinear(a))
97 {
98 // don't need to do anything:
99 ae = 0;
100 }
101 else
102 {
103 if (ac->GetActiveComponent() >= 0)
104 {
105 int i = ac->GetAttributeIndex(ac->GetActiveAttribute()) + ac->GetActiveComponent() +
106 ATTRIBUTE_OFFSET;
107 double tmp = leftPoint[i] + alpha * (rightPoint[i] - leftPoint[i]) - midPoint[i];
108 ae = tmp * tmp;
109 }
110 else // module of the vector
111 {
112 int i = ac->GetAttributeIndex(ac->GetActiveAttribute()) + ATTRIBUTE_OFFSET;
113 int j = 0;
114 int c = ac->GetNumberOfComponents();
115 double tmp;
116 #if 0
117 // If x and y are two vectors, we compute: ||x|-|y||
118 double interpolatedValueMod=0;
119 double midValueMod=0;
120 while(j<c)
121 {
122 tmp=leftPoint[i+j]+alpha*(rightPoint[i+j]-leftPoint[i+j]);
123 interpolatedValueMod+=tmp*tmp;
124 tmp=midPoint[i+j];
125 midValueMod+=tmp*tmp;
126 ++j;
127 }
128 tmp=sqrt(midValueMod)-sqrt(interpolatedValueMod);
129 ae=tmp*tmp;
130 #else
131 // If x and y are two vectors, we compute: |x-y|
132 // We should compute ||x|-|y|| but |x-y| is usually enough
133 // and tends to produce less degenerated edges.
134 // Remind that: ||x|-|y||<=|x-y|
135 ae = 0;
136 while (j < c)
137 {
138 tmp = leftPoint[i + j] + alpha * (rightPoint[i + j] - leftPoint[i + j]) - midPoint[i + j];
139 ae += tmp * tmp;
140 ++j;
141 }
142 #endif
143 }
144 assert("check: positive_ae" && ae >= 0);
145 }
146
147 if (this->SquareAbsoluteAttributeTolerance == 0)
148 {
149 result = fabs(ae) > 0.0001;
150 }
151 else
152 {
153 result = ae > this->SquareAbsoluteAttributeTolerance;
154 }
155 return result;
156 }
157
158 //------------------------------------------------------------------------------
159 // Description:
160 // Return the error at the mid-point. The type of error depends on the state
161 // of the concrete error metric. For instance, it can return an absolute
162 // or relative error metric.
163 // See RequiresEdgeSubdivision() for a description of the arguments.
164 // \post positive_result: result>=0
GetError(double * leftPoint,double * midPoint,double * rightPoint,double alpha)165 double vtkAttributesErrorMetric::GetError(
166 double* leftPoint, double* midPoint, double* rightPoint, double alpha)
167 {
168 assert("pre: leftPoint_exists" && leftPoint != nullptr);
169 assert("pre: midPoint_exists" && midPoint != nullptr);
170 assert("pre: rightPoint_exists" && rightPoint != nullptr);
171 assert("pre: clamped_alpha" && alpha > 0 && alpha < 1);
172
173 double ae;
174 vtkGenericAttributeCollection* ac;
175
176 this->ComputeSquareAbsoluteAttributeTolerance();
177
178 const int ATTRIBUTE_OFFSET = 6;
179
180 ac = this->DataSet->GetAttributes();
181 vtkGenericAttribute* a = ac->GetAttribute(ac->GetActiveAttribute());
182
183 if (this->GenericCell->IsAttributeLinear(a))
184 {
185 // don't need to do anything:
186 ae = 0;
187 }
188 else
189 {
190 if (ac->GetActiveComponent() >= 0) // one component
191 {
192 int i = ac->GetAttributeIndex(ac->GetActiveAttribute()) + ac->GetActiveComponent() +
193 ATTRIBUTE_OFFSET;
194 double tmp = leftPoint[i] + alpha * (rightPoint[i] - leftPoint[i]) - midPoint[i];
195 ae = tmp * tmp;
196 }
197 else // module of the vector
198 {
199 // If x and y are two vectors, we compute: |x-y|
200 // We should compute ||x|-|y|| but |x-y| is usually enough
201 // and tends to produce less degenerated edges.
202 // Remind that: ||x|-|y||<=|x-y|
203 int i = ac->GetAttributeIndex(ac->GetActiveAttribute()) + ATTRIBUTE_OFFSET;
204 int j = 0;
205 int c = ac->GetNumberOfComponents();
206 double tmp;
207
208 ae = 0;
209 while (j < c)
210 {
211 tmp = leftPoint[i + j] + alpha * (rightPoint[i + j] - leftPoint[i + j]) - midPoint[i + j];
212 ae += tmp * tmp;
213 ++j;
214 }
215 }
216 }
217
218 double result;
219
220 if (this->Range != 0)
221 {
222 result = sqrt(ae) / this->Range;
223 }
224 else
225 {
226 result = 0;
227 }
228
229 assert("post: positive_result" && result >= 0);
230
231 return result;
232 }
233
234 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)235 void vtkAttributesErrorMetric::PrintSelf(ostream& os, vtkIndent indent)
236 {
237 this->Superclass::PrintSelf(os, indent);
238 os << indent << "AttributeTolerance: " << this->AttributeTolerance << endl;
239 os << indent << "AbsoluteAttributeTolerance: " << this->AbsoluteAttributeTolerance << endl;
240 }
241
242 //------------------------------------------------------------------------------
243 // Description:
244 // Compute the absolute attribute tolerance, only if the cached value is
245 // obsolete.
ComputeSquareAbsoluteAttributeTolerance()246 void vtkAttributesErrorMetric::ComputeSquareAbsoluteAttributeTolerance()
247 {
248 if (!this->DefinedByAbsolute)
249 {
250 if (this->GetMTime() > this->SquareAbsoluteAttributeToleranceComputeTime)
251 {
252 vtkGenericAttributeCollection* ac = this->DataSet->GetAttributes();
253 vtkGenericAttribute* a = ac->GetAttribute(ac->GetActiveAttribute());
254
255 int i = ac->GetActiveComponent();
256
257 double r[2];
258
259 a->GetRange(i, r);
260
261 double tmp = (r[1] - r[0]) * this->AttributeTolerance;
262
263 this->Range = r[1] - r[0];
264
265 this->SquareAbsoluteAttributeTolerance = tmp * tmp;
266 this->SquareAbsoluteAttributeToleranceComputeTime.Modified();
267 this->AbsoluteAttributeTolerance = sqrt(this->SquareAbsoluteAttributeTolerance);
268 }
269 }
270 }
271