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