1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPieChartActor.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkPieChartActor.h"
16 
17 #include "vtkAxisActor2D.h"
18 #include "vtkCellArray.h"
19 #include "vtkCellData.h"
20 #include "vtkFieldData.h"
21 #include "vtkGlyphSource2D.h"
22 #include "vtkLegendBoxActor.h"
23 #include "vtkMath.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkPolyData.h"
26 #include "vtkPolyDataMapper2D.h"
27 #include "vtkProperty2D.h"
28 #include "vtkTextMapper.h"
29 #include "vtkTextProperty.h"
30 #include "vtkTrivialProducer.h"
31 #include "vtkUnsignedCharArray.h"
32 #include "vtkViewport.h"
33 #include "vtkWindow.h"
34 
35 #include <string>
36 #include <vector>
37 
38 vtkStandardNewMacro(vtkPieChartActor);
39 
40 vtkCxxSetObjectMacro(vtkPieChartActor, LabelTextProperty, vtkTextProperty);
41 vtkCxxSetObjectMacro(vtkPieChartActor, TitleTextProperty, vtkTextProperty);
42 
43 // PIMPL'd list of labels
44 class vtkPieceLabelArray : public std::vector<std::string>
45 {
46 };
47 
48 class vtkPieChartActorConnection : public vtkAlgorithm
49 {
50 public:
51   static vtkPieChartActorConnection* New();
52   vtkTypeMacro(vtkPieChartActorConnection, vtkAlgorithm);
53 
vtkPieChartActorConnection()54   vtkPieChartActorConnection() { this->SetNumberOfInputPorts(1); }
55 };
56 
57 vtkStandardNewMacro(vtkPieChartActorConnection);
58 
59 //------------------------------------------------------------------------------
60 // Instantiate object
vtkPieChartActor()61 vtkPieChartActor::vtkPieChartActor()
62 {
63   // Actor2D positions
64   this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
65   this->PositionCoordinate->SetValue(0.1, 0.1);
66   this->Position2Coordinate->SetCoordinateSystemToNormalizedViewport();
67   this->Position2Coordinate->SetValue(0.9, 0.8);
68   this->Position2Coordinate->SetReferenceCoordinate(nullptr);
69 
70   this->ConnectionHolder = vtkPieChartActorConnection::New();
71 
72   this->ArrayNumber = 0;
73   this->ComponentNumber = 0;
74   this->TitleVisibility = 1;
75   this->Title = nullptr;
76   this->Labels = new vtkPieceLabelArray;
77   this->PieceMappers = nullptr;
78   this->PieceActors = nullptr;
79   this->LabelTextProperty = vtkTextProperty::New();
80   this->LabelTextProperty->SetFontSize(12);
81   this->LabelTextProperty->SetBold(1);
82   this->LabelTextProperty->SetItalic(1);
83   this->LabelTextProperty->SetShadow(0);
84   this->LabelTextProperty->SetFontFamilyToArial();
85   this->TitleTextProperty = vtkTextProperty::New();
86   this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);
87   this->TitleTextProperty->SetFontSize(24);
88   this->TitleTextProperty->SetBold(1);
89   this->TitleTextProperty->SetItalic(0);
90   this->TitleTextProperty->SetShadow(1);
91   this->TitleTextProperty->SetFontFamilyToArial();
92   this->LabelVisibility = 1;
93 
94   this->LegendVisibility = 1;
95 
96   this->LegendActor = vtkLegendBoxActor::New();
97   this->LegendActor->GetPositionCoordinate()->SetCoordinateSystemToViewport();
98   this->LegendActor->GetPosition2Coordinate()->SetCoordinateSystemToViewport();
99   this->LegendActor->GetPosition2Coordinate()->SetReferenceCoordinate(nullptr);
100   this->LegendActor->BorderOff();
101   this->LegendActor->SetNumberOfEntries(100); // initial allocation
102   this->LegendActor->SetPadding(2);
103   this->LegendActor->ScalarVisibilityOff();
104   this->GlyphSource = vtkGlyphSource2D::New();
105   this->GlyphSource->SetGlyphTypeToNone();
106   this->GlyphSource->DashOn();
107   this->GlyphSource->FilledOff();
108   this->GlyphSource->Update();
109 
110   this->PlotData = vtkPolyData::New();
111   this->PlotMapper = vtkPolyDataMapper2D::New();
112   this->PlotMapper->SetInputData(this->PlotData);
113   this->PlotActor = vtkActor2D::New();
114   this->PlotActor->SetMapper(this->PlotMapper);
115 
116   this->TitleMapper = vtkTextMapper::New();
117   this->TitleActor = vtkActor2D::New();
118   this->TitleActor->SetMapper(this->TitleMapper);
119   this->TitleActor->GetPositionCoordinate()->SetCoordinateSystemToViewport();
120 
121   this->N = 0;
122   this->Total = 0.0;
123   this->Fractions = nullptr;
124 
125   this->WebData = vtkPolyData::New();
126   this->WebMapper = vtkPolyDataMapper2D::New();
127   this->WebMapper->SetInputData(this->WebData);
128   this->WebActor = vtkActor2D::New();
129   this->WebActor->SetMapper(this->WebMapper);
130 
131   this->LastPosition[0] = this->LastPosition[1] = this->LastPosition2[0] = this->LastPosition2[1] =
132     0;
133 
134   this->P1[0] = this->P1[1] = this->P2[0] = this->P2[1] = 0.0;
135 }
136 
137 //------------------------------------------------------------------------------
~vtkPieChartActor()138 vtkPieChartActor::~vtkPieChartActor()
139 {
140   this->ConnectionHolder->Delete();
141   this->ConnectionHolder = nullptr;
142 
143   delete[] this->Title;
144   this->Title = nullptr;
145 
146   delete this->Labels;
147   this->SetLabelTextProperty(nullptr);
148   this->SetTitleTextProperty(nullptr);
149 
150   this->LegendActor->Delete();
151   this->GlyphSource->Delete();
152 
153   this->Initialize();
154 
155   this->TitleMapper->Delete();
156   this->TitleMapper = nullptr;
157   this->TitleActor->Delete();
158   this->TitleActor = nullptr;
159 
160   this->WebData->Delete();
161   this->WebMapper->Delete();
162   this->WebActor->Delete();
163 
164   this->PlotData->Delete();
165   this->PlotMapper->Delete();
166   this->PlotActor->Delete();
167 }
168 
169 //------------------------------------------------------------------------------
SetInputConnection(vtkAlgorithmOutput * ao)170 void vtkPieChartActor::SetInputConnection(vtkAlgorithmOutput* ao)
171 {
172   this->ConnectionHolder->SetInputConnection(ao);
173 }
174 
175 //------------------------------------------------------------------------------
SetInputData(vtkDataObject * dobj)176 void vtkPieChartActor::SetInputData(vtkDataObject* dobj)
177 {
178   vtkTrivialProducer* tp = vtkTrivialProducer::New();
179   tp->SetOutput(dobj);
180   this->SetInputConnection(tp->GetOutputPort());
181   tp->Delete();
182 }
183 
184 //------------------------------------------------------------------------------
GetInput()185 vtkDataObject* vtkPieChartActor::GetInput()
186 {
187   return this->ConnectionHolder->GetInputDataObject(0, 0);
188 }
189 
190 //------------------------------------------------------------------------------
191 // Free-up axes and related stuff
Initialize()192 void vtkPieChartActor::Initialize()
193 {
194   if (this->PieceActors)
195   {
196     for (int i = 0; i < this->N; i++)
197     {
198       this->PieceMappers[i]->Delete();
199       this->PieceActors[i]->Delete();
200     }
201     delete[] this->PieceMappers;
202     this->PieceMappers = nullptr;
203     delete[] this->PieceActors;
204     this->PieceActors = nullptr;
205   }
206 
207   this->N = 0;
208   this->Total = 0.0;
209   delete[] this->Fractions;
210 }
211 
212 //------------------------------------------------------------------------------
213 // Plot scalar data for each input dataset.
RenderOverlay(vtkViewport * viewport)214 int vtkPieChartActor::RenderOverlay(vtkViewport* viewport)
215 {
216   int renderedSomething = 0;
217 
218   if (!this->BuildPlot(viewport))
219   {
220     return 0;
221   }
222 
223   // Done rebuilding, render as appropriate.
224   if (this->GetInput() == nullptr || this->N <= 0)
225   {
226     vtkErrorMacro(<< "Nothing to plot!");
227     return 0;
228   }
229 
230   if (this->TitleVisibility)
231   {
232     renderedSomething += this->TitleActor->RenderOverlay(viewport);
233   }
234 
235   this->WebActor->SetProperty(this->GetProperty());
236   renderedSomething += this->PlotActor->RenderOverlay(viewport);
237   renderedSomething += this->WebActor->RenderOverlay(viewport);
238 
239   if (this->LabelVisibility)
240   {
241     for (int i = 0; i < this->N; i++)
242     {
243       renderedSomething += this->PieceActors[i]->RenderOverlay(viewport);
244     }
245   }
246 
247   if (this->LegendVisibility)
248   {
249     renderedSomething += this->LegendActor->RenderOverlay(viewport);
250   }
251 
252   return renderedSomething;
253 }
254 
255 //------------------------------------------------------------------------------
256 // Plot scalar data for each input dataset.
RenderOpaqueGeometry(vtkViewport * viewport)257 int vtkPieChartActor::RenderOpaqueGeometry(vtkViewport* viewport)
258 {
259   int renderedSomething = 0;
260 
261   if (!this->BuildPlot(viewport))
262   {
263     return 0;
264   }
265 
266   // Done rebuilding, render as appropriate.
267   if (this->GetInput() == nullptr || this->N <= 0)
268   {
269     vtkErrorMacro(<< "Nothing to plot!");
270     return 0;
271   }
272 
273   if (this->TitleVisibility)
274   {
275     renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
276   }
277 
278   this->WebActor->SetProperty(this->GetProperty());
279   renderedSomething += this->PlotActor->RenderOpaqueGeometry(viewport);
280   renderedSomething += this->WebActor->RenderOpaqueGeometry(viewport);
281 
282   if (this->LabelVisibility)
283   {
284     for (int i = 0; i < this->N; i++)
285     {
286       renderedSomething += this->PieceActors[i]->RenderOpaqueGeometry(viewport);
287     }
288   }
289 
290   if (this->LegendVisibility)
291   {
292     renderedSomething += this->LegendActor->RenderOpaqueGeometry(viewport);
293   }
294 
295   return renderedSomething;
296 }
297 
298 //------------------------------------------------------------------------------
299 // Description:
300 // Does this prop have some translucent polygonal geometry?
HasTranslucentPolygonalGeometry()301 vtkTypeBool vtkPieChartActor::HasTranslucentPolygonalGeometry()
302 {
303   return 0;
304 }
305 
306 //------------------------------------------------------------------------------
BuildPlot(vtkViewport * viewport)307 int vtkPieChartActor::BuildPlot(vtkViewport* viewport)
308 {
309   // Initialize
310   vtkDebugMacro(<< "Building pie chart plot");
311 
312   // Make sure input is up to date, and that the data is the correct shape to
313   // plot.
314   if (!this->GetInput())
315   {
316     vtkErrorMacro(<< "Nothing to plot!");
317     return 0;
318   }
319 
320   if (!this->TitleTextProperty)
321   {
322     vtkErrorMacro(<< "Need title text property to render plot");
323     return 0;
324   }
325   if (!this->LabelTextProperty)
326   {
327     vtkErrorMacro(<< "Need label text property to render plot");
328     return 0;
329   }
330 
331   // Viewport change may not require rebuild
332   int positionsHaveChanged = 0;
333   if (viewport->GetMTime() > this->BuildTime ||
334     (viewport->GetVTKWindow() && viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
335   {
336     int* lastPosition = this->PositionCoordinate->GetComputedViewportValue(viewport);
337     int* lastPosition2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
338     if (lastPosition[0] != this->LastPosition[0] || lastPosition[1] != this->LastPosition[1] ||
339       lastPosition2[0] != this->LastPosition2[0] || lastPosition2[1] != this->LastPosition2[1])
340     {
341       this->LastPosition[0] = lastPosition[0];
342       this->LastPosition[1] = lastPosition[1];
343       this->LastPosition2[0] = lastPosition2[0];
344       this->LastPosition2[1] = lastPosition2[1];
345       positionsHaveChanged = 1;
346     }
347   }
348 
349   // Check modified time to see whether we have to rebuild.
350   this->ConnectionHolder->GetInputAlgorithm()->Update();
351 
352   if (positionsHaveChanged || this->GetMTime() > this->BuildTime ||
353     this->GetInput()->GetMTime() > this->BuildTime ||
354     this->LabelTextProperty->GetMTime() > this->BuildTime ||
355     this->TitleTextProperty->GetMTime() > this->BuildTime)
356   {
357     vtkDebugMacro(<< "Rebuilding plot");
358 
359     // Build axes
360     const int* size = viewport->GetSize();
361     if (!this->PlaceAxes(viewport, size))
362     {
363       return 0;
364     }
365 
366     this->BuildTime.Modified();
367   } // If need to rebuild the plot
368 
369   return 1;
370 }
371 
372 //------------------------------------------------------------------------------
PlaceAxes(vtkViewport * viewport,const int * vtkNotUsed (size))373 int vtkPieChartActor::PlaceAxes(vtkViewport* viewport, const int* vtkNotUsed(size))
374 {
375   vtkIdType i, j;
376   vtkDataObject* input = this->GetInput();
377   vtkFieldData* field = input->GetFieldData();
378   double v = 0.0;
379 
380   this->Initialize();
381 
382   if (!field)
383   {
384     return 0;
385   }
386 
387   // Retrieve the appropriate data array
388   vtkDataArray* da = field->GetArray(this->ArrayNumber);
389   if (!da)
390   {
391     return 0;
392   }
393 
394   // Determine the number of independent variables
395   this->N = da->GetNumberOfTuples();
396   if (this->N <= 0 || this->N >= VTK_ID_MAX)
397   {
398     this->N = 0;
399     vtkErrorMacro(<< "No field data to plot");
400     return 0;
401   }
402 
403   // We need to loop over the field to determine the total
404   this->Total = 0.0;
405   this->Fractions = new double[this->N];
406   for (i = 0; i < this->N; i++)
407   {
408     v = fabs(da->GetComponent(i, this->ComponentNumber));
409     this->Fractions[i] = v;
410     this->Total += v;
411   }
412   if (this->Total > 0.0)
413   {
414     double total = 0.0;
415     for (i = 0; i < this->N; i++)
416     {
417       total += this->Fractions[i];
418       this->Fractions[i] = total / this->Total;
419     }
420   }
421 
422   // Get the location of the corners of the box
423   double* p1 = this->PositionCoordinate->GetComputedDoubleViewportValue(viewport);
424   double* p2 = this->Position2Coordinate->GetComputedDoubleViewportValue(viewport);
425   this->P1[0] = (p1[0] < p2[0] ? p1[0] : p2[0]);
426   this->P1[1] = (p1[1] < p2[1] ? p1[1] : p2[1]);
427   this->P2[0] = (p1[0] > p2[0] ? p1[0] : p2[0]);
428   this->P2[1] = (p1[1] > p2[1] ? p1[1] : p2[1]);
429   p1 = this->P1;
430   p2 = this->P2;
431 
432   // Create the borders of the pie pieces.
433   // Determine the center of the pie. Leave room for the title and the legend.
434   double titleSpace = 0.0, legendSpace = 0.0;
435   if (this->TitleVisibility)
436   {
437     titleSpace = 0.1;
438   }
439   if (this->LegendVisibility)
440   {
441     legendSpace = 0.15;
442   }
443 
444   double d1 = p2[0] - legendSpace * (p2[0] - p1[0]) - p1[0];
445   double d2 = p2[1] - titleSpace * (p2[1] - p1[1]) - p1[1];
446 
447   this->Center[0] = p1[0] + d1 / 2.0;
448   this->Center[1] = p1[1] + d2 / 2.0;
449   this->Center[2] = 0.0;
450   this->Radius = (d1 < d2 ? d1 : d2);
451   this->Radius /= 2.0;
452 
453   // Now generate the web points
454   this->WebData->Initialize(); // remove old polydata, if any
455   vtkPoints* webPts = vtkPoints::New();
456   webPts->Allocate(this->N + 1);
457   vtkCellArray* webLines = vtkCellArray::New();
458   webLines->AllocateEstimate(this->N, 2);
459   this->WebData->SetPoints(webPts);
460   this->WebData->SetLines(webLines);
461   vtkIdType ptId, pIds[2];
462   double theta, x[3];
463   x[2] = 0.0;
464 
465   // Specify the positions for the axes
466   pIds[0] = webPts->InsertNextPoint(this->Center);
467   for (i = 0; i < this->N; i++)
468   {
469     theta = this->Fractions[i] * 2.0 * vtkMath::Pi();
470     x[0] = this->Center[0] + this->Radius * cos(theta);
471     x[1] = this->Center[1] + this->Radius * sin(theta);
472     pIds[1] = webPts->InsertNextPoint(x);
473     webLines->InsertNextCell(2, pIds);
474   }
475 
476   // Draw a bounding ring
477   webLines->InsertNextCell(65);
478   theta = 2.0 * vtkMath::Pi() / 64;
479   for (j = 0; j < 65; j++)
480   {
481     x[0] = this->Center[0] + this->Radius * cos(j * theta);
482     x[1] = this->Center[1] + this->Radius * sin(j * theta);
483     ptId = webPts->InsertNextPoint(x);
484     webLines->InsertCellPoint(ptId);
485   }
486 
487   // Produce labels around the rim of the plot
488   double thetaM;
489   char label[1024];
490   const char* str;
491   int minFontSize = 1000, fontSize, tsize[2];
492   if (this->LabelVisibility)
493   {
494     this->PieceActors = new vtkActor2D*[this->N];
495     this->PieceMappers = new vtkTextMapper*[this->N];
496     for (i = 0; i < this->N; i++)
497     {
498       thetaM = (i == 0 ? 0.0 : this->Fractions[i - 1] * 2.0 * vtkMath::Pi());
499       theta = this->Fractions[i] * 2.0 * vtkMath::Pi();
500       x[0] = this->Center[0] + (this->Radius + 5) * cos((theta + thetaM) / 2.0);
501       x[1] = this->Center[1] + (this->Radius + 5) * sin((theta + thetaM) / 2.0);
502       this->PieceMappers[i] = vtkTextMapper::New();
503       if ((str = this->GetPieceLabel(i)) != nullptr)
504       {
505         this->PieceMappers[i]->SetInput(str);
506       }
507       else
508       {
509         snprintf(label, sizeof(label), "%d", static_cast<int>(i));
510         this->PieceMappers[i]->SetInput(label);
511       }
512       this->PieceMappers[i]->GetTextProperty()->ShallowCopy(this->LabelTextProperty);
513       tsize[0] = static_cast<int>(0.15 * d1);
514       tsize[1] = static_cast<int>(0.15 * d2);
515       fontSize = this->PieceMappers[i]->SetConstrainedFontSize(viewport, tsize[0], tsize[1]);
516       minFontSize = (fontSize < minFontSize ? fontSize : minFontSize);
517       this->PieceActors[i] = vtkActor2D::New();
518       this->PieceActors[i]->SetMapper(this->PieceMappers[i]);
519       this->PieceActors[i]->GetPositionCoordinate()->SetCoordinateSystemToViewport();
520       this->PieceActors[i]->SetPosition(x);
521       // depending on the qudrant, the text is aligned differently
522       if (x[0] >= this->Center[0] && x[1] >= this->Center[1])
523       {
524         this->PieceMappers[i]->GetTextProperty()->SetJustificationToLeft();
525         this->PieceMappers[i]->GetTextProperty()->SetVerticalJustificationToBottom();
526       }
527       else if (x[0] < this->Center[0] && x[1] >= this->Center[1])
528       {
529         this->PieceMappers[i]->GetTextProperty()->SetJustificationToRight();
530         this->PieceMappers[i]->GetTextProperty()->SetVerticalJustificationToBottom();
531       }
532       else if (x[0] < this->Center[0] && x[1] < this->Center[1])
533       {
534         this->PieceMappers[i]->GetTextProperty()->SetJustificationToRight();
535         this->PieceMappers[i]->GetTextProperty()->SetVerticalJustificationToTop();
536       }
537       else if (x[0] >= this->Center[0] && x[1] < this->Center[1])
538       {
539         this->PieceMappers[i]->GetTextProperty()->SetJustificationToLeft();
540         this->PieceMappers[i]->GetTextProperty()->SetVerticalJustificationToTop();
541       }
542     } // for all pieces of pie
543     // Now reset font sizes to the same value
544     for (i = 0; i < this->N; i++)
545     {
546       this->PieceMappers[i]->GetTextProperty()->SetFontSize(minFontSize);
547     }
548   }
549 
550   // Now generate the pie polygons
551   this->PlotData->Initialize(); // remove old polydata, if any
552   vtkPoints* pts = vtkPoints::New();
553   pts->Allocate(this->N * 2);
554   vtkCellArray* polys = vtkCellArray::New();
555   vtkUnsignedCharArray* colors = vtkUnsignedCharArray::New();
556   colors->SetNumberOfComponents(3);
557   this->PlotData->SetPoints(pts);
558   this->PlotData->SetPolys(polys);
559   this->PlotData->GetCellData()->SetScalars(colors);
560   colors->Delete();
561 
562   double *color, delTheta;
563   vtkIdType numDivs;
564   polys->AllocateEstimate(this->N, 12);
565 
566   pIds[0] = pts->InsertNextPoint(this->Center);
567   for (i = 0; i < this->N; i++)
568   {
569     thetaM = (i == 0 ? 0.0 : this->Fractions[i - 1] * 2.0 * vtkMath::Pi());
570     theta = this->Fractions[i] * 2.0 * vtkMath::Pi();
571     numDivs = static_cast<vtkIdType>(32 * (theta - thetaM) / vtkMath::Pi());
572     numDivs = (numDivs < 2 ? 2 : numDivs);
573     delTheta = (theta - thetaM) / numDivs;
574 
575     polys->InsertNextCell(numDivs + 2);
576     polys->InsertCellPoint(pIds[0]);
577     color = this->LegendActor->GetEntryColor(i);
578     colors->InsertNextTuple3(255 * color[0], 255 * color[1], 255 * color[2]);
579     this->LegendActor->SetEntrySymbol(i, this->GlyphSource->GetOutput());
580     if ((str = this->GetPieceLabel(i)) != nullptr)
581     {
582       this->LegendActor->SetEntryString(i, str);
583     }
584     else
585     {
586       snprintf(label, sizeof(label), "%d", static_cast<int>(i));
587       this->LegendActor->SetEntryString(i, label);
588     }
589 
590     for (j = 0; j <= numDivs; j++)
591     {
592       theta = thetaM + j * delTheta;
593       x[0] = this->Center[0] + this->Radius * cos(theta);
594       x[1] = this->Center[1] + this->Radius * sin(theta);
595       ptId = pts->InsertNextPoint(x);
596       polys->InsertCellPoint(ptId);
597     }
598   }
599 
600   // Display the legend
601   if (this->LegendVisibility)
602   {
603     this->LegendActor->GetProperty()->DeepCopy(this->GetProperty());
604     this->LegendActor->GetPositionCoordinate()->SetValue(
605       p1[0] + 0.85 * (p2[0] - p1[0]), p1[1] + 0.20 * (p2[1] - p1[1]));
606     this->LegendActor->GetPosition2Coordinate()->SetValue(p2[0], p1[1] + 0.80 * (p2[1] - p1[1]));
607   }
608 
609   // Build title
610   this->TitleMapper->SetInput(this->Title);
611   if (this->TitleTextProperty->GetMTime() > this->BuildTime)
612   {
613     // Shallow copy here since the justification is changed but we still
614     // want to allow actors to share the same text property, and in that case
615     // specifically allow the title and label text prop to be the same.
616     this->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
617     this->TitleMapper->GetTextProperty()->SetJustificationToCentered();
618   }
619 
620   // We could do some caching here, but hey, that's just the title
621   tsize[0] = static_cast<int>(0.25 * d1);
622   tsize[1] = static_cast<int>(0.15 * d2);
623   this->TitleMapper->SetConstrainedFontSize(viewport, tsize[0], tsize[1]);
624 
625   this->TitleActor->GetPositionCoordinate()->SetValue(
626     this->Center[0], this->Center[1] + this->Radius + tsize[1]);
627 
628   // Clean up
629   webPts->Delete();
630   webLines->Delete();
631   pts->Delete();
632   polys->Delete();
633 
634   return 1;
635 }
636 
637 //------------------------------------------------------------------------------
638 // Release any graphics resources that are being consumed by this actor.
639 // The parameter window could be used to determine which graphic
640 // resources to release.
ReleaseGraphicsResources(vtkWindow * win)641 void vtkPieChartActor::ReleaseGraphicsResources(vtkWindow* win)
642 {
643   this->TitleActor->ReleaseGraphicsResources(win);
644   this->LegendActor->ReleaseGraphicsResources(win);
645   this->WebActor->ReleaseGraphicsResources(win);
646   this->PlotActor->ReleaseGraphicsResources(win);
647   for (int i = 0; this->PieceActors && i < this->N; i++)
648   {
649     this->PieceActors[i]->ReleaseGraphicsResources(win);
650   }
651 }
652 
653 //------------------------------------------------------------------------------
SetPieceLabel(const int i,const char * label)654 void vtkPieChartActor::SetPieceLabel(const int i, const char* label)
655 {
656   if (i < 0)
657   {
658     return;
659   }
660 
661   if (static_cast<unsigned int>(i) >= this->Labels->size())
662   {
663     this->Labels->resize(i + 1);
664   }
665   (*this->Labels)[i] = std::string(label);
666   this->Modified();
667 }
668 
669 //------------------------------------------------------------------------------
GetPieceLabel(int i)670 const char* vtkPieChartActor::GetPieceLabel(int i)
671 {
672   if (i < 0 || static_cast<unsigned int>(i) >= this->Labels->size())
673   {
674     return nullptr;
675   }
676 
677   return this->Labels->at(i).c_str();
678 }
679 
680 //------------------------------------------------------------------------------
SetPieceColor(int i,double r,double g,double b)681 void vtkPieChartActor::SetPieceColor(int i, double r, double g, double b)
682 {
683   this->LegendActor->SetEntryColor(i, r, g, b);
684 }
685 
686 //------------------------------------------------------------------------------
GetPieceColor(int i)687 double* vtkPieChartActor::GetPieceColor(int i)
688 {
689   return this->LegendActor->GetEntryColor(i);
690 }
691 
692 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)693 void vtkPieChartActor::PrintSelf(ostream& os, vtkIndent indent)
694 {
695   this->Superclass::PrintSelf(os, indent);
696 
697   os << indent << "Input: " << this->GetInput() << "\n";
698 
699   os << indent << "Title Visibility: " << (this->TitleVisibility ? "On\n" : "Off\n");
700 
701   os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
702 
703   if (this->TitleTextProperty)
704   {
705     os << indent << "Title Text Property:\n";
706     this->TitleTextProperty->PrintSelf(os, indent.GetNextIndent());
707   }
708   else
709   {
710     os << indent << "Title Text Property: (none)\n";
711   }
712 
713   os << indent << "Label Visibility: " << (this->LabelVisibility ? "On\n" : "Off\n");
714 
715   if (this->LabelTextProperty)
716   {
717     os << indent << "Label Text Property:\n";
718     this->LabelTextProperty->PrintSelf(os, indent.GetNextIndent());
719   }
720   else
721   {
722     os << indent << "Label Text Property: (none)\n";
723   }
724 
725   os << indent << "Legend Visibility: " << (this->LegendVisibility ? "On\n" : "Off\n");
726 
727   os << indent << "Legend Actor: " << this->LegendActor << "\n";
728   this->LegendActor->PrintSelf(os, indent.GetNextIndent());
729 }
730