1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // SALOME SALOME_PY : binding of VTK graphics and Python
23 // File : SalomePy.cxx
24 // Author : Paul RASCLE, EDF
27 #include <vtkPythonUtil.h>
29 #include <vtkVersion.h>
30 #include <vtkRenderer.h>
31 #include <vtkRenderWindow.h>
32 #include <vtkRenderWindowInteractor.h>
34 #include <SALOME_Event.h>
36 #include <SUIT_Session.h>
37 #include <SalomeApp_Application.h>
38 #include <SalomeApp_Study.h>
40 #include <SVTK_ViewManager.h>
41 #include <SVTK_ViewWindow.h>
44 \brief Python wrappings for VTK viewer of the SALOME desktop.
46 All methods are implemented using Event mechanism. The module
47 provides the following functions:
50 - getRenderWindowInteractor()
59 renderer = SalomePy.getRenderer() # get VTK renderer
60 window = SalomePy.getRenderWindow() # get render window
63 The methods getRenderer(), getRenderWindow() and getRenderWindowInteractor()
64 open new VTK viewer if there is no one opened.
65 In case of any error these methods return None object to the Python.
68 #define PUBLISH_ENUM(i) \
72 if ( ( w = PyInt_FromLong( i ) ) == NULL ) return; \
73 rc = PyDict_SetItemString( aModuleDict, #i, w ); \
75 if ( rc < 0 ) return; \
78 //! View operation type
80 ViewFront, //!< front view
81 ViewBack, //!< back view
82 ViewTop, //!< top view
83 ViewBottom, //!< bottom view
84 ViewRight, //!< right view
85 ViewLeft //!< left view
89 \brief Get Python class object by name
91 \param theClassName Python class name
92 \return Python class object or None object if class is not found
94 static PyObject* GetPyClass( const char* theClassName )
96 static PyObject* aVTKModule = 0;
97 PyObject* aPyClass = 0;
99 if ( VTK_MAJOR_VERSION > 3 )
100 aVTKModule = PyImport_ImportModule( "libvtkRenderingPython" );
102 aVTKModule = PyImport_ImportModule( "libVTKGraphicsPython" );
103 if( PyErr_Occurred() ) {
108 PyObject* aVTKDict = PyModule_GetDict( aVTKModule );
109 aPyClass = PyDict_GetItemString(aVTKDict, const_cast<char*>( theClassName ) );
115 \brief VTK window find/create mode
119 __Find, // try to find VTK window; if not found, do nothing
120 __FindOrCreate, // try to find VTK window; if not found, create new one
121 __Create }; // create new VTK window
124 \brief Find or create VTK window.
126 \param toCreate window find/create mode
127 \return VTK window pointer or 0 if it could not be found/created
129 static SVTK_ViewWindow* GetVTKViewWindow( int toCreate = __FindOrCreate ) {
130 SVTK_ViewWindow* aVW = 0;
131 if ( SUIT_Session::session() ) {
133 SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
136 SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
138 // find or create VTK view manager
139 if ( toCreate == __Create ) {
140 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->createViewManager( "VTKViewer" ) );
142 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
144 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->createViewWindow() );
145 // VSR : When new view window is created it can be not active yet at this moment,
146 // so the following is a some workaround
147 if ( !aVW && !aVM->getViews().isEmpty() )
148 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
152 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->getViewManager( "VTKViewer", toCreate == __FindOrCreate ) );
154 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
155 // VSR : When new view window is created it can be not active yet at this moment,
156 // so the following is a some workaround
157 if ( !aVW && !aVM->getViews().isEmpty() )
158 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
168 \fn PyObject* getRenderer( int toCreate = 0 );
169 \brief Get VTK renderer (vtkRenderer).
171 If \a toCreate parameter is 0 (by default) the function tries to find
172 and reuse existing VTK window; if it is not found, the new VTK window
175 If \a toCreate parameter is non-zero, the function always creates
178 If VTK window could not be found and or created, the None Python object
181 \param toCreate window creation mode
182 \return VTK window renderer object
185 class TGetRendererEvent: public SALOME_Event
188 typedef PyObject* TResult;
191 TGetRendererEvent( bool toCreate )
192 : myResult( Py_None ), myCreate( toCreate ) {}
193 virtual void Execute()
195 PyObject* aPyClass = ::GetPyClass( "vtkRenderer" );
196 SVTK_ViewWindow* aVTKViewWindow =
197 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
198 if( aVTKViewWindow && aPyClass ) {
199 vtkRenderer* aVTKObject = aVTKViewWindow->getRenderer();
200 myResult = PyVTKObject_New( aPyClass, aVTKObject );
205 extern "C" PyObject* libSalomePy_getRenderer( PyObject* self, PyObject* args )
207 PyObject* aResult = Py_None;
209 if ( !PyArg_ParseTuple( args, "|i:getRenderer", &toCreate ) )
212 aResult = ProcessEvent( new TGetRendererEvent( toCreate ) );
217 \fn PyObject* getRenderWindow( int toCreate = 0 );
218 \brief Get VTK render window (vtkRenderWindow).
220 If \a toCreate parameter is 0 (by default) the function tries to find
221 and reuse existing VTK window; if it is not found, the new VTK window
224 If \a toCreate parameter is non-zero, the function always creates
227 If VTK window could not be found and or created, the None Python object
230 \param toCreate window creation mode
231 \return VTK window render window object
234 class TGetRenderWindowEvent: public SALOME_Event
237 typedef PyObject* TResult;
240 TGetRenderWindowEvent( bool toCreate )
241 : myResult( Py_None ), myCreate( toCreate ) {}
242 virtual void Execute()
244 PyObject* aPyClass = ::GetPyClass( "vtkRenderWindow" );
245 SVTK_ViewWindow* aVTKViewWindow =
246 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
247 if( aVTKViewWindow && aPyClass ) {
248 vtkRenderWindow* aVTKObject = aVTKViewWindow->getRenderWindow();
249 myResult = PyVTKObject_New( aPyClass, aVTKObject );
254 extern "C" PyObject* libSalomePy_getRenderWindow( PyObject* self, PyObject* args )
256 PyObject* aResult = Py_None;
258 if ( !PyArg_ParseTuple( args, "|i:getRenderWindow", &toCreate ) )
261 aResult = ProcessEvent( new TGetRenderWindowEvent( toCreate ) );
266 \fn PyObject* getRenderWindowInteractor( int toCreate = 0 );
267 \brief Get VTK render window interactor (getRenderWindowInteractor).
269 If \a toCreate parameter is 0 (by default) the function tries to find
270 and reuse existing VTK window; if it is not found, the new VTK window
273 If \a toCreate parameter is non-zero, the function always creates
276 If VTK window could not be found and or created, the None Python object
279 \param toCreate window creation mode
280 \return VTK window render window interactor object
283 class TGetRenderWindowInteractorEvent: public SALOME_Event
286 typedef PyObject* TResult;
289 TGetRenderWindowInteractorEvent( bool toCreate )
290 : myResult( Py_None ), myCreate( toCreate ) {}
291 virtual void Execute()
293 PyObject* aPyClass = ::GetPyClass( "vtkRenderWindowInteractor" );
294 SVTK_ViewWindow* aVTKViewWindow =
295 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
296 if( aVTKViewWindow && aPyClass ) {
297 vtkRenderWindowInteractor* aVTKObject = aVTKViewWindow->getInteractor();
298 myResult = PyVTKObject_New( aPyClass, aVTKObject );
303 extern "C" PyObject* libSalomePy_getRenderWindowInteractor( PyObject* self, PyObject* args )
305 PyObject* aResult = Py_None;
307 if ( !PyArg_ParseTuple( args, "|i:getRenderWindowInteractor", &toCreate ) )
310 aResult = ProcessEvent( new TGetRenderWindowInteractorEvent( toCreate ) );
315 \fn PyObject* showTrihedron( int show );
316 \brief Show/hide trihedron in the current VTK viewer.
318 If there is no active VTK viewer, nothing happens.
320 \param show new trihedron visibility state
321 \return nothing (Py_None)
324 extern "C" PyObject* libSalomePy_showTrihedron( PyObject* self, PyObject* args )
326 class TEvent: public SALOME_Event
332 virtual void Execute()
334 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
335 if ( aVTKViewWindow->isTrihedronDisplayed() != myShow )
336 aVTKViewWindow->onViewTrihedron();
341 PyObject* aResult = Py_None;
343 if ( !PyArg_ParseTuple( args, "i:showTrihedron", &bShow ) )
346 ProcessVoidEvent( new TEvent( bShow ) );
351 \fn PyObject* fitAll();
352 \brief Fit all the contents in the current VTK viewer.
354 If there is no active VTK viewer, nothing happens.
356 \return nothing (Py_None)
359 extern "C" PyObject* libSalomePy_fitAll( PyObject* self, PyObject* args )
361 class TEvent: public SALOME_Event
365 virtual void Execute()
367 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
368 aVTKViewWindow->onFitAll();
373 ProcessVoidEvent( new TEvent() );
378 \fn PyObject* setView( int type );
379 \brief Set view type for the current VTK viewer.
381 If there is no active VTK viewer, nothing happens.
383 \param type view type
384 \return nothing (Py_None)
387 extern "C" PyObject* libSalomePy_setView( PyObject* self, PyObject* args )
389 class TEvent: public SALOME_Event
393 TEvent( long type ) : myType( type) {}
394 virtual void Execute()
396 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
399 aVTKViewWindow->onFrontView(); break;
401 aVTKViewWindow->onBackView(); break;
403 aVTKViewWindow->onTopView(); break;
405 aVTKViewWindow->onBottomView(); break;
407 aVTKViewWindow->onRightView(); break;
409 aVTKViewWindow->onLeftView(); break;
411 PyErr_Format(PyExc_ValueError,"setView%: wrong parameter value; must be between %d and %d", ViewFront, ViewLeft );
419 if ( !PyArg_ParseTuple( args, "l:setView", &type ) )
422 ProcessVoidEvent( new TEvent( type ) );
423 if( PyErr_Occurred() )
430 \fn PyObject* resetView();
431 \brief Reset contents of the current VTK viewer.
433 If there is no active VTK viewer, nothing happens.
435 \return nothing (Py_None)
438 extern "C" PyObject* libSalomePy_resetView( PyObject* self, PyObject* args )
440 class TEvent: public SALOME_Event
444 virtual void Execute()
446 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
447 aVTKViewWindow->onResetView();
452 ProcessVoidEvent( new TEvent() );
456 static PyMethodDef Module_Methods[] =
458 { "getRenderer", libSalomePy_getRenderer, METH_VARARGS },
459 { "getRenderWindow", libSalomePy_getRenderWindow, METH_VARARGS },
460 { "getRenderWindowInteractor", libSalomePy_getRenderWindowInteractor, METH_VARARGS },
461 { "showTrihedron", libSalomePy_showTrihedron, METH_VARARGS },
462 { "fitAll", libSalomePy_fitAll, METH_NOARGS },
463 { "setView", libSalomePy_setView, METH_VARARGS },
464 { "resetView", libSalomePy_resetView, METH_NOARGS },
469 \brief Python module initialization.
472 extern "C" void initlibSalomePy()
474 static char* modulename = "libSalomePy";
477 PyObject* aModule = Py_InitModule( modulename, Module_Methods );
478 if( PyErr_Occurred() ) {
483 // get module's dictionary
484 PyObject *aModuleDict = PyModule_GetDict( aModule );
485 if ( aModuleDict == NULL )
488 // export View type enumeration
489 PUBLISH_ENUM( ViewFront );
490 PUBLISH_ENUM( ViewBack );
491 PUBLISH_ENUM( ViewTop );
492 PUBLISH_ENUM( ViewBottom );
493 PUBLISH_ENUM( ViewRight );
494 PUBLISH_ENUM( ViewLeft );