1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkChart.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 
16 #include "vtkChart.h"
17 #include "vtkAxis.h"
18 #include "vtkBrush.h"
19 #include "vtkTransform2D.h"
20 #include "vtkContextMouseEvent.h"
21 
22 #include "vtkAnnotationLink.h"
23 #include "vtkContextScene.h"
24 #include "vtkTextProperty.h"
25 #include "vtkObjectFactory.h"
26 
27 //-----------------------------------------------------------------------------
MouseActions()28 vtkChart::MouseActions::MouseActions()
29 {
30   this->Pan() = vtkContextMouseEvent::LEFT_BUTTON;
31   this->Zoom() = vtkContextMouseEvent::MIDDLE_BUTTON;
32   this->Select() = vtkContextMouseEvent::RIGHT_BUTTON;
33   this->ZoomAxis() = -1;
34   this->SelectPolygon() = -1;
35   this->ClickAndDrag() = -1;
36 }
37 
38 //-----------------------------------------------------------------------------
MouseClickActions()39 vtkChart::MouseClickActions::MouseClickActions()
40 {
41   this->Data[0] = vtkContextMouseEvent::LEFT_BUTTON;
42   this->Data[1] = vtkContextMouseEvent::RIGHT_BUTTON;
43 }
44 
45 //-----------------------------------------------------------------------------
46 vtkCxxSetObjectMacro(vtkChart, AnnotationLink, vtkAnnotationLink);
47 
48 //-----------------------------------------------------------------------------
vtkChart()49 vtkChart::vtkChart()
50 {
51   this->Geometry[0] = 0;
52   this->Geometry[1] = 0;
53   this->Point1[0] = 0;
54   this->Point1[1] = 0;
55   this->Point2[0] = 0;
56   this->Point2[1] = 0;
57   this->Size.Set(0, 0, 0, 0);
58   this->ShowLegend = false;
59   this->TitleProperties = vtkTextProperty::New();
60   this->TitleProperties->SetJustificationToCentered();
61   this->TitleProperties->SetColor(0.0, 0.0, 0.0);
62   this->TitleProperties->SetFontSize(12);
63   this->TitleProperties->SetFontFamilyToArial();
64   this->AnnotationLink = nullptr;
65   this->LayoutStrategy = vtkChart::FILL_SCENE;
66   this->RenderEmpty = false;
67   this->BackgroundBrush = vtkSmartPointer<vtkBrush>::New();
68   this->BackgroundBrush->SetColorF(1, 1, 1, 0);
69   this->SelectionMode = vtkContextScene::SELECTION_NONE;
70   this->SelectionMethod = vtkChart::SELECTION_ROWS;
71 }
72 
73 //-----------------------------------------------------------------------------
~vtkChart()74 vtkChart::~vtkChart()
75 {
76   for(int i=0; i < 4; i++)
77   {
78     if(this->GetAxis(i))
79     {
80       this->GetAxis(i)->RemoveObservers(vtkChart::UpdateRange);
81     }
82   }
83   this->TitleProperties->Delete();
84   if (this->AnnotationLink)
85   {
86     this->AnnotationLink->Delete();
87   }
88 }
89 
90 //-----------------------------------------------------------------------------
AddPlot(int)91 vtkPlot * vtkChart::AddPlot(int)
92 {
93   return nullptr;
94 }
95 
96 //-----------------------------------------------------------------------------
AddPlot(vtkPlot *)97 vtkIdType vtkChart::AddPlot(vtkPlot*)
98 {
99   return -1;
100 }
101 
102 //-----------------------------------------------------------------------------
RemovePlot(vtkIdType)103 bool vtkChart::RemovePlot(vtkIdType)
104 {
105   return false;
106 }
107 
108 //-----------------------------------------------------------------------------
RemovePlotInstance(vtkPlot * plot)109 bool vtkChart::RemovePlotInstance(vtkPlot* plot)
110 {
111   if (plot)
112   {
113     vtkIdType numberOfPlots = this->GetNumberOfPlots();
114     for (vtkIdType i = 0; i < numberOfPlots; ++i)
115     {
116       if (this->GetPlot(i) == plot)
117       {
118         return this->RemovePlot(i);
119       }
120     }
121   }
122   return false;
123 }
124 
125 //-----------------------------------------------------------------------------
ClearPlots()126 void vtkChart::ClearPlots()
127 {
128 }
129 
130 //-----------------------------------------------------------------------------
GetPlot(vtkIdType)131 vtkPlot* vtkChart::GetPlot(vtkIdType)
132 {
133   return nullptr;
134 }
135 
136 //-----------------------------------------------------------------------------
GetNumberOfPlots()137 vtkIdType vtkChart::GetNumberOfPlots()
138 {
139   return 0;
140 }
141 
142 //-----------------------------------------------------------------------------
GetAxis(int)143 vtkAxis* vtkChart::GetAxis(int)
144 {
145   return nullptr;
146 }
147 
148 //-----------------------------------------------------------------------------
SetAxis(int,vtkAxis *)149 void vtkChart::SetAxis(int, vtkAxis*)
150 {
151 }
152 
153 //-----------------------------------------------------------------------------
GetNumberOfAxes()154 vtkIdType vtkChart::GetNumberOfAxes()
155 {
156   return 0;
157 }
158 
159 //-----------------------------------------------------------------------------
RecalculateBounds()160 void vtkChart::RecalculateBounds()
161 {
162 }
163 
164 //-----------------------------------------------------------------------------
SetSelectionMethod(int method)165 void vtkChart::SetSelectionMethod(int method)
166 {
167   if (method == this->SelectionMethod)
168   {
169     return;
170   }
171   this->SelectionMethod = method;
172   this->Modified();
173 }
174 
175 //-----------------------------------------------------------------------------
GetSelectionMethod()176 int vtkChart::GetSelectionMethod()
177 {
178   return this->SelectionMethod;
179 }
180 
181 //-----------------------------------------------------------------------------
SetShowLegend(bool visible)182 void vtkChart::SetShowLegend(bool visible)
183 {
184   if (this->ShowLegend != visible)
185   {
186     this->ShowLegend = visible;
187     this->Modified();
188   }
189 }
190 
191 //-----------------------------------------------------------------------------
GetShowLegend()192 bool vtkChart::GetShowLegend()
193 {
194   return this->ShowLegend;
195 }
196 
GetLegend()197 vtkChartLegend * vtkChart::GetLegend()
198 {
199   return nullptr;
200 }
201 
202 //-----------------------------------------------------------------------------
SetTitle(const vtkStdString & title)203 void vtkChart::SetTitle(const vtkStdString &title)
204 {
205   if (this->Title != title)
206   {
207     this->Title = title;
208     this->Modified();
209   }
210 }
211 
212 //-----------------------------------------------------------------------------
GetTitle()213 vtkStdString vtkChart::GetTitle()
214 {
215   return this->Title;
216 }
217 
218 //-----------------------------------------------------------------------------
CalculatePlotTransform(vtkAxis * x,vtkAxis * y,vtkTransform2D * transform)219 bool vtkChart::CalculatePlotTransform(vtkAxis *x, vtkAxis *y,
220                                       vtkTransform2D *transform)
221 {
222   if (!x || !y || !transform)
223   {
224     vtkWarningMacro("Called with null arguments.");
225     return false;
226   }
227 
228   vtkVector2d origin(x->GetMinimum(), y->GetMinimum());
229   vtkVector2d scale(x->GetMaximum() - x->GetMinimum(),
230                     y->GetMaximum() - y->GetMinimum());
231   vtkVector2d shift(0.0, 0.0);
232   vtkVector2d factor(1.0, 1.0);
233 
234   for (int i = 0; i < 2; ++i)
235   {
236     if (fabs(log10(origin[i] / scale[i])) > 2)
237     {
238       shift[i] = floor(log10(origin[i] / scale[i]) / 3.0) * 3.0;
239       shift[i] = -origin[i];
240     }
241     if (fabs(log10(scale[i])) > 10)
242     {
243       // We need to scale the transform to show all data, do this in blocks.
244       factor[i] = pow(10.0, floor(log10(scale[i]) / 10.0) * -10.0);
245       scale[i] = scale[i] * factor[i];
246     }
247   }
248   x->SetScalingFactor(factor[0]);
249   x->SetShift(shift[0]);
250   y->SetScalingFactor(factor[1]);
251   y->SetShift(shift[1]);
252 
253   // Get the scale for the plot area from the x and y axes
254   float *min = x->GetPoint1();
255   float *max = x->GetPoint2();
256   if (fabs(max[0] - min[0]) == 0.0)
257   {
258     return false;
259   }
260   float xScale = scale[0] / (max[0] - min[0]);
261 
262   // Now the y axis
263   min = y->GetPoint1();
264   max = y->GetPoint2();
265   if (fabs(max[1] - min[1]) == 0.0)
266   {
267     return false;
268   }
269   float yScale = scale[1] / (max[1] - min[1]);
270 
271   transform->Identity();
272   transform->Translate(this->Point1[0], this->Point1[1]);
273   // Get the scale for the plot area from the x and y axes
274   transform->Scale(1.0 / xScale, 1.0 / yScale);
275   transform->Translate(-(x->GetMinimum() + shift[0]) * factor[0],
276                        -(y->GetMinimum() + shift[1]) * factor[1]);
277   return true;
278 }
279 
280 //-----------------------------------------------------------------------------
CalculateUnscaledPlotTransform(vtkAxis * x,vtkAxis * y,vtkTransform2D * transform)281 bool vtkChart::CalculateUnscaledPlotTransform(vtkAxis *x, vtkAxis *y,
282                                               vtkTransform2D *transform)
283 {
284   if (!x || !y || !transform)
285   {
286     vtkWarningMacro("Called with null arguments.");
287     return false;
288   }
289 
290   vtkVector2d scale(x->GetMaximum() - x->GetMinimum(),
291                     y->GetMaximum() - y->GetMinimum());
292 
293   // Get the scale for the plot area from the x and y axes
294   float *min = x->GetPoint1();
295   float *max = x->GetPoint2();
296   if (fabs(max[0] - min[0]) == 0.0)
297   {
298     return false;
299   }
300   double xScale = scale[0] / (max[0] - min[0]);
301 
302   // Now the y axis
303   min = y->GetPoint1();
304   max = y->GetPoint2();
305   if (fabs(max[1] - min[1]) == 0.0)
306   {
307     return false;
308   }
309   double yScale = scale[1] / (max[1] - min[1]);
310 
311   transform->Identity();
312   transform->Translate(this->Point1[0], this->Point1[1]);
313   // Get the scale for the plot area from the x and y axes
314   transform->Scale(1.0 / xScale, 1.0 / yScale);
315   transform->Translate(-x->GetMinimum(), -y->GetMinimum());
316   return true;
317 }
318 
319 //-----------------------------------------------------------------------------
SetBottomBorder(int border)320 void vtkChart::SetBottomBorder(int border)
321 {
322   this->Point1[1] = border >= 0 ? border : 0;
323   this->Point1[1] += static_cast<int>(this->Size.GetY());
324 }
325 
326 //-----------------------------------------------------------------------------
SetTopBorder(int border)327 void vtkChart::SetTopBorder(int border)
328 {
329  this->Point2[1] = border >=0 ?
330                    this->Geometry[1] - border :
331                    this->Geometry[1];
332  this->Point2[1] += static_cast<int>(this->Size.GetY());
333 }
334 
335 //-----------------------------------------------------------------------------
SetLeftBorder(int border)336 void vtkChart::SetLeftBorder(int border)
337 {
338   this->Point1[0] = border >= 0 ? border : 0;
339   this->Point1[0] += static_cast<int>(this->Size.GetX());
340 }
341 
342 //-----------------------------------------------------------------------------
SetRightBorder(int border)343 void vtkChart::SetRightBorder(int border)
344 {
345   this->Point2[0] = border >=0 ?
346                     this->Geometry[0] - border :
347                     this->Geometry[0];
348   this->Point2[0] += static_cast<int>(this->Size.GetX());
349 }
350 
351 //-----------------------------------------------------------------------------
SetBorders(int left,int bottom,int right,int top)352 void vtkChart::SetBorders(int left, int bottom, int right, int top)
353 {
354   this->SetLeftBorder(left);
355   this->SetRightBorder(right);
356   this->SetTopBorder(top);
357   this->SetBottomBorder(bottom);
358 }
359 
SetSize(const vtkRectf & rect)360 void vtkChart::SetSize(const vtkRectf &rect)
361 {
362   this->Size = rect;
363   this->Geometry[0] = static_cast<int>(rect.GetWidth());
364   this->Geometry[1] = static_cast<int>(rect.GetHeight());
365 }
366 
GetSize()367 vtkRectf vtkChart::GetSize()
368 {
369   return this->Size;
370 }
371 
SetActionToButton(int action,int button)372 void vtkChart::SetActionToButton(int action, int button)
373 {
374   if (action < -1 || action >= MouseActions::MaxAction)
375   {
376     vtkErrorMacro("Error, invalid action value supplied: " << action)
377     return;
378   }
379   this->Actions[action] = button;
380   for (int i = 0; i < MouseActions::MaxAction; ++i)
381   {
382     if (this->Actions[i] == button && i != action)
383     {
384       this->Actions[i] = -1;
385     }
386   }
387 }
388 
GetActionToButton(int action)389 int vtkChart::GetActionToButton(int action)
390 {
391   return this->Actions[action];
392 }
393 
SetClickActionToButton(int action,int button)394 void vtkChart::SetClickActionToButton(int action, int button)
395 {
396   if (action != vtkChart::SELECT && action != vtkChart::NOTIFY)
397   {
398     vtkErrorMacro("Error, invalid click action value supplied: " << action)
399     return;
400   }
401 
402   if (action == vtkChart::NOTIFY)
403   {
404     this->ActionsClick[0] = button;
405   }
406   else if (action == vtkChart::SELECT)
407   {
408     this->ActionsClick[1] = button;
409   }
410 }
411 
GetClickActionToButton(int action)412 int vtkChart::GetClickActionToButton(int action)
413 {
414   if (action == vtkChart::NOTIFY)
415   {
416     return this->ActionsClick[0];
417   }
418   else if (action == vtkChart::SELECT)
419   {
420     return this->ActionsClick[1];
421   }
422 
423   return -1;
424 }
425 
426 //-----------------------------------------------------------------------------
SetBackgroundBrush(vtkBrush * brush)427 void vtkChart::SetBackgroundBrush(vtkBrush *brush)
428 {
429   if(brush == nullptr)
430   {
431     // set to transparent white if brush is null
432     this->BackgroundBrush->SetColorF(1, 1, 1, 0);
433   }
434   else
435   {
436     this->BackgroundBrush = brush;
437   }
438 
439   this->Modified();
440 }
441 
442 //-----------------------------------------------------------------------------
GetBackgroundBrush()443 vtkBrush* vtkChart::GetBackgroundBrush()
444 {
445   return this->BackgroundBrush;
446 }
447 
448 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)449 void vtkChart::PrintSelf(ostream &os, vtkIndent indent)
450 {
451   this->Superclass::PrintSelf(os, indent);
452   // Print out the chart's geometry if it has been set
453   os << indent << "Point1: " << this->Point1[0] << "\t" << this->Point1[1]
454      << endl;
455   os << indent << "Point2: " << this->Point2[0] << "\t" << this->Point2[1]
456      << endl;
457   os << indent << "Width: " << this->Geometry[0] << endl
458      << indent << "Height: " << this->Geometry[1] << endl;
459   os << indent << "SelectionMode: " << this->SelectionMode << endl;
460 }
461 //-----------------------------------------------------------------------------
AttachAxisRangeListener(vtkAxis * axis)462 void vtkChart::AttachAxisRangeListener(vtkAxis* axis)
463 {
464   axis->AddObserver(vtkChart::UpdateRange, this, &vtkChart::AxisRangeForwarderCallback);
465 }
466 
467 //-----------------------------------------------------------------------------
AxisRangeForwarderCallback(vtkObject *,unsigned long,void *)468 void vtkChart::AxisRangeForwarderCallback(vtkObject*, unsigned long, void*)
469 {
470   double fullAxisRange[8];
471   for(int i=0; i < 4; i++)
472   {
473     this->GetAxis(i)->GetRange(&fullAxisRange[i*2]);
474   }
475   this->InvokeEvent(vtkChart::UpdateRange, fullAxisRange);
476 }
477 
478 //-----------------------------------------------------------------------------
SetSelectionMode(int selMode)479 void vtkChart::SetSelectionMode(int selMode)
480 {
481   if (this->SelectionMode == selMode ||
482     selMode < vtkContextScene::SELECTION_NONE ||
483     selMode > vtkContextScene::SELECTION_TOGGLE)
484   {
485     return;
486   }
487   this->SelectionMode = selMode;
488   this->Modified();
489 }
490