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