// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkJoinTables.h" #include "vtkAbstractArray.h" #include "vtkAlgorithmOutput.h" #include "vtkArray.h" #include "vtkDataArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkIntArray.h" #include "vtkSmartPointer.h" #include "vtkStringArray.h" #include "vtkTable.h" #include "vtkType.h" #include "vtkVariant.h" #include "vtkVariantArray.h" #include #include #include #include VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkJoinTables); //------------------------------------------------------------------------------ vtkJoinTables::vtkJoinTables() { this->SetNumberOfInputPorts(2); } //------------------------------------------------------------------------------ void vtkJoinTables::SetSourceConnection(vtkAlgorithmOutput* algOutput) { this->SetInputConnection(1, algOutput); } //------------------------------------------------------------------------------ void vtkJoinTables::SetSourceData(vtkTable* source) { this->SetInputData(1, source); } //------------------------------------------------------------------------------ bool HasDuplicates(vtkAbstractArray* array) { vtkIdType size = array->GetNumberOfValues(); for (int i = 1; i < size; i++) { for (int j = 0; j < i; j++) { if (array->GetVariantValue(i) == array->GetVariantValue(j)) { return true; } } } return false; } //------------------------------------------------------------------------------ int vtkJoinTables::RequestData( vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { vtkTable* left = vtkTable::GetData(inputVector[0]); vtkTable* right = vtkTable::GetData(inputVector[1]); vtkTable* output = vtkTable::GetData(outputVector); if (!left || !right || !output) { vtkErrorMacro("No inputs or output."); return 0; } // If one of the inputs is an empty table, also return an empty table. if (left->GetNumberOfColumns() == 0 || right->GetNumberOfColumns() == 0) { return 1; } // Assert that LeftKey and RightKey refer to valid existing columns vtkAbstractArray* leftKeyCol = left->GetColumnByName(this->LeftKey.c_str()); if (!leftKeyCol) { vtkErrorMacro("Left key is invalid"); return 0; } vtkAbstractArray* rightKeyCol = right->GetColumnByName(this->RightKey.c_str()); if (!rightKeyCol) { vtkErrorMacro("Right key is invalid"); return 0; } if (!(leftKeyCol->GetDataType() == rightKeyCol->GetDataType())) { vtkErrorMacro("Key columns data types do not match : " << leftKeyCol->GetDataType() << " and " << rightKeyCol->GetDataType() << "."); return 0; } // Assert that each key column contains unique elements if (HasDuplicates(leftKeyCol) || HasDuplicates(rightKeyCol)) { vtkErrorMacro("The key columns must not contain duplicate values."); return 0; } // Core Algorithm if (auto leftKeyDA = vtkDataArray::SafeDownCast(leftKeyCol)) { auto rightKeyDA = vtkDataArray::SafeDownCast(rightKeyCol); auto maps = Maps(); this->JoinAlgorithm(left, right, output, leftKeyDA, rightKeyDA, &maps); } else if (auto leftKeySA = vtkStringArray::SafeDownCast(leftKeyCol)) { auto rightKeySA = vtkStringArray::SafeDownCast(rightKeyCol); auto maps = Maps(); this->JoinAlgorithm( left, right, output, leftKeySA, rightKeySA, &maps); } else { vtkErrorMacro("Unsupported types for the key columns."); return 0; } this->CheckAbort(); return 1; } //------------------------------------------------------------------------------ int vtkJoinTables::FillInputPortInformation(int, vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable"); return 1; } //------------------------------------------------------------------------------ void vtkJoinTables::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Left Key Column: " << this->LeftKey << std::endl; os << indent << "Right Key Column: " << this->RightKey << std::endl; os << indent << "Replacement Value: " << this->ReplacementValue << std::endl; os << indent << "Mode: "; switch (this->Mode) { case INTERSECTION: os << "Intersection"; break; case UNION: os << "Union"; break; case LEFT: os << "Left Join"; break; case RIGHT: os << "Right Join"; break; default: os << "Undefined"; break; } os << endl; } VTK_ABI_NAMESPACE_END