// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkAppendPoints.h" #include "vtkDataSetAttributes.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkSmartPointer.h" #include "vtkStringArray.h" #include "vtkTable.h" #include #include VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkAppendPoints); //------------------------------------------------------------------------------ vtkAppendPoints::vtkAppendPoints() { this->InputIdArrayName = nullptr; this->OutputPointsPrecision = vtkAlgorithm::DEFAULT_PRECISION; } //------------------------------------------------------------------------------ vtkAppendPoints::~vtkAppendPoints() { this->SetInputIdArrayName(nullptr); } //------------------------------------------------------------------------------ // This method is much too long, and has to be broken up! // Append data sets into single polygonal data set. int vtkAppendPoints::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkInformation* outInfo = outputVector->GetInformationObject(0); vtkPolyData* output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // Find common array names. vtkIdType totalPoints = 0; int numInputs = this->GetNumberOfInputConnections(0); bool first = true; std::set arrayNames; for (int idx = 0; idx < numInputs; ++idx) { if (this->CheckAbort()) { break; } vtkInformation* inInfo = inputVector[0]->GetInformationObject(idx); vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); if (input && input->GetNumberOfPoints() > 0) { totalPoints += input->GetNumberOfPoints(); if (first) { int numArrays = input->GetPointData()->GetNumberOfArrays(); for (int a = 0; a < numArrays; ++a) { arrayNames.insert(input->GetPointData()->GetAbstractArray(a)->GetName()); } first = false; } else { std::set toErase; std::set::iterator it, itEnd; itEnd = arrayNames.end(); for (it = arrayNames.begin(); it != itEnd; ++it) { if (!input->GetPointData()->GetAbstractArray(it->c_str())) { toErase.insert(*it); } } itEnd = toErase.end(); for (it = toErase.begin(); it != itEnd; ++it) { arrayNames.erase(*it); } } } } std::vector> inputs; for (int idx = 0; idx < numInputs; ++idx) { if (this->CheckAbort()) { break; } vtkInformation* inInfo = inputVector[0]->GetInformationObject(idx); vtkPolyData* input = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); if (input && input->GetNumberOfPoints() > 0) { vtkSmartPointer copy = vtkSmartPointer::New(); copy->SetPoints(input->GetPoints()); std::set::iterator it, itEnd; itEnd = arrayNames.end(); for (it = arrayNames.begin(); it != itEnd; ++it) { copy->GetPointData()->AddArray(input->GetPointData()->GetAbstractArray(it->c_str())); } inputs.push_back(copy); } else { inputs.emplace_back(nullptr); } } vtkPointData* pd = nullptr; vtkIdType index = 0; vtkSmartPointer pts = vtkSmartPointer::New(); // Set the desired precision for the points in the output. if (this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION) { // The points in distinct inputs may be of differing precisions. pts->SetDataType(VTK_FLOAT); for (size_t idx = 0; idx < inputs.size(); ++idx) { vtkPolyData* input = inputs[idx]; // Set the desired precision to VTK_DOUBLE if the precision of the // points in any of the inputs is VTK_DOUBLE. if (input && input->GetPoints() && input->GetPoints()->GetDataType() == VTK_DOUBLE) { pts->SetDataType(VTK_DOUBLE); break; } } } else if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION) { pts->SetDataType(VTK_FLOAT); } else if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION) { pts->SetDataType(VTK_DOUBLE); } pts->SetNumberOfPoints(totalPoints); vtkSmartPointer idArr; if (this->InputIdArrayName) { idArr = vtkSmartPointer::New(); idArr->SetName(this->InputIdArrayName); idArr->SetNumberOfTuples(totalPoints); } for (size_t idx = 0; idx < inputs.size(); ++idx) { if (this->CheckAbort()) { break; } vtkPolyData* input = inputs[idx]; if (input) { vtkPointData* ipd = input->GetPointData(); if (!pd) { pd = output->GetPointData(); pd->CopyAllocate(ipd, totalPoints); } vtkIdType numPoints = input->GetNumberOfPoints(); for (vtkIdType i = 0; i < numPoints; ++i) { pd->CopyData(ipd, i, index); pts->InsertPoint(index, input->GetPoint(i)); if (this->InputIdArrayName) { idArr->InsertValue(index, static_cast(idx)); } ++index; } } } output->SetPoints(pts); if (this->InputIdArrayName) { output->GetPointData()->AddArray(idArr); } return 1; } //------------------------------------------------------------------------------ void vtkAppendPoints::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "InputIdArrayName: " << (this->InputIdArrayName ? this->InputIdArrayName : "(none)") << endl << indent << "Output Points Precision: " << this->OutputPointsPrecision << endl; } //------------------------------------------------------------------------------ int vtkAppendPoints::FillInputPortInformation(int port, vtkInformation* info) { if (!this->Superclass::FillInputPortInformation(port, info)) { return 0; } info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); return 1; } VTK_ABI_NAMESPACE_END