Salome HOME
a6755381339772b94d273354e213133579846cb7
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_VTKUtils.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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_NodeLabelActor.h"
38 #include "SMESH_CellLabelActor.h"
39 #include <SMESH_ObjectDef.h>
40 #include <SMDS_Mesh.hxx>
41
42 // SALOME GUI includes
43 #include <SUIT_Desktop.h>
44 #include <SUIT_Session.h>
45 #include <SUIT_MessageBox.h>
46 #include <SUIT_ViewManager.h>
47 #include <SUIT_ResourceMgr.h>
48
49 #include <SALOME_ListIO.hxx>
50 #include <SALOME_ListIteratorOfListIO.hxx>
51
52 #include <SVTK_Selector.h>
53 #include <SVTK_ViewModel.h>
54 #include <SVTK_ViewWindow.h>
55
56 #include <VTKViewer_Algorithm.h>
57
58 #include <LightApp_SelectionMgr.h>
59 #include <SalomeApp_Application.h>
60 #include <SalomeApp_Study.h>
61
62 // SALOME KERNEL includes
63 #include <utilities.h>
64
65 // IDL includes
66 #include <SALOMEconfig.h>
67 #include CORBA_CLIENT_HEADER(SMESH_Mesh)
68 #include CORBA_CLIENT_HEADER(SMESH_Group)
69
70 // VTK includes
71 #include <vtkMath.h>
72 #include <vtkRenderer.h>
73 #include <vtkActorCollection.h>
74 #include <vtkUnstructuredGrid.h>
75
76 // OCCT includes
77 #include <TColStd_IndexedMapOfInteger.hxx>
78 #include <Standard_ErrorHandler.hxx>
79 #include <ProjLib.hxx>
80 #include <gp_Pln.hxx>
81 #include <gp_Lin.hxx>
82 #include <gce_MakePln.hxx>
83 #include <gce_MakeLin.hxx>
84 #include <GeomAPI_IntCS.hxx>
85 #include <Geom_Line.hxx>
86 #include <Geom_Plane.hxx>
87
88 namespace SMESH
89 {
90   typedef std::map<TKeyOfVisualObj,TVisualObjPtr> TVisualObjCont;
91   static TVisualObjCont VISUAL_OBJ_CONT;
92
93   //=============================================================================
94   /*!
95    * \brief Allocate some memory at construction and release it at destruction.
96    * Is used to be able to continue working after mesh generation or visualization
97    * break due to lack of memory
98    */
99   //=============================================================================
100
101   struct MemoryReserve
102   {
103     char* myBuf;
104     MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M
105     void Free() { if (myBuf) { delete [] myBuf; myBuf = 0; }}
106     ~MemoryReserve() { Free(); }
107   };
108   static MemoryReserve* theVISU_MemoryReserve = new MemoryReserve;
109
110   //================================================================================
111   /*!
112    * \brief Remove VisualObj and its actor from all views
113    */
114   //================================================================================
115
116   void RemoveVisualObjectWithActors( const char* theEntry, bool fromAllViews )
117   {
118     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>(SUIT_Session::session()->activeApplication());
119     if(!app)
120       return;
121     SalomeApp_Study* aStudy  = dynamic_cast<SalomeApp_Study*>(app->activeStudy());
122     if(!aStudy)
123       return;
124     ViewManagerList aList;
125
126     if(fromAllViews) {
127       app->viewManagers(SVTK_Viewer::Type() , aList);
128     } else {
129       SUIT_ViewManager* aVM = app->getViewManager(SVTK_Viewer::Type(), true);
130       if(aVM)
131         aList.append(aVM);
132     }    
133     bool actorRemoved = false;
134     ViewManagerList::ConstIterator it = aList.begin();
135     SUIT_ViewManager* aViewManager = 0;
136     for( ; it!=aList.end();it++) {
137       aViewManager = *it;
138       QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
139       for ( int iV = 0; iV < views.count(); ++iV ) {
140         if ( SMESH_Actor* actor = FindActorByEntry( views[iV], theEntry)) {
141           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
142             vtkWnd->RemoveActor(actor);
143             actorRemoved = true;
144           }
145           actor->Delete();
146         }
147       }
148     }
149     
150     if (aViewManager ) {
151       int aStudyId = aViewManager->study()->id();
152       TVisualObjCont::key_type aKey(aStudyId,theEntry);
153       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
154       if(anIter != VISUAL_OBJ_CONT.end()) {
155         // for unknown reason, object destructor is not called, so clear object manually
156         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
157         anIter->second->GetUnstructuredGrid()->SetPoints(0);
158       }
159       VISUAL_OBJ_CONT.erase(aKey);
160     }
161
162     if(actorRemoved)
163       aStudy->setVisibilityState(theEntry, Qtx::HiddenState);
164   }
165   //================================================================================
166   /*!
167    * \brief Remove all VisualObjs and their actors from all views
168    */
169   //================================================================================
170
171   void RemoveAllObjectsWithActors()
172   {
173     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
174       ( SUIT_Session::session()->activeApplication() );
175     if (!app) return;
176     ViewManagerList viewMgrs = app->viewManagers();
177     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
178       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
179       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type()) {
180         QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
181         for ( int iV = 0; iV < views.count(); ++iV ) {
182           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
183             vtkRenderer *aRenderer = vtkWnd->getRenderer();
184             VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
185             vtkActorCollection *actors = aCopy.GetActors();
186             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
187               // size of actors changes inside the loop
188               if (SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
189               {
190                 vtkWnd->RemoveActor(actor);
191                 actor->Delete();
192               }
193             }
194           }
195         }
196       }
197     }
198     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
199     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
200       // for unknown reason, object destructor is not called, so clear object manually
201       anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
202       anIter->second->GetUnstructuredGrid()->SetPoints(0);
203     }
204     VISUAL_OBJ_CONT.clear();
205   }
206
207   //================================================================================
208   /*!
209    * \brief Remove all VisualObjs of a study
210    */
211   //================================================================================
212
213   void RemoveVisuData(int studyID)
214   {
215     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
216       ( SUIT_Session::session()->activeApplication() );
217     if (!app) return;
218     ViewManagerList viewMgrs = app->viewManagers();
219     for ( int iM = 0; iM < viewMgrs.count(); ++iM ) {
220       SUIT_ViewManager* aViewManager = viewMgrs.at( iM );
221       if ( aViewManager && aViewManager->getType() == SVTK_Viewer::Type() &&
222            aViewManager->study()->id() == studyID ) {
223         QVector<SUIT_ViewWindow*> views = aViewManager->getViews();
224         for ( int iV = 0; iV < views.count(); ++iV ) {
225           if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(views[iV])) {
226             vtkRenderer *aRenderer = vtkWnd->getRenderer();
227             VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
228             vtkActorCollection *actors = aCopy.GetActors();
229             for (int i = 0; i < actors->GetNumberOfItems(); ++i ) {
230               // size of actors changes inside the loop
231               if(SMESH_Actor *actor = dynamic_cast<SMESH_Actor*>(actors->GetItemAsObject(i)))
232               {
233                 vtkWnd->RemoveActor(actor);
234                 actor->Delete();
235               }
236             }
237           }
238         }
239       }
240     }
241     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
242     for ( ; anIter != VISUAL_OBJ_CONT.end(); ) {
243       int curId = anIter->first.first;
244       if ( curId == studyID ) {
245         // for unknown reason, object destructor is not called, so clear object manually
246         anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
247         anIter->second->GetUnstructuredGrid()->SetPoints(0);
248         VISUAL_OBJ_CONT.erase( anIter++ ); // anIter++ returns a copy of self before incrementing
249       }
250       else {
251         anIter++;
252       }
253     }
254   }
255
256   //================================================================================
257   /*!
258    * \brief Notify the user on problems during visualization
259    */
260   //================================================================================
261
262   void OnVisuException()
263   {
264     try {
265 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
266       OCC_CATCH_SIGNALS;
267 #endif
268       // PAL16774 (Crash after display of many groups). Salome sometimes crashes just
269       // after or at showing this message, so we do an additional check of available memory
270 //       char* buf = new char[100*1024];
271 //       delete [] buf;
272       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
273                                QObject::tr("SMESH_VISU_PROBLEM"));
274     } catch (...) {
275       // no more memory at all: last resort
276       MESSAGE_BEGIN ( "SMESHGUI_VTKUtils::OnVisuException(), exception even at showing a message!!!" <<
277                       std::endl << "Try to remove all visual data..." );
278       if (theVISU_MemoryReserve) {
279         delete theVISU_MemoryReserve;
280         theVISU_MemoryReserve = 0;
281       }
282       RemoveAllObjectsWithActors();
283       SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
284                                QObject::tr("SMESH_VISU_PROBLEM_CLEAR"));
285       MESSAGE_END ( "...done" );
286     }
287   }
288   //================================================================================
289   /*!
290    * \brief Returns an updated visual object
291    */
292   //================================================================================
293
294   TVisualObjPtr GetVisualObj(int theStudyId, const char* theEntry, bool nulData){
295     TVisualObjPtr aVisualObj;
296     TVisualObjCont::key_type aKey(theStudyId,theEntry);
297     try{
298 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
299       OCC_CATCH_SIGNALS;
300 #endif
301       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
302       if(anIter != VISUAL_OBJ_CONT.end()){
303         aVisualObj = anIter->second;
304       }else{
305         SalomeApp_Application* app =
306           dynamic_cast<SalomeApp_Application*>( SMESHGUI::activeStudy()->application() );
307         _PTR(Study) aStudy = SMESHGUI::activeStudy()->studyDS();
308         _PTR(SObject) aSObj = aStudy->FindObjectID(theEntry);
309         if(aSObj){
310           _PTR(GenericAttribute) anAttr;
311           if(aSObj->FindAttribute(anAttr,"AttributeIOR")){
312             _PTR(AttributeIOR) anIOR = anAttr;
313             CORBA::String_var aVal = anIOR->Value().c_str();
314             CORBA::Object_var anObj = app->orb()->string_to_object( aVal.in() );
315             if(!CORBA::is_nil(anObj)){
316               //Try narrow to SMESH_Mesh interface
317               SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow(anObj);
318               if(!aMesh->_is_nil()){
319                 aVisualObj.reset(new SMESH_MeshObj(aMesh));
320                 TVisualObjCont::value_type aValue(aKey,aVisualObj);
321                 VISUAL_OBJ_CONT.insert(aValue);
322               }
323               //Try narrow to SMESH_Group interface
324               SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow(anObj);
325               if(!aGroup->_is_nil()){
326                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
327                 if(!aFatherSObj) return aVisualObj;
328                 aFatherSObj = aFatherSObj->GetFather();
329                 if(!aFatherSObj) return aVisualObj;
330                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
331                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
332                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
333                   aVisualObj.reset(new SMESH_GroupObj(aGroup,aMeshObj));
334                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
335                   VISUAL_OBJ_CONT.insert(aValue);
336                 }
337               }
338               //Try narrow to SMESH_subMesh interface
339               SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj);
340               if(!aSubMesh->_is_nil()){
341                 _PTR(SObject) aFatherSObj = aSObj->GetFather();
342                 if(!aFatherSObj) return aVisualObj;
343                 aFatherSObj = aFatherSObj->GetFather();
344                 if(!aFatherSObj) return aVisualObj;
345                 CORBA::String_var anEntry = aFatherSObj->GetID().c_str();
346                 TVisualObjPtr aVisObj = GetVisualObj(theStudyId,anEntry.in());
347                 if(SMESH_MeshObj* aMeshObj = dynamic_cast<SMESH_MeshObj*>(aVisObj.get())){
348                   aVisualObj.reset(new SMESH_subMeshObj(aSubMesh,aMeshObj));
349                   TVisualObjCont::value_type aValue(aKey,aVisualObj);
350                   VISUAL_OBJ_CONT.insert(aValue);
351                 }
352               }
353             }
354           }
355         }
356       }
357     }catch(...){
358       INFOS("GetMeshObj - There is no SMESH_Mesh object for the SALOMEDS::Strudy and Entry!!!");
359       return TVisualObjPtr();
360     }
361     // Update object
362     bool objModified = false;
363     if ( aVisualObj ) {
364       try {
365 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
366         OCC_CATCH_SIGNALS;
367 #endif
368         //MESSAGE("GetVisualObj");
369         if (nulData)
370                 objModified = aVisualObj->NulData();
371         else
372           objModified = aVisualObj->Update();
373       }
374       catch (...) {
375 #ifdef _DEBUG_
376         MESSAGE ( "Exception in SMESHGUI_VTKUtils::GetVisualObj()" );
377 #endif
378         RemoveVisualObjectWithActors( theEntry ); // remove this object
379         OnVisuException();
380         aVisualObj.reset();
381       }
382     }
383
384     if ( objModified ) {
385       // PAL16631. Mesurements showed that to show aVisualObj in SHADING(default) mode,
386       // ~5 times more memory is used than it occupies.
387       // Warn the user if there is less free memory than 30 sizes of a grid
388       // TODO: estimate memory usage in other modes and take current mode into account
389       int freeMB = SMDS_Mesh::CheckMemory(true);
390       int usedMB = aVisualObj->GetUnstructuredGrid()->GetActualMemorySize() / 1024;
391       MESSAGE("SMESHGUI_VTKUtils::GetVisualObj(), freeMB=" << freeMB << ", usedMB=" <<usedMB);
392       if ( freeMB > 0 && usedMB * 5 > freeMB ) {
393        bool continu = false;
394        if ( usedMB * 3 > freeMB )
395          // even dont try to show
396          SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
397                                   QObject::tr("SMESH_NO_MESH_VISUALIZATION"));
398        else
399          // there is a chance to succeed
400          continu = SUIT_MessageBox::warning
401            (SMESHGUI::desktop(),
402             QObject::tr("SMESH_WRN_WARNING"),
403             QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
404             SUIT_MessageBox::Yes | SUIT_MessageBox::No,
405             SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes;
406        if ( !continu ) {
407          // remove the corresponding actors from all views
408          RemoveVisualObjectWithActors( theEntry );
409          aVisualObj.reset();
410        }
411       }
412     }
413
414     return aVisualObj;
415   }
416
417
418   /*! Return active view window, if it instantiates SVTK_ViewWindow class,
419    *  overwise find or create corresponding view window, make it active and return it.
420    *  \note Active VVTK_ViewWindow can be returned, because it inherits SVTK_ViewWindow.
421    */
422   SVTK_ViewWindow* GetViewWindow (const SalomeApp_Module* theModule,
423                                   bool createIfNotFound)
424   {
425     SalomeApp_Application* anApp;
426     if (theModule)
427       anApp = theModule->getApp();
428     else
429       anApp = dynamic_cast<SalomeApp_Application*>
430         (SUIT_Session::session()->activeApplication());
431
432     if (anApp) {
433       if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(anApp->desktop()->activeWindow()))
434         return aView;
435
436       SUIT_ViewManager* aViewManager =
437         anApp->getViewManager(SVTK_Viewer::Type(), createIfNotFound);
438       if (aViewManager) {
439         if (SUIT_ViewWindow* aViewWindow = aViewManager->getActiveView()) {
440           if (SVTK_ViewWindow* aView = dynamic_cast<SVTK_ViewWindow*>(aViewWindow)) {
441             aViewWindow->raise();
442             aViewWindow->setFocus();
443             return aView;
444           }
445         }
446       }
447     }
448     return NULL;
449   }
450
451   SVTK_ViewWindow* FindVtkViewWindow (SUIT_ViewManager* theMgr,
452                                       SUIT_ViewWindow * theWindow)
453   {
454     if( !theMgr )
455       return NULL;
456
457     QVector<SUIT_ViewWindow*> views = theMgr->getViews();
458     if( views.contains( theWindow ) )
459       return GetVtkViewWindow( theWindow );
460     else
461       return NULL;
462   }
463
464   SVTK_ViewWindow* GetVtkViewWindow(SUIT_ViewWindow* theWindow){
465     return dynamic_cast<SVTK_ViewWindow*>(theWindow);
466   }
467
468 /*  SUIT_ViewWindow* GetActiveWindow()
469   {
470     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
471     if( !app )
472       return NULL;
473     SUIT_ViewManager* mgr = app->activeViewManager();
474     if( mgr )
475       return mgr->getActiveView();
476     else
477       return NULL;
478   }*/
479
480   SVTK_ViewWindow* GetCurrentVtkView(){
481     return GetVtkViewWindow( GetActiveWindow() );
482   }
483
484
485   void RepaintCurrentView()
486   {
487     if (SVTK_ViewWindow* wnd = GetCurrentVtkView())
488     {
489       try {
490 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
491         OCC_CATCH_SIGNALS;
492 #endif
493         wnd->getRenderer()->Render();
494         wnd->Repaint(false);
495       }
496       catch (...) {
497 #ifdef _DEBUG_
498         MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintCurrentView()" );
499 #endif
500         OnVisuException();
501       }
502     }
503   }
504
505   void RepaintViewWindow(SVTK_ViewWindow* theWindow)
506   {
507     try {
508 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
509       OCC_CATCH_SIGNALS;
510 #endif
511       theWindow->getRenderer()->Render();
512       theWindow->Repaint();
513     }
514     catch (...) {
515 #ifdef _DEBUG_
516       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RepaintViewWindow(SVTK_ViewWindow*)" );
517 #endif
518       OnVisuException();
519     }
520   }
521
522   void RenderViewWindow(SVTK_ViewWindow* theWindow)
523   {
524     try {
525 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
526       OCC_CATCH_SIGNALS;
527 #endif
528       theWindow->getRenderer()->Render();
529       theWindow->Repaint();
530     }
531     catch (...) {
532 #ifdef _DEBUG_
533       MESSAGE ( "Exception in SMESHGUI_VTKUtils::RenderViewWindow(SVTK_ViewWindow*)" );
534 #endif
535       OnVisuException();
536     }
537   }
538
539   void FitAll(){
540     if(SVTK_ViewWindow* wnd = GetCurrentVtkView() ){
541       try {
542 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
543         OCC_CATCH_SIGNALS;
544 #endif
545         wnd->onFitAll();
546         wnd->Repaint();
547       }
548       catch (...) {
549 #ifdef _DEBUG_
550         MESSAGE ( "Exception in SMESHGUI_VTKUtils::FitAll()" );
551 #endif
552         OnVisuException();
553       }
554     }
555   }
556
557
558   SMESH_Actor* FindActorByEntry(SUIT_ViewWindow *theWindow,
559                                 const char* theEntry)
560   {
561     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
562       vtkRenderer *aRenderer = aViewWindow->getRenderer();
563       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
564       vtkActorCollection *aCollection = aCopy.GetActors();
565       aCollection->InitTraversal();
566       while(vtkActor *anAct = aCollection->GetNextActor()){
567         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
568           if(anActor->hasIO()){
569             Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
570             if(anIO->hasEntry() && strcmp(anIO->getEntry(),theEntry) == 0){
571               return anActor;
572             }
573           }
574         }
575       }
576     }
577     return NULL;
578   }
579
580
581   SMESH_Actor* FindActorByEntry(const char* theEntry){
582     return FindActorByEntry(GetActiveWindow(),theEntry);
583   }
584
585
586   SMESH_Actor* FindActorByObject(CORBA::Object_ptr theObject){
587     SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
588     if( !app )
589       return NULL;
590
591     if(!CORBA::is_nil(theObject)){
592       _PTR(Study) aStudy = GetActiveStudyDocument();
593       CORBA::String_var anIOR = app->orb()->object_to_string( theObject );
594       _PTR(SObject) aSObject = aStudy->FindObjectIOR(anIOR.in());
595       if(aSObject){
596         CORBA::String_var anEntry = aSObject->GetID().c_str();
597         return FindActorByEntry(anEntry.in());
598       }
599     }
600     return NULL;
601   }
602
603
604   SMESH_Actor* CreateActor(_PTR(Study) theStudy,
605                            const char* theEntry,
606                            int theIsClear)
607   {
608     SMESH_Actor *anActor = NULL;
609     CORBA::Long anId = theStudy->StudyId();
610     if(TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry)){
611       _PTR(SObject) aSObj = theStudy->FindObjectID(theEntry);
612       if(aSObj){
613         _PTR(GenericAttribute) anAttr;
614         if(aSObj->FindAttribute(anAttr,"AttributeName")){
615           _PTR(AttributeName) aName = anAttr;
616           std::string aNameVal = aName->Value();
617           anActor = SMESH_Actor::New(aVisualObj,theEntry,aNameVal.c_str(),theIsClear);
618         }
619
620         SMESH::SMESH_GroupBase_var aGroup = SMESH::SMESH_GroupBase::_narrow( SMESH::SObjectToObject( aSObj ));
621         if(!CORBA::is_nil(aGroup) && anActor)
622         {
623           QColor c;
624           int deltaF, deltaV;
625           SMESH::GetColor( "SMESH", "fill_color", c, deltaF, "0,170,255|-100"  );
626           SMESH::GetColor( "SMESH", "volume_color", c, deltaV, "255,0,170|-100"  );
627           c = SMESH::GetColor( "SMESH", "default_grp_color", c );
628           SALOMEDS::Color aColor = aGroup->GetColor();
629           if( !( aColor.R > 0 || aColor.G > 0 || aColor.B > 0 ))
630           {
631             aColor.R = c.redF();
632             aColor.G = c.greenF();
633             aColor.B = c.blueF();
634             aGroup->SetColor( aColor );
635           }
636           if( aGroup->GetType() == SMESH::NODE )
637             anActor->SetNodeColor( aColor.R, aColor.G, aColor.B );
638           else if( aGroup->GetType() == SMESH::EDGE )
639             anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B );
640           else if( aGroup->GetType() == SMESH::ELEM0D )
641             anActor->Set0DColor( aColor.R, aColor.G, aColor.B );
642           else if( aGroup->GetType() == SMESH::BALL )
643             anActor->SetBallColor( aColor.R, aColor.G, aColor.B );
644           else if( aGroup->GetType() == SMESH::VOLUME )
645             anActor->SetVolumeColor( aColor.R, aColor.G, aColor.B, deltaV );
646           else
647             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B, deltaF );
648         }
649       }
650     }
651     MESSAGE("CreateActor " << anActor);
652     if( anActor )
653       if( SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI() )
654         aSMESHGUI->addActorAsObserver( anActor );
655     return anActor;
656   }
657
658
659   void DisplayActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
660     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
661       try {
662 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
663         OCC_CATCH_SIGNALS;
664 #endif
665         MESSAGE("DisplayActor " << theActor);
666         vtkWnd->AddActor(theActor);
667         vtkWnd->Repaint();
668       }
669       catch (...) {
670 #ifdef _DEBUG_
671         MESSAGE ( "Exception in SMESHGUI_VTKUtils::DisplayActor()" );
672 #endif
673         OnVisuException();
674       }
675     }
676   }
677
678
679   void RemoveActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
680     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
681         MESSAGE("RemoveActor " << theActor);
682       vtkWnd->RemoveActor(theActor);
683       if(theActor->hasIO()){
684         Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
685         if(anIO->hasEntry()){
686           std::string anEntry = anIO->getEntry();
687           SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
688           int aStudyId = aStudy->id();
689           TVisualObjCont::key_type aKey(aStudyId,anEntry);
690           VISUAL_OBJ_CONT.erase(aKey);
691         }
692       }
693       theActor->Delete();
694       vtkWnd->Repaint();
695     }
696   }
697
698   //================================================================================
699   /*!
700    * \brief Return true if there are no SMESH actors in a view
701    */
702   //================================================================================
703
704   bool noSmeshActors(SUIT_ViewWindow *theWnd)
705   {
706     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWnd)) {
707       vtkRenderer *aRenderer = aViewWindow->getRenderer();
708       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
709       vtkActorCollection *aCollection = aCopy.GetActors();
710       aCollection->InitTraversal();
711       while(vtkActor *anAct = aCollection->GetNextActor())
712         if(dynamic_cast<SMESH_Actor*>(anAct))
713           return false;
714     }
715     return true;
716   }
717
718   bool UpdateView(SUIT_ViewWindow *theWnd, EDisplaing theAction, const char* theEntry)
719   {
720         //MESSAGE("UpdateView");
721     bool OK = false;
722     SVTK_ViewWindow* aViewWnd = GetVtkViewWindow(theWnd);
723     if (!aViewWnd)
724       return OK;
725
726     SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd);
727     if (!vtkWnd)
728       return OK;
729
730     SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( vtkWnd->getViewManager()->study() );
731     
732     if (!aStudy)
733       return OK;
734
735     {
736       OK = true;
737       vtkRenderer *aRenderer = aViewWnd->getRenderer();
738       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
739       vtkActorCollection *aCollection = aCopy.GetActors();
740       aCollection->InitTraversal();
741
742       switch (theAction) {
743       case eDisplayAll: {
744         while (vtkActor *anAct = aCollection->GetNextActor()) {
745           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
746                 MESSAGE("--- display " << anActor);
747             anActor->SetVisibility(true);
748
749             if(anActor->hasIO()){
750               Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
751               if(anIO->hasEntry()){
752                 aStudy->setVisibilityState(anIO->getEntry(), Qtx::ShownState);
753               }
754             }
755           }
756         }
757         break;
758       }
759       case eDisplayOnly:
760       case eEraseAll: {
761         //MESSAGE("---case eDisplayOnly");
762         while (vtkActor *anAct = aCollection->GetNextActor()) {
763           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
764                 //MESSAGE("--- erase " << anActor);
765             anActor->SetVisibility(false);
766           }
767         }
768         aStudy->setVisibilityStateForAll(Qtx::HiddenState);
769       }
770       default: {
771         if (SMESH_Actor *anActor = FindActorByEntry(theWnd,theEntry)) {
772           switch (theAction) {
773             case eDisplay:
774             case eDisplayOnly:
775                 //MESSAGE("--- display " << anActor);
776               anActor->Update();
777               anActor->SetVisibility(true);
778               if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
779               aStudy->setVisibilityState(theEntry, Qtx::ShownState);
780               break;
781             case eErase:
782                 //MESSAGE("--- erase " << anActor);
783               anActor->SetVisibility(false);
784               aStudy->setVisibilityState(theEntry, Qtx::HiddenState);
785               break;
786           }
787         } else {
788           switch (theAction) {
789           case eDisplay:
790           case eDisplayOnly:
791             {
792                 //MESSAGE("---");
793               SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(theWnd->getViewManager()->study());
794               _PTR(Study) aDocument = aStudy->studyDS();
795               // Pass non-visual objects (hypotheses, etc.), return true in this case
796               CORBA::Long anId = aDocument->StudyId();
797               TVisualObjPtr aVisualObj;
798               if ( (aVisualObj = GetVisualObj(anId,theEntry)) && aVisualObj->IsValid())
799               {
800                 if ((anActor = CreateActor(aDocument,theEntry,true))) {
801                   bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
802                   DisplayActor(theWnd,anActor);
803                   aStudy->setVisibilityState(theEntry, Qtx::ShownState);
804                   // FitAll(); - PAL16770(Display of a group performs an automatic fit all)
805                   if (needFitAll) FitAll();
806                 } else {
807                   OK = false;
808                 }
809               }
810               break;
811             }
812           }
813         }
814       }
815       }
816     }
817     return OK;
818   }
819
820
821   bool UpdateView(EDisplaing theAction, const char* theEntry){
822         //MESSAGE("UpdateView");
823     SalomeApp_Study* aStudy = dynamic_cast< SalomeApp_Study* >( GetActiveStudy() );
824     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( aStudy->application() );
825     SUIT_ViewWindow *aWnd = app->activeViewManager()->getActiveView();
826     return UpdateView(aWnd,theAction,theEntry);
827   }
828
829   void UpdateView(){
830     if(SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView()){
831       LightApp_SelectionMgr* mgr = SMESHGUI::selectionMgr();
832       SALOME_ListIO selected; mgr->selectedObjects( selected );
833
834       if( selected.Extent() == 0){
835         vtkRenderer* aRenderer = aWnd->getRenderer();
836         VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
837         vtkActorCollection *aCollection = aCopy.GetActors();
838         aCollection->InitTraversal();
839         while(vtkActor *anAct = aCollection->GetNextActor()){
840           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
841             if(anActor->hasIO())
842               if (!Update(anActor->getIO(),anActor->GetVisibility()))
843                 break; // avoid multiple warinings if visu failed
844           }
845         }
846       }else{
847         SALOME_ListIteratorOfListIO anIter( selected );
848         for( ; anIter.More(); anIter.Next()){
849           Handle(SALOME_InteractiveObject) anIO = anIter.Value();
850           if ( !Update(anIO,true) )
851             break; // avoid multiple warinings if visu failed
852         }
853       }
854       RepaintCurrentView();
855     }
856   }
857
858
859   bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
860   {
861         MESSAGE("Update");
862     _PTR(Study) aStudy = GetActiveStudyDocument();
863     CORBA::Long anId = aStudy->StudyId();
864     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) {
865       if ( theDisplay )
866         UpdateView(SMESH::eDisplay,theIO->getEntry());
867       return true;
868     }
869     return false;
870   }
871
872   bool UpdateNulData(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
873   {
874         MESSAGE("UpdateNulData");
875     _PTR(Study) aStudy = GetActiveStudyDocument();
876     CORBA::Long anId = aStudy->StudyId();
877     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry(), true)) {
878       if ( theDisplay )
879         UpdateView(SMESH::eDisplay,theIO->getEntry());
880       return true;
881     }
882     return false;
883   }
884
885   void UpdateSelectionProp( SMESHGUI* theModule ) {
886     if( !theModule )
887       return;
888
889     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
890     if( !app )
891     {
892       MESSAGE( "UpdateSelectionProp: Application is null" );
893       return;
894     }
895
896     SUIT_ViewManager* vm = app->activeViewManager();
897     if( !vm )
898     {
899       MESSAGE( "UpdateSelectionProp: View manager is null" );
900       return;
901     }
902
903     QVector<SUIT_ViewWindow*> views = vm->getViews();
904
905     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
906     if( !mgr )
907     {
908       MESSAGE( "UpdateSelectionProp: Resource manager is null" );
909       return;
910     }
911
912     QColor aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
913            aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ),
914            aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan );
915
916     int aElem0DSize = mgr->integerValue("SMESH", "elem0d_size", 5);
917     int aBallSize   = mgr->integerValue("SMESH", "ball_elem_size", 5);
918     int aLineWidth  = mgr->integerValue("SMESH", "element_width", 1);
919     int maxSize = aElem0DSize;
920     if (aElem0DSize > maxSize) maxSize = aElem0DSize;
921     if (aLineWidth > maxSize) maxSize = aLineWidth;
922     if (aBallSize > maxSize) maxSize = aBallSize;
923
924     double SP1 = mgr->doubleValue( "SMESH", "selection_precision_node", 0.025 ),
925            SP2 = mgr->doubleValue( "SMESH", "selection_precision_element", 0.001 ),
926            SP3 = mgr->doubleValue( "SMESH", "selection_precision_object", 0.025 );
927
928     for ( int i=0, n=views.count(); i<n; i++ ){
929       // update VTK viewer properties
930       if(SVTK_ViewWindow* aVtkView = GetVtkViewWindow( views[i] )){
931         // mesh element selection
932         aVtkView->SetSelectionProp(aSelColor.red()/255.,
933                                    aSelColor.green()/255.,
934                                    aSelColor.blue()/255.);
935         // tolerances
936         aVtkView->SetSelectionTolerance(SP1, SP2, SP3);
937
938         // pre-selection
939         aVtkView->SetPreselectionProp(aPreColor.red()/255.,
940                                       aPreColor.green()/255.,
941                                       aPreColor.blue()/255.);
942         // update actors
943         vtkRenderer* aRenderer = aVtkView->getRenderer();
944         VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
945         vtkActorCollection *aCollection = aCopy.GetActors();
946         aCollection->InitTraversal();
947         while(vtkActor *anAct = aCollection->GetNextActor()){
948           if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
949             anActor->SetHighlightColor(aHiColor.red()/255.,
950                                        aHiColor.green()/255.,
951                                        aHiColor.blue()/255.);
952             anActor->SetPreHighlightColor(aPreColor.red()/255.,
953                                           aPreColor.green()/255.,
954                                           aPreColor.blue()/255.);
955           }
956         }
957       }
958     }
959   }
960
961
962   void UpdateFontProp( SMESHGUI* theModule )
963   {
964     if ( !theModule ) return;
965
966     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( theModule->application() );
967     if ( !app ) return;
968
969     SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( theModule );
970     if ( !mgr ) return;
971     //
972     double anRGBNd[3] = {1,1,1};
973     SMESH::GetColor( "SMESH", "numbering_node_color", anRGBNd[0], anRGBNd[1], anRGBNd[2], QColor( 255, 255, 255 ) );
974     int aSizeNd = 10;
975     SMESH::LabelFont aFamilyNd = SMESH::FntTimes;
976     bool aBoldNd    = true;
977     bool anItalicNd = false;
978     bool aShadowNd  = false;
979
980     if ( mgr->hasValue( "SMESH", "numbering_node_font" ) ) {
981       QFont f = mgr->fontValue( "SMESH", "numbering_node_font" );
982       if ( f.family()      == "Arial" )   aFamilyNd = SMESH::FntArial;
983       else if ( f.family() == "Courier" ) aFamilyNd = SMESH::FntCourier;
984       else if ( f.family() == "Times" )   aFamilyNd = SMESH::FntTimes;
985       aBoldNd    = f.bold();
986       anItalicNd = f.italic();
987       aShadowNd  = f.overline();
988       aSizeNd    = f.pointSize();
989     }
990     //
991     double anRGBEl[3] = {0,1,0};
992     SMESH::GetColor( "SMESH", "numbering_elem_color", anRGBEl[0], anRGBEl[1], anRGBEl[2], QColor( 0, 255, 0 ) );
993     int aSizeEl = 12;
994     SMESH::LabelFont aFamilyEl = SMESH::FntTimes;
995     bool aBoldEl    = true;
996     bool anItalicEl = false;
997     bool aShadowEl  = false;
998
999     if ( mgr->hasValue( "SMESH", "numbering_elem_font" ) ) {
1000       QFont f = mgr->fontValue( "SMESH", "numbering_elem_font" );
1001
1002       if ( f.family()      == "Arial" )   aFamilyEl = SMESH::FntArial;
1003       else if ( f.family() == "Courier" ) aFamilyEl = SMESH::FntCourier;
1004       else if ( f.family() == "Times" )   aFamilyEl = SMESH::FntTimes;    
1005       aBoldEl    = f.bold();
1006       anItalicEl = f.italic();
1007       aShadowEl  = f.overline();
1008       aSizeEl    = f.pointSize();
1009     }
1010     //
1011     ViewManagerList vmList;
1012     app->viewManagers( SVTK_Viewer::Type(), vmList );
1013     foreach ( SUIT_ViewManager* vm, vmList ) {
1014       QVector<SUIT_ViewWindow*> views = vm->getViews();
1015       foreach ( SUIT_ViewWindow* vw, views ) {
1016         // update VTK viewer properties
1017         if ( SVTK_ViewWindow* aVtkView = GetVtkViewWindow( vw ) ) {
1018           // update actors
1019           vtkRenderer* aRenderer = aVtkView->getRenderer();
1020           VTK::ActorCollectionCopy aCopy( aRenderer->GetActors() );
1021           vtkActorCollection* aCollection = aCopy.GetActors();
1022           aCollection->InitTraversal();
1023           while ( vtkActor* anAct = aCollection->GetNextActor() ) {
1024             if ( SMESH_NodeLabelActor* anActor = dynamic_cast< SMESH_NodeLabelActor* >( anAct ) ) {
1025               anActor->SetFontProperties( aFamilyNd, aSizeNd, aBoldNd, anItalicNd, aShadowNd, anRGBNd[0], anRGBNd[1], anRGBNd[2] );
1026             }
1027             else if ( SMESH_CellLabelActor* anActor = dynamic_cast< SMESH_CellLabelActor* >( anAct ) ) {
1028               anActor->SetFontProperties( aFamilyEl, aSizeEl, aBoldEl, anItalicEl, aShadowEl, anRGBEl[0], anRGBEl[1], anRGBEl[2] );
1029             }
1030           }
1031           aVtkView->Repaint( false ); 
1032         }
1033       }
1034     }
1035   }
1036
1037   //----------------------------------------------------------------------------
1038   SVTK_Selector*
1039   GetSelector(SUIT_ViewWindow *theWindow)
1040   {
1041     if(SVTK_ViewWindow* aWnd = GetVtkViewWindow(theWindow))
1042       return aWnd->GetSelector();
1043
1044     return NULL;
1045   }
1046
1047   void SetFilter(const Handle(VTKViewer_Filter)& theFilter,
1048                  SVTK_Selector* theSelector)
1049   {
1050     if (theSelector)
1051       theSelector->SetFilter(theFilter);
1052   }
1053
1054   Handle(VTKViewer_Filter) GetFilter(int theId, SVTK_Selector* theSelector)
1055   {
1056     return theSelector->GetFilter(theId);
1057   }
1058
1059   bool IsFilterPresent(int theId, SVTK_Selector* theSelector)
1060   {
1061     return theSelector->IsFilterPresent(theId);
1062   }
1063
1064   void RemoveFilter(int theId, SVTK_Selector* theSelector)
1065   {
1066     theSelector->RemoveFilter(theId);
1067   }
1068
1069   void RemoveFilters(SVTK_Selector* theSelector)
1070   {
1071     for ( int id = SMESH::NodeFilter; theSelector && id < SMESH::LastFilter; id++ )
1072       theSelector->RemoveFilter( id );
1073   }
1074
1075   bool IsValid(SALOME_Actor* theActor, int theCellId,
1076                SVTK_Selector* theSelector)
1077   {
1078     return theSelector->IsValid(theActor,theCellId);
1079   }
1080
1081
1082   //----------------------------------------------------------------------------
1083   void SetPointRepresentation(bool theIsVisible){
1084     if(SVTK_ViewWindow* aViewWindow = GetCurrentVtkView()){
1085       vtkRenderer *aRenderer = aViewWindow->getRenderer();
1086       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1087       vtkActorCollection *aCollection = aCopy.GetActors();
1088       aCollection->InitTraversal();
1089       while(vtkActor *anAct = aCollection->GetNextActor()){
1090         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
1091           if(anActor->GetVisibility()){
1092             anActor->SetPointRepresentation(theIsVisible);
1093           }
1094         }
1095       }
1096       RepaintCurrentView();
1097     }
1098   }
1099
1100
1101   void SetPickable(SMESH_Actor* theActor){
1102     if(SVTK_ViewWindow* aWnd = GetCurrentVtkView()){
1103       int anIsAllPickable = (theActor == NULL);
1104       vtkRenderer *aRenderer = aWnd->getRenderer();
1105       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1106       vtkActorCollection *aCollection = aCopy.GetActors();
1107       aCollection->InitTraversal();
1108       while(vtkActor *anAct = aCollection->GetNextActor()){
1109         if(SALOME_Actor *anActor = dynamic_cast<SALOME_Actor*>(anAct)){
1110           if(anActor->GetVisibility()){
1111             anActor->SetPickable(anIsAllPickable);
1112           }
1113         }
1114       }
1115       if(theActor)
1116         theActor->SetPickable(!anIsAllPickable);
1117       RepaintCurrentView();
1118     }
1119   }
1120
1121
1122   //----------------------------------------------------------------------------
1123   int GetNameOfSelectedSortedNodes( SMDSAbs_EntityType theElementType,
1124                                     SVTK_Selector* theSelector,
1125                                     SMESH_Actor* theActor,
1126                                     int theShift,
1127                                     QString& theName)
1128   {
1129     theName = "";
1130     TColStd_IndexedMapOfInteger aMapIndex;
1131     Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
1132     theSelector->GetIndex(anIO, aMapIndex);
1133
1134     SMDS_Mesh* aMesh = 0;
1135     if (theActor)
1136       aMesh = theActor->GetObject()->GetMesh();
1137
1138     std::vector<SMESH_TNodeXYZ> aVectorOfNode;
1139     std::list<int> aListOfId;
1140     int aSize = aMapIndex.Extent();
1141     for( int i = 1 ; i <= aSize; i++) {
1142       SMESH_TNodeXYZ aCurNode = aMesh->FindNode( aMapIndex(i) );
1143       aVectorOfNode.push_back( aCurNode );
1144       aListOfId.push_back( aCurNode._node->GetID() );
1145     }
1146     SMESH_TNodeXYZ aFirstNode;
1147     if ( aSize > 0 )
1148       aFirstNode = aVectorOfNode[0];
1149     int myNbNodes = 0;
1150     std::list<int> aResultListId;
1151     switch ( theElementType ) {
1152       case SMDSEntity_0D:
1153         myNbNodes = 1;
1154         break;
1155       case SMDSEntity_Ball:
1156         myNbNodes = 1;
1157         break;
1158       case SMDSEntity_Edge:
1159       case SMDSEntity_Quad_Edge:
1160         myNbNodes = 2;
1161         break;
1162       case SMDSEntity_Triangle:
1163       case SMDSEntity_Quad_Triangle:
1164       case SMDSEntity_BiQuad_Triangle:
1165         myNbNodes = 3;
1166         break;
1167       case SMDSEntity_Quadrangle:
1168       case SMDSEntity_Quad_Quadrangle:
1169       case SMDSEntity_BiQuad_Quadrangle:
1170         myNbNodes = 4;
1171         if ( myNbNodes <= aSize ) {
1172           aVectorOfNode.resize( myNbNodes );
1173           aVectorOfNode[0] = aVectorOfNode[theShift % myNbNodes];
1174           aVectorOfNode[theShift % myNbNodes] = aFirstNode;
1175           GetSortedNodesOnPolygon( aVectorOfNode, aResultListId );
1176         }
1177         break;
1178       case SMDSEntity_Polygon:
1179         myNbNodes = 0;
1180         if ( aSize > 0 ) {
1181           aVectorOfNode[0] = aVectorOfNode[theShift % aVectorOfNode.size()];
1182           aVectorOfNode[theShift % aVectorOfNode.size()] = aFirstNode;
1183         }
1184         GetSortedNodesOnPolygon( aVectorOfNode, aResultListId );
1185         break;
1186       case SMDSEntity_Tetra:
1187       case SMDSEntity_Quad_Tetra:
1188         myNbNodes = 4;
1189         break;
1190       case SMDSEntity_Pyramid:
1191       case SMDSEntity_Quad_Pyramid:
1192         myNbNodes = 5;
1193         if ( myNbNodes <= aSize ) {
1194           aVectorOfNode.resize( myNbNodes );
1195           aVectorOfNode[0] = aVectorOfNode[theShift % myNbNodes];
1196           aVectorOfNode[theShift % myNbNodes] = aFirstNode;
1197           GetSortedNodesOnPyramid( aVectorOfNode, aResultListId );
1198         }
1199         break;
1200       case SMDSEntity_Hexa:
1201       case SMDSEntity_Quad_Hexa:
1202       case SMDSEntity_TriQuad_Hexa:
1203         myNbNodes = 8;
1204         if ( myNbNodes <= aSize ) {
1205           aVectorOfNode.resize( myNbNodes );
1206           aVectorOfNode[0] = aVectorOfNode[theShift % myNbNodes];
1207           aVectorOfNode[theShift % myNbNodes] = aFirstNode;
1208           GetSortedNodesOnPrism( aVectorOfNode, aResultListId );
1209         }
1210         break;
1211       case SMDSEntity_Penta:
1212       case SMDSEntity_Quad_Penta:
1213         myNbNodes = 6;
1214         if ( myNbNodes <= aSize ) {
1215           aVectorOfNode.resize( myNbNodes );
1216           aVectorOfNode[0] = aVectorOfNode[theShift % myNbNodes];
1217           aVectorOfNode[theShift % myNbNodes] = aFirstNode;
1218           GetSortedNodesOnPrism( aVectorOfNode, aResultListId );
1219         }
1220         break;
1221       case SMDSEntity_Hexagonal_Prism:
1222         myNbNodes = 12;
1223         if ( myNbNodes <= aSize ) {
1224           aVectorOfNode.resize( myNbNodes );
1225           aVectorOfNode[0] = aVectorOfNode[theShift % myNbNodes];
1226           aVectorOfNode[theShift % myNbNodes] = aFirstNode;
1227           GetSortedNodesOnPrism( aVectorOfNode, aResultListId );
1228         }
1229         break;
1230       default:
1231         myNbNodes = 2;
1232       }
1233     if( myNbNodes > 0 ) {
1234       if ( myNbNodes <= 3 || myNbNodes > aSize || theElementType == SMDSEntity_Tetra )
1235         aResultListId = aListOfId;
1236       if ( myNbNodes < aSize ) {
1237         if ( aResultListId.size() == 0 )
1238           return 0;
1239         aVectorOfNode.resize( myNbNodes );
1240         aResultListId.resize( myNbNodes );
1241       }
1242     }
1243     std::list<int>::iterator anIter = aResultListId.begin();
1244
1245     for( ; anIter != aResultListId.end(); anIter++ ) {
1246       theName += QString(" %1").arg( *anIter );
1247     }
1248     if ( myNbNodes <= 3 || myNbNodes > aSize || theElementType == SMDSEntity_Tetra )
1249       return aSize;
1250     return aVectorOfNode.size();
1251   }
1252   int GetNameOfSelectedNodes(SVTK_Selector* theSelector,
1253                              const Handle(SALOME_InteractiveObject)& theIO,
1254                              QString& theName)
1255   {
1256     theName = "";
1257     TColStd_IndexedMapOfInteger aMapIndex;
1258     theSelector->GetIndex(theIO,aMapIndex);
1259
1260     for(int i = 1; i <= aMapIndex.Extent(); i++)
1261       theName += QString(" %1").arg(aMapIndex(i));
1262
1263     return aMapIndex.Extent();
1264   }
1265
1266   int GetNameOfSelectedElements(SVTK_Selector* theSelector,
1267                                 const Handle(SALOME_InteractiveObject)& theIO,
1268                                 QString& theName)
1269   {
1270     theName = "";
1271     TColStd_IndexedMapOfInteger aMapIndex;
1272     theSelector->GetIndex(theIO,aMapIndex);
1273
1274     typedef std::set<int> TIdContainer;
1275     TIdContainer anIdContainer;
1276     for( int i = 1; i <= aMapIndex.Extent(); i++)
1277       anIdContainer.insert(aMapIndex(i));
1278
1279     TIdContainer::const_iterator anIter = anIdContainer.begin();
1280     for( ; anIter != anIdContainer.end(); anIter++)
1281       theName += QString(" %1").arg(*anIter);
1282
1283     return aMapIndex.Extent();
1284   }
1285
1286
1287   int GetEdgeNodes(SVTK_Selector* theSelector,
1288                    const TVisualObjPtr& theVisualObject,
1289                    int& theId1,
1290                    int& theId2)
1291   {
1292     const SALOME_ListIO& selected = theSelector->StoredIObjects();
1293
1294     if ( selected.Extent() != 1 )
1295       return -1;
1296
1297     Handle(SALOME_InteractiveObject) anIO = selected.First();
1298     if ( anIO.IsNull() || !anIO->hasEntry() )
1299       return -1;
1300
1301     TColStd_IndexedMapOfInteger aMapIndex;
1302     theSelector->GetIndex( anIO, aMapIndex );
1303     if ( aMapIndex.Extent() != 2 )
1304       return -1;
1305
1306     int anObjId = -1, anEdgeNum = -1;
1307     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1308       int aVal = aMapIndex( i );
1309       if ( aVal > 0 )
1310         anObjId = aVal;
1311       else
1312         anEdgeNum = abs( aVal ) - 1;
1313     }
1314
1315     if ( anObjId == -1 || anEdgeNum == -1 )
1316       return -1;
1317
1318     return theVisualObject->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1319   }
1320
1321   //----------------------------------------------------------------------------
1322   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr,
1323                              const Handle(SALOME_InteractiveObject)& theIO,
1324                              QString& theName)
1325   {
1326     theName = "";
1327     if(theIO->hasEntry()){
1328       if(FindActorByEntry(theIO->getEntry())){
1329         TColStd_IndexedMapOfInteger aMapIndex;
1330         theMgr->GetIndexes(theIO,aMapIndex);
1331         for(int i = 1; i <= aMapIndex.Extent(); i++){
1332           theName += QString(" %1").arg(aMapIndex(i));
1333         }
1334         return aMapIndex.Extent();
1335       }
1336     }
1337     return -1;
1338   }
1339
1340   int GetNameOfSelectedNodes(LightApp_SelectionMgr *theMgr, QString& theName){
1341     theName = "";
1342     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1343     if(selected.Extent() == 1){
1344       Handle(SALOME_InteractiveObject) anIO = selected.First();
1345       return GetNameOfSelectedNodes(theMgr,anIO,theName);
1346     }
1347     return -1;
1348   }
1349
1350
1351   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr,
1352                                 const Handle(SALOME_InteractiveObject)& theIO,
1353                                 QString& theName)
1354   {
1355     theName = "";
1356     if(theIO->hasEntry()){
1357       if(FindActorByEntry(theIO->getEntry())){
1358         TColStd_IndexedMapOfInteger aMapIndex;
1359         theMgr->GetIndexes(theIO,aMapIndex);
1360         typedef std::set<int> TIdContainer;
1361         TIdContainer anIdContainer;
1362         for( int i = 1; i <= aMapIndex.Extent(); i++)
1363           anIdContainer.insert(aMapIndex(i));
1364         TIdContainer::const_iterator anIter = anIdContainer.begin();
1365         for( ; anIter != anIdContainer.end(); anIter++){
1366           theName += QString(" %1").arg(*anIter);
1367         }
1368         return aMapIndex.Extent();
1369       }
1370     }
1371     return -1;
1372   }
1373
1374
1375   int GetNameOfSelectedElements(LightApp_SelectionMgr *theMgr, QString& theName)
1376   {
1377     theName = "";
1378     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1379
1380     if( selected.Extent() == 1){
1381       Handle(SALOME_InteractiveObject) anIO = selected.First();
1382       return GetNameOfSelectedElements(theMgr,anIO,theName);
1383     }
1384     return -1;
1385   }
1386
1387   int GetSelected(LightApp_SelectionMgr*       theMgr,
1388                   TColStd_IndexedMapOfInteger& theMap,
1389                   const bool                   theIsElement)
1390   {
1391     theMap.Clear();
1392     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1393
1394     if ( selected.Extent() == 1 )
1395     {
1396       Handle(SALOME_InteractiveObject) anIO = selected.First();
1397       if ( anIO->hasEntry() ) {
1398         theMgr->GetIndexes( anIO, theMap );
1399       }
1400     }
1401     return theMap.Extent();
1402   }
1403
1404
1405   int GetEdgeNodes( LightApp_SelectionMgr* theMgr, int& theId1, int& theId2 )
1406   {
1407     SALOME_ListIO selected; theMgr->selectedObjects( selected );
1408
1409     if ( selected.Extent() != 1 )
1410       return -1;
1411
1412     Handle(SALOME_InteractiveObject) anIO = selected.First();
1413     if ( anIO.IsNull() || !anIO->hasEntry() )
1414       return -1;
1415
1416     SMESH_Actor *anActor = SMESH::FindActorByEntry( anIO->getEntry() );
1417     if ( anActor == 0 )
1418       return -1;
1419
1420     TColStd_IndexedMapOfInteger aMapIndex;
1421     theMgr->GetIndexes( anIO, aMapIndex );
1422     if ( aMapIndex.Extent() != 2 )
1423       return -1;
1424
1425     int anObjId = -1, anEdgeNum = -1;
1426     for ( int i = 1; i <= aMapIndex.Extent(); i++ ) {
1427       int aVal = aMapIndex( i );
1428       if ( aVal > 0 )
1429         anObjId = aVal;
1430       else
1431         anEdgeNum = abs( aVal );
1432     }
1433
1434     if ( anObjId == -1 || anEdgeNum == -1 )
1435       return -1;
1436
1437     return anActor->GetObject()->GetEdgeNodes( anObjId, anEdgeNum, theId1, theId2 ) ? 1 : -1;
1438   }
1439
1440   void SetControlsPrecision( const long theVal )
1441   {
1442     if( SVTK_ViewWindow* aWnd = SMESH::GetCurrentVtkView() )
1443     {
1444       vtkRenderer *aRenderer = aWnd->getRenderer();
1445       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
1446       vtkActorCollection *aCollection = aCopy.GetActors();
1447       aCollection->InitTraversal();
1448
1449       while ( vtkActor *anAct = aCollection->GetNextActor())
1450       {
1451         if ( SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>( anAct ) )
1452         {
1453           anActor->SetControlsPrecision( theVal );
1454           anActor->SetControlMode( anActor->GetControlMode() );
1455         }
1456       }
1457
1458     }
1459   }
1460
1461   //----------------------------------------------------------------------------
1462   // internal function
1463   void ComputeBoundsParam( double theBounds[6],
1464                            double theDirection[3],
1465                            double theMinPnt[3],
1466                            double& theMaxBoundPrj,
1467                            double& theMinBoundPrj )
1468   {
1469     //Enlarge bounds in order to avoid conflicts of precision
1470     for(int i = 0; i < 6; i += 2){
1471       static double EPS = 1.0E-3;
1472       double aDelta = (theBounds[i+1] - theBounds[i])*EPS;
1473       theBounds[i] -= aDelta;
1474       theBounds[i+1] += aDelta;
1475     }
1476
1477     double aBoundPoints[8][3] = { {theBounds[0],theBounds[2],theBounds[4]},
1478                                                 {theBounds[1],theBounds[2],theBounds[4]},
1479                                                 {theBounds[0],theBounds[3],theBounds[4]},
1480                                                 {theBounds[1],theBounds[3],theBounds[4]},
1481                                                 {theBounds[0],theBounds[2],theBounds[5]},
1482                                                 {theBounds[1],theBounds[2],theBounds[5]}, 
1483                                                 {theBounds[0],theBounds[3],theBounds[5]}, 
1484                                                 {theBounds[1],theBounds[3],theBounds[5]}};
1485
1486     int aMaxId = 0;
1487     theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]);
1488     theMinBoundPrj = theMaxBoundPrj;
1489     for(int i = 1; i < 8; i++){
1490       double aTmp = vtkMath::Dot(theDirection,aBoundPoints[i]);
1491       if(theMaxBoundPrj < aTmp){
1492         theMaxBoundPrj = aTmp;
1493         aMaxId = i;
1494       }
1495       if(theMinBoundPrj > aTmp){
1496         theMinBoundPrj = aTmp;
1497       }
1498     }
1499     double *aMinPnt = aBoundPoints[aMaxId];
1500     theMinPnt[0] = aMinPnt[0];
1501     theMinPnt[1] = aMinPnt[1];
1502     theMinPnt[2] = aMinPnt[2];
1503   }
1504
1505   // internal function
1506   void DistanceToPosition( double theBounds[6],
1507                            double theDirection[3],
1508                            double theDist,
1509                            double thePos[3] )
1510   {
1511     double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
1512     ComputeBoundsParam(theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
1513     double aLength = (aMaxBoundPrj-aMinBoundPrj)*theDist;
1514     thePos[0] = aMinPnt[0]-theDirection[0]*aLength;
1515     thePos[1] = aMinPnt[1]-theDirection[1]*aLength;
1516     thePos[2] = aMinPnt[2]-theDirection[2]*aLength;
1517   }
1518
1519   // internal function (currently unused, left just in case)
1520   void PositionToDistance( double theBounds[6],
1521                            double theDirection[3],
1522                            double thePos[3],
1523                            double& theDist )
1524   {
1525     double aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
1526     ComputeBoundsParam(theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
1527     double aPrj = vtkMath::Dot(theDirection,thePos);
1528     theDist = (aPrj-aMinBoundPrj)/(aMaxBoundPrj-aMinBoundPrj);
1529   }
1530
1531   bool ComputeClippingPlaneParameters( std::list<vtkActor*> theActorList,
1532                                        double theNormal[3],
1533                                        double theDist,
1534                                        double theBounds[6],
1535                                        double theOrigin[3] )
1536   {
1537     bool anIsOk = false;
1538     anIsOk = ComputeBounds( theActorList, theBounds );
1539
1540
1541     if( !anIsOk )
1542       return false;
1543
1544     DistanceToPosition( theBounds, theNormal, theDist, theOrigin );
1545     return true;
1546   }
1547   bool CreatePlaneOnThreePoints( const gp_Pnt& thePoint1,
1548                                  const gp_Pnt& thePoint2,
1549                                  const gp_Pnt& thePoint3,
1550                                  gp_Pln& thePlane )
1551   {
1552     gp_Vec aVec1, aVec2;
1553     aVec1 = gp_Vec( thePoint1, thePoint2 );
1554     aVec2 = gp_Vec( thePoint1, thePoint3 );
1555     double anAngle = aVec1.Angle( aVec2 );
1556     bool isOnStraight = ( anAngle != 0 && anAngle != M_PI );
1557     if ( isOnStraight ) {
1558       gce_MakePln aMakePln (thePoint1, thePoint2, thePoint3);
1559       if ( aMakePln.IsDone() ) {
1560         thePlane = aMakePln.Value();
1561       }
1562     }
1563     return isOnStraight;
1564   }
1565
1566   void FindNbLowestPoint( std::list<gp_Pnt2d> theList, gp_Pnt2d& theNode )
1567   {
1568     std::list<gp_Pnt2d>::iterator anIter = theList.begin();
1569     gp_Pnt2d aNode = gp_Pnt2d ( (*anIter).X(), (*anIter).Y());
1570     for( ; anIter != theList.end(); anIter++ ) {
1571       if ( (*anIter).Y() < aNode.Y() || ( (*anIter).Y() == aNode.Y() && (*anIter).X() < aNode.X() ) )
1572         aNode = *anIter;
1573     }
1574     theNode = aNode;
1575   }
1576
1577   static bool CompareNodeOfAngleAndDist (const TNodeOfAngleAndDist& first, const TNodeOfAngleAndDist& second )
1578   {
1579     if ( first.second.second == 0 )
1580       return true;
1581     if ( second.second.second == 0 )
1582       return false;
1583     if ( first.second.first == 0 && second.second.first == 0 )
1584       if ( first.second.second > second.second.second )
1585         return false;
1586       else
1587         return true;
1588     if ( first.second.first < second.second.first ||
1589        ( first.second.first == second.second.first && first.second.second >= second.second.second ) )
1590       return true;
1591     return false;
1592   }
1593
1594   static bool CompareNodeOfDist (const TNodeOfAngleAndDist& first, const TNodeOfAngleAndDist& second )
1595   {
1596     if ( first.second.second < second.second.second )
1597       return true;
1598     return false;
1599   }
1600
1601   static bool CompareDistOfPlane ( const TNodeOfDistToPlaneAndDist& first, const TNodeOfDistToPlaneAndDist& second )
1602   {
1603     if ( first.second.first == 0 && second.second.first != 0 )
1604       return true;
1605     if ( first.second.first != 0 && second.second.first == 0 )
1606       return false;
1607     if ( first.second.first < second.second.first ||
1608        (  first.second.first != 0 && second.second.first != 0 &&
1609           first.second.first == second.second.first && first.second.second > second.second.second ) )
1610       return true;
1611     return false;
1612   }
1613
1614   static bool CompareDistOfPlaneById ( const TIdOfDistToPlaneAndDist& first, const TIdOfDistToPlaneAndDist& second )
1615   {
1616     if ( first.second.first == 0 && second.second.first != 0 )
1617       return true;
1618     if ( first.second.first != 0 && second.second.first == 0 )
1619       return false;
1620     if ( first.second.first < second.second.first ||
1621        (  first.second.first != 0 && second.second.first != 0 &&
1622           first.second.first == second.second.first && first.second.second > second.second.second ) )
1623       return true;
1624     return false;
1625   }
1626
1627   static bool CompareDistForCorrectPlane ( const TNodeOfDist& first, const TNodeOfDist& second )
1628   {
1629     if ( first.second < second.second ) return true;
1630     return false;
1631   }
1632
1633   bool IsNotPlaneIntersection( std::vector<SMESH_TNodeXYZ>& theVector, const gp_Pln& thePlane )
1634   {
1635     double A, B, C, D, aCur;
1636     thePlane.Coefficients(A, B, C, D);
1637     int aPlus = -1;
1638     for ( int i = 0 ; i < (int)theVector.size(); ++i ) {
1639       aCur = A * theVector[i]._xyz[0] + B * theVector[i]._xyz[1] + C * theVector[i]._xyz[2] + D;
1640       if ( aCur == 0 )
1641         continue;
1642       if ( aPlus == -1 && aCur != 0 )
1643         aPlus = ( aCur < 0 ) ? 0 : 1;
1644       if ( aPlus > -1 && aPlus != ( aCur < 0 ) ? 0 : 1 )
1645         return false;
1646     }
1647     return true;
1648   }
1649
1650   bool GetNextCombination ( std::vector<int>& theVector1, std::vector<int>& theVector2, int theNbPoint )
1651   {
1652    int aSize = (int)theVector1.size();
1653    for ( int i = aSize - 1; i >= 0; --i ) {
1654      if ( theVector1[i] < theNbPoint - aSize + i ) {
1655        ++theVector1[i];
1656        for ( int j = i + 1; j < aSize; ++j )
1657          theVector1[j] = theVector1[j-1] + 1;
1658        int it = 0;
1659        int it2 = 0;
1660        bool isVec;
1661        for ( int k = 0; k < theNbPoint; ++k ) {
1662          isVec = false;
1663          if( it < aSize ) {
1664            if( k == theVector1[it] ) {
1665              isVec = true;
1666              ++it;
1667            }
1668          }
1669          if ( isVec )
1670            continue;
1671          theVector2[it2] = k;
1672          it2++;
1673          if ( it2 == (int)theVector2.size() )
1674            break;
1675        }
1676        return true;
1677      }
1678    }
1679      return false;
1680   }
1681
1682   bool Get2BasePlane( std::vector<SMESH_TNodeXYZ>& theVector,
1683                       std::vector<SMESH_TNodeXYZ>& thePlane1,
1684                       std::vector<SMESH_TNodeXYZ>& thePlane2 )
1685   {
1686     int aSize = (int)theVector.size() / 2;
1687     if ( aSize < 3 || (int)theVector.size() % 2 != 0 )
1688       return false;
1689     int anArr1[3];
1690     int anArr2[2 * aSize - 3];
1691     for (int i = 0; i < 3 ; i++) {
1692       anArr1[i] = i;
1693     }
1694     for (int i = 0; i < 2 * aSize - 3 ; i++) {
1695       anArr2[i] = i + 3;
1696     }
1697     int aNbSwapFirstPoint = 0;
1698     while ( thePlane1.empty() && thePlane2.empty() && aNbSwapFirstPoint < aSize * 2 ) {
1699       std::vector<int> anIndexPlane1( anArr1, anArr1 + 3 );
1700       std::vector<int> anIndexPlane2( anArr2, anArr2 + 2 * aSize - 3);
1701       int aNbCombination = 0;
1702       double aMax = 0;
1703       double aSumMin = -1;
1704       int aMaxCombination = 0;
1705       thePlane1.clear();
1706       thePlane2.clear();
1707       for (int i = 1; i < 2 * aSize - 1; i++ ) {
1708         aMaxCombination += i;
1709       }
1710       while ( aNbCombination < aMaxCombination ) {
1711         gp_Pln aPlane;
1712         double aSumMinDist1 = 0;
1713         double aSumMinDist2 = 0;
1714         std::vector<SMESH_TNodeXYZ> aVectorOfPoint;
1715         for(int i = 0; i < 2 * aSize - 3; i++) {
1716           aVectorOfPoint.push_back(theVector[anIndexPlane2[i]]);
1717         }
1718         bool isCorrectPlane = false;
1719         bool isCreatePlane = CreatePlaneOnThreePoints( gp_Pnt(theVector[anIndexPlane1[0]]._xyz[0], theVector[anIndexPlane1[0]]._xyz[1], theVector[anIndexPlane1[0]]._xyz[2]),
1720             gp_Pnt(theVector[anIndexPlane1[1]]._xyz[0], theVector[anIndexPlane1[1]]._xyz[1], theVector[anIndexPlane1[1]]._xyz[2]),
1721             gp_Pnt(theVector[anIndexPlane1[2]]._xyz[0], theVector[anIndexPlane1[2]]._xyz[1], theVector[anIndexPlane1[2]]._xyz[2]),
1722             aPlane );
1723         if ( isCreatePlane ) {
1724           isCorrectPlane = IsNotPlaneIntersection( aVectorOfPoint, aPlane );
1725         }
1726         if ( !isCorrectPlane ) {
1727           GetNextCombination( anIndexPlane1, anIndexPlane2, 2*aSize );
1728           aNbCombination++;
1729           continue;
1730         }
1731         std::vector<int> anIndexCorrectPlane1;
1732         std::vector<int> anIndexCorrectPlane2;
1733         if ( aSize == 3 ) {
1734           for (int i = 0; i < aSize ; i++) {
1735             anIndexCorrectPlane1.push_back( anIndexPlane1[i] );
1736             anIndexCorrectPlane2.push_back( anIndexPlane2[i] );
1737           }
1738         }
1739         if ( aSize >= 4 ) {
1740           std::list<TIdOfDistToPlaneAndDist> aListBaseOfPoint;
1741           TIdOfDistToPlaneAndDist aCurDistOfPlane;
1742           for (int i = 0; i < 2 * aSize - 3; i++ ) {
1743             aCurDistOfPlane.second.first = aPlane.Distance( gp_Pnt( theVector[anIndexPlane2[i]]._xyz[0], theVector[anIndexPlane2[i]]._xyz[1], theVector[anIndexPlane2[i]]._xyz[2] ));
1744             if ( aCurDistOfPlane.second.first == 0 )
1745               aCurDistOfPlane.second.second = 0;
1746             else {
1747               double aCurDist = 0;
1748               for (int j = 0; j < 3; j++) {
1749                 aCurDist += pow( theVector[anIndexPlane1[j]]._xyz[0] - theVector[anIndexPlane2[i]]._xyz[0], 2.0 ) +
1750                     pow( theVector[anIndexPlane1[j]]._xyz[1] - theVector[anIndexPlane2[i]]._xyz[1], 2.0 ) +
1751                     pow( theVector[anIndexPlane1[j]]._xyz[2] - theVector[anIndexPlane2[i]]._xyz[2], 2.0 );
1752               }
1753               aCurDistOfPlane.second.second = aCurDist;
1754             }
1755             aCurDistOfPlane.first = anIndexPlane2[i];
1756             aListBaseOfPoint.push_back( aCurDistOfPlane );
1757           }
1758           aListBaseOfPoint.sort( CompareDistOfPlaneById );
1759           std::list<TIdOfDistToPlaneAndDist>::iterator anIterDist = aListBaseOfPoint.begin();
1760           for (int i = 0; i < 3; i++) {
1761             anIndexCorrectPlane1.push_back( anIndexPlane1[i] );
1762           }
1763           for (int i = 0; i < aSize - 3; i++, anIterDist++) {
1764             anIndexCorrectPlane1.push_back((*anIterDist).first);
1765           }
1766           for (int i = 0; i < 2 * aSize - 3 ; i++) {
1767             anIterDist = aListBaseOfPoint.begin();
1768             bool isFinded = false;
1769             for (int j = 0; j < aSize - 3; j++, anIterDist++) {
1770               if ( anIndexPlane2[i] == (*anIterDist).first ) {
1771                 isFinded = true;
1772                 break;
1773               }
1774             }
1775             if ( !isFinded )
1776               anIndexCorrectPlane2.push_back( anIndexPlane2[i] );
1777           }
1778         }
1779         double aCurDist1, aCurDist2, aMinDist1, aMinDist2, aSumDist1, aSumDist2, aSumDistBase1, aSumDistBase2;
1780         bool isCorrect2Base = true;
1781         aSumDist1 = aSumDistBase1 = aSumDist2 = aSumDistBase2 = 0;
1782         for( int i = 0 ; i < aSize ; i++ ) {
1783           aMinDist1 = 0;
1784           aMinDist2 = 0;
1785           for(int j = 0 ; j < aSize ; j++ ) {
1786             aCurDist1 = pow( theVector[anIndexCorrectPlane1[i]]._xyz[0] - theVector[anIndexCorrectPlane2[j]]._xyz[0], 2.0 ) +
1787                 pow( theVector[anIndexCorrectPlane1[i]]._xyz[1] - theVector[anIndexCorrectPlane2[j]]._xyz[1], 2.0 ) +
1788                 pow( theVector[anIndexCorrectPlane1[i]]._xyz[2] - theVector[anIndexCorrectPlane2[j]]._xyz[2], 2.0 );
1789             aCurDist2 = pow( theVector[anIndexCorrectPlane1[j]]._xyz[0] - theVector[anIndexCorrectPlane2[i]]._xyz[0], 2.0 ) +
1790                 pow( theVector[anIndexCorrectPlane1[j]]._xyz[1] - theVector[anIndexCorrectPlane2[i]]._xyz[1], 2.0 ) +
1791                 pow( theVector[anIndexCorrectPlane1[j]]._xyz[2] - theVector[anIndexCorrectPlane2[i]]._xyz[2], 2.0 );
1792             aSumDistBase1 += pow( theVector[anIndexCorrectPlane1[i]]._xyz[0] - theVector[anIndexCorrectPlane1[j]]._xyz[0], 2.0 ) +
1793                 pow( theVector[anIndexCorrectPlane1[i]]._xyz[1] - theVector[anIndexCorrectPlane1[j]]._xyz[1], 2.0 ) +
1794                 pow( theVector[anIndexCorrectPlane1[i]]._xyz[2] - theVector[anIndexCorrectPlane1[j]]._xyz[2], 2.0 );
1795             aSumDistBase2 += pow( theVector[anIndexCorrectPlane2[i]]._xyz[0] - theVector[anIndexCorrectPlane2[j]]._xyz[0], 2.0 ) +
1796                 pow( theVector[anIndexCorrectPlane2[i]]._xyz[1] - theVector[anIndexCorrectPlane2[j]]._xyz[1], 2.0 ) +
1797                 pow( theVector[anIndexCorrectPlane2[i]]._xyz[2] - theVector[anIndexCorrectPlane2[j]]._xyz[2], 2.0 );
1798             if ( aCurDist1 < aMinDist1 || aMinDist1 == 0)
1799               aMinDist1 = aCurDist1;
1800             if ( aCurDist2 < aMinDist2 || aMinDist2 == 0)
1801               aMinDist2 = aCurDist2;
1802             aSumDist1 += aCurDist1;
1803             aSumDist2 += aCurDist2;
1804           }
1805           aSumMinDist1 += aMinDist1;
1806           aSumDist1 -= aMinDist1;
1807           aSumMinDist2 += aMinDist2;
1808           aSumDist2 -= aMinDist2;
1809         }
1810         isCorrect2Base = ( aSumDistBase1 + aSumDistBase2 <= aSumDist1 + aSumDist2 );
1811         if ( isCorrect2Base && ( aSumMinDist1 == aSumMinDist2 || ( aSumMinDist1 + aSumMinDist2 )  > aMax || aMax == 0 ||
1812             ( (aSumMinDist1 + aSumMinDist2 ) == aMax && ( (aSumDist1 + aSumDist2 - aSumDistBase1 - aSumDistBase2) < aSumMin || aSumMin == -1 ) ) ) ) {
1813           aMax = aSumMinDist1 + aSumMinDist2;
1814           aSumMin = aSumDist1 + aSumDist2 - aSumDistBase1 - aSumDistBase2;
1815           thePlane1.clear();
1816           thePlane2.clear();
1817           for(int i = 0; i < aSize; i++) {
1818             thePlane1.push_back(theVector[anIndexCorrectPlane1[i]]);
1819             thePlane2.push_back(theVector[anIndexCorrectPlane2[i]]);
1820           }
1821         }
1822         if ( aSumMinDist1 == aSumMinDist2 )
1823           break;
1824         if ( !GetNextCombination( anIndexPlane1, anIndexPlane2, 2 * aSize) )
1825           break;
1826         aNbCombination++;
1827       }
1828       if ( thePlane1.empty() && thePlane2.empty() ) {
1829         aNbSwapFirstPoint++;
1830         SMESH_TNodeXYZ aPoint;
1831         aPoint = theVector[0];
1832         theVector[0] = theVector[aNbSwapFirstPoint];
1833         theVector[aNbSwapFirstPoint] = aPoint;
1834       }
1835     }
1836     if ( thePlane1.empty() && thePlane2.empty() )
1837       return false;
1838     return true;
1839   }
1840
1841   bool GetCorrectSequenceOfId( std::vector<SMESH_TNodeXYZ>& theVector )
1842   {
1843     std::list<gp_Pnt2d> aListProjection;
1844     gp_Pnt2d aCurPoint;
1845     int aSize = (int)theVector.size();
1846     if ( aSize < 3 )
1847       return false;
1848     gp_Pln aPlane;
1849     bool isCreatePlane = false;
1850     for (int i = 0; i < aSize - 1; i++ ) {
1851       isCreatePlane = CreatePlaneOnThreePoints( gp_Pnt( theVector[i]._xyz[0], theVector[i]._xyz[1], theVector[i]._xyz[2] ),
1852                                                 gp_Pnt( theVector[i+1]._xyz[0], theVector[i+1]._xyz[1], theVector[i+1]._xyz[2] ),
1853                                                 gp_Pnt( theVector[i+2]._xyz[0], theVector[i+2]._xyz[1], theVector[i+2]._xyz[2] ), aPlane );
1854       if ( isCreatePlane)
1855         break;
1856     }
1857     if ( !isCreatePlane )
1858       return false;
1859     for ( int i = 0; i < aSize; i++) {
1860       aCurPoint = ProjLib::Project( aPlane, gp_Pnt( theVector[i]._xyz[0], theVector[i]._xyz[1], theVector[i]._xyz[2] ));
1861       aListProjection.push_back( aCurPoint );
1862     }
1863     std::list<TNodeOfAngleAndDist> aListIdOfAngleAndDist;
1864     TNodeOfAngleAndDist aCurIdOfAngleAndDist;
1865     FindNbLowestPoint( aListProjection, aCurPoint);
1866     std::list<gp_Pnt2d>::iterator anIter2d = aListProjection.begin();
1867     gp_Vec2d aCurVec;
1868     gp_Vec2d aAxisVec = gp_Vec2d( 1, 0 );
1869     for( int i = 0 ; anIter2d != aListProjection.end(); anIter2d++, i++) {
1870       aCurVec = gp_Vec2d( (*anIter2d).X() - aCurPoint.X(), (*anIter2d).Y() - aCurPoint.Y() );
1871       aCurIdOfAngleAndDist.first = theVector[i];
1872       if ( (*anIter2d).X() == aCurPoint.X() && (*anIter2d).Y() == aCurPoint.Y() )
1873         aCurIdOfAngleAndDist.second.first = 0;
1874       else {
1875         double anAngle = aAxisVec.Angle( aCurVec );
1876         double anRoundAngle = anAngle * 100000;
1877         int anIntAngle = anRoundAngle + 0.5;
1878         anRoundAngle = (double) anIntAngle / 100000;
1879         aCurIdOfAngleAndDist.second.first = anRoundAngle;
1880       }
1881       aCurIdOfAngleAndDist.second.second = pow( (*anIter2d).X() - aCurPoint.X(), 2.0 ) +
1882                                            pow( (*anIter2d).Y() - aCurPoint.Y(), 2.0 ) +
1883                                            pow( aPlane.Distance( gp_Pnt( theVector[i]._xyz[0], theVector[i]._xyz[1], theVector[i]._xyz[2] )), 2.0 );
1884       aListIdOfAngleAndDist.push_back( aCurIdOfAngleAndDist );
1885     }
1886     aListIdOfAngleAndDist.sort( CompareNodeOfAngleAndDist );
1887     std::list<TNodeOfAngleAndDist>::iterator anIter = aListIdOfAngleAndDist.begin();
1888     std::list<TNodeOfAngleAndDist> aListResult;
1889     double anAngle = 0;
1890     bool isSort = true;
1891     for(int i = 0 ; anIter != aListIdOfAngleAndDist.end(); anIter++, i++) {
1892       if ( anAngle == (*anIter).second.first && anAngle != 0 ) {
1893         isSort = false;
1894         break;
1895       }
1896       if ( ( anAngle > (*anIter).second.first && anAngle != 0 ) || i > 1)
1897         break;
1898       if ( (*anIter).second.first > 0 )
1899         anAngle = (*anIter).second.first;
1900     }
1901     if ( !isSort ) {
1902       anIter = aListIdOfAngleAndDist.begin();
1903       for( ; anIter != aListIdOfAngleAndDist.end(); anIter++) {
1904         if ( anAngle == (*anIter).second.first)
1905           aListResult.push_back( *anIter );
1906         else if ( anAngle < (*anIter).second.first)
1907           break;
1908       }
1909     }
1910     else
1911       anAngle = 0;
1912     aListResult.sort(CompareNodeOfDist);
1913     anIter = aListIdOfAngleAndDist.begin();
1914     theVector.clear();
1915     for( ; anIter != aListIdOfAngleAndDist.end(); anIter++) {
1916       if ( !isSort && anAngle == (*anIter).second.first ){
1917         for( std::list<TNodeOfAngleAndDist>::iterator anIter2 = aListResult.begin() ; anIter2 != aListResult.end(); anIter2++) {
1918           theVector.push_back((*anIter2).first);
1919         }
1920         isSort = true;
1921       }
1922       if ( isSort && anAngle != 0 && anAngle == (*anIter).second.first )
1923         continue;
1924       theVector.push_back((*anIter).first);
1925     }
1926
1927     return true;
1928 }
1929
1930   void GetCorrectSequenceTwoPlaneOfId( std::vector<SMESH_TNodeXYZ>& thePlane1, std::vector<SMESH_TNodeXYZ>& thePlane2, std::list<int>& theResultListId )
1931   {
1932     int anIndex1, anIndex2, aShift = 0;
1933     double aCurSum;
1934     std::pair<int, double> aShiftOfDist;
1935     int aSize = (int)thePlane1.size();
1936     aShiftOfDist.first = aShiftOfDist.second = 0;
1937     int anArr1[3];
1938     int anArr2[aSize - 3];
1939     for (int i = 0; i < 3 ; i++) {
1940       anArr1[i] = i;
1941     }
1942     for (int i = 0; i < aSize - 3 ; i++) {
1943       anArr2[i] = i + 3;
1944     }
1945     std::vector<int> anIndexPlane1( anArr1, anArr1 + 3 );
1946     std::vector<int> anIndexPlane2( anArr2, anArr2 + aSize - 3);
1947     std::vector<int> anIndexCorrectPlane;
1948     std::vector<SMESH_TNodeXYZ> theNewPlane;
1949     std::vector<SMESH_TNodeXYZ> theCorrectPlane;
1950
1951     GetCorrectSequenceOfId ( thePlane1 );
1952
1953     while( true ) {
1954       anIndexCorrectPlane.clear();
1955       std::vector<SMESH_TNodeXYZ> theNewPlane;
1956       for (int i = 0; i < 3; i++) {
1957         anIndexCorrectPlane.push_back( anIndexPlane1[i] );
1958       }
1959       for (int i = 0; i < aSize - 3; i++) {
1960         anIndexCorrectPlane.push_back( anIndexPlane2[i] );
1961       }
1962       for (int i = 0; i < aSize; i++) {
1963         theNewPlane.push_back( thePlane2[anIndexCorrectPlane[i]] );
1964       }
1965       aShift = 0;
1966       if ( GetCorrectSequenceOfId ( theNewPlane ) )
1967       {
1968         std::vector<double> aVectorSum;
1969         while ( aShift != 2 * aSize ) {
1970           anIndex1 = 0;
1971           aCurSum = 0;
1972           ( aShift < aSize ) ? anIndex2 = 0 : anIndex2 = aSize - 1;
1973           while ( ( aShift < aSize && anIndex2 < aSize ) || ( aShift >= aSize && anIndex2 >= 0 ) ) {
1974             aCurSum += pow( thePlane1[anIndex1]._xyz[0] - theNewPlane[ ( anIndex2 + aShift ) % aSize ]._xyz[0], 2.0 ) +
1975                        pow( thePlane1[anIndex1]._xyz[1] - theNewPlane[ ( anIndex2 + aShift ) % aSize ]._xyz[1], 2.0 ) +
1976                        pow( thePlane1[anIndex1]._xyz[2] - theNewPlane[ ( anIndex2 + aShift ) % aSize ]._xyz[2], 2.0 );
1977             ( aShift < aSize ) ? anIndex2++ : anIndex2--;
1978             anIndex1++;
1979           }
1980           aVectorSum.push_back( aCurSum );
1981           aShift++;
1982         }
1983         double aCurSumMin = 0;
1984         std::pair<int, double> aCurShiftOfDist;
1985         aCurShiftOfDist.first = aCurShiftOfDist.second = 0;
1986         for ( int i = 0; i < (int)aVectorSum.size(); i++ ) {
1987           if ( aVectorSum[i] < aCurShiftOfDist.second || aCurShiftOfDist.second == 0 ) {
1988             aCurShiftOfDist.first = i;
1989             aCurShiftOfDist.second = aVectorSum[i];
1990           }
1991         }
1992         if ( aCurShiftOfDist.second <= aShiftOfDist.second || aShiftOfDist.second == 0){
1993           aShiftOfDist = aCurShiftOfDist;
1994           theCorrectPlane = theNewPlane;
1995         }
1996       }
1997       if ( !GetNextCombination( anIndexPlane1, anIndexPlane2, aSize) )
1998         break;
1999     }
2000     thePlane2 = theCorrectPlane;
2001     aShift = aShiftOfDist.first;
2002     anIndex1 = 0;
2003     theResultListId.clear();
2004     ( aShift < aSize ) ? anIndex2 = 0 : anIndex2 = aSize - 1;
2005     while ( anIndex1 != aSize ) {
2006       theResultListId.push_back(thePlane1[anIndex1]._node->GetID());
2007       anIndex1++;
2008     }
2009     while ( ( aShift < aSize && anIndex2 < aSize ) || ( aShift >= aSize && anIndex2 >= 0 ) ) {
2010       theResultListId.push_back( thePlane2[( anIndex2 + aShift ) % aSize]._node->GetID() );
2011       ( aShift < aSize ) ? anIndex2++ : anIndex2--;
2012     }
2013   }
2014
2015   void GetSortedNodesOnPolygon( std::vector<SMESH_TNodeXYZ>& theVectorOfNode, std::list<int>& theResultListId )
2016   {
2017     GetCorrectSequenceOfId ( theVectorOfNode );
2018     for (int i = 0; i < theVectorOfNode.size(); i++) {
2019       theResultListId.push_back( theVectorOfNode[i]._node->GetID() );
2020     }
2021   }
2022
2023   void GetSortedNodesOnPrism( std::vector<SMESH_TNodeXYZ>& theVectorOfNode, std::list<int>& theResultListId )
2024   {
2025     int aSize = (int)theVectorOfNode.size();
2026     if ( aSize < 6 && aSize % 2 == 0)
2027       return;
2028     std::vector<SMESH_TNodeXYZ> aPlane1, aPlane2;
2029     if ( Get2BasePlane( theVectorOfNode, aPlane1, aPlane2 ) ) {
2030       GetCorrectSequenceTwoPlaneOfId( aPlane1, aPlane2, theResultListId);
2031     }
2032   }
2033
2034   void GetSortedNodesOnPyramid( std::vector<SMESH_TNodeXYZ>& theVectorOfNode, std::list<int>& theResultListId )
2035   {
2036     int aSize = (int)theVectorOfNode.size();
2037     if ( aSize < 5 )
2038       return;
2039     gp_Pln aPlane;
2040     bool isCreatePlane, isCorrectPlane;
2041     int aNumPlane = 0;
2042     double aMax = 0;
2043     while ( aNumPlane != aSize ) {
2044       isCreatePlane = CreatePlaneOnThreePoints( gp_Pnt( theVectorOfNode[aNumPlane]._xyz[0], theVectorOfNode[aNumPlane]._xyz[1], theVectorOfNode[aNumPlane]._xyz[2] ),
2045                                                 gp_Pnt( theVectorOfNode[(aNumPlane + 1) % aSize]._xyz[0], theVectorOfNode[(aNumPlane + 1) % aSize]._xyz[1], theVectorOfNode[(aNumPlane + 1) % aSize]._xyz[2] ),
2046                                                 gp_Pnt( theVectorOfNode[(aNumPlane + 2) % aSize]._xyz[0], theVectorOfNode[(aNumPlane + 2) % aSize]._xyz[1], theVectorOfNode[(aNumPlane + 2) % aSize]._xyz[2] ), aPlane );
2047       isCorrectPlane = false;
2048       std::vector<SMESH_TNodeXYZ> aVectorOfPoint;
2049       if ( isCreatePlane ) {
2050         for(int j = 0; j < aSize - 3; j++) {
2051           aVectorOfPoint.push_back(theVectorOfNode[(aNumPlane + j + 3) % aSize]);
2052         }
2053         isCorrectPlane = IsNotPlaneIntersection( aVectorOfPoint, aPlane );
2054       }
2055       if ( !isCorrectPlane ) {
2056        aNumPlane++;
2057        continue;
2058       }
2059       std::vector<SMESH_TNodeXYZ> aVectorBaseOfPoint;
2060       std::list<TNodeOfDistToPlaneAndDist> aListBaseOfPoint;
2061       TNodeOfDistToPlaneAndDist aCurDistOfPlane;
2062       aListBaseOfPoint.clear();
2063       for (int i = 0; i < aSize; i++ ) {
2064         aCurDistOfPlane.second.first = aPlane.Distance( gp_Pnt( theVectorOfNode[i]._xyz[0], theVectorOfNode[i]._xyz[1], theVectorOfNode[i]._xyz[2] ));
2065         if ( aCurDistOfPlane.second.first == 0 )
2066           aCurDistOfPlane.second.second = 0;
2067         else {
2068           double aCurDist = 0;
2069           for (int j = 0; j < 3; j++) {
2070             aCurDist += pow( theVectorOfNode[(aNumPlane + j) % aSize]._xyz[0] - theVectorOfNode[i]._xyz[0], 2.0 ) +
2071                         pow( theVectorOfNode[(aNumPlane + j) % aSize]._xyz[1] - theVectorOfNode[i]._xyz[1], 2.0 ) +
2072                         pow( theVectorOfNode[(aNumPlane + j) % aSize]._xyz[2] - theVectorOfNode[i]._xyz[2], 2.0 );
2073           }
2074           aCurDistOfPlane.second.second = aCurDist;
2075         }
2076         aCurDistOfPlane.first = theVectorOfNode[i];
2077         aListBaseOfPoint.push_back( aCurDistOfPlane );
2078       }
2079       aListBaseOfPoint.sort( CompareDistOfPlane );
2080       std::list<TNodeOfDistToPlaneAndDist>::iterator anIterDist = aListBaseOfPoint.begin();
2081       for (; anIterDist != aListBaseOfPoint.end(); anIterDist++ ) {
2082         aVectorBaseOfPoint.push_back((*anIterDist).first);
2083       }
2084       SMESH_TNodeXYZ aTopNode = aVectorBaseOfPoint.back();
2085       aVectorBaseOfPoint.resize( aVectorBaseOfPoint.size() - 1);
2086       double aCur = 0;
2087       double aSum = 0;
2088       std::list<TNodeOfDist> aListBaseCorrect;
2089       for (int i = 0; i < aSize - 1; i++) {
2090         aCur =  pow( aVectorBaseOfPoint[i]._xyz[0] - aTopNode._xyz[0], 2.0 ) +
2091                 pow( aVectorBaseOfPoint[i]._xyz[1] - aTopNode._xyz[1], 2.0 ) +
2092                 pow( aVectorBaseOfPoint[i]._xyz[2] - aTopNode._xyz[2], 2.0 );
2093         aListBaseCorrect.push_back(std::make_pair(aVectorBaseOfPoint[i], aCur) );
2094       }
2095       bool isCorrectTop = true;
2096       for (int i = 0; i < aSize - 1; i++) {
2097         isCreatePlane = CreatePlaneOnThreePoints( gp_Pnt( aVectorBaseOfPoint[i]._xyz[0], aVectorBaseOfPoint[i]._xyz[1], aVectorBaseOfPoint[i]._xyz[2] ),
2098                                                   gp_Pnt( aVectorBaseOfPoint[(i+1) % (aSize - 1)]._xyz[0], aVectorBaseOfPoint[(i+1) % (aSize - 1)]._xyz[1], aVectorBaseOfPoint[(i+1) % (aSize - 1)]._xyz[2] ),
2099                                                   gp_Pnt( aVectorBaseOfPoint[(i+2) % (aSize - 1)]._xyz[0], aVectorBaseOfPoint[(i+2) % (aSize - 1)]._xyz[1], aVectorBaseOfPoint[(i+2) % (aSize - 1)]._xyz[2] ), aPlane );
2100         if ( isCreatePlane ) {
2101           aCur = aPlane.Distance( gp_Pnt( aTopNode._xyz[0], aTopNode._xyz[1], aTopNode._xyz[2] ));
2102           if ( aCur == 0 ) {
2103             isCorrectTop = false;
2104             continue;
2105           }
2106           aSum += aCur;
2107         }
2108       }
2109       aNumPlane++;
2110       if ( ( isCorrectTop || aSum == 0 ) && ( aMax == 0 || aSum > aMax ) ) {
2111         aListBaseCorrect.sort(CompareDistForCorrectPlane);
2112         aVectorBaseOfPoint.clear();
2113         std::list<TNodeOfDist>::iterator anIter = aListBaseCorrect.begin();
2114         for ( ; anIter != aListBaseCorrect.end(); anIter++) {
2115           aVectorBaseOfPoint.push_back((*anIter).first);
2116         }
2117         GetCorrectSequenceOfId( aVectorBaseOfPoint );
2118         aMax = aSum;
2119         theResultListId.clear();
2120         for (int i = 0; i < aVectorBaseOfPoint.size(); i++) {
2121           theResultListId.push_back( aVectorBaseOfPoint[i]._node->GetID() );
2122         }
2123         theResultListId.push_back( aTopNode._node->GetID() );
2124         if ( aSum == 0 )
2125           break;
2126       }
2127     }
2128   }
2129   bool ComputeBounds( std::list<vtkActor*> theActorList,
2130       double theBounds[6])
2131   {
2132     bool anIsOk = false;
2133     theBounds[0] = theBounds[2] = theBounds[4] = VTK_DOUBLE_MAX;
2134     theBounds[1] = theBounds[3] = theBounds[5] = -VTK_DOUBLE_MAX;
2135     std::list<vtkActor*>::iterator anIter = theActorList.begin();
2136     for( ; anIter != theActorList.end(); anIter++ ) {
2137       if( vtkActor* aVTKActor = *anIter ) {
2138         if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
2139           double aBounds[6];
2140           anActor->GetUnstructuredGrid()->GetBounds( aBounds );
2141           theBounds[0] = std::min( theBounds[0], aBounds[0] );
2142           theBounds[1] = std::max( theBounds[1], aBounds[1] );
2143           theBounds[2] = std::min( theBounds[2], aBounds[2] );
2144           theBounds[3] = std::max( theBounds[3], aBounds[3] );
2145           theBounds[4] = std::min( theBounds[4], aBounds[4] );
2146           theBounds[5] = std::max( theBounds[5], aBounds[5] );
2147           anIsOk = true;
2148         }
2149       }
2150     }
2151     return anIsOk;
2152   }
2153
2154 #ifndef DISABLE_PLOT2DVIEWER
2155   //================================================================================
2156   /*!
2157    * \brief Find all SMESH_Actor's in the View Window.
2158    * If actor constains Plot2d_Histogram object remove it from each Plot2d Viewer.
2159    */
2160   //================================================================================
2161
2162   void ClearPlot2Viewers( SUIT_ViewWindow* theWindow ) {
2163     if(SVTK_ViewWindow* aViewWindow = GetVtkViewWindow(theWindow)){
2164       vtkRenderer *aRenderer = aViewWindow->getRenderer();
2165       VTK::ActorCollectionCopy aCopy(aRenderer->GetActors());
2166       vtkActorCollection *aCollection = aCopy.GetActors();
2167       aCollection->InitTraversal();
2168       while(vtkActor *anAct = aCollection->GetNextActor()){
2169         if(SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)){
2170           if(anActor->hasIO() && anActor->GetPlot2Histogram() ){
2171             ProcessIn2DViewers(anActor,RemoveFrom2dViewer);
2172           }
2173         }
2174       }
2175     }
2176   }
2177   
2178 #endif
2179
2180 } // end of namespace SMESH