1 #include "vtkLabelSizeCalculator.h"
2
3 #include "vtkCellData.h"
4 #include "vtkDataObject.h"
5 #include "vtkDataSet.h"
6 #include "vtkDataSetAttributes.h"
7 #include "vtkFieldData.h"
8 #include "vtkGraph.h"
9 #include "vtkInformation.h"
10 #include "vtkInformationVector.h"
11 #include "vtkIntArray.h"
12 #include "vtkLabelHierarchy.h"
13 #include "vtkObjectFactory.h"
14 #include "vtkPointData.h"
15 #include "vtkPointSet.h"
16 #include "vtkSmartPointer.h"
17 #include "vtkStringArray.h"
18 #include "vtkTable.h"
19 #include "vtkTextProperty.h"
20 #include "vtkTextRenderer.h"
21
22 #include <map>
23
24 class vtkLabelSizeCalculator::Internals
25 {
26 public:
27 std::map<int, vtkSmartPointer<vtkTextProperty> > FontProperties;
28 };
29
30 vtkStandardNewMacro(vtkLabelSizeCalculator);
31 vtkCxxSetObjectMacro(vtkLabelSizeCalculator,FontUtil,vtkTextRenderer);
32
vtkLabelSizeCalculator()33 vtkLabelSizeCalculator::vtkLabelSizeCalculator()
34 {
35 this->Implementation = new Internals;
36 // Always defined but user may set to nullptr.
37 this->Implementation->FontProperties[0] = vtkSmartPointer<vtkTextProperty>::New();
38 this->FontUtil = vtkTextRenderer::New(); // Never a nullptr moment.
39 this->LabelSizeArrayName = nullptr;
40 this->SetLabelSizeArrayName( "LabelSize" );
41 this->DPI = 72;
42 this->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "LabelText");
43 this->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Type");
44 }
45
~vtkLabelSizeCalculator()46 vtkLabelSizeCalculator::~vtkLabelSizeCalculator()
47 {
48 this->SetFontUtil( nullptr );
49 this->SetLabelSizeArrayName( nullptr );
50 delete this->Implementation;
51 }
52
PrintSelf(ostream & os,vtkIndent indent)53 void vtkLabelSizeCalculator::PrintSelf( ostream& os, vtkIndent indent )
54 {
55 this->Superclass::PrintSelf( os, indent );
56 os << indent << "LabelSizeArrayName: " << this->LabelSizeArrayName << "\n";
57 os << indent << "FontProperties: ";
58 std::map<int, vtkSmartPointer<vtkTextProperty> >::iterator it, itEnd;
59 it = this->Implementation->FontProperties.begin();
60 itEnd = this->Implementation->FontProperties.end();
61 for ( ; it != itEnd; ++it )
62 {
63 os << indent << " " << it->first << ": " << it->second << endl;
64 }
65 os << indent << "FontUtil: " << this->FontUtil << "\n";
66 }
67
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)68 int vtkLabelSizeCalculator::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info )
69 {
70 info->Remove( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE() );
71 info->Append( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet" );
72 info->Append( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph" );
73 return 1;
74 }
75
SetFontProperty(vtkTextProperty * prop,int type)76 void vtkLabelSizeCalculator::SetFontProperty(vtkTextProperty* prop, int type)
77 {
78 this->Implementation->FontProperties[type] = prop;
79 }
80
GetFontProperty(int type)81 vtkTextProperty* vtkLabelSizeCalculator::GetFontProperty(int type)
82 {
83 if (this->Implementation->FontProperties.find(type) !=
84 this->Implementation->FontProperties.end())
85 {
86 return this->Implementation->FontProperties[type];
87 }
88 return nullptr;
89 }
90
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)91 int vtkLabelSizeCalculator::RequestData(
92 vtkInformation* vtkNotUsed(request),
93 vtkInformationVector** inputVector,
94 vtkInformationVector* outputVector )
95 {
96 // get the info objects
97 vtkInformation* inInfo = inputVector[0]->GetInformationObject( 0 );
98 vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
99
100 // get the input and output
101 vtkDataObject* input = inInfo->Get( vtkDataObject::DATA_OBJECT() );
102 vtkDataObject* output = outInfo->Get( vtkDataObject::DATA_OBJECT() );
103
104 vtkFieldData* inFD = nullptr;
105 vtkFieldData* outFD = nullptr;
106
107 vtkDataSet* dsInput = vtkDataSet::SafeDownCast( input );
108 vtkDataSet* dsOutput = vtkDataSet::SafeDownCast( output );
109 vtkGraph* graphInput = vtkGraph::SafeDownCast( input );
110 vtkGraph* graphOutput = vtkGraph::SafeDownCast( output );
111
112 // if input is empty, we are done
113 if (graphInput && graphInput->GetNumberOfVertices() == 0)
114 {
115 return 1;
116 }
117 if (dsInput && dsInput->GetNumberOfPoints() == 0)
118 {
119 return 1;
120 }
121
122 if ( ! this->Implementation->FontProperties[0] )
123 {
124 vtkErrorMacro( "nullptr default font property, so I cannot compute label sizes." );
125 return 0;
126 }
127
128 if ( ! this->LabelSizeArrayName )
129 {
130 vtkErrorMacro( "nullptr value for LabelSizeArrayName." );
131 return 0;
132 }
133
134 // Figure out which array to process
135 vtkAbstractArray* inArr = this->GetInputAbstractArrayToProcess( 0, inputVector );
136 if ( ! inArr )
137 {
138 vtkErrorMacro( "No input array available." );
139 return 0;
140 }
141 vtkIntArray* typeArr = vtkArrayDownCast<vtkIntArray>(
142 this->GetInputAbstractArrayToProcess( 1, inputVector ));
143
144 vtkInformation* inArrInfo = this->GetInputArrayInformation( 0 );
145 int fieldAssoc = inArrInfo->Get( vtkDataObject::FIELD_ASSOCIATION() );
146
147 vtkIntArray* lsz = this->LabelSizesForArray( inArr, typeArr );
148 #if 0
149 cout
150 << "Input array... port: " << port << " connection: " << connection
151 << " field association: " << fieldAssoc << " attribute type: " << attribType << "\n";
152 #endif // 0
153
154 if ( dsInput )
155 {
156 dsOutput->CopyStructure( dsInput );
157 dsOutput->CopyAttributes( dsInput );
158 if (
159 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE ||
160 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS ||
161 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS ||
162 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_VERTICES ||
163 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE )
164 {
165 outFD = dsOutput->GetPointData();
166 outFD->AddArray( lsz );
167 }
168 if (
169 ! inFD && (
170 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS ||
171 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_CELLS ||
172 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_EDGES
173 ) )
174 {
175 outFD = dsOutput->GetCellData();
176 outFD->AddArray( lsz );
177 }
178 vtkLabelHierarchy* hierarchyOutput = vtkLabelHierarchy::SafeDownCast( output );
179 if ( hierarchyOutput )
180 {
181 hierarchyOutput->SetSizes( lsz );
182 }
183 }
184 else if ( graphInput )
185 {
186 graphOutput->ShallowCopy( graphInput );
187 if (
188 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE ||
189 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS ||
190 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS ||
191 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_VERTICES ||
192 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE )
193 {
194 outFD = graphOutput->GetVertexData();
195 outFD->AddArray( lsz );
196 }
197 if (
198 ! inFD && (
199 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS ||
200 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_CELLS ||
201 fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_EDGES
202 ) )
203 {
204 outFD = graphOutput->GetEdgeData();
205 outFD->AddArray( lsz );
206 }
207 }
208 lsz->Delete();
209
210 return 1;
211 }
212
LabelSizesForArray(vtkAbstractArray * labels,vtkIntArray * types)213 vtkIntArray* vtkLabelSizeCalculator::LabelSizesForArray(
214 vtkAbstractArray* labels,
215 vtkIntArray* types )
216 {
217 vtkIdType nl = labels->GetNumberOfTuples();
218
219 vtkIntArray* lsz = vtkIntArray::New();
220 lsz->SetName( this->LabelSizeArrayName );
221 lsz->SetNumberOfComponents( 4 );
222 lsz->SetNumberOfTuples( nl );
223
224 int bbox[4];
225 int* bds = lsz->GetPointer( 0 );
226 for ( vtkIdType i = 0; i < nl; ++ i )
227 {
228 int type = 0;
229 if ( types )
230 {
231 type = types->GetValue( i );
232 }
233 vtkTextProperty* prop = this->Implementation->FontProperties[type];
234 if (!prop)
235 {
236 prop = this->Implementation->FontProperties[0];
237 }
238 this->FontUtil->GetBoundingBox(
239 prop, labels->GetVariantValue(i).ToString().c_str(), bbox, this->DPI);
240 bds[0] = bbox[1] - bbox[0];
241 bds[1] = bbox[3] - bbox[2];
242 bds[2] = bbox[0];
243 bds[3] = bbox[2];
244
245 if( this->GetDebug() )
246 {
247 cout << "LSC: "
248 << bds[0] << " " << bds[1] << " " << bds[2] << " " << bds[3]
249 << " \"" << labels->GetVariantValue( i ).ToString().c_str() << "\"\n";
250 }
251
252 bds += 4;
253 }
254
255 return lsz;
256 }
257
258