|
|
(4 intermediate revisions by the same user not shown) |
Line 7: |
Line 7: |
|
| |
|
| [[Image:Marks.png]] | | [[Image:Marks.png]] |
| | |
| | [[VTK/Marks/Design]] describes some API design considerations. |
|
| |
|
| == Initial Prototype == | | == Initial Prototype == |
|
| |
|
| The purpose of this prototype was to see how closely C++ code can resemble Protovis Javascript code. The properties are defined as boost::function objects. boost::lambda expressions (lines using the special _index and _d variables) may be used to specify functions. Alternately, free/static functions or function objects may be used. The bottom images show the results from both pieces of code. | | The purpose of this prototype was to see how closely C++ code can resemble Protovis Javascript code. The properties are defined as boost::function instances. boost::lambda expressions (lines using the special _index and _d variables) may be used to specify functions. Alternately, free/static functions or function objects may be used. The bottom images show the results from both pieces of code. |
| | |
| | The source code is currently available as part of the [http://titan.sandia.gov Titan Toolkit] under the Libraries/Marks subdirectory, and it is slated to be moved into VTK in late 2010 or early 2011. Examples may be found in the tests under Libraries/Marks/Testing/Cxx. |
|
| |
|
| {| border="1" | | {| border="1" |
Line 40: |
Line 44: |
| | | | | |
| <source lang="cpp"> | | <source lang="cpp"> |
| | // Sizing and scales. |
| int w = 400; | | int w = 400; |
| int h = 250; | | int h = 250; |
Line 61: |
Line 66: |
| | | | | |
| <source lang="cpp"> | | <source lang="cpp"> |
| | // The root panel. |
| Panel vis; | | Panel vis; |
| vis.width(w); | | vis.width(w); |
Line 82: |
Line 88: |
| | | | | |
| <source lang="cpp"> | | <source lang="cpp"> |
| | // The bars. |
| Bar* bar = vis.addBar(); | | Bar* bar = vis.addBar(); |
| bar->data(data); | | bar->data(data); |
Line 99: |
Line 106: |
| | | | | |
| <source lang="cpp"> | | <source lang="cpp"> |
| | // The value label. |
| Label* label = bar->anchor("right")->addLabel(); | | Label* label = bar->anchor("right")->addLabel(); |
| label->textStyle(vtkColor4d(1, 1, 1, 1)); | | label->textStyle(vtkColor4d(1, 1, 1, 1)); |
Line 114: |
Line 122: |
| | | | | |
| <source lang="cpp"> | | <source lang="cpp"> |
| | // The variable label. |
| Label* label2 = bar->anchor("left")->addLabel(); | | Label* label2 = bar->anchor("left")->addLabel(); |
| label2->textMargin(5); | | label2->textMargin(5); |
| label2->textAlign(vtkStdString("right")); | | label2->textAlign(vtkStdString("right")); |
| label2->text(bind(charAt, vtkStdString("ABCDEFGHIJK"), _index)); | | label2->text(bind(charAt, "ABCDEFGHIJK", _index)); |
| </source> | | </source> |
| |- | | |- |
Line 136: |
Line 145: |
| | | | | |
| <source lang="cpp"> | | <source lang="cpp"> |
| | // X-axis ticks. |
| Rule* rule = vis.addRule(); | | Rule* rule = vis.addRule(); |
| rule->data(x.ticks(5)); | | rule->data(x.ticks(5)); |
Line 150: |
Line 160: |
| </source> | | </source> |
| |- | | |- |
| | [[Image:ProtovisBarChart.png]] | | | |
| | [[Image:MarksBarChart.png]]
| | <source lang="javascript"> |
| |-
| | // Render the scene. |
| |}
| | vis.render(); |
| | |
| == Fleshing Out the vtkMark API ==
| |
| The fundamental type would be vtkMark, the superclass of all mark types. Its interface would define how programmers would work with all marks in VTK. The following sections enumerate some possible use cases with code snippets showing what functionality the feature would allow.
| |
| | |
| === Possible Supported Parameter Types ===
| |
| | |
| {| border="1"
| |
| ! Description
| |
| ! Example Code
| |
| |-
| |
| | Basic types (double, int, string, vtkVariant)
| |
| | <source lang="cpp">
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", 10);
| |
| </source>
| |
| |-
| |
| | Data object
| |
| | <source lang="cpp">
| |
| vtkDirectedGraph* g = vtkDirectedGraph::New();
| |
| //... | |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("data", g);
| |
| </source> | | </source> |
| |-
| |
| | Pipeline output port
| |
| | <source lang="cpp">
| |
| vtkRandomGraphSource* s = vtkRandomGraphSource::New();
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("data", s->GetOutputPort());
| |
| </source>
| |
| |-
| |
| | vtkArray
| |
| | <source lang="cpp">
| |
| vtkDenseArray<double>* a = vtkDenseArray<double>::New();
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", a);
| |
| </source>
| |
| |-
| |
| | vtkAbstractArray
| |
| | <source lang="cpp">
| |
| vtkDoubleArray* a = vtkDoubleArray::New();
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", a);
| |
| </source>
| |
| |-
| |
| | Data object + field type + array name
| |
| | <source lang="cpp">
| |
| vtkTable* t = vtkTable::New();
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", t, vtkDataObject::ROW, "columnName");
| |
| </source>
| |
| |-
| |
| | Data object + field type + array name + component index
| |
| | <source lang="cpp">
| |
| vtkTable* t = vtkTable::New();
| |
| vtkDoubleArray* loc = vtkDoubleArray::New();
| |
| loc->SetNumberOfComponents(2);
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("left", t, vtkDataObject::ROW, "location", 0);
| |
| m->SetParameter("bottom", t, vtkDataObject::ROW, "location", 1);
| |
| </source>
| |
| |-
| |
| | Function pointer
| |
| | <source lang="cpp">
| |
| double MySize(vtkMark* m, int i) { return 10*i; }
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", &MySize);
| |
| </source>
| |
| |-
| |
| | Functor (i.e. struct type with operator()) - requires SetParameter to be templated.
| |
| | <source lang="cpp">
| |
| struct MySize {
| |
| double operator()(vtkMark* m, int i) { return 10*i; }
| |
| }
| |
| //...
| |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", MySize());
| |
| </source>
| |
| |-
| |
| | Lambda function (boost::lambda)
| |
| | | | | |
| |-
| | <source lang="cpp"> |
| | Parameter strategies
| | // Render the scene. |
| | <source lang="cpp">
| | vis.render(); |
| class vtkDoubleParameter {
| |
| virtual double Get(vtkMark* m, int i) = 0;
| |
| }
| |
| | |
| class MySize : public vtkDoubleParameter {
| |
| protected:
| |
| double Get(vtkMark* m, int i) { return 10*i; }
| |
| }
| |
| //... | |
| vtkDotMark* m = vtkDotMark::New();
| |
| m->SetParameter("size", MySize());
| |
| </source> | | </source> |
| |- | | |- |
| | Override virtual methods in mark | | | [[Image:ProtovisBarChart.png]] |
| | <source lang="cpp"> | | | [[Image:MarksBarChart.png]] |
| class vtkDotMark : public vtkMark {
| |
| protected:
| |
| virtual double GetSize(int i) { return 10; }
| |
| }
| |
| | |
| class MyMark : public vtkDotMark {
| |
| protected:
| |
| double GetSize(int i) { return 10*i; }
| |
| }
| |
| //...
| |
| MyMark* m = MyMark::New();
| |
| </source>
| |
| |- | | |- |
| | Inherit from parent mark
| |
| | <source lang="cpp">
| |
| vtkDotMark* parent = vtkDotMark::New();
| |
| parent->SetParameter("size", 10);
| |
| vtkDotMark* child = vtkDotMark::New();
| |
| parent->Add(child); // Child has size 10
| |
| </source>
| |
| |} | | |} |
|
| |
|
| |
| === Possible Parameter Storage and Access ===
| |
|
| |
| ==== Named member variables ====
| |
| <source lang="cpp">
| |
| class vtkDotMark {
| |
| public:
| |
| ParamType GetSize() { return this->Size; }
| |
| void SetSize(ParamType p) { this->Size = p; }
| |
| private:
| |
| ParamType Size;
| |
| }
| |
| </source>
| |
|
| |
| ==== Named member variables with import/export to name/value map ====
| |
| <source lang="cpp">
| |
| class vtkMark {
| |
| public:
| |
| ParamType GetParameter(string key)
| |
| { this->ExportSettings()->GetParameter(key); }
| |
| void SetParameter(string key, ParamType p)
| |
| { this->ImportSettings(this->ExportSettings()->SetParameter(key, p)); }
| |
| virtual void ImportSettings(vtkSettings* s) { }
| |
| virtual vtkSettings* ExportSettings() { return vtkSettings::New(); }
| |
| }
| |
|
| |
| class vtkDotMark {
| |
| public:
| |
| ParamType GetSize() { return this->Size; }
| |
| void SetSize(ParamType p) { this->Size = p; }
| |
| virtual vtkSettings* ExportSettings()
| |
| { return this->Parent->ExportSettings()->SetParameter("size", this->Size); }
| |
| virutal void ImportSettings(vtkSettings* s)
| |
| { this->Size = s->GetParameter("size"); }
| |
| private:
| |
| ParamType Size;
| |
| }
| |
| </source>
| |
|
| |
| ==== Generic name/value map ====
| |
| <source lang="cpp">
| |
| class vtkMark {
| |
| public:
| |
| ParamType GetParameter(string key)
| |
| { return this->Parameters[key].Valid ? this->Parameters[key] : this->Parent->GetParameter(key); }
| |
| void SetParameter(string key, ParamType p)
| |
| { this->Parameters[key] = p; }
| |
| private:
| |
| map<string, ParamType> Parameters;
| |
| }
| |
| </source>
| |
|
| |
| ==== Generic name/value map with setter/getter syntactic sugar for discoverability ====
| |
| <source lang="cpp">
| |
| class vtkDotMark : public vtkMark {
| |
| public:
| |
| ParamType GetSize() { return this->GetParameter("size"); }
| |
| void SetSize(ParamType p) { this->SetParameter("size", p); }
| |
| }
| |
| </source>
| |
|
| |
| ==== vtkInformation/value map ====
| |
| The idea here is that valid parameter names/types/bounds are queryable at runtime, instead of in an opaque map.
| |
| <source lang="cpp">
| |
| class vtkMark {
| |
| public:
| |
| // Keys to describe parameters
| |
| static vtkInformationIntegerKey* PARAMETER_TYPE();
| |
| static vtkInformationStringKey* PARAMETER_NAME();
| |
| static vtkInformationIntegerKey* PARAMETER_NUMBER_OF_COMPONENTS();
| |
| static vtkInformationIntegerVectorKey* PARAMETER_INTEGER_BOUNDS();
| |
| static vtkInformationDoubleVectorKey* PARAMETER_REAL_BOUNDS();
| |
|
| |
| int GetNumberOfParameters() { return this->ParameterInfo->size(); }
| |
| vtkInformation* GetParameterInfo(int i) { return this->ParameterInfo[i]; }
| |
| int GetParameterHandle(const char* name)
| |
| { /* search ParameterInfo for name, return index */ }
| |
| void SetParameter(int handle, ParamType p)
| |
| { this->ParameterValues[handle] = p; }
| |
|
| |
| protected:
| |
| virtual void SetupParameters() = 0;
| |
| vector<vtkInformation*> ParameterInfo;
| |
| vector<ParamType> ParameterValues;
| |
| }
| |
|
| |
| class vtkDotMark : public vtkMark {
| |
| protected:
| |
| void SetupParameters()
| |
| {
| |
| vtkInformation* sizeInfo = vtkInformation::New();
| |
| double sizeBounds[2] = { 0., VTK_DOUBLE_MAX };
| |
| sizeInfo->Set( vtkPointMark::PARAMETER_NAME(), "size" );
| |
| sizeInfo->Set( vtkPointMark::PARAMETER_TYPE(), VTK_DOUBLE );
| |
| sizeInfo->Set( vtkPointMark::PARAMETER_NUMBER_OF_COMPONENTS(), 1 );
| |
| sizeInfo->Set( vtkPointMark::PARAMETER_REAL_BOUNDS(), sizeBounds, 2 );
| |
| this->ParameterInfo.push_back(sizeInfo);
| |
| this->ParameterValues.push_back(10);
| |
| }
| |
| }
| |
| </source>
| |
|
| |
| === Possible Other Features ===
| |
|
| |
| * Declarative API
| |
| * Iterator support
| |