VTK/CanvasAPI: Difference between revisions
m (VTK/Charts/CanvasAPI moved to VTK/CanvasAPI: The canvas based API is more general - can do more than charts. Moving into the main VTK space.) |
|
(No difference)
|
Revision as of 15:52, 11 December 2009
After recent discussions I have been prototyping a simple canvas style API for VTK. The diagram below shows a rough equivalence to the QGraphicsView framework present in Qt, but with a much more basic API at this stage.
The vtkContextActor essentially holds the rendering context, window etc and hooks into the RenderOverlay phase of VTK rendering. The vtkContextScene can hold multiple vtkContextItems (items derived from vtkContextItem). It handles coordination of rendering, propogation of events, hit detection and persistence. I have prepared a short example program with two movable vtkBlockItem objects. The performance in our initial tests is still doing OK.
vtkMark Back Ends
The following shows basically the same mark configuration built with a QGraphicsView-based canvas elements and the proposed VTK-based canvas.
Qt back-end | VTK/OpenGL back-end |
---|---|
Using Function Pointers
It seems that there is a wish to be able to declare functions that override certain aspects of rendering. In a traditional C++ API this would normally be accomplished by inheritance and overriding of a virtual function. The same thing can be accomplished by supplying function pointers without needing to derive a class.
The QtConcurrent API uses function pointers, and boost_bind optionally. Check out the relevant sections of their API documentation here for more details. So a specific signature is required for the function pointer, but this could optionally be created by boost::bind (or possibly boost lambda functions).
As an example the equivalent code would be.
<source lang="cpp">#include <mymark.h>
double scalarFunction(int index);
int main() {
MyMark *mark = new MyMark; mark->SetScalarFunctor(scalarFunction);
}
double scalarFunction(int index) {
return index * 3.0 / (index - 1.0);
}</source>
Compared with a more traditional inherited class API.
<source lang="cpp">#include <mymark.h>
class InheritedMark : public MyMark { protected:
virtual double scalarFunction(int index);
};
int main() {
InheritedMark *mark = new InheritedMark;
}
double InheritedMark::scalarFunction(int index) {
return index * 3.0 / (index - 1.0);
}</source>
Example Scene
Below is the boilerplate code to set up and instantiate a new scene.
<source lang="cpp">int main( int argc, char * argv [] ) {
// Qt initialization QApplication app(argc, argv); QMainWindow *mainWindow = new QMainWindow; mainWindow->setGeometry(0, 0, 800, 600);
// QVTK set up and initialization QVTKWidget *qvtkWidget = new QVTKWidget(mainWindow); mainWindow->setCentralWidget(qvtkWidget);
// Set up a 2D chart actor, APIDiagram object andn add them to the renderer VTK_CREATE(vtkContextActor, actor); VTK_CREATE(vtkRenderer, renderer); renderer->SetBackground(1.0, 1.0, 1.0); vtkRenderWindow *renderWindow = vtkRenderWindow::New(); renderWindow->AddRenderer(renderer); qvtkWidget->SetRenderWindow(renderWindow); renderer->AddActor(actor); // Try to set an interactor style on the chart vtkInteractorStyleRubberBand2D *interactor = vtkInteractorStyleRubberBand2D::New(); renderWindow->GetInteractor()->SetInteractorStyle(interactor); actor->GetScene()->AddInteractorStyle(interactor); // The scene currently needs the render window to trigger updates actor->GetScene()->SetWindow(renderWindow);</source>
Then the code to add a few new elements to the scene.
<source lang="cpp"> // Create two new block items and add them to the scene
VTK_CREATE(vtkBlockItem, block); actor->GetScene()->AddItem(block); block->SetLabel("Test"); block->SetDimensions(100, 50, 200, 100); block->SetScalarFunctor(myFunction); VTK_CREATE(vtkBlockItem, block2); actor->GetScene()->AddItem(block2); block2->SetLabel("Test 2"); block2->SetDimensions(100, 250, 200, 100);</source>
Finally, the event loop is started.
<source lang="cpp"> // Now show the application and start the event loop
mainWindow->show(); return app.exec();
}</source>