74 vtkInformationVector **inputVector,
75 vtkInformationVector *outputVector) {
80 auto surface = vtkPolyData::GetData(inputVector[0], 0);
83 printErr(
"Unable to load triangulation.");
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");
94 if(surfaceYArray ==
nullptr) {
95 this->
printErr(
"Cannot find the required surface data Y array");
100 auto coefficients = vtkTable::GetData(inputVector[1], 0);
101 auto xArrayName = surfaceXArray->GetName();
102 auto tableXArray = coefficients->GetColumnByName(xArrayName);
104 printErr(
"Can not find " + std::string{xArrayName} +
" X array in table");
107 auto tableDataXArray = vtkDataArray::SafeDownCast(tableXArray);
108 if(!tableDataXArray) {
109 printErr(
"Can not load " + std::string{xArrayName}
110 +
" X data array in table");
113 auto yArrayName = surfaceYArray->GetName();
114 auto tableYArray = coefficients->GetColumnByName(yArrayName);
116 printErr(
"Can not find " + std::string{yArrayName} +
" Y array in table");
119 auto tableDataYArray = vtkDataArray::SafeDownCast(tableYArray);
120 if(!tableDataYArray) {
121 printErr(
"Can not load " + std::string{yArrayName}
122 +
" Y data array in table");
126 const auto nSurfaceValues = surfaceXArray->GetNumberOfTuples();
127 const auto nTableValues = tableDataXArray->GetNumberOfTuples();
133 std::vector<std::tuple<int, double, double>> orderedValues;
135#ifndef TTK_ENABLE_DOUBLE_TEMPLATING
136 switch(surfaceXArray->GetDataType()) {
144 switch(vtkTemplate2PackMacro(
145 surfaceXArray->GetDataType(), surfaceYArray->GetDataType())) {
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);
163 const long nUniqueXValues
164 = std::unique(xValues.begin(), xValues.end()) - xValues.begin();
166 const long nUniqueYValues
167 = std::unique(yValues.begin(), yValues.end()) - yValues.begin();
168 std::array<const long, 2> surfaceDim{nUniqueXValues, nUniqueYValues};
170 if(nUniqueXValues * nUniqueYValues != surface->GetNumberOfPoints()) {
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");
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;
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));
194 this->
threadNumber_, orderedValues.begin(), orderedValues.end(), cmp);
199 std::vector<std::vector<double>> inputPoints;
200#ifndef TTK_ENABLE_DOUBLE_TEMPLATING
201 switch(tableDataXArray->GetDataType()) {
203 triangulation, orderedValues, surfaceDim,
206 nTableValues, inputPoints));
209 switch(vtkTemplate2PackMacro(
210 tableDataXArray->GetDataType(), tableDataYArray->GetDataType())) {
212 triangulation, orderedValues, surfaceDim,
215 nTableValues, inputPoints));
222 auto output = vtkPolyData::GetData(outputVector, 0);
223 output->DeepCopy(surface);
225 std::set<std::string> toRemove;
226 for(
unsigned int i = 0; i < inputPoints.size(); ++i) {
228 for(
unsigned int j = 0; j < 3; ++j) {
229 point[j] = inputPoints[i][j];
231 output->GetPoints()->InsertNextPoint(point);
234 for(
int j = 0; j < output->GetPointData()->GetNumberOfArrays(); ++j) {
235 auto outputArray = output->GetPointData()->GetAbstractArray(j);
236 std::string
const name = outputArray->GetName();
237 auto array = coefficients->GetColumnByName(name.c_str());
239 outputArray->InsertNextTuple(i, array);
241 auto dataArray = vtkDataArray::SafeDownCast(outputArray);
243 const double val = std::nan(
"");
244 dataArray->InsertNextTuple(&val);
246 auto stringArray = vtkStringArray::SafeDownCast(outputArray);
248 stringArray->InsertNextValue(
"");
250 toRemove.insert(name);
256 int const noPointsOri = output->GetNumberOfPoints() - inputPoints.size();
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
const name = inputArray->GetName();
265 auto array = output->GetPointData()->GetAbstractArray(name.c_str());
266 if(not array and (dataArray or stringArray))
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) {
279 if(i < noPointsOri) {
281 double const val = std::nan(
"");
282 dataArray->SetTuple1(i, val);
283 }
else if(stringArray) {
284 stringArray->SetValue(i,
"");
286 printWrn(
"Can not convert " + name +
" to dataArray or stringArray.");
288 inputArray->SetTuple(
289 i, i - noPointsOri, coefficients->GetColumnByName(name.c_str()));
292 output->GetPointData()->AddArray(inputArray);
295 for(
auto &name : toRemove)
296 output->GetPointData()->RemoveArray(name.c_str());
299 vtkNew<vtkIntArray> isSurfaceArray{};
300 isSurfaceArray->SetName(
"isSurface");
301 isSurfaceArray->SetNumberOfTuples(output->GetNumberOfPoints());
302 for(
int i = 0; i < output->GetNumberOfPoints(); ++i) {
303 bool const isSurface = (i < noPointsOri);
304 isSurfaceArray->SetTuple1(i, isSurface);
306 output->GetPointData()->AddArray(isSurfaceArray);
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));
316 output->GetCellData()->AddArray(cellTypeArray);