// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkDataObjectTree.h" #include "vtkCellGrid.h" #include "vtkDataObjectTreeInternals.h" #include "vtkDataObjectTreeIterator.h" #include "vtkDataSet.h" #include "vtkInformation.h" #include "vtkInformationIntegerKey.h" #include "vtkInformationStringKey.h" #include "vtkInformationVector.h" #include "vtkPartitionedDataSet.h" //------------------------------------------------------------------------------ VTK_ABI_NAMESPACE_BEGIN vtkDataObjectTree::vtkDataObjectTree() { this->Internals = new vtkDataObjectTreeInternals; } //------------------------------------------------------------------------------ vtkDataObjectTree::~vtkDataObjectTree() { delete this->Internals; } //------------------------------------------------------------------------------ vtkDataObjectTree* vtkDataObjectTree::GetData(vtkInformation* info) { return info ? vtkDataObjectTree::SafeDownCast(info->Get(DATA_OBJECT())) : nullptr; } //------------------------------------------------------------------------------ vtkDataObjectTree* vtkDataObjectTree::GetData(vtkInformationVector* v, int i) { return vtkDataObjectTree::GetData(v->GetInformationObject(i)); } //------------------------------------------------------------------------------ void vtkDataObjectTree::SetNumberOfChildren(unsigned int num) { this->Internals->Children.resize(num); this->Modified(); } //------------------------------------------------------------------------------ unsigned int vtkDataObjectTree::GetNumberOfChildren() { return static_cast(this->Internals->Children.size()); } //------------------------------------------------------------------------------ void vtkDataObjectTree::SetChild(unsigned int index, vtkDataObject* dobj) { if (this->Internals->Children.size() <= index) { this->SetNumberOfChildren(index + 1); } vtkDataObjectTreeItem& item = this->Internals->Children[index]; if (item.DataObject != dobj) { item.DataObject = dobj; this->Modified(); } } //------------------------------------------------------------------------------ void vtkDataObjectTree::RemoveChild(unsigned int index) { if (this->Internals->Children.size() <= index) { vtkErrorMacro("The input index is out of range."); return; } vtkDataObjectTreeItem& item = this->Internals->Children[index]; item.DataObject = nullptr; this->Internals->Children.erase(this->Internals->Children.begin() + index); this->Modified(); } //------------------------------------------------------------------------------ vtkDataObject* vtkDataObjectTree::GetChild(unsigned int index) { if (index < this->Internals->Children.size()) { return this->Internals->Children[index].DataObject; } return nullptr; } //------------------------------------------------------------------------------ vtkInformation* vtkDataObjectTree::GetChildMetaData(unsigned int index) { if (index < this->Internals->Children.size()) { vtkDataObjectTreeItem& item = this->Internals->Children[index]; if (!item.MetaData) { // New vtkInformation is allocated is none is already present. item.MetaData.TakeReference(vtkInformation::New()); } return item.MetaData; } return nullptr; } //------------------------------------------------------------------------------ void vtkDataObjectTree::SetChildMetaData(unsigned int index, vtkInformation* info) { if (this->Internals->Children.size() <= index) { this->SetNumberOfChildren(index + 1); } vtkDataObjectTreeItem& item = this->Internals->Children[index]; item.MetaData = info; } //------------------------------------------------------------------------------ vtkTypeBool vtkDataObjectTree::HasChildMetaData(unsigned int index) { if (index < this->Internals->Children.size()) { vtkDataObjectTreeItem& item = this->Internals->Children[index]; return (item.MetaData != nullptr) ? 1 : 0; } return 0; } //------------------------------------------------------------------------------ void vtkDataObjectTree::CopyStructure(vtkCompositeDataSet* compositeSource) { if (!compositeSource) { return; } auto dObjTree = vtkDataObjectTree::SafeDownCast(compositeSource); if (dObjTree == this) { return; } this->Superclass::CopyStructure(compositeSource); this->Internals->Children.clear(); if (dObjTree) { this->Internals->Children.resize(dObjTree->Internals->Children.size()); for (auto dObjTreeIter = dObjTree->Internals->Children.begin(), thisIter = this->Internals->Children.begin(); dObjTreeIter != dObjTree->Internals->Children.end(); ++dObjTreeIter, ++thisIter) { vtkDataObjectTree* subDObjTree = vtkDataObjectTree::SafeDownCast(dObjTreeIter->DataObject); if (subDObjTree) { if (vtkDataObjectTree* copy = this->CreateForCopyStructure(subDObjTree)) { thisIter->DataObject.TakeReference(copy); copy->CopyStructure(subDObjTree); } else { vtkErrorMacro("CopyStructure has encountered an error and will fail!"); } } // shallow copy meta data. if (dObjTreeIter->MetaData) { vtkNew info; info->Copy(dObjTreeIter->MetaData, /*deep=*/0); thisIter->MetaData = info; } } } else { // WARNING: // If we copy the structure from a non-tree composite data set // we create a special structure of two levels, the first level // is just a single partitioned dataSet and the second level are all the data sets. // This is likely to change in the future! vtkNew tempPds; auto pds = vtk::TakeSmartPointer(this->CreateForCopyStructure(tempPds)); this->SetChild(0, pds); vtkNew info; info->Set(vtkCompositeDataSet::NAME(), "All Blocks"); this->SetChildMetaData(0, info); int totalNumBlocks = 0; auto iter = vtk::TakeSmartPointer(compositeSource->NewIterator()); iter->SkipEmptyNodesOff(); for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) { ++totalNumBlocks; } pds->SetNumberOfChildren(totalNumBlocks); } this->Modified(); } //------------------------------------------------------------------------------ vtkDataObjectTree* vtkDataObjectTree::CreateForCopyStructure(vtkDataObjectTree* other) { return other ? other->NewInstance() : nullptr; } //------------------------------------------------------------------------------ vtkDataObjectTreeIterator* vtkDataObjectTree::NewTreeIterator() { vtkDataObjectTreeIterator* dObjTreeIter = vtkDataObjectTreeIterator::New(); dObjTreeIter->SetDataSet(this); return dObjTreeIter; } //------------------------------------------------------------------------------ vtkCompositeDataIterator* vtkDataObjectTree::NewIterator() { return this->NewTreeIterator(); } //------------------------------------------------------------------------------ void vtkDataObjectTree::SetDataSet(vtkCompositeDataIterator* iter, vtkDataObject* dataObj) { if (auto dObjTreeIter = vtkDataObjectTreeIterator::SafeDownCast(iter)) { this->SetDataSetFrom(dObjTreeIter, dataObj); return; } if (!iter || iter->IsDoneWithTraversal()) { vtkErrorMacro("Invalid iterator location."); return; } // WARNING: We are doing something special here. See comments // in CopyStructure() unsigned int index = iter->GetCurrentFlatIndex(); if (this->GetNumberOfChildren() != 1) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return; } auto parent = vtkPartitionedDataSet::SafeDownCast(this->GetChild(0)); if (!parent) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return; } parent->SetChild(index, dataObj); } //------------------------------------------------------------------------------ void vtkDataObjectTree::SetDataSetFrom( vtkDataObjectTreeIterator* dObjTreeIter, vtkDataObject* dataObj) { if (!dObjTreeIter || dObjTreeIter->IsDoneWithTraversal()) { vtkErrorMacro("Invalid iterator location."); return; } vtkDataObjectTreeIndex index = dObjTreeIter->GetCurrentIndex(); if (index.empty()) { // Sanity check. vtkErrorMacro("Invalid index returned by iterator."); return; } vtkDataObjectTree* parent = this; int numIndices = static_cast(index.size()); for (int cc = 0; cc < numIndices - 1; cc++) { if (!parent || parent->GetNumberOfChildren() <= index[cc]) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return; } parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc])); } if (!parent || parent->GetNumberOfChildren() <= index.back()) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return; } parent->SetChild(index.back(), dataObj); } //------------------------------------------------------------------------------ vtkDataObject* vtkDataObjectTree::GetDataSet(vtkCompositeDataIterator* compositeIter) { if (!compositeIter || compositeIter->IsDoneWithTraversal()) { vtkErrorMacro("Invalid iterator location."); return nullptr; } if (auto dObjTreeIter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter)) { vtkDataObjectTreeIndex index = dObjTreeIter->GetCurrentIndex(); if (index.empty()) { // Sanity check. vtkErrorMacro("Invalid index returned by iterator."); return nullptr; } vtkDataObjectTree* parent = this; int numIndices = static_cast(index.size()); for (int cc = 0; cc < numIndices - 1; cc++) { if (!parent || parent->GetNumberOfChildren() <= index[cc]) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return nullptr; } parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc])); } if (!parent || parent->GetNumberOfChildren() <= index.back()) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return nullptr; } return parent->GetChild(index.back()); } else { // WARNING: We are doing something special here. See comments // in CopyStructure() // To do: More clear check of structures here. At least something like this->Depth()==1 unsigned int currentFlatIndex = compositeIter->GetCurrentFlatIndex(); if (this->GetNumberOfChildren() != 1) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return nullptr; } auto parent = vtkPartitionedDataSet::SafeDownCast(this->GetChild(0)); if (!parent) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return nullptr; } if (currentFlatIndex < parent->GetNumberOfChildren()) { return parent->GetChild(currentFlatIndex); } else { return nullptr; } } } //------------------------------------------------------------------------------ vtkInformation* vtkDataObjectTree::GetMetaData(vtkCompositeDataIterator* compositeIter) { auto dObjTreeIter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter); if (!dObjTreeIter || dObjTreeIter->IsDoneWithTraversal()) { vtkErrorMacro("Invalid iterator location."); return nullptr; } vtkDataObjectTreeIndex index = dObjTreeIter->GetCurrentIndex(); if (index.empty()) { // Sanity check. vtkErrorMacro("Invalid index returned by iterator."); return nullptr; } vtkDataObjectTree* parent = this; int numIndices = static_cast(index.size()); for (int cc = 0; cc < numIndices - 1; cc++) { if (!parent || parent->GetNumberOfChildren() <= index[cc]) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return nullptr; } parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc])); } if (!parent || parent->GetNumberOfChildren() <= index.back()) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return nullptr; } return parent->GetChildMetaData(index.back()); } //------------------------------------------------------------------------------ vtkTypeBool vtkDataObjectTree::HasMetaData(vtkCompositeDataIterator* compositeIter) { auto dObjTreeIter = vtkDataObjectTreeIterator::SafeDownCast(compositeIter); if (!dObjTreeIter || dObjTreeIter->IsDoneWithTraversal()) { vtkErrorMacro("Invalid iterator location."); return 0; } vtkDataObjectTreeIndex index = dObjTreeIter->GetCurrentIndex(); if (index.empty()) { // Sanity check. vtkErrorMacro("Invalid index returned by iterator."); return 0; } vtkDataObjectTree* parent = this; int numIndices = static_cast(index.size()); for (int cc = 0; cc < numIndices - 1; cc++) { if (!parent || parent->GetNumberOfChildren() <= index[cc]) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return 0; } parent = vtkDataObjectTree::SafeDownCast(parent->GetChild(index[cc])); } if (!parent || parent->GetNumberOfChildren() <= index.back()) { vtkErrorMacro("Structure is not expected. Did you forget to use copy structure?"); return 0; } return parent->HasChildMetaData(index.back()); } //------------------------------------------------------------------------------ void vtkDataObjectTree::CompositeShallowCopy(vtkCompositeDataSet* src) { if (src == this) { return; } this->Internals->Children.clear(); this->Superclass::CompositeShallowCopy(src); if (auto from = vtkDataObjectTree::SafeDownCast(src)) { unsigned int numChildren = from->GetNumberOfChildren(); this->SetNumberOfChildren(numChildren); for (unsigned int cc = 0; cc < numChildren; cc++) { if (auto child = from->GetChild(cc)) { if (auto childTree = vtkDataObjectTree::SafeDownCast(child)) { vtkDataObjectTree* clone = childTree->NewInstance(); clone->CompositeShallowCopy(childTree); this->SetChild(cc, clone); clone->FastDelete(); } else { this->SetChild(cc, child); } } if (from->HasChildMetaData(cc)) { vtkInformation* toInfo = this->GetChildMetaData(cc); toInfo->Copy(from->GetChildMetaData(cc), 0); } } } this->Modified(); } //------------------------------------------------------------------------------ void vtkDataObjectTree::DeepCopy(vtkDataObject* src) { if (src == this) { return; } this->Internals->Children.clear(); this->Superclass::DeepCopy(src); if (auto from = vtkDataObjectTree::SafeDownCast(src)) { unsigned int numChildren = from->GetNumberOfChildren(); this->SetNumberOfChildren(numChildren); for (unsigned int cc = 0; cc < numChildren; cc++) { if (auto fromChild = from->GetChild(cc)) { vtkDataObject* toChild = fromChild->NewInstance(); toChild->DeepCopy(fromChild); this->SetChild(cc, toChild); toChild->FastDelete(); if (from->HasChildMetaData(cc)) { vtkInformation* toInfo = this->GetChildMetaData(cc); toInfo->Copy(from->GetChildMetaData(cc), /*deep=*/1); } } } } this->Modified(); } //------------------------------------------------------------------------------ void vtkDataObjectTree::ShallowCopy(vtkDataObject* src) { if (src == this) { return; } this->Internals->Children.clear(); this->Superclass::ShallowCopy(src); if (auto from = vtkDataObjectTree::SafeDownCast(src)) { unsigned int numChildren = from->GetNumberOfChildren(); this->SetNumberOfChildren(numChildren); for (unsigned int cc = 0; cc < numChildren; cc++) { if (auto child = from->GetChild(cc)) { auto clone = child->NewInstance(); clone->ShallowCopy(child); this->SetChild(cc, clone); clone->FastDelete(); } if (from->HasChildMetaData(cc)) { vtkInformation* toInfo = this->GetChildMetaData(cc); toInfo->Copy(from->GetChildMetaData(cc), /*deep=*/0); } } } this->Modified(); } //------------------------------------------------------------------------------ void vtkDataObjectTree::Initialize() { this->Internals->Children.clear(); this->Superclass::Initialize(); } //------------------------------------------------------------------------------ vtkIdType vtkDataObjectTree::GetNumberOfPoints() { vtkIdType numPts = 0; auto dObjTreeIter = vtk::TakeSmartPointer(this->NewIterator()); for (dObjTreeIter->InitTraversal(); !dObjTreeIter->IsDoneWithTraversal(); dObjTreeIter->GoToNextItem()) { if (auto ds = vtkDataSet::SafeDownCast(dObjTreeIter->GetCurrentDataObject())) { numPts += ds->GetNumberOfPoints(); } } return numPts; } //------------------------------------------------------------------------------ vtkIdType vtkDataObjectTree::GetNumberOfCells() { vtkIdType numCells = 0; auto dObjTreeIter = vtk::TakeSmartPointer(this->NewIterator()); for (dObjTreeIter->InitTraversal(); !dObjTreeIter->IsDoneWithTraversal(); dObjTreeIter->GoToNextItem()) { if (auto ds = vtkDataSet::SafeDownCast(dObjTreeIter->GetCurrentDataObject())) { numCells += ds->GetNumberOfCells(); } else if (auto cg = vtkCellGrid::SafeDownCast(dObjTreeIter->GetCurrentDataObject())) { numCells += cg->GetNumberOfCells(); } } return numCells; } //------------------------------------------------------------------------------ unsigned long vtkDataObjectTree::GetActualMemorySize() { unsigned long memSize = 0; auto dObjTreeIter = vtk::TakeSmartPointer(this->NewIterator()); for (dObjTreeIter->InitTraversal(); !dObjTreeIter->IsDoneWithTraversal(); dObjTreeIter->GoToNextItem()) { vtkDataObject* dobj = dObjTreeIter->GetCurrentDataObject(); memSize += dobj->GetActualMemorySize(); } return memSize; } //------------------------------------------------------------------------------ void vtkDataObjectTree::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Number Of Children: " << this->GetNumberOfChildren() << endl; for (unsigned int cc = 0; cc < this->GetNumberOfChildren(); cc++) { const char* name = (this->HasChildMetaData(cc) && this->GetChildMetaData(cc)->Has(NAME())) ? this->GetChildMetaData(cc)->Get(NAME()) : nullptr; vtkDataObject* child = this->GetChild(cc); if (child) { os << indent << "Child " << cc << ": " << child->GetClassName() << endl; os << indent << "Name: " << (name ? name : "(nullptr)") << endl; child->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Child " << cc << ": nullptr" << endl; os << indent << "Name: " << (name ? name : "(nullptr)") << endl; } } } VTK_ABI_NAMESPACE_END