1 // Copyright (C) 2007-2019 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 aVTKModule = PyImport_ImportModule( "vtk.vtkRenderingCorePython" );
122 if( PyErr_Occurred() ) {
127 PyObject* aVTKDict = PyModule_GetDict( aVTKModule );
128 aPyClass = PyDict_GetItemString(aVTKDict, const_cast<char*>( theClassName ) );
129 if (!PyType_Check(aPyClass))
132 return (PyTypeObject *)aPyClass;
136 \brief VTK window find/create mode
140 __Find, // try to find VTK window; if not found, do nothing
141 __FindOrCreate, // try to find VTK window; if not found, create new one
142 __Create }; // create new VTK window
145 \brief Find or create VTK window.
147 \param toCreate window find/create mode
148 \return VTK window pointer or 0 if it could not be found/created
150 static SVTK_ViewWindow* GetVTKViewWindow( int toCreate = __FindOrCreate ) {
151 SVTK_ViewWindow* aVW = 0;
152 if ( SUIT_Session::session() ) {
154 LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() );
157 LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( anApp->activeStudy() );
159 // find or create VTK view manager
160 if ( toCreate == __Create ) {
161 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->createViewManager( "VTKViewer" ) );
163 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
165 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->createViewWindow() );
166 // VSR : When new view window is created it can be not active yet at this moment,
167 // so the following is a some workaround
168 if ( !aVW && !aVM->getViews().isEmpty() )
169 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
173 SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->getViewManager( "VTKViewer", toCreate == __FindOrCreate ) );
175 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
176 // VSR : When new view window is created it can be not active yet at this moment,
177 // so the following is a some workaround
178 if ( !aVW && !aVM->getViews().isEmpty() )
179 aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
189 \fn PyObject* getRenderer( int toCreate = 0 );
190 \brief Get VTK renderer (vtkRenderer).
192 If \a toCreate parameter is 0 (by default) the function tries to find
193 and reuse existing VTK window; if it is not found, the new VTK window
196 If \a toCreate parameter is non-zero, the function always creates
199 If VTK window could not be found and or created, the None Python object
202 \param toCreate window creation mode
203 \return VTK window renderer object
206 class SALOMEPY_EXPORT TGetRendererEvent: public SALOME_Event
209 typedef PyObject* TResult;
212 TGetRendererEvent( bool toCreate )
213 : myResult( Py_None ), myCreate( toCreate ) {}
214 virtual void Execute()
216 PyTypeObject* aPyClass = ::GetPyClass( "vtkRenderer" );
217 SVTK_ViewWindow* aVTKViewWindow =
218 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
219 if( aVTKViewWindow && aPyClass ) {
220 vtkRenderer* aVTKObject = aVTKViewWindow->getRenderer();
221 #if VTK_XVERSION < 50700
222 myResult = PyVTKObject_New( aPyClass, aVTKObject );
224 myResult = PyVTKObject_FromPointer( aPyClass, NULL, aVTKObject );
230 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderer( PyObject* self, PyObject* args )
232 PyObject* aResult = Py_None;
234 if ( !PyArg_ParseTuple( args, "|i:getRenderer", &toCreate ) )
237 aResult = ProcessEvent( new TGetRendererEvent( toCreate ) );
242 \fn PyObject* getRenderWindow( int toCreate = 0 );
243 \brief Get VTK render window (vtkRenderWindow).
245 If \a toCreate parameter is 0 (by default) the function tries to find
246 and reuse existing VTK window; if it is not found, the new VTK window
249 If \a toCreate parameter is non-zero, the function always creates
252 If VTK window could not be found and or created, the None Python object
255 \param toCreate window creation mode
256 \return VTK window render window object
259 class SALOMEPY_EXPORT TGetRenderWindowEvent: public SALOME_Event
262 typedef PyObject* TResult;
265 TGetRenderWindowEvent( bool toCreate )
266 : myResult( Py_None ), myCreate( toCreate ) {}
267 virtual void Execute()
269 PyTypeObject* aPyClass = ::GetPyClass( "vtkRenderWindow" );
270 SVTK_ViewWindow* aVTKViewWindow =
271 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
272 if( aVTKViewWindow && aPyClass ) {
273 vtkRenderWindow* aVTKObject = aVTKViewWindow->getRenderWindow();
274 #if VTK_XVERSION < 50700
275 myResult = PyVTKObject_New( aPyClass, aVTKObject );
277 myResult = PyVTKObject_FromPointer( aPyClass, NULL, aVTKObject );
283 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderWindow( PyObject* self, PyObject* args )
285 PyObject* aResult = Py_None;
287 if ( !PyArg_ParseTuple( args, "|i:getRenderWindow", &toCreate ) )
290 aResult = ProcessEvent( new TGetRenderWindowEvent( toCreate ) );
295 \fn PyObject* getRenderWindowInteractor( int toCreate = 0 );
296 \brief Get VTK render window interactor (getRenderWindowInteractor).
298 If \a toCreate parameter is 0 (by default) the function tries to find
299 and reuse existing VTK window; if it is not found, the new VTK window
302 If \a toCreate parameter is non-zero, the function always creates
305 If VTK window could not be found and or created, the None Python object
308 \param toCreate window creation mode
309 \return VTK window render window interactor object
312 class SALOMEPY_EXPORT TGetRenderWindowInteractorEvent: public SALOME_Event
315 typedef PyObject* TResult;
318 TGetRenderWindowInteractorEvent( bool toCreate )
319 : myResult( Py_None ), myCreate( toCreate ) {}
320 virtual void Execute()
322 PyTypeObject* aPyClass = ::GetPyClass( "vtkRenderWindowInteractor" );
323 SVTK_ViewWindow* aVTKViewWindow =
324 ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
325 if( aVTKViewWindow && aPyClass ) {
326 vtkRenderWindowInteractor* aVTKObject = aVTKViewWindow->getInteractor();
327 #if VTK_XVERSION < 50700
328 myResult = PyVTKObject_New( aPyClass, aVTKObject );
330 myResult = PyVTKObject_FromPointer( aPyClass, NULL, aVTKObject );
336 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_getRenderWindowInteractor( PyObject* self, PyObject* args )
338 PyObject* aResult = Py_None;
340 if ( !PyArg_ParseTuple( args, "|i:getRenderWindowInteractor", &toCreate ) )
343 aResult = ProcessEvent( new TGetRenderWindowInteractorEvent( toCreate ) );
348 \fn PyObject* showTrihedron( int show );
349 \brief Show/hide trihedron in the current VTK viewer.
351 If there is no active VTK viewer, nothing happens.
353 \param show new trihedron visibility state
354 \return nothing (Py_None)
357 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_showTrihedron( PyObject* self, PyObject* args )
359 class TEvent: public SALOME_Event
365 virtual void Execute()
367 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
368 if ( aVTKViewWindow->isTrihedronDisplayed() != myShow )
369 aVTKViewWindow->onViewTrihedron(myShow);
374 PyObject* aResult = Py_None;
376 if ( !PyArg_ParseTuple( args, "i:showTrihedron", &bShow ) )
379 ProcessVoidEvent( new TEvent( bShow ) );
384 \fn PyObject* fitAll();
385 \brief Fit all the contents in the current VTK viewer.
387 If there is no active VTK viewer, nothing happens.
389 \return nothing (Py_None)
392 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_fitAll( PyObject* self, PyObject* args )
394 class TEvent: public SALOME_Event
398 virtual void Execute()
400 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
401 aVTKViewWindow->onFitAll();
406 ProcessVoidEvent( new TEvent() );
411 \fn PyObject* setView( int type );
412 \brief Set view type for the current VTK viewer.
414 If there is no active VTK viewer, nothing happens.
416 \param type view type
417 \return nothing (Py_None)
420 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_setView( PyObject* self, PyObject* args )
422 class TEvent: public SALOME_Event
426 TEvent( long type ) : myType( type) {}
427 virtual void Execute()
429 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
432 aVTKViewWindow->onFrontView(); break;
434 aVTKViewWindow->onBackView(); break;
436 aVTKViewWindow->onTopView(); break;
438 aVTKViewWindow->onBottomView(); break;
440 aVTKViewWindow->onRightView(); break;
442 aVTKViewWindow->onLeftView(); break;
444 PyErr_Format(PyExc_ValueError,"setView: wrong parameter value; must be between %d and %d", ViewFront, ViewLeft );
452 if ( !PyArg_ParseTuple( args, "l:setView", &type ) )
455 ProcessVoidEvent( new TEvent( type ) );
456 if( PyErr_Occurred() )
463 \fn PyObject* resetView();
464 \brief Reset contents of the current VTK viewer.
466 If there is no active VTK viewer, nothing happens.
468 \return nothing (Py_None)
471 extern "C" SALOMEPY_EXPORT PyObject* libSalomePy_resetView( PyObject* self, PyObject* args )
473 class TEvent: public SALOME_Event
477 virtual void Execute()
479 if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
480 aVTKViewWindow->onResetView();
485 ProcessVoidEvent( new TEvent() );
489 static PyMethodDef libSalomePy_methods[] =
491 { "getRenderer", libSalomePy_getRenderer, METH_VARARGS },
492 { "getRenderWindow", libSalomePy_getRenderWindow, METH_VARARGS },
493 { "getRenderWindowInteractor", libSalomePy_getRenderWindowInteractor, METH_VARARGS },
494 { "showTrihedron", libSalomePy_showTrihedron, METH_VARARGS },
495 { "fitAll", libSalomePy_fitAll, METH_NOARGS },
496 { "setView", libSalomePy_setView, METH_VARARGS },
497 { "resetView", libSalomePy_resetView, METH_NOARGS },
501 struct module_state {
505 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
507 static int libSalomePy_traverse(PyObject *m, visitproc visit, void *arg) {
508 Py_VISIT(GETSTATE(m)->error);
512 static int libSalomePy_clear(PyObject *m) {
513 Py_CLEAR(GETSTATE(m)->error);
517 static struct PyModuleDef moduledef = {
518 PyModuleDef_HEAD_INIT,
521 sizeof(struct module_state),
524 libSalomePy_traverse,
530 \brief Python module initialization.
533 extern "C" SALOMEPY_EXPORT PyMODINIT_FUNC PyInit_libSalomePy(void)
536 PyObject *aModule = PyModule_Create(&moduledef);
537 if( PyErr_Occurred() ) {
542 // get module's dictionary
543 PyObject *aModuleDict = PyModule_GetDict( aModule );
544 if ( aModuleDict == NULL )
547 // export View type enumeration
548 PUBLISH_ENUM( ViewFront );
549 PUBLISH_ENUM( ViewBack );
550 PUBLISH_ENUM( ViewTop );
551 PUBLISH_ENUM( ViewBottom );
552 PUBLISH_ENUM( ViewRight );
553 PUBLISH_ENUM( ViewLeft );