]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESHGUI/SMESHGUI_VTKUtils.cxx
Salome HOME
PAL15429 Computation of the mesh, based on "014.brep" via Tetrahedron(NETGEN), is...
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_VTKUtils.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "SMESHGUI_VTKUtils.h"
23 #include "SMESHGUI_Utils.h"
24 #include "SMESHGUI_Filter.h"
25
26 #include "SMESHGUI.h"
27 #include "SMESH_Actor.h"
28 #include "SMESH_ActorUtils.h"
29 #include "SMESH_ObjectDef.h"
30 #include <SMDS_Mesh.hxx>
31
32 #include <SUIT_Desktop.h>
33 #include <SUIT_Session.h>
34 #include <SUIT_Study.h>
35 #include <SUIT_MessageBox.h>
36
37 #include <SALOME_ListIO.hxx>
38 #include <SALOME_ListIteratorOfListIO.hxx>
39
40 #include <SVTK_Selector.h>
41 #include <SVTK_ViewModel.h>
42 #include <SVTK_ViewWindow.h>
43
44 #include <LightApp_SelectionMgr.h>
45 #include <SalomeApp_Application.h>
46 #include <SalomeApp_Study.h>
47
48 #include <utilities.h>
49
50 #include <SALOMEconfig.h>
51 #include CORBA_CLIENT_HEADER(SMESH_Gen)
52 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
53 #include CORBA_CLIENT_HEADER(SMESH_Group)
54 #include CORBA_CLIENT_HEADER(SMESH_Hypothesis)
55
56 #include <SALOMEDSClient_Study.hxx>
57 #include <SALOMEDSClient_SObject.hxx>
58
59 // VTK
60 #include <vtkRenderer.h>
61 #include <vtkActorCollection.h>
62 #include <vtkUnstructuredGrid.h>
63
64 // OCCT
65 #include <TColStd_IndexedMapOfInteger.hxx>
66 #include <Standard_ErrorHandler.hxx>
67
68 // STL
69 #include <set>
70 using namespace std;
71
72
73 namespace SMESH {
74
75   typedef map<TKeyOfVisualObj,TVisualObjPtr> TVisualObjCont;
76   static TVisualObjCont VISUAL_OBJ_CONT;
77
78   //=============================================================================
79   /*!
80    * \brief Allocate some memory at construction and release it at destruction.
81    * Is used to be able to continue working after mesh generation or visualization
82    * break due to lack of memory
83    */
84   //=============================================================================
85
86   struct MemoryReserve
87   {
88     char* myBuf;
89     MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M
90     void Free() { if (myBuf) { delete [] myBuf; myBuf = 0; }}
91     ~MemoryReserve() { Free(); }
92   };
93   static MemoryReserve* theVISU_MemoryReserve = new MemoryReserve;
94
95   //================================================================================
96   /*!
97    * \brief Remove VisualObj and its actor from all views
98    */
99   //================================================================================
100
101   void RemoveVisualObjectWithActors( const char* theEntry )
102   {
103     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
104       ( SUIT_Session::session()->activeApplication() );
105     SUIT_ViewManager* aViewManager =
106       app ? app->getViewManager(SVTK_Viewer::Type(), true) : 0;
107     if ( aViewManager ) {
108       QPtrVector<SUIT_ViewWindow> views = aViewManager->getViews();
109       for ( int iV = 0; iV < views.count(); ++iV ) {
110         if ( SMESH_Actor* actor = FindActorByEntry( views[iV], theEntry)) {
111           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV]))
112             vtkWnd->RemoveActor(actor);
113           actor->Delete();
114         }
115       }
116       int aStudyId = aViewManager->study()->id();
117       TVisualObjCont::key_type aKey(aStudyId,theEntry);
118       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
119       if(anIter != VISUAL_OBJ_CONT.end()) {
120         // for unknown reason, object destructor is not called, so clear object manually
121         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
122         anIter->second->GetUnstructuredGrid()->SetPoints(0);
123       }
124       VISUAL_OBJ_CONT.erase(aKey);
125     }
126   }
127   //================================================================================
128   /*!
129    * \brief Remove all VisualObjs and their actors from all views
130    */
131   //================================================================================
132
133   void RemoveAllObjectsWithActors()
134   {
135     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
136       ( SUIT_Session::session()->activeApplication() );
137     if (!app) return;
138     ViewManagerList viewMgrs = app->viewManagers();
139     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
140       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
141       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type()) {
142         QPtrVector<SUIT_ViewWindow> views = aViewManager->getViews();
143         for ( int iV = 0; iV < views.count(); ++iV ) {
144           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
145             vtkRenderer *aRenderer = vtkWnd->getRenderer();
146             vtkActorCollection *actors = aRenderer->GetActors();
147             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
148               // size of actors changes inside the loop
149               while (SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
150               {
151                 vtkWnd->RemoveActor(actor);
152                 actor->Delete();
153               }
154             }
155           }
156         }
157       }
158     }
159     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
160     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
161       // for unknown reason, object destructor is not called, so clear object manually
162       anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
163       anIter->second->GetUnstructuredGrid()->SetPoints(0);
164     }
165     VISUAL_OBJ_CONT.clear();
166   }
167
168   //================================================================================
169   /*!
170    * \brief Remove all VisualObjs of a study
171    */
172   //================================================================================
173
174   void RemoveVisuData(int studyID)
175   {
176     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
177       ( SUIT_Session::session()->activeApplication() );
178     if (!app) return;
179     ViewManagerList viewMgrs = app->viewManagers();
180     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
181       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
182       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type() &&
183            aViewManager->study()->id() == studyID ) {
184         QPtrVector<SUIT_ViewWindow> views = aViewManager->getViews();
185         for ( int iV = 0; iV < views.count(); ++iV ) {
186           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
187             vtkRenderer *aRenderer = vtkWnd->getRenderer();
188             vtkActorCollection *actors = aRenderer->GetActors();
189             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
190               // size of actors changes inside the loop
191               while(SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
192               {
193                 vtkWnd->RemoveActor(actor);
194                 actor->Delete();
195               }
196             }
197           }
198         }
199       }
200     }
201     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
202     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
203       int curId = anIter->first.first;
204       if ( curId == studyID ) {
205         // for unknown reason, object destructor is not called, so clear object manually
206         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
207         anIter->second->GetUnstructuredGrid()->SetPoints(0);
208         VISUAL_OBJ_CONT.erase( anIter-- );  // dercement occures before erase()
209       }
210     }
211   }
212
213   //================================================================================
214   /*!
215    * \brief Notify the user on problems during visualization
216    */
217   //================================================================================
218
219   void OnVisuException()
220   {
221     try {
222 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
223       OCC_CATCH_SIGNALS;
224 #endif
225       // PAL16774 (Crash after display of many groups). Salome sometimes crashes just
226       // after or at showing this message, so we do an additional check of available memory
227 //       char* buf = new char[100*1024];
228 //       delete [] buf;
229       SUIT_MessageBox::warn1 (SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
230                               QObject::tr("SMESH_VISU_PROBLEM"),
231                               QObject::tr("SMESH_BUT_OK"));
232     } catch (...) {
233       // no more memory at all: last resort
234       MESSAGE_BEGIN ( "SMESHGUI_VTKUtils::OnVisuException(), exception even at showing a message!!!" <<
235                       std::endl << "Try to remove all visual data..." );
236       if (theVISU_MemoryReserve) {
237         delete theVISU_MemoryReserve;
238         theVISU_MemoryReserve = 0;
239       }
240       RemoveAllObjectsWithActors();
241       SUIT_MessageBox::warn1 (SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
242                               QObject::tr("SMESH_VISU_PROBLEM_CLEAR"),
243                               QObject::tr("SMESH_BUT_OK"));
244       MESSAGE_END ( "...done" );
245     }
246   }
247   //================================================================================
248   /*!
249    * \brief Returns an updated visual object
250    */
251   //================================================================================
252
253   TVisualObjPtr GetVisualObj(int theStudyId, const char* theEntry){
254     TVisualObjPtr aVisualObj;
255     TVisualObjCont::key_type aKey(theStudyId,theEntry);
256     try{
257 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
258       OCC_CATCH_SIGNALS;
259 #endif
260       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
261       if(anIter != VISUAL_OBJ_CONT.end()){
262         aVisualObj = anIter->second;
263       }else{
264         SalomeApp_Application* app =
265           dynamic_cast<SalomeApp_Application*>( SMESHGUI::activeStudy()->application() );
266         _PTR(Study) aStudy = SMESHGUI::activeStudy()->studyDS();
267         _PTR(SObject) aSObj = aStudy->FindObjectID(theEntry);
268         if(aSObj){
269           _PTR(GenericAttribute) anAttr;
270           if(aSObj->FindAttribute(anAttr,"AttributeIOR")){
271             _PTR(AttributeIOR) anIOR = anAttr;
272             CORBA::String_var aVal = anIOR->Value().c_str();
273             CORBA::Object_var anObj = app->orb()->string_to_object( aVal.in() );
274             if(!CORBA::is_nil(anObj)){
275               //Try narrow to SMESH_Mesh interface
276               SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow(anObj);
277               if(!aMesh->_is_nil()){
278                 aVisualObj.reset(new SMESH_MeshObj(aMesh));
279                 TVisualObjCont::value_type aValue(aKey,aVisualObj);
280                 VISUAL_OBJ_CONT.insert(aValue);
281               }
282               //Try narrow to SMESH_Group interface
283               SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow(anObj);
284               if(!aGroup->_is_nil()){
285                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
286                 if(!aFatherSObj) return aVisualObj;
287                 aFatherSObj = aFatherSObj->GetFather();
288                 if(!aFatherSObj) return aVisualObj;
289                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
290                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
291                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
292                   aVisualObj.reset(new SMESH_GroupObj(aGroup,aMeshObj));
293                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
294                   VISUAL_OBJ_CONT.insert(aValue);
295                 }
296               }
297               //Try narrow to SMESH_subMesh interface
298               SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj);
299               if(!aSubMesh->_is_nil()){
300                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
301                 if(!aFatherSObj) return aVisualObj;
302                 aFatherSObj = aFatherSObj->GetFather();
303                 if(!aFatherSObj) return aVisualObj;
304                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
305                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
306                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
307                   aVisualObj.reset(new SMESH_subMeshObj(aSubMesh,aMeshObj));
308                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
309                   VISUAL_OBJ_CONT.insert(aValue);
310                 }
311               }
312             }
313           }
314         }
315       }
316     }catch(...){
317       INFOS("GetMeshObj - There is no SMESH_Mesh object for the SALOMEDS::Strudy and Entry!!!");
318       return TVisualObjPtr();
319     }
320     // Update object
321     bool objModified = false;
322     if ( aVisualObj ) {
323       try {
324 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
325         OCC_CATCH_SIGNALS;
326 #endif
327         objModified = aVisualObj->Update();
328       }
329       catch (...) {
330 #ifdef _DEBUG_
331         MESSAGE ( "Exception in SMESHGUI_VTKUtils::GetVisualObj()" );
332 #endif
333         RemoveVisualObjectWithActors( theEntry ); // remove this object
334         OnVisuException();
335         aVisualObj.reset();
336       }
337     }
338
339     if ( objModified ) {
340       // PAL16631. Mesurements showed that to show aVisualObj in SHADING(default) mode,
341       // ~10 times more memory is used than it occupies.
342       // Warn the user if there is less free memory than 30 sizes of a grid
343       // TODO: estimate memory usage in other modes and take current mode into account
344       int freeMB = SMDS_Mesh::CheckMemory(true);
345       int usedMB = aVisualObj->GetUnstructuredGrid()->GetActualMemorySize() / 1024;
346       if ( freeMB > 0 && usedMB * 30 > freeMB ) {
347 #ifdef _DEBUG_
348         MESSAGE ( "SMESHGUI_VTKUtils::GetVisualObj(), freeMB=" << freeMB
349                << ", usedMB=" << usedMB );
350 #endif
351         int continu = 0;
352         if ( usedMB * 10 > freeMB )
353           // even dont try to show
354           SUIT_MessageBox::warn1 (SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
355                                   QObject::tr("SMESH_NO_MESH_VISUALIZATION"),
356                                   QObject::tr("SMESH_BUT_OK"));
357         else
358           // there is a chance to succeed
359           continu = SUIT_MessageBox::warn2
360             (SMESHGUI::desktop(),
361              QObject::tr("SMESH_WRN_WARNING"),
362              QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
363              QObject::tr("SMESH_BUT_YES"),  QObject::tr("SMESH_BUT_NO"),
364              1, 0, 1);
365         if ( !continu ) {
366           // remove the corresponding actors from all views
367           RemoveVisualObjectWithActors( theEntry );
368           aVisualObj.reset();
369         }
370       }
371     }
372
373     return aVisualObj;
374   }
375
376
377   /*! Return active view window, if it instantiates SVTK_ViewWindow class,
378    *  overwise find or create corresponding view window, make it active and return it.
379    *  \note Active VVTK_ViewWindow can be returned, because it inherits SVTK_ViewWindow.
380    */
381   SVTK_ViewWindow* GetViewWindow (const SalomeApp_Module* theModule,
382                                   bool createIfNotFound)
383   {
384     SalomeApp_Application* anApp;
385     if (theModule)
386       anApp = theModule->getApp();
387     else
388       anApp = dynamic_cast<SalomeApp_Application*>
389         (SUIT_Session::session()->activeApplication());
390
391     if (anApp) {
392       if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(anApp->desktop()->activeWindow()))
393         return aView;
394
395       SUIT_ViewManager* aViewManager =
396         anApp->getViewManager(SVTK_Viewer::Type(), createIfNotFound);
397       if (aViewManager) {
398         if (SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView()) {
399           if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(aViewWindow)) {
400             aViewWindow->raise();
401             aViewWindow->setFocus();
402             return aView;
403           }
404         }
405       }
406     }
407     return NULL;
408   }
409
410   SVTK_ViewWindow* FindVtkViewWindow (SUIT_ViewManager* theMgr,
411                                       SUIT_ViewWindow * theWindow)
412   {
413     if( !theMgr )
414       return NULL;
415
416     QPtrVector<SUIT_ViewWindow> views = theMgr->getViews();
417     if( views.containsRef( theWindow ) )
418       return GetVtkViewWindow( theWindow );
419     else
420       return NULL;
421   }
422
423   SVTK_ViewWindow* GetVtkViewWindow(SUIT_ViewWindow* theWindow){
424     return dynamic_cast<SVTK_ViewWindow*>(theWindow);
425   }
426
427 /*  SUIT_ViewWindow* GetActiveWindow()
428   {
429     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
430     if( !app )
431       return NULL;
432     SUIT_ViewManager* mgr = app->activeViewManager();
433     if( mgr )
434       return mgr->getActiveView();
435     else
436       return NULL;
437   }*/
438
439   SVTK_ViewWindow* GetCurrentVtkView(){
440     return GetVtkViewWindow( GetActiveWindow() );
441   }
442
443
444   void RepaintCurrentView()
445   {
446     if (SVTK_ViewWindow* wnd = GetCurrentVtkView())
447     {
448       try {
449 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
450         OCC_CATCH_SIGNALS;
451 #endif
452         wnd->getRenderer()->Render();
453         wnd->Repaint(false);
454       }
455       catch (...) {
456 #ifdef _DEBUG_
457         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintCurrentView()" );
458 #endif
459         OnVisuException();
460       }
461     }
462   }
463
464   void RepaintViewWindow(SVTK_ViewWindow* theWindow)
465   {
466     try {
467 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
468       OCC_CATCH_SIGNALS;
469 #endif
470       theWindow->getRenderer()->Render();
471       theWindow->Repaint();
472     }
473     catch (...) {
474 #ifdef _DEBUG_
475         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintViewWindow(SVTK_ViewWindow)" );
476 #endif
477       OnVisuException();
478     }
479   }
480
481   void RenderViewWindow(SVTK_ViewWindow* theWindow)
482   {
483     try {
484 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
485       OCC_CATCH_SIGNALS;
486 #endif
487       theWindow->getRenderer()->Render();
488       theWindow->Repaint();
489     }
490     catch (...) {
491 #ifdef _DEBUG_
492         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RenderViewWindow(SVTK_ViewWindow)" );
493 #endif
494       OnVisuException();
495     }
496   }
497
498   void FitAll(){
499     if(SVTK_ViewWindow* wnd = GetCurrentVtkView() ){
500       try {
501 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
502         OCC_CATCH_SIGNALS;
503 #endif
504         wnd->onFitAll();
505         wnd->Repaint();
506       }
507       catch (...) {
508 #ifdef _DEBUG_
509         MESSAGE ( "Exception in SMESHGUI_VTKUtils::FitAll()" );
510 #endif
511         OnVisuException();
512       }
513     }
514   }
515
516
517   SMESH_Actor* FindActorByEntry(SUIT_ViewWindow *theWindow,
518                                 const char* theEntry)
519   {
520     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
521       vtkRenderer *aRenderer = aViewWindow->getRenderer();
522       vtkActorCollection *aCollection = aRenderer->GetActors();
523       aCollection->InitTraversal();
524       while(vtkActor *anAct = aCollection->GetNextActor()){
525         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
526           if(anActor->hasIO()){
527             Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
528             if(anIO->hasEntry() && strcmp(anIO->getEntry(),theEntry) == 0){
529               return anActor;
530             }
531           }
532         }
533       }
534     }
535     return NULL;
536   }
537
538
539   SMESH_Actor* FindActorByEntry(const char* theEntry){
540     return FindActorByEntry(GetActiveWindow(),theEntry);
541   }
542
543
544   SMESH_Actor* FindActorByObject(CORBA::Object_ptr theObject){
545     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
546     if( !app )
547       return NULL;
548
549     if(!CORBA::is_nil(theObject)){
550       _PTR(Study) aStudy = GetActiveStudyDocument();
551       CORBA::String_var anIOR = app->orb()->object_to_string( theObject );
552       _PTR(SObject) aSObject = aStudy->FindObjectIOR(anIOR.in());
553       if(aSObject){
554         CORBA::String_var anEntry = aSObject->GetID().c_str();
555         return FindActorByEntry(anEntry.in());
556       }
557     }
558     return NULL;
559   }
560
561
562   SMESH_Actor* CreateActor(_PTR(Study) theStudy,
563                            const char* theEntry,
564                            int theIsClear)
565   {
566     SMESH_Actor *anActor = NULL;
567     CORBA::Long anId = theStudy->StudyId();
568     if(TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry)){
569       _PTR(SObject) aSObj = theStudy->FindObjectID(theEntry);
570       if(aSObj){
571         _PTR(GenericAttribute) anAttr;
572         if(aSObj->FindAttribute(anAttr,"AttributeName")){
573           _PTR(AttributeName) aName = anAttr;
574           std::string aNameVal = aName->Value();
575           anActor = SMESH_Actor::New(aVisualObj,theEntry,aNameVal.c_str(),theIsClear);
576         }
577
578         SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( SMESH::SObjectToObject( aSObj ));
579         if(!CORBA::is_nil(aGroup))
580         {
581           SALOMEDS::Color aColor = aGroup->GetColor();
582           if( !( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 ) )
583           {
584             int r = 0, g = 0, b = 0;
585             SMESH::GetColor( "SMESH", "fill_color", r, g, b, QColor( 0, 170, 255 ) );
586             aColor.R = (float)r / 255.0;
587             aColor.G = (float)g / 255.0;
588             aColor.B = (float)b / 255.0;
589             aGroup->SetColor( aColor );
590           }
591           if( aGroup->GetType() == SMESH::NODE )
592             anActor->SetNodeColor( aColor.R, aColor.G, aColor.B );
593           else if( aGroup->GetType() == SMESH::EDGE )
594             anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B );
595           else
596             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B );
597         }
598       }
599     }
600     return anActor;
601   }
602
603
604   void DisplayActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
605     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
606       try {
607 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
608         OCC_CATCH_SIGNALS;
609 #endif
610         vtkWnd->AddActor(theActor);
611         vtkWnd->Repaint();
612       }
613       catch (...) {
614 #ifdef _DEBUG_
615         MESSAGE ( "Exception in SMESHGUI_VTKUtils::DisplayActor()" );
616 #endif
617         OnVisuException();
618       }
619     }
620   }
621
622
623   void RemoveActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
624     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
625       vtkWnd->RemoveActor(theActor);
626       if(theActor->hasIO()){
627         Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
628         if(anIO->hasEntry()){
629           std::string anEntry = anIO->getEntry();
630           SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
631           int aStudyId = aStudy->id();
632           TVisualObjCont::key_type aKey(aStudyId,anEntry);
633           VISUAL_OBJ_CONT.erase(aKey);
634         }
635       }
636       theActor->Delete();
637       vtkWnd->Repaint();
638     }
639   }
640
641   //================================================================================
642   /*!
643    * \brief Return true if there are no SMESH actors in a view
644    */
645   //================================================================================
646
647   bool noSmeshActors(SUIT_ViewWindow *theWnd)
648   {
649     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWnd)) {
650       vtkRenderer *aRenderer = aViewWindow->getRenderer();
651       vtkActorCollection *aCollection = aRenderer->GetActors();
652       aCollection->InitTraversal();
653       while(vtkActor *anAct = aCollection->GetNextActor())
654         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct))
655           return false;
656     }
657     return true;
658   }
659
660   bool UpdateView(SUIT_ViewWindow *theWnd, EDisplaing theAction, const char* theEntry)
661   {
662     bool OK = false;
663     SVTK_ViewWindow* aViewWnd = GetVtkViewWindow(theWnd);
664     if (!aViewWnd)
665       return OK;
666
667     {
668       OK = true;
669       vtkRenderer *aRenderer = aViewWnd->getRenderer();
670       vtkActorCollection *aCollection = aRenderer->GetActors();
671       aCollection->InitTraversal();
672
673       switch (theAction) {
674       case eDisplayAll: {
675         while (vtkActor *anAct = aCollection->GetNextActor()) {
676           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
677             anActor->SetVisibility(true);
678           }
679         }
680         break;
681       }
682       case eDisplayOnly:
683       case eEraseAll: {
684         while (vtkActor *anAct = aCollection->GetNextActor()) {
685           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
686             anActor->SetVisibility(false);
687           }
688         }
689       }
690       default: {
691         if (SMESH_Actor *anActor = FindActorByEntry(theWnd,theEntry)) {
692           switch (theAction) {
693             case eDisplay:
694             case eDisplayOnly:
695               anActor->SetVisibility(true);
696               if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
697               break;
698             case eErase:
699               anActor->SetVisibility(false);
700               break;
701           }
702         } else {
703           switch (theAction) {
704           case eDisplay:
705           case eDisplayOnly:
706             {
707               SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(theWnd->getViewManager()->study());
708               _PTR(Study) aDocument = aStudy->studyDS();
709               // Pass non-visual objects (hypotheses, etc.), return true in this case
710               CORBA::Long anId = aDocument->StudyId();
711               if (TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry))
712               {
713                 if ((anActor = CreateActor(aDocument,theEntry,true))) {
714                   bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
715                   DisplayActor(theWnd,anActor);
716                   // FitAll(); - PAL16770(Display of a group performs an automatic fit all)
717                   if (needFitAll) FitAll();
718                 } else {
719                   OK = false;
720                 }
721               }
722               break;
723             }
724           }
725         }
726       }
727       }
728     }
729     return OK;
730   }
731
732
733   bool UpdateView(EDisplaing theAction, const char* theEntry){
734     SalomeApp_Study* aStudy = dynamic_cast< SalomeApp_Study* >( GetActiveStudy() );
735     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( aStudy->application() );
736     SUIT_ViewWindow *aWnd = app->activeViewManager()->getActiveView();
737     return UpdateView(aWnd,theAction,theEntry);
738   }
739
740   void UpdateView(){
741     if(SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView()){
742       LightApp_SelectionMgr* mgr = SMESHGUI::selectionMgr();
743       SALOME_ListIO selected; mgr->selectedObjects( selected );
744
745       if( selected.Extent() == 0){
746         vtkRenderer* aRenderer = aWnd->getRenderer();
747         vtkActorCollection *aCollection = aRenderer->GetActors();
748         aCollection->InitTraversal();
749         while(vtkActor *anAct = aCollection->GetNextActor()){
750           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
751             if(anActor->hasIO())
752               if (!Update(anActor->getIO(),anActor->GetVisibility()))
753                 break; // avoid multiple warinings if visu failed
754           }
755         }
756       }else{
757         SALOME_ListIteratorOfListIO anIter( selected );
758         for(; anIter.More(); anIter.Next()){
759           Handle(SALOME_InteractiveObject) anIO = anIter.Value();
760           if ( !Update(anIO,true) )
761             break; // avoid multiple warinings if visu failed
762         }
763       }
764       RepaintCurrentView();
765     }
766   }
767
768
769   bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
770   {
771     _PTR(Study) aStudy = GetActiveStudyDocument();
772     CORBA::Long anId = aStudy->StudyId();
773     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) {
774       if ( theDisplay )
775         UpdateView(SMESH::eDisplay,theIO->getEntry());
776       return true;
777     }
778     return false;
779   }
780
781
782   void UpdateSelectionProp( SMESHGUI* theModule ) {
783     if( !theModule )
784       return;
785
786     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
787     if( !app )
788     {
789       MESSAGE( "UpdateSelectionProp: Application is null" );
790       return;
791     }
792
793     SUIT_ViewManager* vm = app->activeViewManager();
794     if( !vm )
795     {
796       MESSAGE( "UpdateSelectionProp: View manager is null" );
797       return;
798     }
799
800     QPtrVector<SUIT_ViewWindow> views = vm->getViews();
801
802     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
803     if( !mgr )
804     {
805       MESSAGE( "UpdateSelectionProp: Resource manager is null" );
806       return;
807     }
808
809     QColor aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
810            aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ),
811            aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan );
812
813     int SW = mgr->integerValue( "SMESH", "selection_width", 5 ),
814         PW = mgr->integerValue( "SMESH", "highlight_width", 5 );
815
816     double SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ),
817            SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ),
818            SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 );
819
820     for ( int i=0, n=views.count(); i<n; i++ ){
821       // update VTK viewer properties
822       if(SVTK_ViewWindow* aVtkView = GetVtkViewWindow( views[i] )){
823         // mesh element selection
824         aVtkView->SetSelectionProp(aSelColor.red()/255.,
825                                    aSelColor.green()/255.,
826                                    aSelColor.blue()/255.,
827                                    SW );
828         // tolerances
829         aVtkView->SetSelectionTolerance(SP1, SP2, SP3);
830
831         // pre-selection
832         aVtkView->SetPreselectionProp(aPreColor.red()/255.,
833                                       aPreColor.green()/255.,
834                                       aPreColor.blue()/255.,
835                                       PW);
836         // update actors
837         vtkRenderer* aRenderer = aVtkView->getRenderer();
838         vtkActorCollection *aCollection = aRenderer->GetActors();
839         aCollection->InitTraversal();
840         while(vtkActor *anAct = aCollection->GetNextActor()){
841           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
842             anActor->SetHighlightColor(aHiColor.red()/255.,
843                                        aHiColor.green()/255.,
844                                        aHiColor.blue()/255.);
845             anActor->SetPreHighlightColor(aPreColor.red()/255.,
846                                           aPreColor.green()/255.,
847                                           aPreColor.blue()/255.);
848           }
849         }
850       }
851     }
852   }
853
854
855   //----------------------------------------------------------------------------
856   SVTK_Selector*
857   GetSelector(SUIT_ViewWindow *theWindow)
858   {
859     if(SVTK_ViewWindow* aWnd = GetVtkViewWindow(theWindow))
860       return aWnd->GetSelector();
861
862     return NULL;
863   }
864
865   void SetFilter(const Handle(VTKViewer_Filter)& theFilter,
866                  SVTK_Selector* theSelector)
867   {
868     if (theSelector)
869       theSelector->SetFilter(theFilter);
870   }
871
872   Handle(VTKViewer_Filter) GetFilter(int theId, SVTK_Selector* theSelector)
873   {
874     return theSelector->GetFilter(theId);
875   }
876
877   bool IsFilterPresent(int theId, SVTK_Selector* theSelector)
878   {
879     return theSelector->IsFilterPresent(theId);
880   }
881
882   void RemoveFilter(int theId, SVTK_Selector* theSelector)
883   {
884     theSelector->RemoveFilter(theId);
885   }
886
887   void RemoveFilters(SVTK_Selector* theSelector)
888   {
889     for ( int id = SMESHGUI_NodeFilter; theSelector && id < SMESHGUI_LastFilter; id++ )
890       theSelector->RemoveFilter( id );
891   }
892
893   bool IsValid(SALOME_Actor* theActor, int theCellId,
894                SVTK_Selector* theSelector)
895   {
896     return theSelector->IsValid(theActor,theCellId);
897   }
898
899
900   //----------------------------------------------------------------------------
901   void SetPointRepresentation(bool theIsVisible){
902     if(SVTK_ViewWindow* aViewWindow = GetCurrentVtkView()){
903       vtkRenderer *aRenderer = aViewWindow->getRenderer();
904       vtkActorCollection *aCollection = aRenderer->GetActors();
905       aCollection->InitTraversal();
906       while(vtkActor *anAct = aCollection->GetNextActor()){
907         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
908           if(anActor->GetVisibility()){
909             anActor->SetPointRepresentation(theIsVisible);
910           }
911         }
912       }
913       RepaintCurrentView();
914     }
915   }
916
917
918   void SetPickable(SMESH_Actor* theActor){
919     if(SVTK_ViewWindow* aWnd = GetCurrentVtkView()){
920       int anIsAllPickable = (theActor == NULL);
921       vtkRenderer *aRenderer = aWnd->getRenderer();
922       vtkActorCollection *aCollection = aRenderer->GetActors();
923       aCollection->InitTraversal();
924       while(vtkActor *anAct = aCollection->GetNextActor()){
925         if(SALOME_Actor *anActor = dynamic_cast<SALOME_Actor*>(anAct)){
926           if(anActor->GetVisibility()){
927             anActor->SetPickable(anIsAllPickable);
928           }
929         }
930       }
931       if(theActor)
932         theActor->SetPickable(!anIsAllPickable);
933       RepaintCurrentView();
934     }
935   }
936
937
938   //----------------------------------------------------------------------------
939   int GetNameOfSelectedNodes(SVTK_Selector* theSelector,
940                              const Handle(SALOME_InteractiveObject)& theIO,
941                              QString& theName)
942   {
943     theName = "";
944     TColStd_IndexedMapOfInteger aMapIndex;
945     theSelector->GetIndex(theIO,aMapIndex);
946
947     for(int i = 1; i <= aMapIndex.Extent(); i++)
948       theName += QString(" %1").arg(aMapIndex(i));
949
950     return aMapIndex.Extent();
951   }
952
953   int GetNameOfSelectedElements(SVTK_Selector* theSelector,
954                                 const Handle(SALOME_InteractiveObject)& theIO,
955                                 QString& theName)
956   {
957     theName = "";
958     TColStd_IndexedMapOfInteger aMapIndex;
959     theSelector->GetIndex(theIO,aMapIndex);
960
961     typedef std::set<int> TIdContainer;
962     TIdContainer anIdContainer;
963     for( int i = 1; i <= aMapIndex.Extent(); i++)
964       anIdContainer.insert(aMapIndex(i));
965
966     TIdContainer::const_iterator anIter = anIdContainer.begin();
967     for(; anIter != anIdContainer.end(); anIter++)
968       theName += QString(" %1").arg(*anIter);
969
970     return aMapIndex.Extent();
971   }
972
973
974   int GetEdgeNodes(SVTK_Selector* theSelector,
975                    const TVisualObjPtr& theVisualObject,
976                    int& theId1,
977                    int& theId2)
978   {
979     const SALOME_ListIO& selected = theSelector->StoredIObjects();
980
981     if ( selected.Extent() != 1 )
982       return -1;
983
984     Handle(SALOME_InteractiveObject) anIO = selected.First();
985     if ( anIO.IsNull() || !anIO->hasEntry() )
986       return -1;
987
988     TColStd_IndexedMapOfInteger aMapIndex;
989     theSelector->GetIndex( anIO, aMapIndex );
990     if ( aMapIndex.Extent() != 2 )
991       return -1;
992
993     int anObjId = -1, anEdgeNum = -1;
994     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
995       int aVal = aMapIndex( i );
996       if ( aVal > 0 )
997         anObjId = aVal;
998       else
999         anEdgeNum = abs( aVal ) - 1;
1000     }
1001
1002     if ( anObjId == -1 || anEdgeNum == -1 )
1003       return -1;
1004
1005     return theVisualObject->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1006   }
1007
1008   //----------------------------------------------------------------------------
1009   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr,
1010                              const Handle(SALOME_InteractiveObject)& theIO,
1011                              QString& theName)
1012   {
1013     theName = "";
1014     if(theIO->hasEntry()){
1015       if(FindActorByEntry(theIO->getEntry())){
1016         TColStd_IndexedMapOfInteger aMapIndex;
1017         theMgr->GetIndexes(theIO,aMapIndex);
1018         for(int i = 1; i <= aMapIndex.Extent(); i++){
1019           theName += QString(" %1").arg(aMapIndex(i));
1020         }
1021         return aMapIndex.Extent();
1022       }
1023     }
1024     return -1;
1025   }
1026
1027   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName){
1028     theName = "";
1029     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1030     if(selected.Extent() == 1){
1031       Handle(SALOME_InteractiveObject) anIO = selected.First();
1032       return GetNameOfSelectedNodes(theMgr,anIO,theName);
1033     }
1034     return -1;
1035   }
1036
1037
1038   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr,
1039                                 const Handle(SALOME_InteractiveObject)& theIO,
1040                                 QString& theName)
1041   {
1042     theName = "";
1043     if(theIO->hasEntry()){
1044       if(FindActorByEntry(theIO->getEntry())){
1045         TColStd_IndexedMapOfInteger aMapIndex;
1046         theMgr->GetIndexes(theIO,aMapIndex);
1047         typedef set<int> TIdContainer;
1048         TIdContainer anIdContainer;
1049         for( int i = 1; i <= aMapIndex.Extent(); i++)
1050           anIdContainer.insert(aMapIndex(i));
1051         TIdContainer::const_iterator anIter = anIdContainer.begin();
1052         for(; anIter != anIdContainer.end(); anIter++){
1053           theName += QString(" %1").arg(*anIter);
1054         }
1055         return aMapIndex.Extent();
1056       }
1057     }
1058     return -1;
1059   }
1060
1061
1062   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr, QString& theName)
1063   {
1064     theName = "";
1065     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1066
1067     if( selected.Extent() == 1){
1068       Handle(SALOME_InteractiveObject) anIO = selected.First();
1069       return GetNameOfSelectedElements(theMgr,anIO,theName);
1070     }
1071     return -1;
1072   }
1073
1074   int GetSelected(LightApp_SelectionMgr*       theMgr,
1075                   TColStd_IndexedMapOfInteger& theMap,
1076                   const bool                   theIsElement)
1077   {
1078     theMap.Clear();
1079     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1080
1081     if ( selected.Extent() == 1 )
1082     {
1083       Handle(SALOME_InteractiveObject) anIO = selected.First();
1084       if ( anIO->hasEntry() ) {
1085         theMgr->GetIndexes( anIO, theMap );
1086       }
1087     }
1088     return theMap.Extent();
1089   }
1090
1091
1092   int GetEdgeNodes( LightApp_SelectionMgr* theMgr, int& theId1, int& theId2 )
1093   {
1094     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1095
1096     if ( selected.Extent() != 1 )
1097       return -1;
1098
1099     Handle(SALOME_InteractiveObject) anIO = selected.First();
1100     if ( anIO.IsNull() || !anIO->hasEntry() )
1101       return -1;
1102
1103     SMESH_Actor *anActor = SMESH::FindActorByEntry( anIO->getEntry() );
1104     if ( anActor == 0 )
1105       return -1;
1106
1107     TColStd_IndexedMapOfInteger aMapIndex;
1108     theMgr->GetIndexes( anIO, aMapIndex );
1109     if ( aMapIndex.Extent() != 2 )
1110       return -1;
1111
1112     int anObjId = -1, anEdgeNum = -1;
1113     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1114       int aVal = aMapIndex( i );
1115       if ( aVal > 0 )
1116         anObjId = aVal;
1117       else
1118         anEdgeNum = abs( aVal );
1119     }
1120
1121     if ( anObjId == -1 || anEdgeNum == -1 )
1122       return -1;
1123
1124     return anActor->GetObject()->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1125   }
1126
1127   void SetControlsPrecision( const long theVal )
1128   {
1129     if( SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView() )
1130     {
1131       vtkRenderer *aRenderer = aWnd->getRenderer();
1132       vtkActorCollection *aCollection = aRenderer->GetActors();
1133       aCollection->InitTraversal();
1134
1135       while ( vtkActor *anAct = aCollection->GetNextActor())
1136       {
1137         if ( SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>( anAct ) )
1138         {
1139           anActor->SetControlsPrecision( theVal );
1140           anActor->SetControlMode( anActor->GetControlMode() );
1141         }
1142       }
1143
1144     }
1145   }
1146 }