Salome HOME
IPAL52704: TC7.6.0: "Modification of orientation" don't work on volumes
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MultiEditDlg.cxx
index 1384b9376713c74804b1a53d647ead8b91ba3c60..018006f27c36a1f6046c0be6a9e5a8ebda637942 100755 (executable)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "SMESHGUI_MeshUtils.h"
 #include "SMESHGUI_FilterUtils.h"
 #include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_MeshEditPreview.h"
 
-#include <SMESH_Actor.h>
-#include <SMESH_TypeFilter.hxx>
-#include <SMDS_Mesh.hxx>
+#include "SMDS_Mesh.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMESH_Actor.h"
+#include "SMESH_MeshAlgos.hxx"
+#include "SMESH_TypeFilter.hxx"
 
 // SALOME GUI includes
 #include <SUIT_Desktop.h>
@@ -49,7 +53,6 @@
 #include <LightApp_SelectionMgr.h>
 #include <LightApp_Application.h>
 #include <SALOME_ListIO.hxx>
-#include <SALOME_ListIteratorOfListIO.hxx>
 #include <SalomeApp_Tools.h>
 
 #include <SVTK_Selector.h>
 #include <VTKViewer_CellLocationsArray.h>
 
 // OCCT includes
-#include <TColStd_IndexedMapOfInteger.hxx>
+#include <Bnd_B3d.hxx>
 #include <TColStd_DataMapOfIntegerInteger.hxx>
+#include <TColStd_IndexedMapOfInteger.hxx>
 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
+#include <gp_Ax1.hxx>
 
 // VTK includes
 #include <vtkIdList.h>
 // Purpose : Constructor
 //=======================================================================
 SMESHGUI_MultiEditDlg
-::SMESHGUI_MultiEditDlg(SMESHGUI* theModule,
-                        const int theMode,
-                        const bool the3d2d):
-  QDialog(SMESH::GetDesktop(theModule)),
+::SMESHGUI_MultiEditDlg(SMESHGUI*  theModule,
+                        const int  theMode,
+                        const bool the3d2d,
+                        bool       theDoInit):
+  SMESHGUI_PreviewDlg(theModule),
   mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
   mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
   mySMESHGUI(theModule)
@@ -127,7 +133,8 @@ SMESHGUI_MultiEditDlg
   aDlgLay->addWidget(aMainFrame);
   aDlgLay->addWidget(aBtnFrame);
 
-  Init();
+  if ( theDoInit )
+    Init();
 }
 
 //=======================================================================
@@ -161,6 +168,7 @@ QWidget* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool
     QRadioButton* aFaceRb = new QRadioButton(tr("SMESH_FACE"), aEntityTypeGrp);
     QRadioButton* aVolumeRb = new QRadioButton(tr("SMESH_VOLUME"), aEntityTypeGrp);
 
+
     aEntityLayout->addWidget(aFaceRb);
     aEntityLayout->addWidget(aVolumeRb);
 
@@ -225,9 +233,6 @@ QWidget* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool
   myComboBoxFunctor->addItem(tr("ASPECTRATIO_ELEMENTS"));
   myComboBoxFunctor->addItem(tr("MINIMUMANGLE_ELEMENTS"));
   myComboBoxFunctor->addItem(tr("SKEW_ELEMENTS"));
-  //myComboBoxFunctor->addItem(tr("AREA_ELEMENTS"));
-  //myComboBoxFunctor->addItem(tr("LENGTH2D_EDGES")); // for existing elements only
-  //myComboBoxFunctor->addItem(tr("MULTI2D_BORDERS")); // for existing elements only
   myComboBoxFunctor->setCurrentIndex(0);
 
   aCriterionLayout->addWidget(myChoiceWidget);
@@ -304,7 +309,7 @@ QWidget* SMESHGUI_MultiEditDlg::createButtonFrame (QWidget* theParent)
 bool SMESHGUI_MultiEditDlg::isValid (const bool /*theMess*/)
 {
   return (!myMesh->_is_nil() &&
-          (myListBox->count() > 0 || (myToAllChk->isChecked()/* && myActor*/)));
+          (myListBox->count() > 0 || (myToAllChk->isChecked() && nbElemsInMesh() > 0)));
 }
 
 //=======================================================================
@@ -733,7 +738,7 @@ void SMESHGUI_MultiEditDlg::updateButtons()
   bool isListBoxNonEmpty = myListBox->count() > 0;
   bool isToAll = myToAllChk->isChecked();
   myFilterBtn->setEnabled(!isToAll);
-  myRemoveBtn->setEnabled(isListBoxNonEmpty && !isToAll);
+  myRemoveBtn->setEnabled(myListBox->selectedItems().count() && !isToAll);
   mySortBtn->setEnabled(isListBoxNonEmpty &&!isToAll);
 
   const SALOME_ListIO& aList = mySelector->StoredIObjects();
@@ -853,6 +858,8 @@ void SMESHGUI_MultiEditDlg::onListSelectionChanged()
   mySelector->AddOrRemoveIndex(anActor->getIO(),anIndexes,false);
   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
     aViewWindow->highlight(anActor->getIO(),true,true);
+
+  myRemoveBtn->setEnabled( anIndexes.Extent() );
 }
 
 //=======================================================================
@@ -988,6 +995,7 @@ bool SMESHGUI_MultiEditDlg::onApply()
 
     updateButtons();
   }
+  obj._retn(); // else myMesh is deleted by ~obj
 
   myBusy = false;
   return aResult;
@@ -1069,6 +1077,11 @@ bool SMESHGUI_ChangeOrientationDlg::process (SMESH::SMESH_MeshEditor_ptr theEdit
     return theEditor->ReorientObject( obj );
 }
 
+int SMESHGUI_ChangeOrientationDlg::nbElemsInMesh()
+{
+  return ( myFilterType == SMESH::FaceFilter ) ? myMesh->NbFaces() : myMesh->NbVolumes();
+}
+
 /*!
  *  Class       : SMESHGUI_UnionOfTrianglesDlg
  *  Description : Construction of quadrangles by automatic association of triangles
@@ -1080,6 +1093,11 @@ SMESHGUI_UnionOfTrianglesDlg
 {
   setWindowTitle(tr("CAPTION"));
 
+  //Preview check box
+  myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), mySelGrp);
+  QGridLayout* aLay = (QGridLayout*)(mySelGrp->layout());
+  aLay->addWidget(myPreviewCheckBox, aLay->rowCount(), 0, 1, aLay->columnCount());
+
   myComboBoxFunctor->setEnabled(true);  
   myComboBoxFunctor->addItem(tr("AREA_ELEMENTS"));
   myComboBoxFunctor->addItem(tr("WARP_ELEMENTS")); // for quadrangles only
@@ -1102,6 +1120,14 @@ SMESHGUI_UnionOfTrianglesDlg
   ((QVBoxLayout*)(myCriterionGrp->layout()))->addWidget(aMaxAngleGrp);
   myCriterionGrp->show();
 
+  connect(myComboBoxFunctor, SIGNAL(activated(int)),       this, SLOT(toDisplaySimulation()));
+  connect(myMaxAngleSpin,    SIGNAL(valueChanged(int)),    this, SLOT(toDisplaySimulation()));
+  connect(this,              SIGNAL(ListContensChanged()), this, SLOT(toDisplaySimulation()));
+  connectPreviewControl(); //To Connect preview check box
+
+  myPreviewCheckBox->setChecked(false);
+  onDisplaySimulation(false);
+
   myHelpFileName = "uniting_set_of_triangles_page.html";
 }
 
@@ -1149,6 +1175,51 @@ bool SMESHGUI_UnionOfTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theEdito
   return ok;
 }
 
+int SMESHGUI_UnionOfTrianglesDlg::nbElemsInMesh()
+{
+  return myMesh->NbTriangles();
+}
+  
+void SMESHGUI_UnionOfTrianglesDlg::onDisplaySimulation( bool toDisplayPreview )
+{
+  if ( myPreviewCheckBox->isChecked() && toDisplayPreview ) {
+    if ( isValid( true ) ) {
+      try{
+        SUIT_OverrideCursor aWaitCursor;
+        // get Ids of elements
+        SMESH::SMESH_IDSource_var obj;
+        SMESH::long_array_var anElemIds = getIds( obj );
+
+        SMESH::NumericalFunctor_var aCriterion  = getNumericalFunctor();
+        SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditPreviewer();
+
+        double aMaxAngle = myMaxAngleSpin->GetValue() * M_PI / 180.0;
+      
+        if ( CORBA::is_nil( obj ) )
+          aMeshEditor->TriToQuad( anElemIds.inout(), aCriterion, aMaxAngle );
+        else
+          aMeshEditor->TriToQuadObject( obj, aCriterion, aMaxAngle );
+      
+        SMESH::MeshPreviewStruct_var aMeshPreviewStruct = aMeshEditor->GetPreviewData();
+
+        vtkProperty* aProp = vtkProperty::New();
+        aProp->SetRepresentationToWireframe();
+        aProp->SetColor( 250, 0, 250 );
+        aProp->SetLineWidth( SMESH::GetFloat( "SMESH:element_width", 1 ) + 3 );
+        mySimulation->GetActor()->SetProperty( aProp );
+        aProp->Delete();
+
+        mySimulation->SetData( aMeshPreviewStruct._retn() );
+      } catch ( ... ) {
+        hidePreview();
+      }
+    } else {
+      hidePreview();
+    }
+  } else {
+    hidePreview();
+  }
+}
 
 /*!
  *  Class       : SMESHGUI_CuttingOfQuadsDlg
@@ -1212,7 +1283,7 @@ bool SMESHGUI_CuttingOfQuadsDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
     {
       if ( hasObj )
         return theEditor->QuadTo4Tri( obj ), true;
-      SMESH::SMESH_IDSource_wrap elems = theEditor->MakeIDSource( theIds, SMESH::FACE );
+      SMESH::IDSource_wrap elems = theEditor->MakeIDSource( theIds, SMESH::FACE );
       theEditor->QuadTo4Tri( elems );
       return true;
     }
@@ -1224,6 +1295,12 @@ bool SMESHGUI_CuttingOfQuadsDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
   return hasObj ? theEditor->QuadToTriObject(obj, aCrit) : theEditor->QuadToTri(theIds, aCrit);
 }
 
+int SMESHGUI_CuttingOfQuadsDlg::nbElemsInMesh()
+{
+  return myMesh->NbQuadrangles();
+}
+
+
 void SMESHGUI_CuttingOfQuadsDlg::onCriterionRB()
 {
   if (myGroupChoice->checkedId() == 2) // Use numeric functor
@@ -1270,6 +1347,7 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
   if (myPreviewActor != 0)
     erasePreview();
 
+  SUIT_OverrideCursor aWaitCursor;
   // get Ids of elements
   SMESH::SMESH_IDSource_var obj;
   SMESH::long_array_var anElemIds = getIds(obj);
@@ -1291,6 +1369,10 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
       return;
   }
 
+  if ( anElemIds->length() == 0 ) {
+    anElemIds = obj->GetIDs();
+  }
+
   //Create grid
   vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
 
@@ -1428,51 +1510,149 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
 }
 
 /*!
- *  Class       : SMESHGUI_CuttingIntoTetraDlg
- *  Description : Modification of orientation of faces
+ *  Class       : SMESHGUI_SplitVolumesDlg
+ *  Description : Spliter of volumes into tetrahedra or prisms
  */
 
-SMESHGUI_CuttingIntoTetraDlg::SMESHGUI_CuttingIntoTetraDlg(SMESHGUI* theModule)
-  : SMESHGUI_MultiEditDlg(theModule, SMESH::VolumeFilter, false)
+SMESHGUI_SplitVolumesDlg::SMESHGUI_SplitVolumesDlg(SMESHGUI* theModule)
+  : SMESHGUI_MultiEditDlg(theModule, SMESH::VolumeFilter, /*the3d2d=*/true, /*doInit=*/false)
 {
   setWindowTitle(tr("CAPTION"));
   myHelpFileName = "split_to_tetra_page.html";
   myEntityType = 1;
+  myCellSize = -1.;
+
+  // Facet selection group
+
+  myFacetSelGrp = new QGroupBox(tr("FACET_TO_SPLIT"), myCriterionGrp->parentWidget());
+  QGridLayout* facetSelLayout = new QGridLayout( myFacetSelGrp );
+  facetSelLayout->setMargin(MARGIN);
+  facetSelLayout->setSpacing(SPACING);
+
+  QLabel* pointLbl = new QLabel( tr("START_POINT"), myFacetSelGrp);
+  QLabel* normalLbl = new QLabel( tr("FACET_NORMAL"), myFacetSelGrp);
+  myFacetSelBtn = new QPushButton( mySubmeshBtn->icon(), "", myFacetSelGrp );
+  myFacetSelBtn->setCheckable( true );
+  QLabel* XLbl = new QLabel( tr("SMESH_X"), myFacetSelGrp);
+  QLabel* YLbl = new QLabel( tr("SMESH_Y"), myFacetSelGrp);
+  QLabel* ZLbl = new QLabel( tr("SMESH_Z"), myFacetSelGrp);
+  QLabel* dXLbl = new QLabel( tr("SMESH_DX"), myFacetSelGrp);
+  QLabel* dYLbl = new QLabel( tr("SMESH_DY"), myFacetSelGrp);
+  QLabel* dZLbl = new QLabel( tr("SMESH_DZ"), myFacetSelGrp);
+  QPushButton* axisBtn[3];
+  for ( int i = 0; i < 3; ++i )
+  {
+    myPointSpin[i] = new SMESHGUI_SpinBox( myFacetSelGrp );
+    myDirSpin  [i] = new SMESHGUI_SpinBox( myFacetSelGrp );
+    myPointSpin[i]->RangeStepAndValidator( -1e10, 1e10, 10 );
+    myDirSpin  [i]->RangeStepAndValidator( -1., 1., 0.1 );
+    myPointSpin[i]->SetValue(0.);
+    myDirSpin  [i]->SetValue(0.);
+    myAxisBtn  [i] = new QPushButton( QString("|| O") + char('X'+i ), myFacetSelGrp);
+  }
+  myDirSpin[2]->SetValue(1.);
+
+  myAllDomainsChk = new QCheckBox( tr("ALL_DOMAINS"), mySelGrp );
+
+  facetSelLayout->addWidget( pointLbl,      0, 0 );
+  facetSelLayout->addWidget( myFacetSelBtn, 0, 1 );
+  facetSelLayout->addWidget( XLbl,          0, 2 );
+  facetSelLayout->addWidget( myPointSpin[0],0, 3 );
+  facetSelLayout->addWidget( YLbl,          0, 4 );
+  facetSelLayout->addWidget( myPointSpin[1],0, 5 );
+  facetSelLayout->addWidget( ZLbl,          0, 6 );
+  facetSelLayout->addWidget( myPointSpin[2],0, 7 );
+
+  facetSelLayout->addWidget( normalLbl,     1, 0 );
+  facetSelLayout->addWidget( dXLbl,         1, 2 );
+  facetSelLayout->addWidget( myDirSpin[0],  1, 3 );
+  facetSelLayout->addWidget( dYLbl,         1, 4 );
+  facetSelLayout->addWidget( myDirSpin[1],  1, 5 );
+  facetSelLayout->addWidget( dZLbl,         1, 6 );
+  facetSelLayout->addWidget( myDirSpin[2],  1, 7 );
+
+  facetSelLayout->addWidget( myAxisBtn[0],  2, 2, 1, 2 );
+  facetSelLayout->addWidget( myAxisBtn[1],  2, 4, 1, 2 );
+  facetSelLayout->addWidget( myAxisBtn[2],  2, 6, 1, 2 );
+
+  myCriterionGrp->layout()->addWidget( myFacetSelGrp );
+  myCriterionGrp->layout()->addWidget( myAllDomainsChk );
+  //myChoiceWidget->layout()->addWidget( myAllDomainsChk );
+
+  connect( myFacetSelBtn,    SIGNAL(clicked(bool)), SLOT(onFacetSelection(bool)) );
+  for ( int i = 0; i < 3; ++i )
+  {
+    connect( myAxisBtn  [i], SIGNAL(clicked()),     SLOT(onSetDir()) );
+    connect( myPointSpin[i], SIGNAL(valueChanged       (const QString&)),
+             this,           SLOT  (updateNormalPreview(const QString&)) );
+    connect( myDirSpin  [i], SIGNAL(valueChanged       (const QString&)),
+             this,           SLOT  (updateNormalPreview(const QString&)) );
+  }
+  if ( myEntityTypeGrp )
+  {
+    myEntityTypeGrp->button(0)->setText( tr("SMESH_TETRAS"));
+    myEntityTypeGrp->button(1)->setText( tr("SMESH_PRISM"));
+    if ( QGroupBox* gb = qobject_cast< QGroupBox* >( myEntityTypeGrp->button(0)->parent() ))
+      gb->setTitle( tr("TARGET_ELEM_TYPE"));
+  }
 
   myToAllChk->setChecked( true ); //aplly to the whole mesh by default
 
   bool hasHexa = true;//myMesh->_is_nil() ? false : myMesh->NbHexas();
-
   if ( hasHexa )
   {
-    myGroupChoice->button(0)->setText( tr("SPLIT_HEX_TO_5_TETRA"));
-    myGroupChoice->button(1)->setText( tr("SPLIT_HEX_TO_6_TETRA"));
-    myGroupChoice->button(2)->setText( tr("SPLIT_HEX_TO_24_TETRA"));
-
     myCriterionGrp->setTitle( tr("SPLIT_METHOD"));
     myCriterionGrp->show();
     myComboBoxFunctor->hide();
     myChoiceWidget->show();
   }
-  setSelectionMode();
-  updateButtons();
+
+  on3d2dChanged( 0 );
+  Init();
 }
 
-SMESHGUI_CuttingIntoTetraDlg::~SMESHGUI_CuttingIntoTetraDlg()
+SMESHGUI_SplitVolumesDlg::~SMESHGUI_SplitVolumesDlg()
 {
 }
 
-bool SMESHGUI_CuttingIntoTetraDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
-                                            const SMESH::long_array&    theIds,
-                                            SMESH::SMESH_IDSource_ptr   theObj)
+bool SMESHGUI_SplitVolumesDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
+                                        const SMESH::long_array&    theIds,
+                                        SMESH::SMESH_IDSource_ptr   theObj)
 {
-  SMESH::SMESH_IDSource_wrap obj = theObj;
+  SMESH::IDSource_wrap obj = theObj;
   if ( CORBA::is_nil( obj ))
-    obj = theEditor->MakeIDSource( theIds, myEntityType ? SMESH::VOLUME : SMESH::FACE );
+    obj = theEditor->MakeIDSource( theIds, SMESH::VOLUME );
   else
     obj->Register();
   try {
-    theEditor->SplitVolumesIntoTetra( obj, myGroupChoice->checkedId()+1 );
+    if ( isIntoPrisms() )
+    {
+      QStringList aParameters;
+      aParameters << myPointSpin[0]->text();
+      aParameters << myPointSpin[1]->text();
+      aParameters << myPointSpin[2]->text();
+      aParameters << myDirSpin[0]->text();
+      aParameters << myDirSpin[1]->text();
+      aParameters << myDirSpin[2]->text();
+      myMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
+
+      SMESH::PointStruct_var point = new SMESH::PointStruct;
+      point->x  = myPointSpin[0]->GetValue();
+      point->y  = myPointSpin[1]->GetValue();
+      point->z  = myPointSpin[2]->GetValue();
+      SMESH::DirStruct_var norm = new SMESH::DirStruct;
+      norm->PS.x = myDirSpin[0]->GetValue();
+      norm->PS.y = myDirSpin[1]->GetValue();
+      norm->PS.z = myDirSpin[2]->GetValue();
+
+      theEditor->SplitHexahedraIntoPrisms( obj, point, norm,
+                                           myGroupChoice->checkedId()+1,
+                                           myAllDomainsChk->isChecked() );
+    }
+    else
+    {
+      theEditor->SplitVolumesIntoTetra( obj, myGroupChoice->checkedId()+1 );
+    }
   }
   catch ( const SALOME::SALOME_Exception& S_ex ) {
     SalomeApp_Tools::QtCatchCorbaException( S_ex );
@@ -1483,3 +1663,314 @@ bool SMESHGUI_CuttingIntoTetraDlg::process (SMESH::SMESH_MeshEditor_ptr theEdito
   }
   return true;
 }
+
+int SMESHGUI_SplitVolumesDlg::nbElemsInMesh()
+{
+  return isIntoPrisms() ? myMesh->NbHexas() : myMesh->NbVolumes() - myMesh->NbTetras();
+}
+
+bool SMESHGUI_SplitVolumesDlg::isIntoPrisms()
+{
+  return ( myEntityTypeGrp->checkedId() == 1 );
+}
+
+//================================================================================
+/*!
+ * \brief Slot called when a target element type changes
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::on3d2dChanged(int isPrism)
+{
+  if ( isPrism )
+  {
+    myFacetSelGrp->show();
+    myAllDomainsChk->show();
+    myGroupChoice->button(2)->hide();
+    myGroupChoice->button(0)->setText( tr("SPLIT_HEX_TO_2_PRISMS"));
+    myGroupChoice->button(1)->setText( tr("SPLIT_HEX_TO_4_PRISMS"));
+  }
+  else
+  {
+    myFacetSelGrp->hide();
+    myAllDomainsChk->hide();
+    myGroupChoice->button(2)->show();
+    myGroupChoice->button(0)->setText( tr("SPLIT_HEX_TO_5_TETRA"));
+    myGroupChoice->button(1)->setText( tr("SPLIT_HEX_TO_6_TETRA"));
+    myGroupChoice->button(2)->setText( tr("SPLIT_HEX_TO_24_TETRA"));
+  }
+  SMESHGUI_MultiEditDlg::on3d2dChanged( !myEntityType );
+  myEntityType = 1; // == VOLUME
+  myChoiceWidget->hide();
+  myChoiceWidget->show();
+  resize(minimumSizeHint());
+  onSelectionDone();
+}
+
+//================================================================================
+/*!
+ * \brief Set selection mode
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::setSelectionMode()
+{
+  if ( myBusy || !isEnabled() ) return;
+
+  SMESH::RemoveFilters();
+
+  mySelectionMgr->clearFilters();
+
+  if (mySubmeshChk->isChecked()) {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode(ActorSelection);
+    mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::SUBMESH));
+    myFacetSelBtn->setChecked( false );
+  }
+  else if (myGroupChk->isChecked()) {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode(ActorSelection);
+    mySelectionMgr->installFilter(new SMESH_TypeFilter(SMESH::GROUP));
+    myFacetSelBtn->setChecked( false );
+  }
+
+  if ( myFacetSelBtn->isChecked() )
+  {
+    // facet selection - select any element
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( CellSelection );
+    myFilterType = SMESH::AllElementsFilter;
+  }
+  else
+  {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( VolumeSelection );
+    if ( isIntoPrisms() )
+    {
+      SMESH::SetFilter(new SMESHGUI_VolumeShapeFilter( SMDSGeom_HEXA ));
+      myFilterType = SMESHGUI_VolumeShapeFilter::GetId( SMDSGeom_HEXA );
+    }
+    else // to tetrahedra
+    {
+      SMESH::SetFilter(new SMESHGUI_VolumesFilter());
+      myFilterType = SMESH::VolumeFilter;
+    }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief SLOT called when selection changed
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::onSelectionDone()
+{
+  if (myBusy || !isEnabled()) return;
+
+  if ( !myFacetSelBtn->isChecked() )
+  {
+    SMESHGUI_MultiEditDlg::onSelectionDone();
+  }
+  else // set point and normal by a selected element
+  {
+    const SALOME_ListIO& aList = mySelector->StoredIObjects();
+    int nbSel = aList.Extent();
+    if (nbSel > 0)
+    {
+      Handle(SALOME_InteractiveObject) anIO = aList.First();
+
+      myActor = SMESH::FindActorByEntry( anIO->getEntry() );
+
+      SMESH::SMESH_Mesh_var aSelMesh = SMESH::GetMeshByIO(anIO);
+      if (!aSelMesh->_is_nil())
+        myMesh = aSelMesh;
+
+      TColStd_IndexedMapOfInteger aMapIndex;
+      mySelector->GetIndex( anIO, aMapIndex );
+      if ( !aMapIndex.IsEmpty() )
+        showFacetByElement( aMapIndex(1) );
+      else if ( myCellSize < 0 )
+        showFacetByElement( 1 );
+    }
+    updateButtons();
+  }
+
+  myCriterionGrp->setEnabled( !myMesh->_is_nil() && nbElemsInMesh() > 0 );
+}
+
+//================================================================================
+/*!
+ * \brief Show facet normal by a selected element
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::showFacetByElement( int elemID )
+{
+  if ( !isIntoPrisms() || !myActor )
+  {
+    mySimulation->SetVisibility( false );
+    return;
+  }
+  SMDS_Mesh*              mesh = myActor->GetObject()->GetMesh();
+  const SMDS_MeshElement* elem = mesh->FindElement( elemID );
+  if ( !elem ) return;
+
+  // set point XYZ by the element barycenter
+  gp_XYZ bc( 0,0,0 );
+  Bnd_B3d bbox;
+  SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
+  vector< const SMDS_MeshNode* > nodes;
+  nodes.reserve( elem->NbNodes() );
+  while ( nIt->more() )
+  {
+    nodes.push_back( nIt->next() );
+    gp_XYZ p = SMESH_TNodeXYZ( nodes.back() );
+    bc += p;
+    bbox.Add( p );
+  }
+  bc /= nodes.size();
+
+  myPointSpin[0]->SetValue( bc.X() );
+  myPointSpin[1]->SetValue( bc.Y() );
+  myPointSpin[2]->SetValue( bc.Z() );
+
+  // set size
+  myCellSize = sqrt( bbox.SquareExtent() );
+
+  // set normal and size
+  gp_XYZ norm;
+  switch ( elem->GetType())
+  {
+  case SMDSAbs_Edge:
+  {
+    norm = SMESH_TNodeXYZ( nodes[1] ) - SMESH_TNodeXYZ( nodes[0] );
+    break;
+  }
+  case SMDSAbs_Face:
+  {
+    if ( !SMESH_MeshAlgos::FaceNormal( elem, norm, /*normalized=*/false ))
+      return;
+    break;
+  }
+  case SMDSAbs_Volume:
+  {
+    SMDS_VolumeTool vTool( elem );
+    vTool.SetExternalNormal();
+    bool freeFacetFound = false;
+    double n[3];
+    for ( int i = 0; i < vTool.NbFaces() && !freeFacetFound; ++i )
+      if (( freeFacetFound = vTool.IsFreeFace( i )))
+        vTool.GetFaceNormal( i, n[0], n[1], n[2] );
+    if ( !freeFacetFound )
+      vTool.GetFaceNormal( 0, n[0], n[1], n[2] );
+    norm.SetCoord( n[0], n[1], n[2] );
+    break;
+  }
+  default: return;
+  }
+
+  double size = norm.Modulus();
+  if ( size < 1e-20 )
+    return;
+  norm /= size;
+
+  myDirSpin[0]->SetValue( norm.X() );
+  myDirSpin[1]->SetValue( norm.Y() );
+  myDirSpin[2]->SetValue( norm.Z() );
+
+  if ( myCellSize > 0. )
+    updateNormalPreview();
+}
+
+//================================================================================
+/*!
+ * \brief SLOT called when a point or a normal changes
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::updateNormalPreview(const QString&)
+{
+  if ( myCellSize < 0. )
+  {
+    showFacetByElement( 1 );
+    return;
+  }
+
+  gp_Pnt point ( myPointSpin[0]->GetValue(),
+                 myPointSpin[1]->GetValue(),
+                 myPointSpin[2]->GetValue() );
+  gp_XYZ norm  ( myDirSpin[0]->GetValue(),
+                 myDirSpin[1]->GetValue(),
+                 myDirSpin[2]->GetValue() );
+  if ( norm.Modulus() < 1e-20 )
+    return;
+
+  vtkUnstructuredGrid* grid = mySimulation->GetGrid();
+
+  // Initialize the preview mesh of an arrow
+  if ( grid->GetNumberOfPoints() == 0 )
+  {
+    mySimulation->SetArrowShapeAndNb( /*nb=*/1, /*hLen=*/0.3, /*R=*/0.1, /*start=*/0 );
+  }
+
+  // Compute new coordinates of the grid according to the dialog controls
+
+  gp_Ax1 axis( point, norm );
+  mySimulation->SetArrows( &axis, 4 * myCellSize );
+  mySimulation->SetVisibility(true);
+}
+
+//================================================================================
+/*!
+ * \brief Slot called when facet selection button is clicked
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::onFacetSelection(bool isFacetSelection)
+{
+  setSelectionMode();
+  onSelectionDone();
+  mySelGrp->setEnabled( !isFacetSelection );
+}
+
+//================================================================================
+/*!
+ * \brief Slot called when an || axis button is clicked
+ */
+//================================================================================
+
+void SMESHGUI_SplitVolumesDlg::onSetDir()
+{
+  myDirSpin[0]->SetValue(0.);
+  myDirSpin[1]->SetValue(0.);
+  myDirSpin[2]->SetValue(0.);
+  int i = 0;
+  for ( ; i < 3; ++i )
+    if ( sender() == myAxisBtn[i] )
+      break;
+  if ( i == 3 )
+    i == 0;
+  myDirSpin[i]->SetValue(1.);
+
+  if ( myActor && !myMesh->_is_nil() && myMesh->NbNodes() > 0 )
+  {
+    double b[6];
+    myActor->GetUnstructuredGrid()->GetBounds(b);
+    gp_XYZ center( 0.5 * ( b[0] + b[1] ),
+                   0.5 * ( b[2] + b[3] ),
+                   0.5 * ( b[4] + b[5] ));
+    gp_XYZ point ( myPointSpin[0]->GetValue(),
+                   myPointSpin[1]->GetValue(),
+                   myPointSpin[2]->GetValue() );
+    gp_XYZ norm  ( myDirSpin[0]->GetValue(),
+                   myDirSpin[1]->GetValue(),
+                   myDirSpin[2]->GetValue() );
+
+    gp_Vec cp( center, point );
+    if ( cp.Dot( norm ) < 0. )
+      myDirSpin[i]->SetValue(-1.);
+  }
+
+  updateNormalPreview();
+}