// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkGraphAnnotationLayersFilter.h" #include "vtkAnnotation.h" #include "vtkAnnotationLayers.h" #include "vtkAppendPolyData.h" #include "vtkCellData.h" #include "vtkConvexHull2D.h" #include "vtkDataSetAttributes.h" #include "vtkDoubleArray.h" #include "vtkGraph.h" #include "vtkIdTypeArray.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkRenderer.h" #include "vtkSelection.h" #include "vtkSelectionNode.h" #include "vtkSmartPointer.h" #include "vtkStringArray.h" #include "vtkUnsignedCharArray.h" VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkGraphAnnotationLayersFilter); //------------------------------------------------------------------------------ vtkGraphAnnotationLayersFilter::vtkGraphAnnotationLayersFilter() { this->SetNumberOfInputPorts(2); this->SetNumberOfOutputPorts(2); this->HullAppend = vtkSmartPointer::New(); this->OutlineAppend = vtkSmartPointer::New(); this->ConvexHullFilter = vtkSmartPointer::New(); } //------------------------------------------------------------------------------ vtkGraphAnnotationLayersFilter::~vtkGraphAnnotationLayersFilter() = default; //------------------------------------------------------------------------------ int vtkGraphAnnotationLayersFilter::FillInputPortInformation(int port, vtkInformation* info) { if (port == 0) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph"); return 1; } else if (port == 1) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkAnnotationLayers"); return 1; } return 0; } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::OutlineOn() { this->ConvexHullFilter->OutlineOn(); } void vtkGraphAnnotationLayersFilter::OutlineOff() { this->ConvexHullFilter->OutlineOff(); } void vtkGraphAnnotationLayersFilter::SetOutline(bool b) { this->ConvexHullFilter->SetOutline(b); } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::SetScaleFactor(double scale) { this->ConvexHullFilter->SetScaleFactor(scale); } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::SetHullShapeToBoundingRectangle() { this->ConvexHullFilter->SetHullShape(vtkConvexHull2D::BoundingRectangle); } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::SetHullShapeToConvexHull() { this->ConvexHullFilter->SetHullShape(vtkConvexHull2D::ConvexHull); } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::SetMinHullSizeInWorld(double size) { this->ConvexHullFilter->SetMinHullSizeInWorld(size); } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::SetMinHullSizeInDisplay(int size) { this->ConvexHullFilter->SetMinHullSizeInDisplay(size); } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::SetRenderer(vtkRenderer* renderer) { this->ConvexHullFilter->SetRenderer(renderer); } //------------------------------------------------------------------------------ vtkMTimeType vtkGraphAnnotationLayersFilter::GetMTime() { if (this->ConvexHullFilter) { return this->ConvexHullFilter->GetMTime(); } else { return this->MTime; } } //------------------------------------------------------------------------------ int vtkGraphAnnotationLayersFilter::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // Get the input and output. vtkInformation* inGraphInfo = inputVector[0]->GetInformationObject(0); vtkInformation* inLayersInfo = inputVector[1]->GetInformationObject(0); vtkGraph* graph = vtkGraph::SafeDownCast(inGraphInfo->Get(vtkDataObject::DATA_OBJECT())); vtkPoints* inputPoints = graph->GetPoints(); vtkAnnotationLayers* layers = vtkAnnotationLayers::SafeDownCast(inLayersInfo->Get(vtkDataObject::DATA_OBJECT())); vtkInformation* outInfo0 = outputVector->GetInformationObject(0); vtkInformation* outInfo1 = outputVector->GetInformationObject(1); vtkPolyData* outputHull = vtkPolyData::SafeDownCast(outInfo0->Get(vtkDataObject::DATA_OBJECT())); vtkPolyData* outputOutline = vtkPolyData::SafeDownCast(outInfo1->Get(vtkDataObject::DATA_OBJECT())); this->HullAppend->RemoveAllInputs(); this->OutlineAppend->RemoveAllInputs(); unsigned numberOfAnnotations = layers->GetNumberOfAnnotations(); // Generate one hull/polydata per selection node vtkIdType hullId = 0; for (unsigned annotationId = 0; annotationId < numberOfAnnotations; ++annotationId) { vtkAnnotation* annotation = layers->GetAnnotation(annotationId); if (annotation->GetInformation()->Get(vtkAnnotation::ENABLE()) == 0) { continue; } vtkSelection* selection = annotation->GetSelection(); unsigned numberOfSelectionNodes = selection->GetNumberOfNodes(); for (unsigned selectionNodeId = 0; selectionNodeId < numberOfSelectionNodes; ++selectionNodeId) { vtkSmartPointer hullPoints = vtkSmartPointer::New(); hullId++; vtkSelectionNode* selectionNode = selection->GetNode(selectionNodeId); if (selectionNode->GetFieldType() != vtkSelectionNode::VERTEX) { continue; } vtkIdTypeArray* vertexIds = vtkArrayDownCast(selectionNode->GetSelectionList()); // Get points from graph vtkIdType numberOfNodePoints = vertexIds->GetNumberOfTuples(); if (numberOfNodePoints == 0) { continue; } for (vtkIdType i = 0; i < numberOfNodePoints; ++i) { hullPoints->InsertNextPoint(inputPoints->GetPoint(vertexIds->GetValue(i))); } // Create filled polygon vtkSmartPointer hullPolyData = vtkSmartPointer::New(); hullPolyData->SetPoints(hullPoints); ConvexHullFilter->SetInputData(hullPolyData); ConvexHullFilter->Update(); hullPolyData->ShallowCopy(ConvexHullFilter->GetOutput()); // Add data arrays to the polydata vtkIdType representativeVertex = vertexIds->GetValue(0); vtkIdType numberOfCells = hullPolyData->GetNumberOfCells(); vtkUnsignedCharArray* outColors = vtkUnsignedCharArray::New(); outColors->SetNumberOfComponents(4); outColors->SetName("Hull color"); double* color = annotation->GetInformation()->Get(vtkAnnotation::COLOR()); double opacity = annotation->GetInformation()->Get(vtkAnnotation::OPACITY()); unsigned char outColor[4] = { static_cast(color[0] * 255), static_cast(color[1] * 255), static_cast(color[2] * 255), static_cast(opacity * 255) }; for (vtkIdType i = 0; i < numberOfCells; ++i) { outColors->InsertNextTypedTuple(outColor); } hullPolyData->GetCellData()->AddArray(outColors); outColors->Delete(); vtkIdTypeArray* hullIds = vtkIdTypeArray::New(); hullIds->SetName("Hull id"); for (vtkIdType i = 0; i < numberOfCells; ++i) { hullIds->InsertNextValue(hullId); } hullPolyData->GetCellData()->AddArray(hullIds); hullIds->Delete(); vtkStringArray* hullName = vtkStringArray::New(); hullName->SetName("Hull name"); for (vtkIdType i = 0; i < numberOfCells; ++i) { hullName->InsertNextValue(annotation->GetInformation()->Get(vtkAnnotation::LABEL())); } hullPolyData->GetCellData()->AddArray(hullName); hullName->Delete(); vtkDoubleArray* hullCentreVertex = vtkDoubleArray::New(); hullCentreVertex->SetName("Hull point"); hullCentreVertex->SetNumberOfComponents(3); for (vtkIdType i = 0; i < numberOfCells; ++i) { hullCentreVertex->InsertNextTuple(inputPoints->GetPoint(representativeVertex)); } hullPolyData->GetCellData()->AddArray(hullCentreVertex); hullCentreVertex->Delete(); this->HullAppend->AddInputData(hullPolyData); if (this->ConvexHullFilter->GetOutline()) { vtkSmartPointer outlinePolyData = vtkSmartPointer::New(); outlinePolyData->ShallowCopy(ConvexHullFilter->GetOutput(1)); this->OutlineAppend->AddInputData(outlinePolyData); } } // Next selection node. } // Next annotation. // Send data to output if (this->HullAppend->GetNumberOfInputConnections(0) > 0) { this->HullAppend->Update(); outputHull->ShallowCopy(this->HullAppend->GetOutput()); } if (this->OutlineAppend->GetNumberOfInputConnections(0) > 0) { this->OutlineAppend->Update(); outputOutline->ShallowCopy(this->OutlineAppend->GetOutput()); } return 1; } //------------------------------------------------------------------------------ void vtkGraphAnnotationLayersFilter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "ConvexHull2D: "; if (this->ConvexHullFilter) { os << endl; this->ConvexHullFilter->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } } VTK_ABI_NAMESPACE_END