Difference between revisions of "VTK/Charts/API"

From KitwarePublic
< VTK‎ | Charts
Jump to navigationJump to search
(Some comments.)
(One more comment.)
Line 17: Line 17:


I could also overload the New() function to accept an argument such as vtkChart::New(vtkChart::LINE) which would create a new chart object with a line chart contained. The chart can iterate over the plots and paint each one in turn, this allows an intuitive interface where multiple plot types can be plotted on the same axes.
I could also overload the New() function to accept an argument such as vtkChart::New(vtkChart::LINE) which would create a new chart object with a line chart contained. The chart can iterate over the plots and paint each one in turn, this allows an intuitive interface where multiple plot types can be plotted on the same axes.
::<font color="green">AddPlot() or the vtkChart::New() variant that takes an argument should take strings and not enums. That will allow run-time addition of new plot types. A few simple functions would make it easy to create new types of plots (or even just shortcuts for plots with some style defaults set differently).</font>
 
::<font color="green">The biggest problem I have with this is that many plot/chart settings will be specific to one particular subclass. For instance, a line plot might have line thickness but no glyph size while a scatterplot would have glyph size but no line thickness. If you only get a pointer to a vtkPlot you won't be able to call either unless every possible property is defined on the base class. This could get '''very''' ugly. So, rather than using the traditional SetXXX() calls, I would argue that charts should make heavy use of a Set() method that takes some property object or string along with the value.</font>
 
::<font color="green">Also, AddPlot() or the vtkChart::New() variant that takes an argument should take strings and not enums. That will allow run-time addition of new plot types. A few simple functions would make it easy to create new types of plots (or even just shortcuts for plots with some style defaults set differently).</font>


There has been a lot of talk about API. Do we want a declarative API? This would make constructs such as,
There has been a lot of talk about API. Do we want a declarative API? This would make constructs such as,

Revision as of 16:36, 20 October 2009

After looking at various other frameworks, tools and products out there here are some thoughts on the API. Employing a factory based interface seems like it would give us the most intuitive API. So a chart could be instantiated in the following way,

// Instantiate a new chart
vtkChart *chart = vtkChart::New();
// Add a bar plot
vtkPlot *barPlot = chart->AddPlot(Chart::BAR);
// Set the data source to table, column 0 is x, column 2 is y
barPlot->SetData(table, 0, 2);
// Set the width of the bars
barPlot->SetWidth(20);
// Add a line plot
vtkPlot *linePlot = chart->AddPlot(Chart::LINE);
// Set the data source to table, column 0 is x, column 2 is y
linePlot->SetData(table, 0, 2);
// Set the line width
linePlot->SetWidth(2);

I could also overload the New() function to accept an argument such as vtkChart::New(vtkChart::LINE) which would create a new chart object with a line chart contained. The chart can iterate over the plots and paint each one in turn, this allows an intuitive interface where multiple plot types can be plotted on the same axes.

The biggest problem I have with this is that many plot/chart settings will be specific to one particular subclass. For instance, a line plot might have line thickness but no glyph size while a scatterplot would have glyph size but no line thickness. If you only get a pointer to a vtkPlot you won't be able to call either unless every possible property is defined on the base class. This could get very ugly. So, rather than using the traditional SetXXX() calls, I would argue that charts should make heavy use of a Set() method that takes some property object or string along with the value.
Also, AddPlot() or the vtkChart::New() variant that takes an argument should take strings and not enums. That will allow run-time addition of new plot types. A few simple functions would make it easy to create new types of plots (or even just shortcuts for plots with some style defaults set differently).

There has been a lot of talk about API. Do we want a declarative API? This would make constructs such as,

vtkChart *chart = vtkChart::New();
chart->SetWidth(200)
  ->SetHeight(200);

chart->AddPlot(vtkChart::BAR)
  ->SetData(table, 1, 2)
  ->SetWidth(20)
  ->SetLabel("My Data");

This would require setter functions that returned a pointer to the object, i.e.

vtkChart * vtkChart::SetWidth(int width);
vtkPlot * vtkChart::AddPlot(enum);
vtkPlot * vtkPlot::SetLabel(const char *label);

One nice thing about this approach is that ignoring the pointer returned allows traditional VTK syntax to be used.

vtkPlot *plot = chart->AddPlot(vtkChart::BAR);
plot->SetData(table, 1, 2);
plot->SetWidth(20);
plot->SetLabel("My Data");

Admittedly it is not in keeping with the current pattern used in VTK, there are numerous examples of its use in other libraries and frameworks. It should possibly be more of a global change to the library API, rather than isolated to one or two components.

I am not sure declarative properties are that useful. However, I think there's no harm (other than a lot of work) in changing vtkSetMacro and other SetXXX() methods to return "this" instead of void. Note that
      find /path/to/ParaView -name "*.h" -exec grep "void Set[A-Z].*(" {} \; | grep -v "static " | wc -l
returned 5262 SetXXX() methods that were declared directly instead of using vtkSetMacro (many may involve pointers to vtkObject subclasses).