1 /*
2 * Copyright 2003 Sandia Corporation.
3 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
4 * license for use of this work by or on behalf of the
5 * U.S. Government. Redistribution and use in source and binary forms, with
6 * or without modification, are permitted provided that this Notice and any
7 * statement of authorship are reproduced on all copies.
8 */
9
10 #include "vtkEdgeSubdivisionCriterion.h"
11 #include "vtkDataSetAttributes.h"
12 #include "vtkMatrix4x4.h"
13 #include "vtkStreamingTessellator.h"
14
15 #include <cmath>
16
PrintSelf(ostream & os,vtkIndent indent)17 void vtkEdgeSubdivisionCriterion::PrintSelf(ostream& os, vtkIndent indent)
18 {
19 this->Superclass::PrintSelf(os, indent);
20 }
21
vtkEdgeSubdivisionCriterion()22 vtkEdgeSubdivisionCriterion::vtkEdgeSubdivisionCriterion()
23 {
24 this->FieldIds = new int[vtkStreamingTessellator::MaxFieldSize];
25 this->FieldOffsets = new int[vtkStreamingTessellator::MaxFieldSize + 1];
26 this->FieldOffsets[0] = 0;
27 this->NumberOfFields = 0;
28 }
29
~vtkEdgeSubdivisionCriterion()30 vtkEdgeSubdivisionCriterion::~vtkEdgeSubdivisionCriterion()
31 {
32 delete[] this->FieldIds;
33 delete[] this->FieldOffsets;
34 };
35
ResetFieldList()36 void vtkEdgeSubdivisionCriterion::ResetFieldList()
37 {
38 this->NumberOfFields = 0;
39 }
40
PassField(int sourceId,int sourceSize,vtkStreamingTessellator * t)41 int vtkEdgeSubdivisionCriterion::PassField(int sourceId, int sourceSize, vtkStreamingTessellator* t)
42 {
43 if (sourceSize + this->FieldOffsets[this->NumberOfFields] > vtkStreamingTessellator::MaxFieldSize)
44 {
45 vtkErrorMacro(
46 "PassField source size (" << sourceSize << ") was too large for vtkStreamingTessellator");
47 return -1;
48 }
49
50 int off = this->GetOutputField(sourceId);
51 if (off == -1)
52 {
53 this->FieldIds[this->NumberOfFields] = sourceId;
54 off = this->FieldOffsets[this->NumberOfFields];
55 t->SetFieldSize(-1, this->FieldOffsets[++this->NumberOfFields] = off + sourceSize);
56 this->Modified();
57 }
58 else
59 {
60 off = this->FieldOffsets[off];
61 vtkWarningMacro("Field " << sourceId << " is already being passed as offset " << off << ".");
62 }
63
64 return off;
65 }
66
DontPassField(int sourceId,vtkStreamingTessellator * t)67 bool vtkEdgeSubdivisionCriterion::DontPassField(int sourceId, vtkStreamingTessellator* t)
68 {
69 int id = this->GetOutputField(sourceId);
70 if (id == -1)
71 return false;
72
73 int sz = this->FieldOffsets[id + 1] - this->FieldOffsets[id];
74 for (int i = id + 1; i < this->GetNumberOfFields(); ++i)
75 {
76 this->FieldIds[i - 1] = this->FieldIds[i];
77 this->FieldOffsets[i] = this->FieldOffsets[i + 1] - sz;
78 }
79 t->SetFieldSize(-1, this->FieldOffsets[this->GetNumberOfFields()]);
80 this->Modified();
81
82 return true;
83 }
84
GetOutputField(int sourceId) const85 int vtkEdgeSubdivisionCriterion::GetOutputField(int sourceId) const
86 {
87 for (int i = 0; i < this->NumberOfFields; ++i)
88 if (this->FieldIds[i] == sourceId)
89 return i;
90
91 return -1;
92 }
93
ViewDependentEval(const double * p0,double * p1,double * real_p1,const double * p2,int,vtkMatrix4x4 * Transform,const double * PixelSize,double AllowableChordError) const94 bool vtkEdgeSubdivisionCriterion::ViewDependentEval(const double* p0, double* p1, double* real_p1,
95 const double* p2, int, vtkMatrix4x4* Transform, const double* PixelSize,
96 double AllowableChordError) const
97 {
98 double real_p1t[4];
99 double intr_p1t[4];
100
101 Transform->MultiplyPoint(real_p1, real_p1t);
102 Transform->MultiplyPoint(p1, intr_p1t);
103 double eprod = fabs(AllowableChordError * real_p1t[3] * intr_p1t[3]);
104 /*
105 fprintf( stderr, "eprod=%g, compare to <%g,%g>\n", eprod,
106 fabs(real_p1t[0]*intr_p1t[3]-intr_p1t[0]*real_p1t[3])/PixelSize[0],
107 fabs(real_p1t[1]*intr_p1t[3]-intr_p1t[1]*real_p1t[3])/PixelSize[1] );
108 */
109 if ((real_p1t[0] > real_p1t[3]) || (real_p1t[0] < -real_p1t[3]) || (real_p1t[1] > real_p1t[3]) ||
110 (real_p1t[1] < -real_p1t[3]))
111 {
112 double p0t[4];
113 double p2t[4];
114 for (int i = 0; i < 3; i++)
115 {
116 p0t[i] = p0[i];
117 p2t[i] = p2[i];
118 }
119 p0t[3] = p2t[3] = 1.;
120 Transform->MultiplyPoint(p0t, p0t);
121 Transform->MultiplyPoint(p2t, p2t);
122 int p0Code = 0, p2Code = 0;
123 #define ENDPOINT_CODE(code, pt) \
124 if (pt[0] > pt[3]) \
125 code += 1; \
126 else if (pt[0] < -pt[3]) \
127 code += 2; \
128 if (pt[1] > pt[3]) \
129 code += 4; \
130 else if (pt[1] < -pt[3]) \
131 code += 8;
132
133 ENDPOINT_CODE(p0Code, p0t);
134 ENDPOINT_CODE(p2Code, p2t);
135 if (p0Code & p2Code)
136 {
137 return false;
138 }
139 }
140 if (fabs(real_p1t[0] * intr_p1t[3] - intr_p1t[0] * real_p1t[3]) / PixelSize[0] > eprod ||
141 fabs(real_p1t[1] * intr_p1t[3] - intr_p1t[1] * real_p1t[3]) / PixelSize[1] > eprod)
142 {
143 // copy the properly interpolated point into the result
144 for (int c = 0; c < 3; ++c)
145 p1[c] = real_p1[c];
146 return true; // need to subdivide
147 }
148
149 return false; // no need to subdivide
150 }
151
FixedFieldErrorEval(double * p1,double * real_pf,int field_start,int criteria,double * AllowableL2Error2) const152 bool vtkEdgeSubdivisionCriterion::FixedFieldErrorEval(
153 double* p1, double* real_pf, int field_start, int criteria, double* AllowableL2Error2) const
154 {
155 int id = 0;
156 double mag;
157 while (criteria)
158 {
159 if (!(criteria & 1))
160 {
161 criteria >>= 1;
162 ++id;
163 continue;
164 }
165
166 mag = 0.;
167 int fsz = this->FieldOffsets[id + 1] - this->FieldOffsets[id];
168 for (int c = 0; c < fsz; ++c)
169 {
170 double tmp = real_pf[c + field_start] - p1[c + field_start];
171 mag += tmp * tmp;
172 }
173 if (mag > AllowableL2Error2[id])
174 {
175 return true;
176 }
177 criteria >>= 1;
178 ++id;
179 }
180
181 return false;
182 }
183