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