VTK/Marks: Difference between revisions

From KitwarePublic
< VTK
Jump to navigationJump to search
No edit summary
Line 7: Line 7:


[[Image:Marks.png]]
[[Image:Marks.png]]
Alternately, we could move Qt up a few layers and include it as an alternative back-end to marks. We would want this if we determine it is not worth the effort to implement certain advanced types of drawing or interactivity in VTK itself. In this case, some views may require the QGraphicsView framework.
[[Image:MarksWithQt.png]]


== Fleshing Out the vtkMark API ==
== Fleshing Out the vtkMark API ==
Line 17: Line 13:
=== Possible Supported Parameter Types ===
=== Possible Supported Parameter Types ===


* Basic types (double, int, string, vtkVariant)
{| border="1"
<source lang="cpp">
! Description
! Example Code
|-
| Basic types (double, int, string, vtkVariant)
| <source lang="cpp">
vtkDotMark* m = vtkDotMark::New();
vtkDotMark* m = vtkDotMark::New();
m->SetParameter("size", 10);
m->SetParameter("size", 10);
</source>
</source>
 
|-
* Data object
| Data object
<source lang="cpp">
| <source lang="cpp">
vtkDirectedGraph* g = vtkDirectedGraph::New();
vtkDirectedGraph* g = vtkDirectedGraph::New();
//...
//...
Line 30: Line 30:
m->SetParameter("data", g);
m->SetParameter("data", g);
</source>
</source>
 
|-
* Pipeline output port
| Pipeline output port
<source lang="cpp">
| <source lang="cpp">
vtkRandomGraphSource* s = vtkRandomGraphSource::New();
vtkRandomGraphSource* s = vtkRandomGraphSource::New();
//...
//...
Line 38: Line 38:
m->SetParameter("data", s->GetOutputPort());
m->SetParameter("data", s->GetOutputPort());
</source>
</source>
 
|-
* vtkArray
| vtkArray
<source lang="cpp">
| <source lang="cpp">
vtkDenseArray<double>* a = vtkDenseArray<double>::New();
vtkDenseArray<double>* a = vtkDenseArray<double>::New();
//...
//...
Line 46: Line 46:
m->SetParameter("size", a);
m->SetParameter("size", a);
</source>
</source>
 
|-
* vtkAbstractArray
| vtkAbstractArray
<source lang="cpp">
| <source lang="cpp">
vtkDoubleArray* a = vtkDoubleArray::New();
vtkDoubleArray* a = vtkDoubleArray::New();
//...
//...
Line 54: Line 54:
m->SetParameter("size", a);
m->SetParameter("size", a);
</source>
</source>
 
|-
* Data object + field type + array name
| Data object + field type + array name
<source lang="cpp">
| <source lang="cpp">
vtkTable* t = vtkTable::New();
vtkTable* t = vtkTable::New();
//...
//...
Line 62: Line 62:
m->SetParameter("size", t, vtkDataObject::ROW, "columnName");
m->SetParameter("size", t, vtkDataObject::ROW, "columnName");
</source>
</source>
 
|-
* Data object + field type + array name + component index
| Data object + field type + array name + component index
<source lang="cpp">
| <source lang="cpp">
vtkTable* t = vtkTable::New();
vtkTable* t = vtkTable::New();
vtkDoubleArray* loc = vtkDoubleArray::New();
vtkDoubleArray* loc = vtkDoubleArray::New();
Line 73: Line 73:
m->SetParameter("bottom", t, vtkDataObject::ROW, "location", 1);
m->SetParameter("bottom", t, vtkDataObject::ROW, "location", 1);
</source>
</source>
 
|-
* Function pointer
| Function pointer
<source lang="cpp">
| <source lang="cpp">
double MySize(vtkMark* m, int i) { return 10*i; }
double MySize(vtkMark* m, int i) { return 10*i; }
//...
//...
Line 81: Line 81:
m->SetParameter("size", &MySize);
m->SetParameter("size", &MySize);
</source>
</source>
 
|-
* Functor (i.e. struct type with operator()) - requires SetParameter to be templated.
| Functor (i.e. struct type with operator()) - requires SetParameter to be templated.
<source lang="cpp">
| <source lang="cpp">
struct MySize {
struct MySize {
   double operator()(vtkMark* m, int i) { return 10*i; }
   double operator()(vtkMark* m, int i) { return 10*i; }
Line 91: Line 91:
m->SetParameter("size", MySize());
m->SetParameter("size", MySize());
</source>
</source>
 
|-
* Lambda function (boost::lambda)
| Lambda function (boost::lambda)
 
|
* Parameter strategies
|-
<source lang="cpp">
| Parameter strategies
| <source lang="cpp">
class vtkDoubleParameter {
class vtkDoubleParameter {
   virtual double Get(vtkMark* m, int i) = 0;
   virtual double Get(vtkMark* m, int i) = 0;
Line 108: Line 109:
m->SetParameter("size", MySize());
m->SetParameter("size", MySize());
</source>
</source>
 
|-
* Override virtual methods in mark
| Override virtual methods in mark
<source lang="cpp">
| <source lang="cpp">
class vtkDotMark : public vtkMark {
class vtkDotMark : public vtkMark {
protected:
protected:
Line 123: Line 124:
MyMark* m = MyMark::New();
MyMark* m = MyMark::New();
</source>
</source>
 
|-
* Inherit from parent mark
| Inherit from parent mark
<source lang="cpp">
| <source lang="cpp">
vtkDotMark* parent = vtkDotMark::New();
vtkDotMark* parent = vtkDotMark::New();
parent->SetParameter("size", 10);
parent->SetParameter("size", 10);
Line 131: Line 132:
parent->Add(child); // Child has size 10
parent->Add(child); // Child has size 10
</source>
</source>
|}


=== Possible Parameter Storage and Access ===
=== Possible Parameter Storage and Access ===


* Named member variables
==== Named member variables ====
<source lang="cpp">
<source lang="cpp">
class vtkDotMark {
class vtkDotMark {
Line 145: Line 148:
</source>
</source>


* Named member variables with import/export to name/value map
==== Named member variables with import/export to name/value map ====
<source lang="cpp">
<source lang="cpp">
class vtkMark {
class vtkMark {
Line 170: Line 173:
</source>
</source>


* Generic name/value map
==== Generic name/value map ====
<source lang="cpp">
<source lang="cpp">
class vtkMark {
class vtkMark {
Line 183: Line 186:
</source>
</source>


* Generic name/value map with setter/getter syntactic sugar for discoverability
==== Generic name/value map with setter/getter syntactic sugar for discoverability ====
<source lang="cpp">
<source lang="cpp">
class vtkDotMark : public vtkMark {
class vtkDotMark : public vtkMark {
Line 192: Line 195:
</source>
</source>


* vtkInformation/value map. The idea here is that valid parameter names/types/bounds are queryable at runtime, instead of in an opaque map.
==== 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">
<source lang="cpp">
class vtkMark {
class vtkMark {

Revision as of 20:05, 23 February 2010

Overview

Marks can be thought of as highly-configurable vectorized graphics items, or graphics item factories. They are a mid-level API built on more basic rendering primitives like lines, circles, etc. You want to use marks to make it easy to configure a set of primitives, where each primitive's properties will change depending on the item.

Protovis is an API description for marks with a reference implementation in javascript. Take a look at the protovis site for details on their design decisions and features.

In VTK, we want to explore a similar interface for marks in C++. The following is a possible technology stack for using marks in VTK. Qt could be incorporated as an alternative to OpenGL for publication-quality images.

Marks.png

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

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>

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)
Parameter strategies <source lang="cpp">

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>

Override virtual methods in mark <source lang="cpp">

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