#include "vtkLabelSizeCalculator.h" #include "vtkCellData.h" #include "vtkDataObject.h" #include "vtkDataSet.h" #include "vtkDataSetAttributes.h" #include "vtkFieldData.h" #include "vtkGraph.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkIntArray.h" #include "vtkLabelHierarchy.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPointSet.h" #include "vtkSmartPointer.h" #include "vtkStringArray.h" #include "vtkTable.h" #include "vtkTextProperty.h" #include "vtkTextRenderer.h" #include class vtkLabelSizeCalculator::Internals { public: std::map > FontProperties; }; vtkStandardNewMacro(vtkLabelSizeCalculator); vtkCxxSetObjectMacro(vtkLabelSizeCalculator,FontUtil,vtkTextRenderer); vtkLabelSizeCalculator::vtkLabelSizeCalculator() { this->Implementation = new Internals; // Always defined but user may set to nullptr. this->Implementation->FontProperties[0] = vtkSmartPointer::New(); this->FontUtil = vtkTextRenderer::New(); // Never a nullptr moment. this->LabelSizeArrayName = nullptr; this->SetLabelSizeArrayName( "LabelSize" ); this->DPI = 72; this->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "LabelText"); this->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Type"); } vtkLabelSizeCalculator::~vtkLabelSizeCalculator() { this->SetFontUtil( nullptr ); this->SetLabelSizeArrayName( nullptr ); delete this->Implementation; } void vtkLabelSizeCalculator::PrintSelf( ostream& os, vtkIndent indent ) { this->Superclass::PrintSelf( os, indent ); os << indent << "LabelSizeArrayName: " << this->LabelSizeArrayName << "\n"; os << indent << "FontProperties: "; std::map >::iterator it, itEnd; it = this->Implementation->FontProperties.begin(); itEnd = this->Implementation->FontProperties.end(); for ( ; it != itEnd; ++it ) { os << indent << " " << it->first << ": " << it->second << endl; } os << indent << "FontUtil: " << this->FontUtil << "\n"; } int vtkLabelSizeCalculator::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info ) { info->Remove( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE() ); info->Append( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet" ); info->Append( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph" ); return 1; } void vtkLabelSizeCalculator::SetFontProperty(vtkTextProperty* prop, int type) { this->Implementation->FontProperties[type] = prop; } vtkTextProperty* vtkLabelSizeCalculator::GetFontProperty(int type) { if (this->Implementation->FontProperties.find(type) != this->Implementation->FontProperties.end()) { return this->Implementation->FontProperties[type]; } return nullptr; } int vtkLabelSizeCalculator::RequestData( vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector ) { // get the info objects vtkInformation* inInfo = inputVector[0]->GetInformationObject( 0 ); vtkInformation* outInfo = outputVector->GetInformationObject( 0 ); // get the input and output vtkDataObject* input = inInfo->Get( vtkDataObject::DATA_OBJECT() ); vtkDataObject* output = outInfo->Get( vtkDataObject::DATA_OBJECT() ); vtkFieldData* inFD = nullptr; vtkFieldData* outFD = nullptr; vtkDataSet* dsInput = vtkDataSet::SafeDownCast( input ); vtkDataSet* dsOutput = vtkDataSet::SafeDownCast( output ); vtkGraph* graphInput = vtkGraph::SafeDownCast( input ); vtkGraph* graphOutput = vtkGraph::SafeDownCast( output ); // if input is empty, we are done if (graphInput && graphInput->GetNumberOfVertices() == 0) { return 1; } if (dsInput && dsInput->GetNumberOfPoints() == 0) { return 1; } if ( ! this->Implementation->FontProperties[0] ) { vtkErrorMacro( "nullptr default font property, so I cannot compute label sizes." ); return 0; } if ( ! this->LabelSizeArrayName ) { vtkErrorMacro( "nullptr value for LabelSizeArrayName." ); return 0; } // Figure out which array to process vtkAbstractArray* inArr = this->GetInputAbstractArrayToProcess( 0, inputVector ); if ( ! inArr ) { vtkErrorMacro( "No input array available." ); return 0; } vtkIntArray* typeArr = vtkArrayDownCast( this->GetInputAbstractArrayToProcess( 1, inputVector )); vtkInformation* inArrInfo = this->GetInputArrayInformation( 0 ); int fieldAssoc = inArrInfo->Get( vtkDataObject::FIELD_ASSOCIATION() ); vtkIntArray* lsz = this->LabelSizesForArray( inArr, typeArr ); #if 0 cout << "Input array... port: " << port << " connection: " << connection << " field association: " << fieldAssoc << " attribute type: " << attribType << "\n"; #endif // 0 if ( dsInput ) { dsOutput->CopyStructure( dsInput ); dsOutput->CopyAttributes( dsInput ); if ( fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_VERTICES || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE ) { outFD = dsOutput->GetPointData(); outFD->AddArray( lsz ); } if ( ! inFD && ( fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_CELLS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_EDGES ) ) { outFD = dsOutput->GetCellData(); outFD->AddArray( lsz ); } vtkLabelHierarchy* hierarchyOutput = vtkLabelHierarchy::SafeDownCast( output ); if ( hierarchyOutput ) { hierarchyOutput->SetSizes( lsz ); } } else if ( graphInput ) { graphOutput->ShallowCopy( graphInput ); if ( fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_VERTICES || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE ) { outFD = graphOutput->GetVertexData(); outFD->AddArray( lsz ); } if ( ! inFD && ( fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_CELLS || fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_EDGES ) ) { outFD = graphOutput->GetEdgeData(); outFD->AddArray( lsz ); } } lsz->Delete(); return 1; } vtkIntArray* vtkLabelSizeCalculator::LabelSizesForArray( vtkAbstractArray* labels, vtkIntArray* types ) { vtkIdType nl = labels->GetNumberOfTuples(); vtkIntArray* lsz = vtkIntArray::New(); lsz->SetName( this->LabelSizeArrayName ); lsz->SetNumberOfComponents( 4 ); lsz->SetNumberOfTuples( nl ); int bbox[4]; int* bds = lsz->GetPointer( 0 ); for ( vtkIdType i = 0; i < nl; ++ i ) { int type = 0; if ( types ) { type = types->GetValue( i ); } vtkTextProperty* prop = this->Implementation->FontProperties[type]; if (!prop) { prop = this->Implementation->FontProperties[0]; } this->FontUtil->GetBoundingBox( prop, labels->GetVariantValue(i).ToString().c_str(), bbox, this->DPI); bds[0] = bbox[1] - bbox[0]; bds[1] = bbox[3] - bbox[2]; bds[2] = bbox[0]; bds[3] = bbox[2]; if( this->GetDebug() ) { cout << "LSC: " << bds[0] << " " << bds[1] << " " << bds[2] << " " << bds[3] << " \"" << labels->GetVariantValue( i ).ToString().c_str() << "\"\n"; } bds += 4; } return lsz; }