// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkHyperTreeGridCellCenters.h" #include "vtkAlgorithm.h" #include "vtkBitArray.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkHyperTree.h" #include "vtkHyperTreeGrid.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPoints.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkHyperTreeGridNonOrientedGeometryCursor.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkHyperTreeGridCellCenters); //------------------------------------------------------------------------------ vtkHyperTreeGridCellCenters::vtkHyperTreeGridCellCenters() { this->Input = nullptr; this->Output = nullptr; this->InData = nullptr; this->OutData = nullptr; this->Points = nullptr; } //------------------------------------------------------------------------------ vtkHyperTreeGridCellCenters::~vtkHyperTreeGridCellCenters() = default; //------------------------------------------------------------------------------ vtkTypeBool vtkHyperTreeGridCellCenters::ProcessRequest( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // generate the data if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) { return this->RequestData(request, inputVector, outputVector); } if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) { return this->RequestUpdateExtent(request, inputVector, outputVector); } // execute information if (request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) { return this->RequestInformation(request, inputVector, outputVector); } return this->Superclass::ProcessRequest(request, inputVector, outputVector); } //------------------------------------------------------------------------------ int vtkHyperTreeGridCellCenters::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkHyperTreeGrid"); return 1; } //------------------------------------------------------------------------------ void vtkHyperTreeGridCellCenters::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); if (this->Input) { os << indent << "Input:\n"; this->Input->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Input: ( none )\n"; } if (this->Output) { os << indent << "Output:\n"; this->Output->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Output: ( none )\n"; } if (this->Points) { os << indent << "Points:\n"; this->Points->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Points: ( none )\n"; } } //------------------------------------------------------------------------------ int vtkHyperTreeGridCellCenters::RequestData( vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // Get the information objects vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); vtkInformation* outInfo = outputVector->GetInformationObject(0); // Retrieve input and output this->Input = vtkHyperTreeGrid::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); this->Output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // Initialize output cell data this->InData = this->Input->GetCellData(); this->OutData = this->Output->GetPointData(); this->OutData->CopyAllocate(this->InData); // General cell centers of hyper tree grid this->ProcessTrees(); // Squeeze output data this->OutData->Squeeze(); // Clean up this->Input = nullptr; this->Output = nullptr; this->InData = nullptr; this->OutData = nullptr; this->UpdateProgress(1.); return 1; } //------------------------------------------------------------------------------ void vtkHyperTreeGridCellCenters::ProcessTrees() { // Create storage for corners of leaf cells this->Points = vtkPoints::New(); // Retrieve material mask this->InMask = this->Input->HasMask() ? this->Input->GetMask() : nullptr; // Iterate over all hyper trees vtkIdType index; vtkHyperTreeGrid::vtkHyperTreeGridIterator it; this->Input->InitializeTreeIterator(it); vtkNew cursor; while (it.GetNextTree(index)) { if (this->CheckAbort()) { break; } // Initialize new geometric cursor at root of current tree this->Input->InitializeNonOrientedGeometryCursor(cursor, index); // Generate leaf cell centers recursively this->RecursivelyProcessTree(cursor); } // it // Set output geometry and topology if required this->Output->SetPoints(this->Points); if (this->VertexCells) { vtkIdType np = this->Points->GetNumberOfPoints(); vtkCellArray* vertices = vtkCellArray::New(); vertices->AllocateEstimate(np, 1); for (vtkIdType i = 0; i < np; ++i) { vertices->InsertNextCell(1, &i); } // i this->Output->SetVerts(vertices); vertices->Delete(); } // this->VertexCells if (this->VertexCells) { vtkIdType numPoints = this->Points->GetNumberOfPoints(); vtkNew iArray; iArray->SetNumberOfComponents(1); iArray->SetNumberOfTuples(numPoints * 2); for (vtkIdType i = 0; i < numPoints; i++) { iArray->SetValue(2 * i, 1); iArray->SetValue(2 * i + 1, i); } vtkNew verts; verts->AllocateEstimate(numPoints, 1); verts->ImportLegacyFormat(iArray); this->Output->SetVerts(verts); this->Output->GetCellData()->ShallowCopy(this->OutData); } // Clean up this->Points->Delete(); this->Points = nullptr; } //------------------------------------------------------------------------------ void vtkHyperTreeGridCellCenters::RecursivelyProcessTree( vtkHyperTreeGridNonOrientedGeometryCursor* cursor) { // Skip masked cells if (cursor->IsMasked()) { return; } // Create cell center if cursor is at leaf if (cursor->IsLeaf()) { // Cursor is at leaf, retrieve its global index vtkIdType id = cursor->GetGlobalNodeIndex(); // If leaf is masked, skip it if (this->InMask && this->InMask->GetValue(id)) { return; } // Retrieve cell center coordinates double pt[3]; cursor->GetPoint(pt); // Insert next point vtkIdType outId = this->Points->InsertNextPoint(pt); // Copy cell center data from leaf data, when needed this->OutData->CopyData(this->InData, id, outId); } else { // Cursor is not at leaf, recurse to all children int numChildren = this->Input->GetNumberOfChildren(); for (int child = 0; child < numChildren; ++child) { if (this->CheckAbort()) { break; } cursor->ToChild(child); // Recurse this->RecursivelyProcessTree(cursor); cursor->ToParent(); } // child } // else } VTK_ABI_NAMESPACE_END