1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkSimpleElevationFilter.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 "vtkSimpleElevationFilter.h"
16
17 #include "vtkArrayDispatch.h"
18 #include "vtkCellData.h"
19 #include "vtkDataArrayRange.h"
20 #include "vtkFloatArray.h"
21 #include "vtkInformation.h"
22 #include "vtkInformationVector.h"
23 #include "vtkMath.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkPointData.h"
26 #include "vtkPointSet.h"
27 #include "vtkSMPTools.h"
28
29 vtkStandardNewMacro(vtkSimpleElevationFilter);
30
31 namespace
32 {
33
34 // The heart of the algorithm plus interface to the SMP tools.
35 template <class PointArrayT>
36 class vtkSimpleElevationAlgorithm
37 {
38 public:
39 vtkIdType NumPts;
40 double Vector[3];
41 PointArrayT* PointArray;
42 float* Scalars;
43
vtkSimpleElevationAlgorithm(PointArrayT * pointArray,vtkSimpleElevationFilter * filter,float * scalars)44 vtkSimpleElevationAlgorithm(
45 PointArrayT* pointArray, vtkSimpleElevationFilter* filter, float* scalars)
46 : NumPts{ pointArray->GetNumberOfTuples() }
47 , PointArray{ pointArray }
48 , Scalars{ scalars }
49 {
50 filter->GetVector(this->Vector);
51 }
52
53 // Interface implicit function computation to SMP tools.
operator ()(vtkIdType begin,vtkIdType end)54 void operator()(vtkIdType begin, vtkIdType end)
55 {
56 const double* v = this->Vector;
57 float* s = this->Scalars + begin;
58
59 const auto pointRange = vtk::DataArrayTupleRange<3>(this->PointArray, begin, end);
60
61 for (const auto p : pointRange)
62 {
63 *s = v[0] * p[0] + v[1] * p[1] + v[2] * p[2];
64 ++s;
65 }
66 }
67 };
68
69 //------------------------------------------------------------------------------
70 // Templated class is glue between VTK and templated algorithms.
71 struct Elevate
72 {
73 template <typename PointArrayT>
operator ()__anonc7dc14740111::Elevate74 void operator()(PointArrayT* pointArray, vtkSimpleElevationFilter* filter, float* scalars)
75 {
76 vtkSimpleElevationAlgorithm<PointArrayT> algo{ pointArray, filter, scalars };
77 vtkSMPTools::For(0, pointArray->GetNumberOfTuples(), algo);
78 }
79 };
80
81 } // end anon namespace
82
83 // Okay begin the class proper
84 //------------------------------------------------------------------------------
85 // Construct object with Vector=(0,0,1).
vtkSimpleElevationFilter()86 vtkSimpleElevationFilter::vtkSimpleElevationFilter()
87 {
88 this->Vector[0] = 0.0;
89 this->Vector[1] = 0.0;
90 this->Vector[2] = 1.0;
91 }
92
93 //------------------------------------------------------------------------------
94 // Convert position along the ray into scalar value. Example use includes
95 // coloring terrain by elevation.
96 //
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)97 int vtkSimpleElevationFilter::RequestData(vtkInformation* vtkNotUsed(request),
98 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
99 {
100 // get the info objects
101 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
102 vtkInformation* outInfo = outputVector->GetInformationObject(0);
103
104 // get the input and output
105 vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
106 vtkDataSet* output = vtkDataSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
107
108 vtkIdType i, numPts;
109 vtkFloatArray* newScalars;
110 double s, x[3];
111
112 // Initialize
113 //
114 vtkDebugMacro(<< "Generating elevation scalars!");
115
116 // First, copy the input to the output as a starting point
117 output->CopyStructure(input);
118
119 if (((numPts = input->GetNumberOfPoints()) < 1))
120 {
121 vtkDebugMacro(<< "No input!");
122 return 1;
123 }
124
125 // Allocate
126 //
127 newScalars = vtkFloatArray::New();
128 newScalars->SetNumberOfTuples(numPts);
129
130 // Ensure that there is a valid vector
131 //
132 if (vtkMath::Dot(this->Vector, this->Vector) == 0.0)
133 {
134 vtkErrorMacro(<< "Bad vector, using (0,0,1)");
135 this->Vector[0] = this->Vector[1] = 0.0;
136 this->Vector[2] = 1.0;
137 }
138
139 // Create a fast path for point set input
140 //
141 vtkPointSet* ps = vtkPointSet::SafeDownCast(input);
142 if (ps)
143 {
144 float* scalars = newScalars->GetPointer(0);
145 vtkPoints* points = ps->GetPoints();
146 vtkDataArray* pointsArray = points->GetData();
147
148 Elevate worker; // Entry point to vtkSimpleElevationAlgorithm
149
150 // Generate an optimized fast-path for float/double
151 using FastValueTypes = vtkArrayDispatch::Reals;
152 using Dispatcher = vtkArrayDispatch::DispatchByValueType<FastValueTypes>;
153 if (!Dispatcher::Execute(pointsArray, worker, this, scalars))
154 { // fallback for unknown arrays and integral value types:
155 worker(pointsArray, this, scalars);
156 }
157 } // fast path
158
159 else
160 {
161 // Too bad, got to take the scenic route.
162 // Compute dot product.
163 //
164 int abort = 0;
165 vtkIdType progressInterval = numPts / 20 + 1;
166 for (i = 0; i < numPts && !abort; i++)
167 {
168 if (!(i % progressInterval))
169 {
170 this->UpdateProgress((double)i / numPts);
171 abort = this->GetAbortExecute();
172 }
173
174 input->GetPoint(i, x);
175 s = vtkMath::Dot(this->Vector, x);
176 newScalars->SetComponent(i, 0, s);
177 }
178 }
179
180 // Update self
181 //
182 output->GetPointData()->CopyScalarsOff();
183 output->GetPointData()->PassData(input->GetPointData());
184
185 output->GetCellData()->PassData(input->GetCellData());
186
187 newScalars->SetName("Elevation");
188 output->GetPointData()->AddArray(newScalars);
189 output->GetPointData()->SetActiveScalars(newScalars->GetName());
190 newScalars->Delete();
191
192 return 1;
193 }
194
195 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)196 void vtkSimpleElevationFilter::PrintSelf(ostream& os, vtkIndent indent)
197 {
198 this->Superclass::PrintSelf(os, indent);
199
200 os << indent << "Vector: (" << this->Vector[0] << ", " << this->Vector[1] << ", "
201 << this->Vector[2] << ")\n";
202 }
203