1 // Copyright (C) 2007-2016 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, or (at your option) any later version.
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
23 // SALOME SALOME_PY : binding of VTK graphics and Python
24 // File : SalomePy.cxx
25 // Author : Paul RASCLE, EDF
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
36 #include <vtkPythonUtil.h>
38 #include <vtkVersion.h>
39 #include <vtkRenderer.h>
40 #include <vtkRenderWindow.h>
41 #include <vtkRenderWindowInteractor.h>
43 #include <SALOME_Event.h>
45 #include <SUIT_Session.h>
46 #include <LightApp_Application.h>
47 #include <LightApp_Study.h>
49 #include <SVTK_ViewManager.h>
50 #include <SVTK_ViewWindow.h>
52 #define VTK_XVERSION (VTK_MAJOR_VERSION*10000+VTK_MINOR_VERSION*100+VTK_BUILD_VERSION)
55 \brief Python wrappings for VTK viewer of the SALOME desktop.
57 All methods are implemented using Event mechanism. The module
58 provides the following functions:
61 - getRenderWindowInteractor()
70 renderer = SalomePy.getRenderer() # get VTK renderer
71 window = SalomePy.getRenderWindow() # get render window
74 The methods getRenderer(), getRenderWindow() and getRenderWindowInteractor()
75 open new VTK viewer if there is no one opened.
76 In case of any error these methods return None object to the Python.
80 #if defined SALOMEPY_EXPORTS || defined SalomePy_EXPORTS
81 #define SALOMEPY_EXPORT __declspec( dllexport )
83 #define SALOMEPY_EXPORT __declspec( dllimport )
86 #define SALOMEPY_EXPORT
90 #define PUBLISH_ENUM(i) \
94 if ( ( w = PyLong_FromLong( i ) ) == NULL ) return NULL; \
95 rc = PyDict_SetItemString( aModuleDict, #i, w ); \
97 if ( rc < 0 ) return NULL; \
100 //! View operation type
102 ViewFront, //!< front view
103 ViewBack, //!< back view
104 ViewTop, //!< top view
105 ViewBottom, //!< bottom view
106 ViewRight, //!< right view
107 ViewLeft //!< left view
111 \brief Get Python class object by name
113 \param theClassName Python class name
114 \return Python class object or None object if class is not found
116 static PyTypeObject* GetPyClass( const char* theClassName )
118 static PyObject* aVTKModule = 0;
119 PyObject* aPyClass = 0;
121 #if VTK_XVERSION < 30000
122 aVTKModule = PyImport_ImportModule( "libVTKGraphicsPython" );
123 #elif VTK_XVERSION < 50700
124 aVTKModule = PyImport_ImportModule( "vtk.libvtkRenderingPython" );
125 #elif VTK_XVERSION < 60000
126 aVTKModule = PyImport_ImportModule( "vtkRenderingPython" );
128 aVTKModule = PyImport_ImportModule( "vtkRenderingCorePython" );
130 if( PyErr_Occurred() ) {
135 PyObject* aVTKDict = PyModule_GetDict( aVTKModule );
136 aPyClass = PyDict_GetItemString(aVTKDict, const_cast<char*>( theClassName ) );
137 if (!PyType_Check(aPyClass))
140 return (PyTypeObject *)aPyClass;
144 \brief VTK window find/create mode
148 __Find, // try to find VTK window; if not found, do nothing
149 __FindOrCreate, // try to find VTK window; if not found, create new one
150 __Create }; // create new VTK window
153 \brief Find or create VTK window.
155 \param toCreate window find/create mode
156 \return VTK window pointer or 0 if it could not be found/created
158 static SVTK_ViewWindow* GetVTKViewWindow( int toCreate = __FindOrCreate ) {
159 SVTK_ViewWindow* aVW = 0;
160 if ( SUIT_Session::session() ) {
162 LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() );
165 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( anApp->activeStudy() );
167 // find or create VTK view manager
168 if ( toCreate == __Create ) {
169 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->createViewManager( "VTKViewer" ) );
171 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
173 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->createViewWindow() );
174 // VSR : When new view window is created it can be not active yet at this moment,
175 // so the following is a some workaround
176 if ( !aVW && !aVM->getViews().isEmpty() )
177 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
181 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->getViewManager( "VTKViewer", toCreate == __FindOrCreate ) );
183 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
184 // VSR : When new view window is created it can be not active yet at this moment,
185 // so the following is a some workaround
186 if ( !aVW && !aVM->getViews().isEmpty() )
187 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
197 \fn PyObject* getRenderer( int toCreate = 0 );
198 \brief Get VTK renderer (vtkRenderer).
200 If \a toCreate parameter is 0 (by default) the function tries to find
201 and reuse existing VTK window; if it is not found, the new VTK window
204 If \a toCreate parameter is non-zero, the function always creates
207 If VTK window could not be found and or created, the None Python object
210 \param toCreate window creation mode
211 \return VTK window renderer object
214 class SALOMEPY_EXPORT TGetRendererEvent: public SALOME_Event
217 typedef PyObject* TResult;
220 TGetRendererEvent( bool toCreate )
221 : myResult( Py_None ), myCreate( toCreate ) {}
222 virtual void Execute()
224 PyTypeObject* aPyClass = ::GetPyClass( "vtkRenderer" );
225 SVTK_ViewWindow* aVTKViewWindow =
226 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
227 if( aVTKViewWindow && aPyClass ) {
228 vtkRenderer* aVTKObject = aVTKViewWindow->getRenderer();
229 #if VTK_XVERSION < 50700
230 myResult = PyVTKObject_New( aPyClass, aVTKObject );
232 myResult = PyVTKObject_FromPointer( aPyClass, NULL, aVTKObject );
238 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderer( PyObject* self, PyObject* args )
240 PyObject* aResult = Py_None;
242 if ( !PyArg_ParseTuple( args, "|i:getRenderer", &toCreate ) )
245 aResult = ProcessEvent( new TGetRendererEvent( toCreate ) );
250 \fn PyObject* getRenderWindow( int toCreate = 0 );
251 \brief Get VTK render window (vtkRenderWindow).
253 If \a toCreate parameter is 0 (by default) the function tries to find
254 and reuse existing VTK window; if it is not found, the new VTK window
257 If \a toCreate parameter is non-zero, the function always creates
260 If VTK window could not be found and or created, the None Python object
263 \param toCreate window creation mode
264 \return VTK window render window object
267 class SALOMEPY_EXPORT TGetRenderWindowEvent: public SALOME_Event
270 typedef PyObject* TResult;
273 TGetRenderWindowEvent( bool toCreate )
274 : myResult( Py_None ), myCreate( toCreate ) {}
275 virtual void Execute()
277 PyTypeObject* aPyClass = ::GetPyClass( "vtkRenderWindow" );
278 SVTK_ViewWindow* aVTKViewWindow =
279 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
280 if( aVTKViewWindow && aPyClass ) {
281 vtkRenderWindow* aVTKObject = aVTKViewWindow->getRenderWindow();
282 #if VTK_XVERSION < 50700
283 myResult = PyVTKObject_New( aPyClass, aVTKObject );
285 myResult = PyVTKObject_FromPointer( aPyClass, NULL, aVTKObject );
291 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderWindow( PyObject* self, PyObject* args )
293 PyObject* aResult = Py_None;
295 if ( !PyArg_ParseTuple( args, "|i:getRenderWindow", &toCreate ) )
298 aResult = ProcessEvent( new TGetRenderWindowEvent( toCreate ) );
303 \fn PyObject* getRenderWindowInteractor( int toCreate = 0 );
304 \brief Get VTK render window interactor (getRenderWindowInteractor).
306 If \a toCreate parameter is 0 (by default) the function tries to find
307 and reuse existing VTK window; if it is not found, the new VTK window
310 If \a toCreate parameter is non-zero, the function always creates
313 If VTK window could not be found and or created, the None Python object
316 \param toCreate window creation mode
317 \return VTK window render window interactor object
320 class SALOMEPY_EXPORT TGetRenderWindowInteractorEvent: public SALOME_Event
323 typedef PyObject* TResult;
326 TGetRenderWindowInteractorEvent( bool toCreate )
327 : myResult( Py_None ), myCreate( toCreate ) {}
328 virtual void Execute()
330 PyTypeObject* aPyClass = ::GetPyClass( "vtkRenderWindowInteractor" );
331 SVTK_ViewWindow* aVTKViewWindow =
332 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
333 if( aVTKViewWindow && aPyClass ) {
334 vtkRenderWindowInteractor* aVTKObject = aVTKViewWindow->getInteractor();
335 #if VTK_XVERSION < 50700
336 myResult = PyVTKObject_New( aPyClass, aVTKObject );
338 myResult = PyVTKObject_FromPointer( aPyClass, NULL, aVTKObject );
344 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderWindowInteractor( PyObject* self, PyObject* args )
346 PyObject* aResult = Py_None;
348 if ( !PyArg_ParseTuple( args, "|i:getRenderWindowInteractor", &toCreate ) )
351 aResult = ProcessEvent( new TGetRenderWindowInteractorEvent( toCreate ) );
356 \fn PyObject* showTrihedron( int show );
357 \brief Show/hide trihedron in the current VTK viewer.
359 If there is no active VTK viewer, nothing happens.
361 \param show new trihedron visibility state
362 \return nothing (Py_None)
365 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_showTrihedron( PyObject* self, PyObject* args )
367 class TEvent: public SALOME_Event
373 virtual void Execute()
375 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
376 if ( aVTKViewWindow->isTrihedronDisplayed() != myShow )
377 aVTKViewWindow->onViewTrihedron(myShow);
382 PyObject* aResult = Py_None;
384 if ( !PyArg_ParseTuple( args, "i:showTrihedron", &bShow ) )
387 ProcessVoidEvent( new TEvent( bShow ) );
392 \fn PyObject* fitAll();
393 \brief Fit all the contents in the current VTK viewer.
395 If there is no active VTK viewer, nothing happens.
397 \return nothing (Py_None)
400 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_fitAll( PyObject* self, PyObject* args )
402 class TEvent: public SALOME_Event
406 virtual void Execute()
408 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
409 aVTKViewWindow->onFitAll();
414 ProcessVoidEvent( new TEvent() );
419 \fn PyObject* setView( int type );
420 \brief Set view type for the current VTK viewer.
422 If there is no active VTK viewer, nothing happens.
424 \param type view type
425 \return nothing (Py_None)
428 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_setView( PyObject* self, PyObject* args )
430 class TEvent: public SALOME_Event
434 TEvent( long type ) : myType( type) {}
435 virtual void Execute()
437 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
440 aVTKViewWindow->onFrontView(); break;
442 aVTKViewWindow->onBackView(); break;
444 aVTKViewWindow->onTopView(); break;
446 aVTKViewWindow->onBottomView(); break;
448 aVTKViewWindow->onRightView(); break;
450 aVTKViewWindow->onLeftView(); break;
452 PyErr_Format(PyExc_ValueError,"setView: wrong parameter value; must be between %d and %d", ViewFront, ViewLeft );
460 if ( !PyArg_ParseTuple( args, "l:setView", &type ) )
463 ProcessVoidEvent( new TEvent( type ) );
464 if( PyErr_Occurred() )
471 \fn PyObject* resetView();
472 \brief Reset contents of the current VTK viewer.
474 If there is no active VTK viewer, nothing happens.
476 \return nothing (Py_None)
479 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_resetView( PyObject* self, PyObject* args )
481 class TEvent: public SALOME_Event
485 virtual void Execute()
487 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
488 aVTKViewWindow->onResetView();
493 ProcessVoidEvent( new TEvent() );
497 static PyMethodDef libSalomePy_methods[] =
499 { "getRenderer", libSalomePy_getRenderer, METH_VARARGS },
500 { "getRenderWindow", libSalomePy_getRenderWindow, METH_VARARGS },
501 { "getRenderWindowInteractor", libSalomePy_getRenderWindowInteractor, METH_VARARGS },
502 { "showTrihedron", libSalomePy_showTrihedron, METH_VARARGS },
503 { "fitAll", libSalomePy_fitAll, METH_NOARGS },
504 { "setView", libSalomePy_setView, METH_VARARGS },
505 { "resetView", libSalomePy_resetView, METH_NOARGS },
509 struct module_state {
513 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
515 static int libSalomePy_traverse(PyObject *m, visitproc visit, void *arg) {
516 Py_VISIT(GETSTATE(m)->error);
520 static int libSalomePy_clear(PyObject *m) {
521 Py_CLEAR(GETSTATE(m)->error);
525 static struct PyModuleDef moduledef = {
526 PyModuleDef_HEAD_INIT,
529 sizeof(struct module_state),
532 libSalomePy_traverse,
538 \brief Python module initialization.
541 extern "C" SALOMEPY_EXPORT PyMODINIT_FUNC PyInit_libSalomePy(void)
544 PyObject *aModule = PyModule_Create(&moduledef);
545 if( PyErr_Occurred() ) {
550 // get module's dictionary
551 PyObject *aModuleDict = PyModule_GetDict( aModule );
552 if ( aModuleDict == NULL )
555 // export View type enumeration
556 PUBLISH_ENUM( ViewFront );
557 PUBLISH_ENUM( ViewBack );
558 PUBLISH_ENUM( ViewTop );
559 PUBLISH_ENUM( ViewBottom );
560 PUBLISH_ENUM( ViewRight );
561 PUBLISH_ENUM( ViewLeft );