1 // Copyright (C) 2007-2015 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 = PyInt_FromLong( i ) ) == NULL ) return; \
95 rc = PyDict_SetItemString( aModuleDict, #i, w ); \
97 if ( rc < 0 ) return; \
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 PyObject* 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 ) );
142 \brief VTK window find/create mode
146 __Find, // try to find VTK window; if not found, do nothing
147 __FindOrCreate, // try to find VTK window; if not found, create new one
148 __Create }; // create new VTK window
151 \brief Find or create VTK window.
153 \param toCreate window find/create mode
154 \return VTK window pointer or 0 if it could not be found/created
156 static SVTK_ViewWindow* GetVTKViewWindow( int toCreate = __FindOrCreate ) {
157 SVTK_ViewWindow* aVW = 0;
158 if ( SUIT_Session::session() ) {
160 LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() );
163 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( anApp->activeStudy() );
165 // find or create VTK view manager
166 if ( toCreate == __Create ) {
167 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->createViewManager( "VTKViewer" ) );
169 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
171 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->createViewWindow() );
172 // VSR : When new view window is created it can be not active yet at this moment,
173 // so the following is a some workaround
174 if ( !aVW && !aVM->getViews().isEmpty() )
175 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
179 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->getViewManager( "VTKViewer", toCreate == __FindOrCreate ) );
181 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
182 // VSR : When new view window is created it can be not active yet at this moment,
183 // so the following is a some workaround
184 if ( !aVW && !aVM->getViews().isEmpty() )
185 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
195 \fn PyObject* getRenderer( int toCreate = 0 );
196 \brief Get VTK renderer (vtkRenderer).
198 If \a toCreate parameter is 0 (by default) the function tries to find
199 and reuse existing VTK window; if it is not found, the new VTK window
202 If \a toCreate parameter is non-zero, the function always creates
205 If VTK window could not be found and or created, the None Python object
208 \param toCreate window creation mode
209 \return VTK window renderer object
212 class SALOMEPY_EXPORT TGetRendererEvent: public SALOME_Event
215 typedef PyObject* TResult;
218 TGetRendererEvent( bool toCreate )
219 : myResult( Py_None ), myCreate( toCreate ) {}
220 virtual void Execute()
222 PyObject* aPyClass = ::GetPyClass( "vtkRenderer" );
223 SVTK_ViewWindow* aVTKViewWindow =
224 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
225 if( aVTKViewWindow && aPyClass ) {
226 vtkRenderer* aVTKObject = aVTKViewWindow->getRenderer();
227 #if VTK_XVERSION < 50700
228 myResult = PyVTKObject_New( aPyClass, aVTKObject );
230 myResult = PyVTKObject_New( aPyClass, NULL, aVTKObject );
236 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderer( PyObject* self, PyObject* args )
238 PyObject* aResult = Py_None;
240 if ( !PyArg_ParseTuple( args, "|i:getRenderer", &toCreate ) )
243 aResult = ProcessEvent( new TGetRendererEvent( toCreate ) );
248 \fn PyObject* getRenderWindow( int toCreate = 0 );
249 \brief Get VTK render window (vtkRenderWindow).
251 If \a toCreate parameter is 0 (by default) the function tries to find
252 and reuse existing VTK window; if it is not found, the new VTK window
255 If \a toCreate parameter is non-zero, the function always creates
258 If VTK window could not be found and or created, the None Python object
261 \param toCreate window creation mode
262 \return VTK window render window object
265 class SALOMEPY_EXPORT TGetRenderWindowEvent: public SALOME_Event
268 typedef PyObject* TResult;
271 TGetRenderWindowEvent( bool toCreate )
272 : myResult( Py_None ), myCreate( toCreate ) {}
273 virtual void Execute()
275 PyObject* aPyClass = ::GetPyClass( "vtkRenderWindow" );
276 SVTK_ViewWindow* aVTKViewWindow =
277 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
278 if( aVTKViewWindow && aPyClass ) {
279 vtkRenderWindow* aVTKObject = aVTKViewWindow->getRenderWindow();
280 #if VTK_XVERSION < 50700
281 myResult = PyVTKObject_New( aPyClass, aVTKObject );
283 myResult = PyVTKObject_New( aPyClass, NULL, aVTKObject );
289 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderWindow( PyObject* self, PyObject* args )
291 PyObject* aResult = Py_None;
293 if ( !PyArg_ParseTuple( args, "|i:getRenderWindow", &toCreate ) )
296 aResult = ProcessEvent( new TGetRenderWindowEvent( toCreate ) );
301 \fn PyObject* getRenderWindowInteractor( int toCreate = 0 );
302 \brief Get VTK render window interactor (getRenderWindowInteractor).
304 If \a toCreate parameter is 0 (by default) the function tries to find
305 and reuse existing VTK window; if it is not found, the new VTK window
308 If \a toCreate parameter is non-zero, the function always creates
311 If VTK window could not be found and or created, the None Python object
314 \param toCreate window creation mode
315 \return VTK window render window interactor object
318 class SALOMEPY_EXPORT TGetRenderWindowInteractorEvent: public SALOME_Event
321 typedef PyObject* TResult;
324 TGetRenderWindowInteractorEvent( bool toCreate )
325 : myResult( Py_None ), myCreate( toCreate ) {}
326 virtual void Execute()
328 PyObject* aPyClass = ::GetPyClass( "vtkRenderWindowInteractor" );
329 SVTK_ViewWindow* aVTKViewWindow =
330 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
331 if( aVTKViewWindow && aPyClass ) {
332 vtkRenderWindowInteractor* aVTKObject = aVTKViewWindow->getInteractor();
333 #if VTK_XVERSION < 50700
334 myResult = PyVTKObject_New( aPyClass, aVTKObject );
336 myResult = PyVTKObject_New( aPyClass, NULL, aVTKObject );
342 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderWindowInteractor( PyObject* self, PyObject* args )
344 PyObject* aResult = Py_None;
346 if ( !PyArg_ParseTuple( args, "|i:getRenderWindowInteractor", &toCreate ) )
349 aResult = ProcessEvent( new TGetRenderWindowInteractorEvent( toCreate ) );
354 \fn PyObject* showTrihedron( int show );
355 \brief Show/hide trihedron in the current VTK viewer.
357 If there is no active VTK viewer, nothing happens.
359 \param show new trihedron visibility state
360 \return nothing (Py_None)
363 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_showTrihedron( PyObject* self, PyObject* args )
365 class TEvent: public SALOME_Event
371 virtual void Execute()
373 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
374 if ( aVTKViewWindow->isTrihedronDisplayed() != myShow )
375 aVTKViewWindow->onViewTrihedron(myShow);
380 PyObject* aResult = Py_None;
382 if ( !PyArg_ParseTuple( args, "i:showTrihedron", &bShow ) )
385 ProcessVoidEvent( new TEvent( bShow ) );
390 \fn PyObject* fitAll();
391 \brief Fit all the contents in the current VTK viewer.
393 If there is no active VTK viewer, nothing happens.
395 \return nothing (Py_None)
398 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_fitAll( PyObject* self, PyObject* args )
400 class TEvent: public SALOME_Event
404 virtual void Execute()
406 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
407 aVTKViewWindow->onFitAll();
412 ProcessVoidEvent( new TEvent() );
417 \fn PyObject* setView( int type );
418 \brief Set view type for the current VTK viewer.
420 If there is no active VTK viewer, nothing happens.
422 \param type view type
423 \return nothing (Py_None)
426 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_setView( PyObject* self, PyObject* args )
428 class TEvent: public SALOME_Event
432 TEvent( long type ) : myType( type) {}
433 virtual void Execute()
435 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
438 aVTKViewWindow->onFrontView(); break;
440 aVTKViewWindow->onBackView(); break;
442 aVTKViewWindow->onTopView(); break;
444 aVTKViewWindow->onBottomView(); break;
446 aVTKViewWindow->onRightView(); break;
448 aVTKViewWindow->onLeftView(); break;
450 PyErr_Format(PyExc_ValueError,"setView%: wrong parameter value; must be between %d and %d", ViewFront, ViewLeft );
458 if ( !PyArg_ParseTuple( args, "l:setView", &type ) )
461 ProcessVoidEvent( new TEvent( type ) );
462 if( PyErr_Occurred() )
469 \fn PyObject* resetView();
470 \brief Reset contents of the current VTK viewer.
472 If there is no active VTK viewer, nothing happens.
474 \return nothing (Py_None)
477 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_resetView( PyObject* self, PyObject* args )
479 class TEvent: public SALOME_Event
483 virtual void Execute()
485 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
486 aVTKViewWindow->onResetView();
491 ProcessVoidEvent( new TEvent() );
495 static PyMethodDef Module_Methods[] =
497 { "getRenderer", libSalomePy_getRenderer, METH_VARARGS },
498 { "getRenderWindow", libSalomePy_getRenderWindow, METH_VARARGS },
499 { "getRenderWindowInteractor", libSalomePy_getRenderWindowInteractor, METH_VARARGS },
500 { "showTrihedron", libSalomePy_showTrihedron, METH_VARARGS },
501 { "fitAll", libSalomePy_fitAll, METH_NOARGS },
502 { "setView", libSalomePy_setView, METH_VARARGS },
503 { "resetView", libSalomePy_resetView, METH_NOARGS },
508 \brief Python module initialization.
511 extern "C" SALOMEPY_EXPORT void initlibSalomePy()
513 static char* modulename = (char*)"libSalomePy";
516 PyObject* aModule = Py_InitModule( modulename, Module_Methods );
517 if( PyErr_Occurred() ) {
522 // get module's dictionary
523 PyObject *aModuleDict = PyModule_GetDict( aModule );
524 if ( aModuleDict == NULL )
527 // export View type enumeration
528 PUBLISH_ENUM( ViewFront );
529 PUBLISH_ENUM( ViewBack );
530 PUBLISH_ENUM( ViewTop );
531 PUBLISH_ENUM( ViewBottom );
532 PUBLISH_ENUM( ViewRight );
533 PUBLISH_ENUM( ViewLeft );