Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MultiEditDlg.cxx
index 16fc4560ad27220085424da9712bad577e18ad2b..f658c0d539215bed6dad7c8ea1cd4da34c039ccb 100755 (executable)
 //  Module : SMESH
 
 #include "SMESHGUI_MultiEditDlg.h"
-#include "SMESHGUI_FilterDlg.h"
-#include "SMESHGUI_Filter.h"
 
 #include "SMESHGUI.h"
+#include "SMESHGUI_Filter.h"
+#include "SMESHGUI_FilterDlg.h"
 #include "SMESHGUI_Utils.h"
 #include "SMESHGUI_VTKUtils.h"
 #include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_FilterUtils.h"
+#include "SMESHGUI_SpinBox.h"
 
 #include "SMESH_Actor.h"
 #include "SMESH_TypeFilter.hxx"
 
 #include "SUIT_ResourceMgr.h"
 #include "SUIT_Desktop.h"
+#include "SUIT_Session.h"
+#include "SUIT_MessageBox.h"
 
-#include "SalomeApp_SelectionMgr.h"
+#include "LightApp_SelectionMgr.h"
+#include "LightApp_Application.h"
 #include "SALOME_ListIO.hxx"
 #include "SALOME_ListIteratorOfListIO.hxx"
 
 #include "SVTK_Selector.h"
 #include "SVTK_ViewModel.h"
 #include "SVTK_ViewWindow.h"
-#include "SVTK_InteractorStyle.h"
+#include "VTKViewer_CellLocationsArray.h"
 
 // OCCT Includes
 #include <Precision.hxx>
 #include <vtkPolygon.h>
 #include <vtkConvexPointSet.h>
 #include <vtkIdList.h>
-#include <vtkIntArray.h>
 #include <vtkCellArray.h>
 #include <vtkUnsignedCharArray.h>
 #include <vtkUnstructuredGrid.h>
 #include <vtkDataSetMapper.h>
+#include <vtkProperty.h>
 
 // QT Includes
-#include <qcheckbox.h>
 #include <qframe.h>
-#include <qgroupbox.h>
 #include <qlabel.h>
 #include <qlayout.h>
-#include <qlineedit.h>
 #include <qlistbox.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlineedit.h>
 #include <qpushbutton.h>
 #include <qapplication.h>
-#include <qhbuttongroup.h>
 #include <qradiobutton.h>
+#include <qhbuttongroup.h>
 
 // IDL Headers
 #include "SALOMEconfig.h"
@@ -105,9 +111,9 @@ SMESHGUI_MultiEditDlg
                        const int theMode,
                        const bool the3d2d,
                        const char* theName):
-  QDialog(SMESH::GetDesktop(theModule), 
-         theName, 
-         false, 
+  QDialog(SMESH::GetDesktop(theModule),
+         theName,
+         false,
          WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu | WDestructiveClose),
     mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
     mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
@@ -158,7 +164,6 @@ QFrame* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool t
   myListBox = new QListBox(aFrame);
   myListBox->setSelectionMode(QListBox::Extended);
   myListBox->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
-//  myListBox->setColumnMode(QListBox::FitToHeight);
   myListBox->installEventFilter(this);
 
   myFilterBtn = new QPushButton(tr("FILTER")   , aFrame);
@@ -178,6 +183,29 @@ QFrame* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool t
 
   myToAllChk = new QCheckBox(tr("TO_ALL"), mySelGrp);
 
+  // Split/Join criterion group
+  myCriterionGrp = new QGroupBox(3, Qt::Vertical, tr("SPLIT_JOIN_CRITERION"), aMainGrp);
+
+  myGroupChoice = new QButtonGroup(3, Qt::Vertical, myCriterionGrp);
+  myGroupChoice->setInsideMargin(0);
+  myGroupChoice->setFrameStyle(QFrame::NoFrame);
+  (new QRadioButton(tr("USE_DIAGONAL_1_3"), myGroupChoice))->setChecked(true);
+  (new QRadioButton(tr("USE_DIAGONAL_2_4"), myGroupChoice));
+  (new QRadioButton(tr("USE_NUMERIC_FUNC"), myGroupChoice));
+
+  myComboBoxFunctor = new QComboBox(myCriterionGrp);
+  myComboBoxFunctor->insertItem(tr("ASPECTRATIO_ELEMENTS"));
+  myComboBoxFunctor->insertItem(tr("MINIMUMANGLE_ELEMENTS"));
+  myComboBoxFunctor->insertItem(tr("SKEW_ELEMENTS"));
+  myComboBoxFunctor->insertItem(tr("AREA_ELEMENTS"));
+  //myComboBoxFunctor->insertItem(tr("LENGTH2D_EDGES")); // for existing elements only
+  //myComboBoxFunctor->insertItem(tr("MULTI2D_BORDERS")); // for existing elements only
+  myComboBoxFunctor->setCurrentItem(0);
+
+  myCriterionGrp->hide();
+  myGroupChoice->hide();
+  myComboBoxFunctor->setEnabled(false);
+
   // "Select from" group
   QGroupBox* aGrp = new QGroupBox(3, Qt::Horizontal, tr("SELECT_FROM"), aMainGrp);
 
@@ -187,7 +215,7 @@ QFrame* SMESHGUI_MultiEditDlg::createMainFrame (QWidget* theParent, const bool t
   mySubmesh->setReadOnly(true);
   mySubmeshBtn->setPixmap(aPix);
 
-  myGroupChk = new QCheckBox(tr("GROUP"), aGrp);
+  myGroupChk = new QCheckBox(tr("SMESH_GROUP"), aGrp);
   myGroupBtn = new QPushButton(aGrp);
   myGroup = new QLineEdit(aGrp);
   myGroup->setReadOnly(true);
@@ -208,6 +236,7 @@ QFrame* SMESHGUI_MultiEditDlg::createButtonFrame (QWidget* theParent)
   myOkBtn     = new QPushButton (tr("SMESH_BUT_OK"   ), aFrame);
   myApplyBtn  = new QPushButton (tr("SMESH_BUT_APPLY"), aFrame);
   myCloseBtn  = new QPushButton (tr("SMESH_BUT_CLOSE"), aFrame);
+  myHelpBtn   = new QPushButton (tr("SMESH_BUT_HELP"), aFrame);
 
   QSpacerItem* aSpacer = new QSpacerItem (0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
 
@@ -217,6 +246,7 @@ QFrame* SMESHGUI_MultiEditDlg::createButtonFrame (QWidget* theParent)
   aLay->addWidget(myApplyBtn);
   aLay->addItem(aSpacer);
   aLay->addWidget(myCloseBtn);
+  aLay->addWidget(myHelpBtn);
 
   return aFrame;
 }
@@ -258,6 +288,39 @@ bool SMESHGUI_MultiEditDlg::eventFilter (QObject* object, QEvent* event)
   return QDialog::eventFilter(object, event);
 }
 
+//=======================================================================
+// name    : SMESHGUI_MultiEditDlg::getNumericalFunctor
+// Purpose :
+//=======================================================================
+SMESH::NumericalFunctor_ptr SMESHGUI_MultiEditDlg::getNumericalFunctor()
+{
+  SMESH::NumericalFunctor_var aNF = SMESH::NumericalFunctor::_nil();
+
+  SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
+  if (aFilterMgr->_is_nil())
+    return aNF._retn();
+
+  if (myComboBoxFunctor->currentText() == tr("ASPECTRATIO_ELEMENTS"))
+    aNF = aFilterMgr->CreateAspectRatio();
+  else if (myComboBoxFunctor->currentText() == tr("WARP_ELEMENTS"))
+    aNF = aFilterMgr->CreateWarping();
+  else if (myComboBoxFunctor->currentText() == tr("MINIMUMANGLE_ELEMENTS"))
+    aNF = aFilterMgr->CreateMinimumAngle();
+  else if (myComboBoxFunctor->currentText() == tr("TAPER_ELEMENTS"))
+    aNF = aFilterMgr->CreateTaper();
+  else if (myComboBoxFunctor->currentText() == tr("SKEW_ELEMENTS"))
+    aNF = aFilterMgr->CreateSkew();
+  else if (myComboBoxFunctor->currentText() == tr("AREA_ELEMENTS"))
+    aNF = aFilterMgr->CreateArea();
+  else if (myComboBoxFunctor->currentText() == tr("LENGTH2D_EDGES"))
+    aNF = aFilterMgr->CreateLength2D();
+  else if (myComboBoxFunctor->currentText() == tr("MULTI2D_BORDERS"))
+    aNF = aFilterMgr->CreateMultiConnection2D();
+  else ;
+
+  return aNF._retn();
+}
+
 //=======================================================================
 // name    : SMESHGUI_MultiEditDlg::Init
 // Purpose : Init dialog fields, connect signals and slots, show dialog
@@ -275,6 +338,7 @@ void SMESHGUI_MultiEditDlg::Init()
   connect(myOkBtn,    SIGNAL(clicked()), SLOT(onOk()));
   connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
   connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
+  connect(myHelpBtn,  SIGNAL(clicked()), SLOT(onHelp()));
 
   // selection and SMESHGUI
   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
@@ -330,6 +394,35 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds()
       anActor = myActor;
     if (anActor != 0)
     {
+      // skl 07.02.2006
+      SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh();
+      if( myFilterType == SMESHGUI_TriaFilter || 
+         myFilterType == SMESHGUI_QuadFilter ||
+         myFilterType == SMESHGUI_FaceFilter ) {
+       SMDS_FaceIteratorPtr it = aMesh->facesIterator();
+       while(it->more()) {
+         const SMDS_MeshFace* f = it->next();
+         if(myFilterType == SMESHGUI_FaceFilter) {
+           myIds.Add(f->GetID());
+         }
+         else if( myFilterType==SMESHGUI_TriaFilter &&
+                  ( f->NbNodes()==3 || f->NbNodes()==6 ) ) {
+           myIds.Add(f->GetID());
+         }
+         else if( myFilterType==SMESHGUI_QuadFilter &&
+                  ( f->NbNodes()==4 || f->NbNodes()==8 ) ) {
+           myIds.Add(f->GetID());
+         }
+       }
+      }
+      else if(myFilterType == SMESHGUI_VolumeFilter) {
+       SMDS_VolumeIteratorPtr it = aMesh->volumesIterator();
+       while(it->more()) {
+         const SMDS_MeshVolume* f = it->next();
+         myIds.Add(f->GetID());
+       }
+      }
+      /* commented by skl 07.02.2006
       TVisualObjPtr aVisualObj = anActor->GetObject();
       vtkUnstructuredGrid* aGrid = aVisualObj->GetUnstructuredGrid();
       if (aGrid != 0) {
@@ -353,6 +446,7 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds()
           }
         }
       }
+      */
     }
   }
 
@@ -380,12 +474,29 @@ void SMESHGUI_MultiEditDlg::onClose()
   SMESH::RemoveFilters();
   SMESH::SetPickable();
 
-  mySelectionMgr->clearSelected();
+  //mySelectionMgr->clearSelected();
   mySelectionMgr->clearFilters();
 
   reject();
 }
 
+//=================================================================================
+// function : onHelp()
+// purpose  :
+//=================================================================================
+void SMESHGUI_MultiEditDlg::onHelp()
+{
+  LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
+  if (app) 
+    app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
+  else {
+    SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
+                          QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
+                          arg(app->resourceMgr()->stringValue("ExternalBrowser", "application")).arg(myHelpFileName),
+                          QObject::tr("BUT_OK"));
+  }
+}
+
 //=======================================================================
 // name    : SMESHGUI_MultiEditDlg::onSelectionDone
 // Purpose : SLOT called when selection changed
@@ -446,8 +557,8 @@ void SMESHGUI_MultiEditDlg::onSelectionDone()
     myActor = SMESH::FindActorByEntry(aList.First()->getEntry());
     if (!myActor)
       myActor = SMESH::FindActorByObject(myMesh);
-    SVTK_InteractorStyle* aStyle = SMESH::GetInteractorStyle();
-    Handle(VTKViewer_Filter) aFilter = aStyle->GetFilter(myFilterType);
+    SVTK_Selector* aSelector = SMESH::GetSelector();
+    Handle(VTKViewer_Filter) aFilter = aSelector->GetFilter(myFilterType);
     if (!aFilter.IsNull())
       aFilter->SetActor(myActor);
   }
@@ -547,9 +658,9 @@ void SMESHGUI_MultiEditDlg::onFilterAccepted()
 //=======================================================================
 bool SMESHGUI_MultiEditDlg::isIdValid (const int theId) const
 {
-  SVTK_InteractorStyle* aStyle = SMESH::GetInteractorStyle();
+  SVTK_Selector* aSelector = SMESH::GetSelector();
   Handle(SMESHGUI_Filter) aFilter =
-    Handle(SMESHGUI_Filter)::DownCast(aStyle->GetFilter(myFilterType));
+    Handle(SMESHGUI_Filter)::DownCast(aSelector->GetFilter(myFilterType));
 
   return (!aFilter.IsNull() && aFilter->IsObjValid(theId));
 }
@@ -884,7 +995,10 @@ bool SMESHGUI_MultiEditDlg::onApply()
   bool aResult = process(aMeshEditor, anIds.inout());
   if (aResult) {
     if (myActor) {
-      mySelectionMgr->clearSelected();
+      SALOME_ListIO sel;
+      mySelectionMgr->selectedObjects( sel );
+      mySelector->ClearIndex();
+      mySelectionMgr->setSelectedObjects( sel );
       SMESH::UpdateView();
     }
 
@@ -932,17 +1046,18 @@ int SMESHGUI_MultiEditDlg::entityType()
   return myEntityType;
 }
 
-/*
+/*!
  *  Class       : SMESHGUI_ChangeOrientationDlg
  *  Description : Modification of orientation of faces
  */
 
 SMESHGUI_ChangeOrientationDlg
 ::SMESHGUI_ChangeOrientationDlg(SMESHGUI* theModule,
-                               const char* theName): 
+                               const char* theName):
   SMESHGUI_MultiEditDlg(theModule, SMESHGUI_FaceFilter, true, theName)
 {
   setCaption(tr("CAPTION"));
+  myHelpFileName = "/files/changing_orientation_of_elements.htm";
 }
 
 SMESHGUI_ChangeOrientationDlg::~SMESHGUI_ChangeOrientationDlg()
@@ -966,6 +1081,23 @@ SMESHGUI_UnionOfTrianglesDlg
   SMESHGUI_MultiEditDlg(theModule, SMESHGUI_TriaFilter, false, theName)
 {
   setCaption(tr("CAPTION"));
+
+  myComboBoxFunctor->setEnabled(true);
+  myComboBoxFunctor->insertItem(tr("WARP_ELEMENTS")); // for quadrangles only
+  myComboBoxFunctor->insertItem(tr("TAPER_ELEMENTS")); // for quadrangles only
+
+  // Maximum angle
+  QGroupBox* aMaxAngleGrp = new QGroupBox (2, Qt::Horizontal, myCriterionGrp);
+  aMaxAngleGrp->setInsideMargin(0);
+  aMaxAngleGrp->setFrameStyle(QFrame::NoFrame);
+  new QLabel (tr("MAXIMUM_ANGLE"), aMaxAngleGrp);
+  myMaxAngleSpin = new SMESHGUI_SpinBox (aMaxAngleGrp);
+  myMaxAngleSpin->RangeStepAndValidator(0, 180.0, 1.0, 3);
+  myMaxAngleSpin->SetValue(30.0);
+
+  myCriterionGrp->show();
+
+  myHelpFileName = "/files/uniting_a_set_of_triangles.htm";
 }
 
 SMESHGUI_UnionOfTrianglesDlg::~SMESHGUI_UnionOfTrianglesDlg()
@@ -975,12 +1107,15 @@ SMESHGUI_UnionOfTrianglesDlg::~SMESHGUI_UnionOfTrianglesDlg()
 bool SMESHGUI_UnionOfTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
                                             const SMESH::long_array&    theIds)
 {
-  return theEditor->TriToQuad(theIds, SMESH::NumericalFunctor::_nil(), 1.);
+  SMESH::NumericalFunctor_var aCriterion = getNumericalFunctor();
+  double aMaxAngle = myMaxAngleSpin->GetValue() * PI / 180.0;
+  return theEditor->TriToQuad(theIds, aCriterion, aMaxAngle);
 }
 
+
 /*!
  *  Class       : SMESHGUI_CuttingOfQuadsDlg
- *  Description : Construction of quadrangles by automatic association of triangles
+ *  Description : Automatic splitting of quadrangles into triangles
  */
 
 SMESHGUI_CuttingOfQuadsDlg
@@ -991,12 +1126,18 @@ SMESHGUI_CuttingOfQuadsDlg
   setCaption(tr("CAPTION"));
   myPreviewActor = 0;
 
-  myUseDiagChk = new QCheckBox (tr("USE_DIAGONAL_2_4"), mySelGrp);
   myPreviewChk = new QCheckBox (tr("PREVIEW"), mySelGrp);
 
-  connect(myPreviewChk, SIGNAL(stateChanged(int)),    this, SLOT(onPreviewChk()));
-  connect(myUseDiagChk, SIGNAL(stateChanged(int)),    this, SLOT(onPreviewChk()));
-  connect(this,         SIGNAL(ListContensChanged()), this, SLOT(onPreviewChk()));
+  myCriterionGrp->show();
+  myGroupChoice->show();
+  myComboBoxFunctor->setEnabled(false);
+
+  connect(myPreviewChk     , SIGNAL(stateChanged(int))   , this, SLOT(onPreviewChk()));
+  connect(myGroupChoice    , SIGNAL(clicked(int))        , this, SLOT(onCriterionRB()));
+  connect(myComboBoxFunctor, SIGNAL(activated(int))      , this, SLOT(onPreviewChk()));
+  connect(this             , SIGNAL(ListContensChanged()), this, SLOT(onPreviewChk()));
+
+  myHelpFileName = "/files/cutting_quadrangles.htm";
 }
 
 SMESHGUI_CuttingOfQuadsDlg::~SMESHGUI_CuttingOfQuadsDlg()
@@ -1012,7 +1153,27 @@ void SMESHGUI_CuttingOfQuadsDlg::onClose()
 bool SMESHGUI_CuttingOfQuadsDlg::process (SMESH::SMESH_MeshEditor_ptr theEditor,
                                           const SMESH::long_array&    theIds)
 {
-  return theEditor->SplitQuad(theIds, !myUseDiagChk->isChecked());
+  switch (myGroupChoice->id(myGroupChoice->selected())) {
+  case 0: // use diagonal 1-3
+    return theEditor->SplitQuad(theIds, true);
+  case 1: // use diagonal 2-4
+    return theEditor->SplitQuad(theIds, false);
+  default: // use numeric functor
+    break;
+  }
+
+  SMESH::NumericalFunctor_var aCriterion = getNumericalFunctor();
+  return theEditor->QuadToTri(theIds, aCriterion);
+}
+
+void SMESHGUI_CuttingOfQuadsDlg::onCriterionRB()
+{
+  if (myGroupChoice->id(myGroupChoice->selected()) == 2) // Use numeric functor
+    myComboBoxFunctor->setEnabled(true);
+  else
+    myComboBoxFunctor->setEnabled(false);
+
+  onPreviewChk();
 }
 
 void SMESHGUI_CuttingOfQuadsDlg::onPreviewChk()
@@ -1032,7 +1193,7 @@ void SMESHGUI_CuttingOfQuadsDlg::erasePreview()
   myPreviewActor->Delete();
   myPreviewActor = 0;
 }
-
+  
 void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
 {
   if (myActor == 0)
@@ -1050,7 +1211,16 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
   if (aMesh == 0)
     return;
 
-  bool isDiag24 = myUseDiagChk->isChecked();
+  // 0 - use diagonal 1-3, 1 - use diagonal 2-4, 2 - use numerical functor
+  int aChoice = myGroupChoice->id(myGroupChoice->selected());
+  SMESH::NumericalFunctor_var aCriterion  = SMESH::NumericalFunctor::_nil();
+  SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH::SMESH_MeshEditor::_nil();
+  if (aChoice == 2) {
+    aCriterion  = getNumericalFunctor();
+    aMeshEditor = myMesh->GetMeshEditor();
+    if (aMeshEditor->_is_nil())
+      return;
+  }
 
   //Create grid
   vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
@@ -1082,8 +1252,9 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
 
     SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
     int k = 0;
-    while(anIter->more())
-      if (const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next())
+    while (anIter->more()) {
+      const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(anIter->next());
+      if (aNode)
       {
         if (!anIdToVtk.IsBound(aNode->GetID()))
         {
@@ -1093,11 +1264,33 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
 
         aNodes[ k++ ] = aNode->GetID();
       }
+    }
 
     if (k != 4)
       continue;
 
-    if (!isDiag24)
+    bool isDiag13 = true;
+    if (aChoice == 0) // use diagonal 1-3
+    {
+      isDiag13 = true;
+    }
+    else if (aChoice == 1) // use diagonal 2-4
+    {
+      isDiag13 = false;
+    }
+    else // use numerical functor
+    {
+      // compare two sets of possible triangles
+      int diag = aMeshEditor->BestSplit(anElemIds[i], aCriterion);
+      if (diag == 1) // 1-3
+        isDiag13 = true;
+      else if (diag == 2) // 2-4
+        isDiag13 = false;
+      else // error
+        continue;
+    }
+
+    if (isDiag13)
     {
       anIdList->SetId(0, anIdToVtk(aNodes[ 0 ]));
       anIdList->SetId(1, anIdToVtk(aNodes[ 1 ]));
@@ -1127,7 +1320,7 @@ void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
     }
   }
 
-  vtkIntArray* aCellLocationsArray = vtkIntArray::New();
+  VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
   aCellLocationsArray->SetNumberOfComponents(1);
   aCellLocationsArray->SetNumberOfTuples(aNbCells);