ParaView
vtkXYChartRepresentationInternals.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ParaView
4  Module: vtkXYChartRepresentationInternals.h
5 
6  Copyright (c) Kitware, Inc.
7  All rights reserved.
8  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 =========================================================================*/
21 #ifndef vtkXYChartRepresentationInternals_h
22 #define vtkXYChartRepresentationInternals_h
23 
24 #include "vtkCSVExporter.h"
25 #include "vtkChartXY.h"
26 #include "vtkColor.h"
27 #include "vtkDataArray.h"
28 #include "vtkPen.h"
29 #include "vtkPlotBar.h"
30 #include "vtkPlotFunctionalBag.h"
31 #include "vtkPlotPoints.h"
32 #include "vtkSmartPointer.h"
33 #include "vtkTable.h"
34 
35 #include <map>
36 #include <string>
37 
39 {
40 protected:
41  struct PlotInfo
42  {
43  vtkSmartPointer<vtkPlot> Plot;
44  std::string TableName;
45  std::string ColumnName;
46  };
47 
48  typedef std::map<std::string, PlotInfo> PlotsMapItem;
49  class PlotsMap : public std::map<std::string, PlotsMapItem>
50  {
51  bool Contains(const std::string& key, const std::string& role) const
52  {
53  PlotsMap::const_iterator iter1 = this->find(key);
54  if (iter1 != this->end())
55  {
56  PlotsMapItem::const_iterator iter2 = iter1->second.find(role);
57  return (iter2 != iter1->second.end());
58  }
59  return false;
60  }
61 
62  public:
63  vtkSmartPointer<vtkPlot> GetPlot(vtkChartRepresentation* self, const std::string& tableName,
64  const std::string& columnName, const std::string& role = std::string()) const
65  {
66  const std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
67  PlotsMap::const_iterator iter1 = this->find(key);
68  if (iter1 != this->end())
69  {
70  PlotsMapItem::const_iterator iter2 = iter1->second.find(role);
71  if (iter2 != iter1->second.end())
72  {
73  return iter2->second.Plot;
74  }
75  }
76  return vtkSmartPointer<vtkPlot>();
77  }
78 
79  bool RemovePlot(vtkChartRepresentation* self, const std::string& tableName,
80  const std::string& columnName, const std::string& role = std::string())
81  {
82  const std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
83  PlotsMap::iterator iter1 = this->find(key);
84  if (iter1 != this->end())
85  {
86  PlotsMapItem::iterator iter2 = iter1->second.find(role);
87  if (iter2 != iter1->second.end())
88  {
89  iter1->second.erase(iter2);
90  return true;
91  }
92  }
93  return false;
94  }
95 
96  void AddPlot(vtkChartRepresentation* self, const std::string& tableName,
97  const std::string& columnName, const std::string& role, vtkPlot* plot)
98  {
99  const std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
100  PlotInfo& info = (*this)[key][role];
101  info.TableName = tableName;
102  info.ColumnName = columnName;
103  info.Plot = plot;
104  }
105 
106  void SetPlotVisibility(bool val) const
107  {
108  for (PlotsMap::const_iterator iter1 = this->begin(); iter1 != this->end(); ++iter1)
109  {
110  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin();
111  iter2 != iter1->second.end(); ++iter2)
112  {
113  iter2->second.Plot->SetVisible(val);
114  }
115  }
116  }
117 
118  void RemoveAllPlots(vtkChartXY* chartXY)
119  {
120  for (PlotsMap::const_iterator iter1 = this->begin(); iter1 != this->end(); ++iter1)
121  {
122  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin();
123  iter2 != iter1->second.end(); ++iter2)
124  {
125  chartXY->RemovePlotInstance(iter2->second.Plot.GetPointer());
126  }
127  }
128  this->clear();
129  }
130 
131  void Intersect(const PlotsMap& other, vtkChartXY* chartXY)
132  {
133  for (PlotsMap::iterator iter1 = this->begin(); iter1 != this->end(); ++iter1)
134  {
135  for (PlotsMapItem::iterator iter2 = iter1->second.begin(); iter2 != iter1->second.end();)
136  {
137  if (other.Contains(iter1->first, iter2->first) == false)
138  {
139  chartXY->RemovePlotInstance(iter2->second.Plot.GetPointer());
140  PlotsMapItem::iterator iter2old = iter2;
141  ++iter2;
142  iter1->second.erase(iter2old);
143  }
144  else
145  {
146  ++iter2;
147  }
148  }
149  }
150  }
151  };
152 
154 
155  //---------------------------------------------------------------------------
156  // Makes is easy to obtain a value for a series parameter, is set, else the
157  // default. This class supports two mechanisms for addresses series in a
158  // collection (multiblock) of tables: (1) using a name that combines the
159  // table name and the column name (using
160  // vtkChartRepresentation::GetDefaultSeriesLabel), or (2) using the column
161  // name alone. (1) is always checked before (2).
162  template <class T>
163  T GetSeriesParameter(vtkXYChartRepresentation* self, const std::string& tableName,
164  const std::string& columnName, const std::string& vtkNotUsed(role),
165  const std::map<std::string, T>& parameter_map, const T default_value = T()) const
166  {
167  typename std::map<std::string, T>::const_iterator iter;
168 
169  // when setting properties for a series, I want to support two mechanisms:
170  // simply specifying the array name or suffixing it with the block-name.
171  // This logic makes that possible.
172 
173  // first try most specific form of identifying the series.
174  std::string key = self->GetDefaultSeriesLabel(tableName, columnName);
175  iter = parameter_map.find(key);
176  if (iter != parameter_map.end())
177  {
178  return iter->second;
179  }
180 
181  // now try the cheap form for identifying it.
182  key = self->GetDefaultSeriesLabel(std::string(), columnName);
183  iter = parameter_map.find(key);
184  if (iter != parameter_map.end())
185  {
186  return iter->second;
187  }
188  return default_value;
189  }
190 
191 public:
193 
194  // we have to keep these separate since they are set by different properties
195  // and hence may not always match up.
196  std::map<std::string, bool> SeriesVisibilities;
197  std::map<std::string, int> LineThicknesses;
198  std::map<std::string, int> LineStyles;
199  std::map<std::string, vtkColor3d> Colors;
200  std::map<std::string, int> AxisCorners;
201  std::map<std::string, int> MarkerStyles;
202  std::map<std::string, std::string> Labels;
203  std::map<std::string, bool> UseColorMapping;
204  std::map<std::string, vtkScalarsToColors*> Lut;
205 
206  // These are used to determine when to recalculate chart bounds. If user
207  // changes the X axis, we force recalculation of the chart bounds
208  // automatically.
211 
213  : PreviousUseIndexForXAxis(false)
214  {
215  }
216 
217  virtual ~vtkInternals() {}
218 
219  //---------------------------------------------------------------------------
220  // Hide all plots.
221  void HideAllPlots() { this->SeriesPlots.SetPlotVisibility(false); }
222 
223  //---------------------------------------------------------------------------
224  // Destroy all vtkPlot instances.
225  void RemoveAllPlots(vtkChartXY* chartXY) { this->SeriesPlots.RemoveAllPlots(chartXY); }
226 
227  //---------------------------------------------------------------------------
233  virtual std::string GetSeriesRole(
234  const std::string& vtkNotUsed(tableName), const std::string& vtkNotUsed(columnName))
235  {
236  return std::string();
237  }
238 
239  virtual vtkPlot* NewPlot(vtkXYChartRepresentation* self, const std::string& tableName,
240  const std::string& columnName, const std::string& role)
241  {
242  (void)tableName;
243  (void)columnName;
244  (void)role;
245 
246  assert(self);
247  vtkChartXY* chartXY = self->GetChart();
248 
249  assert(chartXY);
250  return chartXY->AddPlot(self->GetChartType());
251  }
252 
253  //---------------------------------------------------------------------------
254  virtual int GetInputArrayIndex(const std::string& vtkNotUsed(tableName),
255  const std::string& vtkNotUsed(columnName), const std::string& vtkNotUsed(role))
256  {
257  return 1;
258  }
259 
260  //---------------------------------------------------------------------------
261  // Update i.e. add/remove plots based on the data in the tables.
262  virtual void UpdatePlots(vtkXYChartRepresentation* self, const MapOfTables& tables)
263  {
264  PlotsMap newPlots;
265  assert(self != NULL);
266  vtkChartXY* chartXY = self->GetChart();
267  for (MapOfTables::const_iterator tablesIter = tables.begin(); tablesIter != tables.end();
268  ++tablesIter)
269  {
270  const std::string& tableName = tablesIter->first;
271  vtkTable* table = tablesIter->second.GetPointer();
272  vtkIdType numCols = table->GetNumberOfColumns();
273  for (vtkIdType cc = 0; cc < numCols; ++cc)
274  {
275  std::string columnName = table->GetColumnName(cc);
276  std::string role = this->GetSeriesRole(tableName, columnName);
277  vtkSmartPointer<vtkPlot> plot =
278  this->SeriesPlots.GetPlot(self, tableName, columnName, role);
279  if (!plot)
280  {
281  plot = this->NewPlot(self, tableName, columnName, role);
282  if (!plot)
283  {
284  continue;
285  }
286  }
287  plot->SetInputData(table);
288  plot->SetUseIndexForXSeries(self->GetUseIndexForXAxis());
289  plot->SetInputArray(0, self->GetXAxisSeriesName());
290  plot->SetInputArray(this->GetInputArrayIndex(tableName, columnName, role), columnName);
291  this->SeriesPlots.AddPlot(self, tableName, columnName, role, plot);
292  newPlots.AddPlot(self, tableName, columnName, role, plot);
293  }
294  }
295 
296  // Remove any plots in this->SeriesPlots that are not in newPlots.
297  this->SeriesPlots.Intersect(newPlots, chartXY);
298  }
299 
300  //---------------------------------------------------------------------------
301  // Update properties for plots in the chart.
303  {
304  vtkChartXY* chartXY = self->GetChart();
305  vtkPlot* lastFunctionalBagPlot = 0;
306  for (PlotsMap::iterator iter1 = this->SeriesPlots.begin(); iter1 != this->SeriesPlots.end();
307  ++iter1)
308  {
309  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin(); iter2 != iter1->second.end();
310  ++iter2)
311  {
312  const PlotInfo& plotInfo = iter2->second;
313  const std::string& tableName = plotInfo.TableName;
314  const std::string& columnName = plotInfo.ColumnName;
315  vtkPlot* plot = plotInfo.Plot;
316  const std::string& role = iter2->first;
317 
318  if (this->UpdateSinglePlotProperties(self, tableName, columnName, role, plot))
319  {
320  // Functional bag plots shall be stacked under the other plots.
321  vtkPlotFunctionalBag* plotBag = vtkPlotFunctionalBag::SafeDownCast(plot);
322  if (plotBag)
323  {
324  // We can't select the median line as it may not exist in other dataset.
325  if (columnName == "QMedianLine")
326  {
327  plotBag->SelectableOff();
328  }
329  if (plotBag->IsBag())
330  {
331  if (!lastFunctionalBagPlot)
332  {
333  chartXY->LowerPlot(plotBag);
334  }
335  else
336  {
337  chartXY->StackPlotAbove(plotBag, lastFunctionalBagPlot);
338  }
339  lastFunctionalBagPlot = plotBag;
340  }
341  }
342  }
343  }
344  }
345  }
346 
347  //---------------------------------------------------------------------------
348  // Export visible plots to a CSV file.
349  virtual bool Export(vtkXYChartRepresentation* self, vtkCSVExporter* exporter)
350  {
351  for (PlotsMap::iterator iter1 = this->SeriesPlots.begin(); iter1 != this->SeriesPlots.end();
352  ++iter1)
353  {
354  for (PlotsMapItem::const_iterator iter2 = iter1->second.begin(); iter2 != iter1->second.end();
355  ++iter2)
356  {
357  const PlotInfo& plotInfo = iter2->second;
358  vtkPlot* plot = plotInfo.Plot;
359  if (!plot->GetVisible())
360  {
361  continue;
362  }
363  const std::string& columnName = plotInfo.ColumnName;
364  vtkTable* table = plot->GetInput();
365  vtkDataArray* xarray = self->GetUseIndexForXAxis()
366  ? NULL
367  : vtkDataArray::SafeDownCast(table->GetColumnByName(self->GetXAxisSeriesName()));
368  vtkAbstractArray* yarray = table->GetColumnByName(columnName.c_str());
369  if (yarray != NULL)
370  {
371  exporter->AddColumn(yarray, plot->GetLabel().c_str(), xarray);
372  }
373  }
374  }
375  return true;
376  }
377 
378 protected:
379  //---------------------------------------------------------------------------
380  // Returns false for in-visible plots.
382  const std::string& tableName, const std::string& columnName, const std::string& role,
383  vtkPlot* plot)
384  {
385  vtkChartXY* chartXY = self->GetChart();
386  const bool visible =
387  this->GetSeriesParameter(self, tableName, columnName, role, this->SeriesVisibilities, false);
388  plot->SetVisible(visible);
389  if (!visible)
390  {
391  return false;
392  }
393 
394  std::string default_label = self->GetDefaultSeriesLabel(tableName, columnName);
395  std::string label =
396  this->GetSeriesParameter(self, tableName, columnName, role, this->Labels, default_label);
397  if (self->GetSeriesLabelPrefix())
398  {
399  label = std::string(self->GetSeriesLabelPrefix()) + label;
400  }
401  plot->SetLabel(label);
402 
403  vtkColor3d color = this->GetSeriesParameter(
404  self, tableName, columnName, role, this->Colors, vtkColor3d(0, 0, 0));
405  plot->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue());
406  plot->GetSelectionPen()->SetColorF(self->SelectionColor);
407 
408  plot->SetWidth(
409  this->GetSeriesParameter(self, tableName, columnName, role, this->LineThicknesses, 2));
410  plot->GetPen()->SetLineType(this->GetSeriesParameter(
411  self, tableName, columnName, role, this->LineStyles, static_cast<int>(vtkPen::SOLID_LINE)));
412 
413  if (vtkPlotPoints* plotPoints = vtkPlotPoints::SafeDownCast(plot))
414  {
415  plotPoints->SetMarkerStyle(this->GetSeriesParameter(self, tableName, columnName, role,
416  this->MarkerStyles, static_cast<int>(vtkPlotPoints::NONE)));
417  // the vtkValidPointMask array is used by some filters (like plot
418  // over line) to indicate invalid points. this instructs the line
419  // plot to not render those points
420  plotPoints->SetValidPointMaskName("vtkValidPointMask");
421  }
422 
423  chartXY->SetPlotCorner(
424  plot, this->GetSeriesParameter(self, tableName, columnName, role, this->AxisCorners, 0));
425 
426  // for now only vtkPlotBar has color mapping
427  vtkPlotBar* plotBar = vtkPlotBar::SafeDownCast(plot);
428  if (plotBar && columnName == "bin_values")
429  {
430  bool colorMapping =
431  this->GetSeriesParameter(self, tableName, columnName, role, this->UseColorMapping, false);
432  plotBar->SetScalarVisibility(colorMapping);
433  plotBar->SelectColorArray("bin_extents");
434  vtkScalarsToColors* lut = this->GetSeriesParameter(
435  self, tableName, columnName, role, this->Lut, static_cast<vtkScalarsToColors*>(NULL));
436  if (lut)
437  {
438  plotBar->SetLookupTable(lut);
439  }
440  }
441  return true;
442  }
443 };
444 
445 #endif
446 // VTK-HeaderTest-Exclude: vtkXYChartRepresentationInternals.h
std::map< std::string, vtkScalarsToColors * > Lut
bool RemovePlot(vtkChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role=std::string())
T GetSeriesParameter(vtkXYChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &vtkNotUsed(role), const std::map< std::string, T > &parameter_map, const T default_value=T()) const
vtkXYChartRepresentation is representation that is used to add vtkPlot subclasses to a vtkChartXY ins...
void AddPlot(vtkChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role, vtkPlot *plot)
virtual std::string GetSeriesRole(const std::string &vtkNotUsed(tableName), const std::string &vtkNotUsed(columnName))
Subclasses can override this method to assign a role for a specific data array in the input dataset...
vtkXYChartRepresentation::MapOfTables MapOfTables
std::map< std::string, vtkSmartPointer< vtkTable > > MapOfTables
virtual int GetInputArrayIndex(const std::string &vtkNotUsed(tableName), const std::string &vtkNotUsed(columnName), const std::string &vtkNotUsed(role))
void AddColumn(vtkAbstractArray *yarray, const char *yarrayname=NULL, vtkDataArray *xarray=NULL)
In STREAM_COLUMNS mode, use this method to add a column (yarray).
virtual bool UpdateSinglePlotProperties(vtkXYChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role, vtkPlot *plot)
vtkSmartPointer< vtkPlot > GetPlot(vtkChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role=std::string()) const
virtual void UpdatePlotProperties(vtkXYChartRepresentation *self)
virtual void UpdatePlots(vtkXYChartRepresentation *self, const MapOfTables &tables)
vtkChartRepresentation is the base representation for charting representations.
exporter used by certain views to export data as a CSV file.
virtual vtkPlot * NewPlot(vtkXYChartRepresentation *self, const std::string &tableName, const std::string &columnName, const std::string &role)
virtual bool Export(vtkXYChartRepresentation *self, vtkCSVExporter *exporter)
void Intersect(const PlotsMap &other, vtkChartXY *chartXY)