Salome HOME
IMP 0020089: Take into account 0D elements (MED_POINT1)
[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 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_VTKUtils.cxx
24 // Author : Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_VTKUtils.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_Filter.h"
32
33 #include <SMESH_Actor.h>
34 #include <SMESH_ActorUtils.h>
35 #include <SMESH_ObjectDef.h>
36 #include <SMDS_Mesh.hxx>
37
38 // SALOME GUI includes
39 #include <SUIT_Desktop.h>
40 #include <SUIT_Session.h>
41 #include <SUIT_MessageBox.h>
42 #include <SUIT_ViewManager.h>
43 #include <SUIT_ResourceMgr.h>
44
45 #include <SALOME_ListIO.hxx>
46 #include <SALOME_ListIteratorOfListIO.hxx>
47
48 #include <SVTK_Selector.h>
49 #include <SVTK_ViewModel.h>
50 #include <SVTK_ViewWindow.h>
51
52 #include <LightApp_SelectionMgr.h>
53 #include <SalomeApp_Application.h>
54 #include <SalomeApp_Study.h>
55
56 // SALOME KERNEL includes
57 #include <utilities.h>
58
59 // IDL includes
60 #include <SALOMEconfig.h>
61 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
62 #include CORBA_CLIENT_HEADER(SMESH_Group)
63
64 // VTK includes
65 #include <vtkRenderer.h>
66 #include <vtkActorCollection.h>
67 #include <vtkUnstructuredGrid.h>
68
69 // OCCT includes
70 #include <TColStd_IndexedMapOfInteger.hxx>
71 #include <Standard_ErrorHandler.hxx>
72
73 namespace SMESH
74 {
75   typedef std::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       QVector<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         QVector<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         QVector<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::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
230                                QObject::tr("SMESH_VISU_PROBLEM"));
231     } catch (...) {
232       // no more memory at all: last resort
233       MESSAGE_BEGIN ( "SMESHGUI_VTKUtils::OnVisuException(), exception even at showing a message!!!" <<
234                       std::endl << "Try to remove all visual data..." );
235       if (theVISU_MemoryReserve) {
236         delete theVISU_MemoryReserve;
237         theVISU_MemoryReserve = 0;
238       }
239       RemoveAllObjectsWithActors();
240       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
241                                QObject::tr("SMESH_VISU_PROBLEM_CLEAR"));
242       MESSAGE_END ( "...done" );
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 interface
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 interface
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 interface
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         MESSAGE ( "Exception in SMESHGUI_VTKUtils::GetVisualObj()" );
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         MESSAGE ( "SMESHGUI_VTKUtils::GetVisualObj(), freeMB=" << freeMB
347                << ", usedMB=" << usedMB );
348 #endif
349         bool continu = false;
350         if ( usedMB * 10 > freeMB )
351           // even dont try to show
352           SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
353                                    QObject::tr("SMESH_NO_MESH_VISUALIZATION"));
354         else
355           // there is a chance to succeed
356           continu = SUIT_MessageBox::warning
357             (SMESHGUI::desktop(),
358              QObject::tr("SMESH_WRN_WARNING"),
359              QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
360              SUIT_MessageBox::Yes | SUIT_MessageBox::No, 
361              SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes;
362         if ( !continu ) {
363           // remove the corresponding actors from all views
364           RemoveVisualObjectWithActors( theEntry );
365           aVisualObj.reset();
366         }
367       }
368     }
369
370     return aVisualObj;
371   }
372
373
374   /*! Return active view window, if it instantiates SVTK_ViewWindow class,
375    *  overwise find or create corresponding view window, make it active and return it.
376    *  \note Active VVTK_ViewWindow can be returned, because it inherits SVTK_ViewWindow.
377    */
378   SVTK_ViewWindow* GetViewWindow (const SalomeApp_Module* theModule,
379                                   bool createIfNotFound)
380   {
381     SalomeApp_Application* anApp;
382     if (theModule)
383       anApp = theModule->getApp();
384     else
385       anApp = dynamic_cast<SalomeApp_Application*>
386         (SUIT_Session::session()->activeApplication());
387
388     if (anApp) {
389       if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(anApp->desktop()->activeWindow()))
390         return aView;
391
392       SUIT_ViewManager* aViewManager =
393         anApp->getViewManager(SVTK_Viewer::Type(), createIfNotFound);
394       if (aViewManager) {
395         if (SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView()) {
396           if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(aViewWindow)) {
397             aViewWindow->raise();
398             aViewWindow->setFocus();
399             return aView;
400           }
401         }
402       }
403     }
404     return NULL;
405   }
406
407   SVTK_ViewWindow* FindVtkViewWindow (SUIT_ViewManager* theMgr,
408                                       SUIT_ViewWindow * theWindow)
409   {
410     if( !theMgr )
411       return NULL;
412
413     QVector<SUIT_ViewWindow*> views = theMgr->getViews();
414     if( views.contains( theWindow ) )
415       return GetVtkViewWindow( theWindow );
416     else
417       return NULL;
418   }
419
420   SVTK_ViewWindow* GetVtkViewWindow(SUIT_ViewWindow* theWindow){
421     return dynamic_cast<SVTK_ViewWindow*>(theWindow);
422   }
423
424 /*  SUIT_ViewWindow* GetActiveWindow()
425   {
426     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
427     if( !app )
428       return NULL;
429     SUIT_ViewManager* mgr = app->activeViewManager();
430     if( mgr )
431       return mgr->getActiveView();
432     else
433       return NULL;
434   }*/
435
436   SVTK_ViewWindow* GetCurrentVtkView(){
437     return GetVtkViewWindow( GetActiveWindow() );
438   }
439
440
441   void RepaintCurrentView()
442   {
443     if (SVTK_ViewWindow* wnd = GetCurrentVtkView())
444     {
445       try {
446 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
447         OCC_CATCH_SIGNALS;
448 #endif
449         wnd->getRenderer()->Render();
450         wnd->Repaint(false);
451       }
452       catch (...) {
453 #ifdef _DEBUG_
454         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintCurrentView()" );
455 #endif
456         OnVisuException();
457       }
458     }
459   }
460
461   void RepaintViewWindow(SVTK_ViewWindow* theWindow)
462   {
463     try {
464 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
465       OCC_CATCH_SIGNALS;
466 #endif
467       theWindow->getRenderer()->Render();
468       theWindow->Repaint();
469     }
470     catch (...) {
471 #ifdef _DEBUG_
472       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintViewWindow(SVTK_ViewWindow*)" );
473 #endif
474       OnVisuException();
475     }
476   }
477
478   void RenderViewWindow(SVTK_ViewWindow* theWindow)
479   {
480     try {
481 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
482       OCC_CATCH_SIGNALS;
483 #endif
484       theWindow->getRenderer()->Render();
485       theWindow->Repaint();
486     }
487     catch (...) {
488 #ifdef _DEBUG_
489       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RenderViewWindow(SVTK_ViewWindow*)" );
490 #endif
491       OnVisuException();
492     }
493   }
494
495   void FitAll(){
496     if(SVTK_ViewWindow* wnd = GetCurrentVtkView() ){
497       try {
498 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
499         OCC_CATCH_SIGNALS;
500 #endif
501         wnd->onFitAll();
502         wnd->Repaint();
503       }
504       catch (...) {
505 #ifdef _DEBUG_
506         MESSAGE ( "Exception in SMESHGUI_VTKUtils::FitAll()" );
507 #endif
508         OnVisuException();
509       }
510     }
511   }
512
513
514   SMESH_Actor* FindActorByEntry(SUIT_ViewWindow *theWindow,
515                                 const char* theEntry)
516   {
517     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
518       vtkRenderer *aRenderer = aViewWindow->getRenderer();
519       vtkActorCollection *aCollection = aRenderer->GetActors();
520       aCollection->InitTraversal();
521       while(vtkActor *anAct = aCollection->GetNextActor()){
522         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
523           if(anActor->hasIO()){
524             Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
525             if(anIO->hasEntry() && strcmp(anIO->getEntry(),theEntry) == 0){
526               return anActor;
527             }
528           }
529         }
530       }
531     }
532     return NULL;
533   }
534
535
536   SMESH_Actor* FindActorByEntry(const char* theEntry){
537     return FindActorByEntry(GetActiveWindow(),theEntry);
538   }
539
540
541   SMESH_Actor* FindActorByObject(CORBA::Object_ptr theObject){
542     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
543     if( !app )
544       return NULL;
545
546     if(!CORBA::is_nil(theObject)){
547       _PTR(Study) aStudy = GetActiveStudyDocument();
548       CORBA::String_var anIOR = app->orb()->object_to_string( theObject );
549       _PTR(SObject) aSObject = aStudy->FindObjectIOR(anIOR.in());
550       if(aSObject){
551         CORBA::String_var anEntry = aSObject->GetID().c_str();
552         return FindActorByEntry(anEntry.in());
553       }
554     }
555     return NULL;
556   }
557
558
559   SMESH_Actor* CreateActor(_PTR(Study) theStudy,
560                            const char* theEntry,
561                            int theIsClear)
562   {
563     SMESH_Actor *anActor = NULL;
564     CORBA::Long anId = theStudy->StudyId();
565     if(TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry)){
566       _PTR(SObject) aSObj = theStudy->FindObjectID(theEntry);
567       if(aSObj){
568         _PTR(GenericAttribute) anAttr;
569         if(aSObj->FindAttribute(anAttr,"AttributeName")){
570           _PTR(AttributeName) aName = anAttr;
571           std::string aNameVal = aName->Value();
572           anActor = SMESH_Actor::New(aVisualObj,theEntry,aNameVal.c_str(),theIsClear);
573         }
574
575         SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( SMESH::SObjectToObject( aSObj ));
576         if(!CORBA::is_nil(aGroup))
577         {
578           SALOMEDS::Color aColor = aGroup->GetColor();
579           if( !( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 ) )
580           {
581             int r = 0, g = 0, b = 0;
582             SMESH::GetColor( "SMESH", "fill_color", r, g, b, QColor( 0, 170, 255 ) );
583             aColor.R = (float)r / 255.0;
584             aColor.G = (float)g / 255.0;
585             aColor.B = (float)b / 255.0;
586             aGroup->SetColor( aColor );
587           }
588           if( aGroup->GetType() == SMESH::NODE )
589             anActor->SetNodeColor( aColor.R, aColor.G, aColor.B );
590           else if( aGroup->GetType() == SMESH::EDGE )
591             anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B );
592           else
593             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B );
594         }
595       }
596     }
597     return anActor;
598   }
599
600
601   void DisplayActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
602     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
603       try {
604 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
605         OCC_CATCH_SIGNALS;
606 #endif
607         vtkWnd->AddActor(theActor);
608         vtkWnd->Repaint();
609       }
610       catch (...) {
611 #ifdef _DEBUG_
612         MESSAGE ( "Exception in SMESHGUI_VTKUtils::DisplayActor()" );
613 #endif
614         OnVisuException();
615       }
616     }
617   }
618
619
620   void RemoveActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
621     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
622       vtkWnd->RemoveActor(theActor);
623       if(theActor->hasIO()){
624         Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
625         if(anIO->hasEntry()){
626           std::string anEntry = anIO->getEntry();
627           SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
628           int aStudyId = aStudy->id();
629           TVisualObjCont::key_type aKey(aStudyId,anEntry);
630           VISUAL_OBJ_CONT.erase(aKey);
631         }
632       }
633       theActor->Delete();
634       vtkWnd->Repaint();
635     }
636   }
637
638   //================================================================================
639   /*!
640    * \brief Return true if there are no SMESH actors in a view
641    */
642   //================================================================================
643
644   bool noSmeshActors(SUIT_ViewWindow *theWnd)
645   {
646     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWnd)) {
647       vtkRenderer *aRenderer = aViewWindow->getRenderer();
648       vtkActorCollection *aCollection = aRenderer->GetActors();
649       aCollection->InitTraversal();
650       while(vtkActor *anAct = aCollection->GetNextActor())
651         if(dynamic_cast<SMESH_Actor*>(anAct))
652           return false;
653     }
654     return true;
655   }
656
657   bool UpdateView(SUIT_ViewWindow *theWnd, EDisplaing theAction, const char* theEntry)
658   {
659     bool OK = false;
660     SVTK_ViewWindow* aViewWnd = GetVtkViewWindow(theWnd);
661     if (!aViewWnd)
662       return OK;
663
664     {
665       OK = true;
666       vtkRenderer *aRenderer = aViewWnd->getRenderer();
667       vtkActorCollection *aCollection = aRenderer->GetActors();
668       aCollection->InitTraversal();
669
670       switch (theAction) {
671       case eDisplayAll: {
672         while (vtkActor *anAct = aCollection->GetNextActor()) {
673           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
674             anActor->SetVisibility(true);
675           }
676         }
677         break;
678       }
679       case eDisplayOnly:
680       case eEraseAll: {
681         while (vtkActor *anAct = aCollection->GetNextActor()) {
682           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
683             anActor->SetVisibility(false);
684           }
685         }
686       }
687       default: {
688         if (SMESH_Actor *anActor = FindActorByEntry(theWnd,theEntry)) {
689           switch (theAction) {
690             case eDisplay:
691             case eDisplayOnly:
692               anActor->SetVisibility(true);
693               if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
694               break;
695             case eErase:
696               anActor->SetVisibility(false);
697               break;
698           }
699         } else {
700           switch (theAction) {
701           case eDisplay:
702           case eDisplayOnly:
703             {
704               SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(theWnd->getViewManager()->study());
705               _PTR(Study) aDocument = aStudy->studyDS();
706               // Pass non-visual objects (hypotheses, etc.), return true in this case
707               CORBA::Long anId = aDocument->StudyId();
708               if (TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry))
709               {
710                 if ((anActor = CreateActor(aDocument,theEntry,true))) {
711                   bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
712                   DisplayActor(theWnd,anActor);
713                   // FitAll(); - PAL16770(Display of a group performs an automatic fit all)
714                   if (needFitAll) FitAll();
715                 } else {
716                   OK = false;
717                 }
718               }
719               break;
720             }
721           }
722         }
723       }
724       }
725     }
726     return OK;
727   }
728
729
730   bool UpdateView(EDisplaing theAction, const char* theEntry){
731     SalomeApp_Study* aStudy = dynamic_cast< SalomeApp_Study* >( GetActiveStudy() );
732     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( aStudy->application() );
733     SUIT_ViewWindow *aWnd = app->activeViewManager()->getActiveView();
734     return UpdateView(aWnd,theAction,theEntry);
735   }
736
737   void UpdateView(){
738     if(SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView()){
739       LightApp_SelectionMgr* mgr = SMESHGUI::selectionMgr();
740       SALOME_ListIO selected; mgr->selectedObjects( selected );
741
742       if( selected.Extent() == 0){
743         vtkRenderer* aRenderer = aWnd->getRenderer();
744         vtkActorCollection *aCollection = aRenderer->GetActors();
745         aCollection->InitTraversal();
746         while(vtkActor *anAct = aCollection->GetNextActor()){
747           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
748             if(anActor->hasIO())
749               if (!Update(anActor->getIO(),anActor->GetVisibility()))
750                 break; // avoid multiple warinings if visu failed
751           }
752         }
753       }else{
754         SALOME_ListIteratorOfListIO anIter( selected );
755         for( ; anIter.More(); anIter.Next()){
756           Handle(SALOME_InteractiveObject) anIO = anIter.Value();
757           if ( !Update(anIO,true) )
758             break; // avoid multiple warinings if visu failed
759         }
760       }
761       RepaintCurrentView();
762     }
763   }
764
765
766   bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
767   {
768     _PTR(Study) aStudy = GetActiveStudyDocument();
769     CORBA::Long anId = aStudy->StudyId();
770     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) {
771       if ( theDisplay )
772         UpdateView(SMESH::eDisplay,theIO->getEntry());
773       return true;
774     }
775     return false;
776   }
777
778
779   void UpdateSelectionProp( SMESHGUI* theModule ) {
780     if( !theModule )
781       return;
782
783     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
784     if( !app )
785     {
786       MESSAGE( "UpdateSelectionProp: Application is null" );
787       return;
788     }
789
790     SUIT_ViewManager* vm = app->activeViewManager();
791     if( !vm )
792     {
793       MESSAGE( "UpdateSelectionProp: View manager is null" );
794       return;
795     }
796
797     QVector<SUIT_ViewWindow*> views = vm->getViews();
798
799     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
800     if( !mgr )
801     {
802       MESSAGE( "UpdateSelectionProp: Resource manager is null" );
803       return;
804     }
805
806     QColor aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
807            aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ),
808            aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan );
809
810     int SW = mgr->integerValue( "SMESH", "selection_width", 5 ),
811         PW = mgr->integerValue( "SMESH", "highlight_width", 5 );
812
813     // adjust highlight_width to the width of mesh entities
814     int aPointSize  = mgr->integerValue("SMESH", "node_size", 3);
815     int aElem0DSize = mgr->integerValue("SMESH", "elem0d_size", 5);
816     int aLineWidth  = mgr->integerValue("SMESH", "element_width", 1);
817     int maxSize = aPointSize;
818     if (aElem0DSize > maxSize) maxSize = aElem0DSize;
819     if (aLineWidth > maxSize) maxSize = aLineWidth;
820     if (PW < maxSize + 2) PW = maxSize + 2;
821
822     double SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ),
823            SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ),
824            SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 );
825
826     for ( int i=0, n=views.count(); i<n; i++ ){
827       // update VTK viewer properties
828       if(SVTK_ViewWindow* aVtkView = GetVtkViewWindow( views[i] )){
829         // mesh element selection
830         aVtkView->SetSelectionProp(aSelColor.red()/255.,
831                                    aSelColor.green()/255.,
832                                    aSelColor.blue()/255.,
833                                    SW );
834         // tolerances
835         aVtkView->SetSelectionTolerance(SP1, SP2, SP3);
836
837         // pre-selection
838         aVtkView->SetPreselectionProp(aPreColor.red()/255.,
839                                       aPreColor.green()/255.,
840                                       aPreColor.blue()/255.,
841                                       PW);
842         // update actors
843         vtkRenderer* aRenderer = aVtkView->getRenderer();
844         vtkActorCollection *aCollection = aRenderer->GetActors();
845         aCollection->InitTraversal();
846         while(vtkActor *anAct = aCollection->GetNextActor()){
847           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
848             anActor->SetHighlightColor(aHiColor.red()/255.,
849                                        aHiColor.green()/255.,
850                                        aHiColor.blue()/255.);
851             anActor->SetPreHighlightColor(aPreColor.red()/255.,
852                                           aPreColor.green()/255.,
853                                           aPreColor.blue()/255.);
854           }
855         }
856       }
857     }
858   }
859
860
861   //----------------------------------------------------------------------------
862   SVTK_Selector*
863   GetSelector(SUIT_ViewWindow *theWindow)
864   {
865     if(SVTK_ViewWindow* aWnd = GetVtkViewWindow(theWindow))
866       return aWnd->GetSelector();
867
868     return NULL;
869   }
870
871   void SetFilter(const Handle(VTKViewer_Filter)& theFilter,
872                  SVTK_Selector* theSelector)
873   {
874     if (theSelector)
875       theSelector->SetFilter(theFilter);
876   }
877
878   Handle(VTKViewer_Filter) GetFilter(int theId, SVTK_Selector* theSelector)
879   {
880     return theSelector->GetFilter(theId);
881   }
882
883   bool IsFilterPresent(int theId, SVTK_Selector* theSelector)
884   {
885     return theSelector->IsFilterPresent(theId);
886   }
887
888   void RemoveFilter(int theId, SVTK_Selector* theSelector)
889   {
890     theSelector->RemoveFilter(theId);
891   }
892
893   void RemoveFilters(SVTK_Selector* theSelector)
894   {
895     for ( int id = SMESH::NodeFilter; theSelector && id < SMESH::LastFilter; id++ )
896       theSelector->RemoveFilter( id );
897   }
898
899   bool IsValid(SALOME_Actor* theActor, int theCellId,
900                SVTK_Selector* theSelector)
901   {
902     return theSelector->IsValid(theActor,theCellId);
903   }
904
905
906   //----------------------------------------------------------------------------
907   void SetPointRepresentation(bool theIsVisible){
908     if(SVTK_ViewWindow* aViewWindow = GetCurrentVtkView()){
909       vtkRenderer *aRenderer = aViewWindow->getRenderer();
910       vtkActorCollection *aCollection = aRenderer->GetActors();
911       aCollection->InitTraversal();
912       while(vtkActor *anAct = aCollection->GetNextActor()){
913         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
914           if(anActor->GetVisibility()){
915             anActor->SetPointRepresentation(theIsVisible);
916           }
917         }
918       }
919       RepaintCurrentView();
920     }
921   }
922
923
924   void SetPickable(SMESH_Actor* theActor){
925     if(SVTK_ViewWindow* aWnd = GetCurrentVtkView()){
926       int anIsAllPickable = (theActor == NULL);
927       vtkRenderer *aRenderer = aWnd->getRenderer();
928       vtkActorCollection *aCollection = aRenderer->GetActors();
929       aCollection->InitTraversal();
930       while(vtkActor *anAct = aCollection->GetNextActor()){
931         if(SALOME_Actor *anActor = dynamic_cast<SALOME_Actor*>(anAct)){
932           if(anActor->GetVisibility()){
933             anActor->SetPickable(anIsAllPickable);
934           }
935         }
936       }
937       if(theActor)
938         theActor->SetPickable(!anIsAllPickable);
939       RepaintCurrentView();
940     }
941   }
942
943
944   //----------------------------------------------------------------------------
945   int GetNameOfSelectedNodes(SVTK_Selector* theSelector,
946                              const Handle(SALOME_InteractiveObject)& theIO,
947                              QString& theName)
948   {
949     theName = "";
950     TColStd_IndexedMapOfInteger aMapIndex;
951     theSelector->GetIndex(theIO,aMapIndex);
952
953     for(int i = 1; i <= aMapIndex.Extent(); i++)
954       theName += QString(" %1").arg(aMapIndex(i));
955
956     return aMapIndex.Extent();
957   }
958
959   int GetNameOfSelectedElements(SVTK_Selector* theSelector,
960                                 const Handle(SALOME_InteractiveObject)& theIO,
961                                 QString& theName)
962   {
963     theName = "";
964     TColStd_IndexedMapOfInteger aMapIndex;
965     theSelector->GetIndex(theIO,aMapIndex);
966
967     typedef std::set<int> TIdContainer;
968     TIdContainer anIdContainer;
969     for( int i = 1; i <= aMapIndex.Extent(); i++)
970       anIdContainer.insert(aMapIndex(i));
971
972     TIdContainer::const_iterator anIter = anIdContainer.begin();
973     for( ; anIter != anIdContainer.end(); anIter++)
974       theName += QString(" %1").arg(*anIter);
975
976     return aMapIndex.Extent();
977   }
978
979
980   int GetEdgeNodes(SVTK_Selector* theSelector,
981                    const TVisualObjPtr& theVisualObject,
982                    int& theId1,
983                    int& theId2)
984   {
985     const SALOME_ListIO& selected = theSelector->StoredIObjects();
986
987     if ( selected.Extent() != 1 )
988       return -1;
989
990     Handle(SALOME_InteractiveObject) anIO = selected.First();
991     if ( anIO.IsNull() || !anIO->hasEntry() )
992       return -1;
993
994     TColStd_IndexedMapOfInteger aMapIndex;
995     theSelector->GetIndex( anIO, aMapIndex );
996     if ( aMapIndex.Extent() != 2 )
997       return -1;
998
999     int anObjId = -1, anEdgeNum = -1;
1000     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1001       int aVal = aMapIndex( i );
1002       if ( aVal > 0 )
1003         anObjId = aVal;
1004       else
1005         anEdgeNum = abs( aVal ) - 1;
1006     }
1007
1008     if ( anObjId == -1 || anEdgeNum == -1 )
1009       return -1;
1010
1011     return theVisualObject->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1012   }
1013
1014   //----------------------------------------------------------------------------
1015   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr,
1016                              const Handle(SALOME_InteractiveObject)& theIO,
1017                              QString& theName)
1018   {
1019     theName = "";
1020     if(theIO->hasEntry()){
1021       if(FindActorByEntry(theIO->getEntry())){
1022         TColStd_IndexedMapOfInteger aMapIndex;
1023         theMgr->GetIndexes(theIO,aMapIndex);
1024         for(int i = 1; i <= aMapIndex.Extent(); i++){
1025           theName += QString(" %1").arg(aMapIndex(i));
1026         }
1027         return aMapIndex.Extent();
1028       }
1029     }
1030     return -1;
1031   }
1032
1033   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName){
1034     theName = "";
1035     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1036     if(selected.Extent() == 1){
1037       Handle(SALOME_InteractiveObject) anIO = selected.First();
1038       return GetNameOfSelectedNodes(theMgr,anIO,theName);
1039     }
1040     return -1;
1041   }
1042
1043
1044   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr,
1045                                 const Handle(SALOME_InteractiveObject)& theIO,
1046                                 QString& theName)
1047   {
1048     theName = "";
1049     if(theIO->hasEntry()){
1050       if(FindActorByEntry(theIO->getEntry())){
1051         TColStd_IndexedMapOfInteger aMapIndex;
1052         theMgr->GetIndexes(theIO,aMapIndex);
1053         typedef std::set<int> TIdContainer;
1054         TIdContainer anIdContainer;
1055         for( int i = 1; i <= aMapIndex.Extent(); i++)
1056           anIdContainer.insert(aMapIndex(i));
1057         TIdContainer::const_iterator anIter = anIdContainer.begin();
1058         for( ; anIter != anIdContainer.end(); anIter++){
1059           theName += QString(" %1").arg(*anIter);
1060         }
1061         return aMapIndex.Extent();
1062       }
1063     }
1064     return -1;
1065   }
1066
1067
1068   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr, QString& theName)
1069   {
1070     theName = "";
1071     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1072
1073     if( selected.Extent() == 1){
1074       Handle(SALOME_InteractiveObject) anIO = selected.First();
1075       return GetNameOfSelectedElements(theMgr,anIO,theName);
1076     }
1077     return -1;
1078   }
1079
1080   int GetSelected(LightApp_SelectionMgr*       theMgr,
1081                   TColStd_IndexedMapOfInteger& theMap,
1082                   const bool                   theIsElement)
1083   {
1084     theMap.Clear();
1085     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1086
1087     if ( selected.Extent() == 1 )
1088     {
1089       Handle(SALOME_InteractiveObject) anIO = selected.First();
1090       if ( anIO->hasEntry() ) {
1091         theMgr->GetIndexes( anIO, theMap );
1092       }
1093     }
1094     return theMap.Extent();
1095   }
1096
1097
1098   int GetEdgeNodes( LightApp_SelectionMgr* theMgr, int& theId1, int& theId2 )
1099   {
1100     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1101
1102     if ( selected.Extent() != 1 )
1103       return -1;
1104
1105     Handle(SALOME_InteractiveObject) anIO = selected.First();
1106     if ( anIO.IsNull() || !anIO->hasEntry() )
1107       return -1;
1108
1109     SMESH_Actor *anActor = SMESH::FindActorByEntry( anIO->getEntry() );
1110     if ( anActor == 0 )
1111       return -1;
1112
1113     TColStd_IndexedMapOfInteger aMapIndex;
1114     theMgr->GetIndexes( anIO, aMapIndex );
1115     if ( aMapIndex.Extent() != 2 )
1116       return -1;
1117
1118     int anObjId = -1, anEdgeNum = -1;
1119     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1120       int aVal = aMapIndex( i );
1121       if ( aVal > 0 )
1122         anObjId = aVal;
1123       else
1124         anEdgeNum = abs( aVal );
1125     }
1126
1127     if ( anObjId == -1 || anEdgeNum == -1 )
1128       return -1;
1129
1130     return anActor->GetObject()->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1131   }
1132
1133   void SetControlsPrecision( const long theVal )
1134   {
1135     if( SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView() )
1136     {
1137       vtkRenderer *aRenderer = aWnd->getRenderer();
1138       vtkActorCollection *aCollection = aRenderer->GetActors();
1139       aCollection->InitTraversal();
1140
1141       while ( vtkActor *anAct = aCollection->GetNextActor())
1142       {
1143         if ( SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>( anAct ) )
1144         {
1145           anActor->SetControlsPrecision( theVal );
1146           anActor->SetControlMode( anActor->GetControlMode() );
1147         }
1148       }
1149
1150     }
1151   }
1152 } // end of namespace SMESH