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 "vtkObjectFactory.h"
18 #include "vtkGenericAttribute.h"
19 #include "vtkGenericAttributeCollection.h"
20 #include "vtkGenericAdaptorCell.h"
21 #include "vtkGenericDataSet.h"
22 #include <cassert>
23
24 vtkStandardNewMacro(vtkAttributesErrorMetric);
25
26 //-----------------------------------------------------------------------------
vtkAttributesErrorMetric()27 vtkAttributesErrorMetric::vtkAttributesErrorMetric()
28 {
29 this->AttributeTolerance = 0.1; // arbitrary
30 this->AbsoluteAttributeTolerance = 0.1; // arbitrary
31 this->SquareAbsoluteAttributeTolerance=this->AbsoluteAttributeTolerance*this->AbsoluteAttributeTolerance;
32 this->Range=0;
33 this->DefinedByAbsolute=1;
34 }
35
36 //-----------------------------------------------------------------------------
37 vtkAttributesErrorMetric::~vtkAttributesErrorMetric() = default;
38
39 //-----------------------------------------------------------------------------
40 // Description:
41 // Set the absolute attribute accuracy to `value'. See
42 // GetAbsoluteAttributeTolerance() for details.
43 // \pre valid_range_value: value>0
SetAbsoluteAttributeTolerance(double value)44 void vtkAttributesErrorMetric::SetAbsoluteAttributeTolerance(double value)
45 {
46 assert("pre: valid_range_value" && value>0);
47 if(this->AbsoluteAttributeTolerance!=value || !this->DefinedByAbsolute)
48 {
49 this->AbsoluteAttributeTolerance=value;
50 this->SquareAbsoluteAttributeTolerance=this->AbsoluteAttributeTolerance*this->AbsoluteAttributeTolerance;
51 this->Range=0;
52 this->DefinedByAbsolute=1;
53 this->Modified();
54 }
55 }
56
57 //-----------------------------------------------------------------------------
58 // Description:
59 // Set the relative attribute accuracy to `value'. See
60 // GetAttributeTolerance() for details.
61 // \pre valid_range_value: value>0 && value<1
SetAttributeTolerance(double value)62 void vtkAttributesErrorMetric::SetAttributeTolerance(double value)
63 {
64 assert("pre: valid_range_value" && value>0 && value<1);
65 if(this->AttributeTolerance!=value || this->DefinedByAbsolute)
66 {
67 this->AttributeTolerance=value;
68 this->DefinedByAbsolute=0;
69 this->Modified();
70 }
71 }
72
73 //-----------------------------------------------------------------------------
RequiresEdgeSubdivision(double * leftPoint,double * midPoint,double * rightPoint,double alpha)74 int vtkAttributesErrorMetric::RequiresEdgeSubdivision(double *leftPoint,
75 double *midPoint,
76 double *rightPoint,
77 double alpha)
78 {
79 assert("pre: leftPoint_exists" && leftPoint!=nullptr);
80 assert("pre: midPoint_exists" && midPoint!=nullptr);
81 assert("pre: rightPoint_exists" && rightPoint!=nullptr);
82 assert("pre: clamped_alpha" && alpha>0 && alpha<1);
83
84 int result;
85 double ae;
86 vtkGenericAttributeCollection *ac;
87
88 this->ComputeSquareAbsoluteAttributeTolerance();
89
90 const int ATTRIBUTE_OFFSET=6;
91
92 ac=this->DataSet->GetAttributes();
93 vtkGenericAttribute *a=ac->GetAttribute(ac->GetActiveAttribute());
94
95 if(this->GenericCell->IsAttributeLinear(a))
96 {
97 //don't need to do anything:
98 ae=0;
99 }
100 else
101 {
102 if(ac->GetActiveComponent()>=0)
103 {
104 int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ac->GetActiveComponent()+ATTRIBUTE_OFFSET;
105 double tmp=leftPoint[i]+alpha*(rightPoint[i]-leftPoint[i])-midPoint[i];
106 ae=tmp*tmp;
107 }
108 else // module of the vector
109 {
110 int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ATTRIBUTE_OFFSET;
111 int j=0;
112 int c=ac->GetNumberOfComponents();
113 double tmp;
114 #if 0
115 // If x and y are two vectors, we compute: ||x|-|y||
116 double interpolatedValueMod=0;
117 double midValueMod=0;
118 while(j<c)
119 {
120 tmp=leftPoint[i+j]+alpha*(rightPoint[i+j]-leftPoint[i+j]);
121 interpolatedValueMod+=tmp*tmp;
122 tmp=midPoint[i+j];
123 midValueMod+=tmp*tmp;
124 ++j;
125 }
126 tmp=sqrt(midValueMod)-sqrt(interpolatedValueMod);
127 ae=tmp*tmp;
128 #else
129 // If x and y are two vectors, we compute: |x-y|
130 // We should compute ||x|-|y|| but |x-y| is usually enough
131 // and tends to produce less degenerated edges.
132 // Remind that: ||x|-|y||<=|x-y|
133 ae=0;
134 while(j<c)
135 {
136 tmp=leftPoint[i+j]+alpha*(rightPoint[i+j]-leftPoint[i+j])-midPoint[i+j];
137 ae+=tmp*tmp;
138 ++j;
139 }
140 #endif
141 }
142 assert("check: positive_ae" && ae>=0);
143 }
144
145 if(this->SquareAbsoluteAttributeTolerance==0)
146 {
147 result=fabs(ae)>0.0001;
148 }
149 else
150 {
151 result=ae>this->SquareAbsoluteAttributeTolerance;
152 }
153 return result;
154 }
155
156 //-----------------------------------------------------------------------------
157 // Description:
158 // Return the error at the mid-point. The type of error depends on the state
159 // of the concrete error metric. For instance, it can return an absolute
160 // or relative error metric.
161 // See RequiresEdgeSubdivision() for a description of the arguments.
162 // \post positive_result: result>=0
GetError(double * leftPoint,double * midPoint,double * rightPoint,double alpha)163 double vtkAttributesErrorMetric::GetError(double *leftPoint,
164 double *midPoint,
165 double *rightPoint,
166 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
184 if(this->GenericCell->IsAttributeLinear(a))
185 {
186 //don't need to do anything:
187 ae=0;
188 }
189 else
190 {
191 if(ac->GetActiveComponent()>=0) // one component
192 {
193 int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ac->GetActiveComponent()+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