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