Passer des objets VTK entre C++ et Python

Cet article montre comment échanger des instancez de classes VTK entre du code Python et du code C++.
Ce code a été testé avec VTK 4.2 et Python 2.3.
Le wrapping a été effectué à l'aide de SWIG 1.2.20 et de Visual Studio 2003 (VC++ 7.1).

Utiliser un objet VTK C++ depuis Python

PyObject * CreateCone()
{
    // create a VTK object from C++
    vtkConeSource * cone = vtkConeSource::New();

    // convert the C++ vtkConeSource object to a Python object
    return vtkPythonGetObjectFromPointer( cone );
}

Utiliser un objet VTK Python depuis C++

void ChangeActorColor( PyObject * Cone )
{
    // try to extract a C++ vtkActor object from the Python object
    vtkActor * actor = (vtkActor*)vtkPythonGetPointerFromObject(
        Cone,
        "vtkActor" );

    if ( actor == 0 ) // if the PyObject is not a vtk.vtkActor object
    {
        // This line will cause Python to print an error message
        // see Python.h for more details
        PyErr_SetString( PyExc_TypeError,
                         "Not a vtkActor" );
    }
    else
    {
        // success : change color to red
        actor->GetProperty()->SetColor( 1, 0, 0 );
    }

Exemple complet

Voici un exemple d'échange d'instances d'objets VTK entre un module C++ et un module Python.

Code C++

Le code source C++, un projet Visual Studio 2003 et un fichier de test Python sont disponibles ici : VtkPythonCpp.zip.
Pour plus de détails concernant la compilation du code à l'aide de SWIG, vous pouvez lire l'article Python Extensions in C++ Using SWIG : Building Extensions On Windows
#ifndef _WRAPPING_H_
#define _WRAPPING_H_

/*
    Libraries needed to link :
        vtkGraphics.lib
        vtkCommonPython.lib
        vtkRendering.lib
        python2x.lib
*/

#define VTK_USE_ANSI_STDLIB
#include <vtkPythonUtil.h> // includes Python.h 

PyObject * CreateCone();
void ChangeActorColor( PyObject * Scalars );

#endif
wrapping.h
#include "wrapping.h"
#include <vtkConeSource.h>
#include <vtkActor.h>
#include <vtkProperty.h>

PyObject * CreateCone()
{
    // create a VTK object from C++
    vtkConeSource * cone = vtkConeSource::New();

    // convert the C++ vtkConeSource object to a Python object
    return vtkPythonGetObjectFromPointer( cone );
}

void ChangeActorColor( PyObject * Cone )
{
    // try to extract a C++ vtkActor object from the Python object
    vtkActor * actor = (vtkActor*)vtkPythonGetPointerFromObject(
        Cone,
        "vtkActor" );

    if ( actor == 0 ) // if the PyObject is not a vtk.vtkActor object
    {
        // This line will cause Python to print an error message
        // see Python.h for more details
        PyErr_SetString( PyExc_TypeError,
                         "Not a vtkActor" );
    }
    else
    {
        // success : change color to red
        actor->GetProperty()->SetColor( 1, 0, 0 );
    }
}
wrapping.cpp
%module wrapping
%{
#include "wrapping.h"
%}
PyObject * CreateCone();
void ChangeActorColor( PyObject * Scalars );
wrapping.i

Code de test Python

#!/usr/bin/env python
import vtk
import wrapping

# create VTK objects
mapper = vtk.vtkPolyDataMapper()
actor = vtk.vtkActor()
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
interactor = vtk.vtkRenderWindowInteractor()

# get a VTK cone from C++
cone = wrapping.CreateCone()           # C++ -> Python
# modify it from Python
cone.SetResolution( 20 )

# pass a VTK Python object to C++
wrapping.ChangeActorColor( actor )     # Python -> C++

# build the visualization pipeline and watch
mapper.SetInput( cone.GetOutput() )
actor.SetMapper( mapper )
renderer.AddActor( actor )
renderWindow.AddRenderer( renderer )
interactor.SetRenderWindow( renderWindow )

interactor.Initialize()
interactor.Start()
test.py

Résultat

It works !


Sommaire