TTK
Loading...
Searching...
No Matches
ttkProjectionFromTable.cpp
Go to the documentation of this file.
2
3#include <vtkInformation.h>
4
5#include <vtkCellData.h>
6#include <vtkCellType.h>
7#include <vtkDataArray.h>
8#include <vtkDataSet.h>
9#include <vtkObjectFactory.h>
10#include <vtkPointData.h>
11#include <vtkSmartPointer.h>
12#include <vtkStringArray.h>
13
14#include <ttkMacros.h>
15#include <ttkUtils.h>
16
17#include <set>
18
19// A VTK macro that enables the instantiation of this class via ::New()
20// You do not have to modify this
22
27 this->SetNumberOfInputPorts(2);
28 this->SetNumberOfOutputPorts(1);
29}
30
35 vtkInformation *info) {
36 if(port == 0) {
37 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
38 } else if(port == 1) {
39 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
40 } else
41 return 0;
42 return 1;
43}
44
49 vtkInformation *info) {
50 if(port == 0) {
51 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData");
52 } else
53 return 0;
54 return 1;
55}
56
60template <typename VTK_T1, typename VTK_T2>
62 std::vector<std::tuple<int, double, double>> &storage,
63 const VTK_T1 *const values,
64 const VTK_T2 *const values2,
65 const size_t nvalues) {
66
67 for(size_t i = 0; i < nvalues; ++i) {
68 storage.emplace_back(
69 i, static_cast<double>(values[i]), static_cast<double>(values2[i]));
70 }
71}
72
74 vtkInformationVector **inputVector,
75 vtkInformationVector *outputVector) {
76 // --------------------------------------------------------------------------
77 // --- Get input object from input vector
78 // --------------------------------------------------------------------------
79 // Get surface
80 auto surface = vtkPolyData::GetData(inputVector[0], 0);
81 auto triangulation = ttkAlgorithm::GetTriangulation(surface);
82 if(!triangulation) {
83 printErr("Unable to load triangulation.");
84 return 0;
85 }
86
87 // Get surface arrays
88 const auto surfaceXArray = this->GetInputArrayToProcess(0, inputVector);
89 const auto surfaceYArray = this->GetInputArrayToProcess(1, inputVector);
90 if(surfaceXArray == nullptr) {
91 this->printErr("Cannot find the required surface data X array");
92 return 0;
93 }
94 if(surfaceYArray == nullptr) {
95 this->printErr("Cannot find the required surface data Y array");
96 return 0;
97 }
98
99 // Get table arrays
100 auto coefficients = vtkTable::GetData(inputVector[1], 0);
101 auto xArrayName = surfaceXArray->GetName();
102 auto tableXArray = coefficients->GetColumnByName(xArrayName);
103 if(!tableXArray) {
104 printErr("Can not find " + std::string{xArrayName} + " X array in table");
105 return 0;
106 }
107 auto tableDataXArray = vtkDataArray::SafeDownCast(tableXArray);
108 if(!tableDataXArray) {
109 printErr("Can not load " + std::string{xArrayName}
110 + " X data array in table");
111 return 0;
112 }
113 auto yArrayName = surfaceYArray->GetName();
114 auto tableYArray = coefficients->GetColumnByName(yArrayName);
115 if(!tableYArray) {
116 printErr("Can not find " + std::string{yArrayName} + " Y array in table");
117 return 0;
118 }
119 auto tableDataYArray = vtkDataArray::SafeDownCast(tableYArray);
120 if(!tableDataYArray) {
121 printErr("Can not load " + std::string{yArrayName}
122 + " Y data array in table");
123 return 0;
124 }
125
126 const auto nSurfaceValues = surfaceXArray->GetNumberOfTuples();
127 const auto nTableValues = tableDataXArray->GetNumberOfTuples();
128
129 // --------------------------------------------------------------------------
130 // --- Get ordered values
131 // --------------------------------------------------------------------------
132 // store point index <-> ordering value in vector
133 std::vector<std::tuple<int, double, double>> orderedValues;
134
135#ifndef TTK_ENABLE_DOUBLE_TEMPLATING
136 switch(surfaceXArray->GetDataType()) {
137 vtkTemplateMacro(
138 dispatch(orderedValues,
139 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(surfaceXArray)),
140 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(surfaceYArray)),
141 nSurfaceValues));
142 }
143#else
144 switch(vtkTemplate2PackMacro(
145 surfaceXArray->GetDataType(), surfaceYArray->GetDataType())) {
146 vtkTemplate2Macro(
147 dispatch(orderedValues,
148 static_cast<VTK_T1 *>(ttkUtils::GetVoidPointer(surfaceXArray)),
149 static_cast<VTK_T2 *>(ttkUtils::GetVoidPointer(surfaceYArray)),
150 nSurfaceValues));
151 }
152#endif // TTK_ENABLE_DOUBLE_TEMPLATING
153
154 // Get number of unique values of each array
155 std::vector<double> xValues(orderedValues.size()),
156 yValues(orderedValues.size());
157 for(unsigned int i = 0; i < orderedValues.size(); ++i) {
158 auto tup = orderedValues[i];
159 xValues[i] = std::get<1>(tup);
160 yValues[i] = std::get<2>(tup);
161 }
162 TTK_PSORT(this->threadNumber_, xValues.begin(), xValues.end());
163 const long nUniqueXValues
164 = std::unique(xValues.begin(), xValues.end()) - xValues.begin();
165 TTK_PSORT(this->threadNumber_, yValues.begin(), yValues.end());
166 const long nUniqueYValues
167 = std::unique(yValues.begin(), yValues.end()) - yValues.begin();
168 std::array<const long, 2> surfaceDim{nUniqueXValues, nUniqueYValues};
169
170 if(nUniqueXValues * nUniqueYValues != surface->GetNumberOfPoints()) {
171 printErr(
172 "Number of unique values in first array times the number of unique "
173 "values in the second one does not equal the number of points");
174 return 0;
175 }
176
177 // Compare two pairs of index/value according to their values
178 double yRange[2] = {*std::min_element(yValues.begin(), yValues.end()),
179 *std::max_element(yValues.begin(), yValues.end())};
180 double minXInterval = std::numeric_limits<double>::max();
181 for(unsigned int i = 1; i < nUniqueXValues; ++i)
182 minXInterval = std::min(minXInterval, xValues[i] - xValues[i - 1]);
183 const auto normValue = [&](double v) {
184 return (v - yRange[0]) / (yRange[1] - yRange[0]) * minXInterval * 0.99;
185 };
186 const auto cmp = [&](const std::tuple<int, double, double> &a,
187 const std::tuple<int, double, double> &b) {
188 return std::get<1>(a) + normValue(std::get<2>(a))
189 < std::get<1>(b) + normValue(std::get<2>(b));
190 };
191
192 // sort the vector of indices/values in ascending order
193 TTK_PSORT(
194 this->threadNumber_, orderedValues.begin(), orderedValues.end(), cmp);
195
196 //---------------------------------------------------------------------------
197 // --- Call base
198 //---------------------------------------------------------------------------
199 std::vector<std::vector<double>> inputPoints;
200#ifndef TTK_ENABLE_DOUBLE_TEMPLATING
201 switch(tableDataXArray->GetDataType()) {
202 vtkTemplateMacro(computeInputPoints(
203 triangulation, orderedValues, surfaceDim,
204 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(tableDataXArray)),
205 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(tableDataYArray)),
206 nTableValues, inputPoints));
207 }
208#else
209 switch(vtkTemplate2PackMacro(
210 tableDataXArray->GetDataType(), tableDataYArray->GetDataType())) {
211 vtkTemplate2Macro(computeInputPoints(
212 triangulation, orderedValues, surfaceDim,
213 static_cast<VTK_T1 *>(ttkUtils::GetVoidPointer(tableDataXArray)),
214 static_cast<VTK_T2 *>(ttkUtils::GetVoidPointer(tableDataYArray)),
215 nTableValues, inputPoints));
216 }
217#endif // TTK_ENABLE_DOUBLE_TEMPLATING
218
219 //---------------------------------------------------------------------------
220 // --- Create output
221 //---------------------------------------------------------------------------
222 auto output = vtkPolyData::GetData(outputVector, 0);
223 output->DeepCopy(surface);
224
225 std::set<std::string> toRemove;
226 for(unsigned int i = 0; i < inputPoints.size(); ++i) {
227 double point[3];
228 for(unsigned int j = 0; j < 3; ++j) {
229 point[j] = inputPoints[i][j];
230 }
231 output->GetPoints()->InsertNextPoint(point);
232
233 // Merge data of arrays in surface also in table or add empty data
234 for(int j = 0; j < output->GetPointData()->GetNumberOfArrays(); ++j) {
235 auto outputArray = output->GetPointData()->GetAbstractArray(j);
236 std::string name = outputArray->GetName();
237 auto array = coefficients->GetColumnByName(name.c_str());
238 if(array) {
239 outputArray->InsertNextTuple(i, array);
240 } else {
241 auto dataArray = vtkDataArray::SafeDownCast(outputArray);
242 if(dataArray) {
243 const double val = std::nan("");
244 dataArray->InsertNextTuple(&val);
245 } else {
246 auto stringArray = vtkStringArray::SafeDownCast(outputArray);
247 if(stringArray)
248 stringArray->InsertNextValue("");
249 else
250 toRemove.insert(name);
251 }
252 }
253 }
254 }
255
256 int noPointsOri = output->GetNumberOfPoints() - inputPoints.size();
257
258 // Merge data of arrays in table also in surface or add empty data
259 std::set<std::string> toGet;
260 for(int j = 0; j < coefficients->GetNumberOfColumns(); ++j) {
261 auto inputArray = coefficients->GetColumn(j);
262 auto dataArray = vtkDataArray::SafeDownCast(inputArray);
263 auto stringArray = vtkStringArray::SafeDownCast(inputArray);
264 std::string name = inputArray->GetName();
265 auto array = output->GetPointData()->GetAbstractArray(name.c_str());
266 if(not array and (dataArray or stringArray))
267 toGet.insert(name);
268 }
269 vtkNew<vtkTable> tableCopy{};
270 if(toGet.size() != 0)
271 tableCopy->DeepCopy(coefficients);
272 for(auto &name : toGet) {
273 auto inputArray = tableCopy->GetColumnByName(name.c_str());
274 auto dataArray = vtkDataArray::SafeDownCast(inputArray);
275 auto stringArray = vtkStringArray::SafeDownCast(inputArray);
276 inputArray->SetNumberOfTuples(output->GetNumberOfPoints());
277 for(int i = 0; i < output->GetNumberOfPoints(); ++i) {
278 // if is surface
279 if(i < noPointsOri) {
280 if(dataArray) {
281 double val = std::nan("");
282 dataArray->SetTuple1(i, val);
283 } else if(stringArray) {
284 stringArray->SetValue(i, "");
285 } else
286 printWrn("Can not convert " + name + " to dataArray or stringArray.");
287 } else {
288 inputArray->SetTuple(
289 i, i - noPointsOri, coefficients->GetColumnByName(name.c_str()));
290 }
291 }
292 output->GetPointData()->AddArray(inputArray);
293 }
294
295 for(auto &name : toRemove)
296 output->GetPointData()->RemoveArray(name.c_str());
297
298 // Some points data
299 vtkNew<vtkIntArray> isSurfaceArray{};
300 isSurfaceArray->SetName("isSurface");
301 isSurfaceArray->SetNumberOfTuples(output->GetNumberOfPoints());
302 for(int i = 0; i < output->GetNumberOfPoints(); ++i) {
303 bool isSurface = (i < noPointsOri);
304 isSurfaceArray->SetTuple1(i, isSurface);
305 }
306 output->GetPointData()->AddArray(isSurfaceArray);
307
308 // Some cells data
309 auto noCells = output->GetNumberOfCells();
310 vtkNew<vtkIntArray> cellTypeArray{};
311 cellTypeArray->SetName("CellType");
312 cellTypeArray->SetNumberOfTuples(noCells);
313 for(int i = 0; i < noCells; ++i) {
314 cellTypeArray->SetTuple1(i, output->GetCellType(i));
315 }
316 output->GetCellData()->AddArray(cellTypeArray);
317
318 return 1;
319}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition: BaseClass.h:47
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
Definition: OpenMP.h:46
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
TTK VTK-filter that wraps the ttk::ProjectionFromTable module.
int FillInputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
void dispatch(std::vector< std::tuple< int, double, double > > &storage, const VTK_T1 *const values, const VTK_T2 *const values2, const size_t nvalues)
int FillOutputPortInformation(int port, vtkInformation *info) override
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition: ttkUtils.cpp:225
int threadNumber_
Definition: BaseClass.h:95
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition: Debug.h:159
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition: Debug.h:149
void computeInputPoints(const triangulationType *triangulation, std::vector< std::tuple< int, double, double > > &surfaceValues, std::array< const long, 2 > &surfaceDim, const xDataType *const tableXValues, const yDataType *const tableYValues, const size_t nTableValues, std::vector< std::vector< double > > &inputPoints)
vtkStandardNewMacro(ttkProjectionFromTable)