Salome HOME
INT PAL: 0052225: Failed mesh - number of isolines does not correspond to settings
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ComputeDlg.cxx
index 1d5555e7eb71f13c1274e12da6315e3efa7c1252..e99cf69b592378bf87049289742b059f487b82cf 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -33,6 +33,7 @@
 #include "SMESHGUI_MeshOrderOp.h"
 #include "SMESHGUI_MeshOrderDlg.h"
 
+#include "SMESH_Actor.h"
 #include "SMESH_ActorUtils.h"
 
 #include <SMDS_SetIterator.hxx>
@@ -61,6 +62,8 @@
 #include <SALOMEDSClient_SObject.hxx>
 #include <SALOMEDS_wrap.hxx>
 
+#include CORBA_SERVER_HEADER(SMESH_Group)
+
 // OCCT includes
 #include <BRep_Tool.hxx>
 #include <TopExp.hxx>
@@ -89,6 +92,7 @@
 #include <QButtonGroup>
 #include <QCloseEvent>
 #include <QTimerEvent>
+#include <QProgressBar>
 
 // VTK includes
 #include <vtkProperty.h>
 #include <vector>
 #include <set>
 
+#ifndef WIN32
+#include <sys/sysinfo.h>
+#endif
+
 #define SPACING 6
 #define MARGIN  11
 
 #define COLONIZE(str)   (QString(str).contains(":") > 0 ? QString(str) : QString(str) + " :" )
 
-/* OBSOLETE
-static void addSeparator( QWidget* parent )
-{
-  QGridLayout* l = qobject_cast<QGridLayout*>( parent->layout() );
-  int row  = l->rowCount();
-  int cols = l->columnCount();
-  for ( int i = 0; i < cols; i++ ) {
-    QFrame* hline = new QFrame( parent );
-    hline->setFrameStyle( QFrame::HLine | QFrame::Sunken );
-    l->addWidget( hline, row, i );
-  }
-}
-*/
-
 enum TCol {
   COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, COL_BAD_MESH, NB_COLUMNS
 };
@@ -204,6 +198,7 @@ namespace SMESH
     void Show( int subShapeID, GEOM::GEOM_Object_var aMainShape, bool only = false)
     {
       SVTK_ViewWindow* aViewWindow  = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() );
+      SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
       std::string mainEntry;
       if ( !aMainShape->_is_nil() )
         mainEntry = aMainShape->GetStudyEntry();
@@ -232,8 +227,13 @@ namespace SMESH
         TopAbs_ShapeEnum type( aShape.ShapeType() >= TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE );
         for ( TopExp_Explorer exp( aShape, type ); exp.More(); exp.Next() ) {
           //checkTriangulation( exp.Current() );
-          if ( GEOM_Actor* anActor = getActor( exp.Current() ))
+          if ( GEOM_Actor* anActor = getActor( exp.Current() ) ) {
+            int UNbIsos = resMgr->integerValue( "Geometry", "iso_number_u", 1);
+            int VNbIsos = resMgr->integerValue( "Geometry", "iso_number_v", 1);
+            int aNbIsos[2] = { UNbIsos ? UNbIsos : 1, VNbIsos ? VNbIsos : 1 };
+            anActor->SetNbIsos( aNbIsos );
             myShownActors.push_back( anActor );
+          }
         }
         if ( type == TopAbs_FACE ) {
           for ( TopExp_Explorer exp( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) {
@@ -349,12 +349,14 @@ namespace SMESH
       CASE2TEXT( COMPERR_BAD_SHAPE        );
       CASE2TEXT( COMPERR_CANCELED         );
       CASE2TEXT( COMPERR_NO_MESH_ON_SHAPE );
+      CASE2TEXT( COMPERR_BAD_PARMETERS    );
     case SMESH::COMPERR_ALGO_FAILED:
       if ( strlen(comment) == 0 )
         text = QObject::tr("COMPERR_ALGO_FAILED");
       break;
     case SMESH::COMPERR_WARNING:
-      return comment ? QString(comment) : QObject::tr("COMPERR_UNKNOWN");
+      text = QObject::tr( (comment && strlen(comment)) ? "COMPERR_WARNING" : "COMPERR_UNKNOWN");
+      break;
     default:
       text = QString("#%1").arg( -errCode );
     }
@@ -460,10 +462,12 @@ namespace SMESH
     foreach( range, selRanges )
     {
       for ( int row = range.topRow(); row <= range.bottomRow(); ++row )
-        rows.append( row );
+        if ( !rows.count( row ))
+             rows.append( row );
     }
     if ( rows.isEmpty() && table->currentRow() > -1 )
-      rows.append( table->currentRow() );
+      if ( !rows.count( table->currentRow() ))
+        rows.append( table->currentRow() );
 
     return rows.count();
   }
@@ -553,6 +557,7 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval)
   myShowBtn      = new QPushButton(tr("SHOW_SHAPE"), myCompErrorGroup);
   myPublishBtn   = new QPushButton(tr("PUBLISH_SHAPE"), myCompErrorGroup);
   myBadMeshBtn   = new QPushButton(tr("SHOW_BAD_MESH"), myCompErrorGroup);
+  myBadMeshToGroupBtn = new QPushButton(tr("GROUP_OF_BAD_MESH"), myCompErrorGroup);
 
   //myTable->setReadOnly( true ); // VSR: check
   myTable->setEditTriggers( QAbstractItemView::NoEditTriggers );
@@ -577,11 +582,12 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval)
   QGridLayout* grpLayout = new QGridLayout(myCompErrorGroup);
   grpLayout->setSpacing(SPACING);
   grpLayout->setMargin(MARGIN);
-  grpLayout->addWidget( myWarningLabel, 0, 0, 1, 4 );
-  grpLayout->addWidget( myTable,        1, 0, 1, 4 );
-  grpLayout->addWidget( myShowBtn,      2, 0 );
-  grpLayout->addWidget( myPublishBtn,   2, 1 );
-  grpLayout->addWidget( myBadMeshBtn,   2, 2 );
+  grpLayout->addWidget( myWarningLabel,      0, 0, 1, 4 );
+  grpLayout->addWidget( myTable,             1, 0, 1, 4 );
+  grpLayout->addWidget( myShowBtn,           2, 0 );
+  grpLayout->addWidget( myPublishBtn,        2, 1 );
+  grpLayout->addWidget( myBadMeshBtn,        2, 2 );
+  grpLayout->addWidget( myBadMeshToGroupBtn, 2, 3 );
   grpLayout->setColumnStretch( 3, 1 );
 
   // Hypothesis definition errors
@@ -733,25 +739,37 @@ SMESHGUI_ComputeDlg_QThreadQDialog::SMESHGUI_ComputeDlg_QThreadQDialog(QWidget
     qthread(gen, mesh, mainShape)
 {
   // --
-  setWindowTitle(tr("Compute"));
+  setWindowTitle(tr("TITLE"));
   setMinimumWidth( 200 );
 
-  cancelButton = new QPushButton(tr("Cancel"));
+  cancelButton = new QPushButton(tr("CANCEL"));
   cancelButton->setDefault(true);
+  cancelButton->setCheckable(true);
 
   QLabel * nbNodesName = new QLabel(tr("SMESH_MESHINFO_NODES"), this );
   QLabel * nbElemsName = new QLabel(tr("SMESH_MESHINFO_ELEMENTS"), this );
+  QLabel * freeRAMName = new QLabel(tr("SMESH_FREERAM"), this );
   nbNodesLabel = new QLabel("0", this );
   nbElemsLabel = new QLabel("0", this );
+  freeRAMLabel = new QLabel("", this );
+  progressBar  = new QProgressBar(this);
+  progressBar->setMinimum( 0 );
+  progressBar->setMaximum( 1000 );
 
   QGridLayout* layout = new QGridLayout(this);
   layout->setMargin( MARGIN );
   layout->setSpacing( SPACING );
-  layout->addWidget(nbNodesName,  0, 0);
-  layout->addWidget(nbNodesLabel, 0, 1);
-  layout->addWidget(nbElemsName,  1, 0);
-  layout->addWidget(nbElemsLabel, 1, 1);
-  layout->addWidget(cancelButton, 2, 0, 1, 2);
+  int row = 0;
+  layout->addWidget(nbNodesName,  row,   0);
+  layout->addWidget(nbNodesLabel, row++, 1);
+  layout->addWidget(nbElemsName,  row,   0);
+  layout->addWidget(nbElemsLabel, row++, 1);
+#ifndef WIN32
+  layout->addWidget(freeRAMName,  row,   0);
+  layout->addWidget(freeRAMLabel, row++, 1);
+#endif
+  layout->addWidget(progressBar,  row++, 0, 1, 2);
+  layout->addWidget(cancelButton, row++, 0, 1, 2);
   adjustSize();
   update();
 
@@ -769,23 +787,40 @@ bool SMESHGUI_ComputeDlg_QThreadQDialog::result()
 void SMESHGUI_ComputeDlg_QThreadQDialog::onCancel()
 {
   qthread.cancel();
-}  
+  cancelButton->setText( tr("CANCELING"));
+  cancelButton->setEnabled(false);
+}
 
 void SMESHGUI_ComputeDlg_QThreadQDialog::timerEvent(QTimerEvent *event)
 {
+  if ( !cancelButton->isChecked() ) // not yet cancelled
+    progressBar->setValue( progressBar->maximum() * qthread.getMesh()->GetComputeProgress() );
+
   if(qthread.isFinished())
-    {
-      close();
-    }
-  nbNodesLabel->setText( QString("%1").arg( qthread.getMesh()->NbNodes() ));
-  nbElemsLabel->setText( QString("%1").arg( qthread.getMesh()->NbElements() ));
+  {
+    close();
+  }
+  else
+  {
+    nbNodesLabel->setText( QString("%1").arg( qthread.getMesh()->NbNodes() ));
+    nbElemsLabel->setText( QString("%1").arg( qthread.getMesh()->NbElements() ));
+#ifndef WIN32
+    struct sysinfo si;
+    const int err = sysinfo( &si );
+    if ( err )
+      freeRAMLabel->setText("");
+    else
+      freeRAMLabel->setText( tr("SMESH_GIGABYTE").arg
+                             ( si.freeram * si.mem_unit /1024./1024./1024., 0, 'f', 2 ));
+#endif
+  }
   event->accept();
 }
 
 void SMESHGUI_ComputeDlg_QThreadQDialog::closeEvent(QCloseEvent *event)
 {
   if(qthread.isRunning())
-    {
+  {
       event->ignore();
       return;
     }
@@ -832,19 +867,11 @@ void SMESHGUI_BaseComputeOp::computeMesh()
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
       OCC_CATCH_SIGNALS;
 #endif
-      //SMESH::UpdateNulData(myIObject, true);
-      bool res;
-#ifdef WITH_SMESH_CANCEL_COMPUTE
       SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myMainShape);
       qthreaddialog.exec();
-      res = qthreaddialog.result();
-#else
-      res = gen->Compute(myMesh, myMainShape);
-#endif
-      if (res)
-        computeFailed = false;
+      computeFailed = !qthreaddialog.result();
     }
-    catch(const SALOME::SALOME_Exception & S_ex){
+    catch(const SALOME::SALOME_Exception & S_ex) {
       memoryLack = true;
     }
     try {
@@ -856,7 +883,7 @@ void SMESHGUI_BaseComputeOp::computeMesh()
       for ( int i = 0; (i < aCompErrors->length()) && !memoryLack; ++i )
         memoryLack = ( aCompErrors[ i ].code == SMESH::COMPERR_MEMORY_PB );
     }
-    catch(const SALOME::SALOME_Exception & S_ex){
+    catch(const SALOME::SALOME_Exception & S_ex) {
       memoryLack = true;
     }
 
@@ -872,17 +899,39 @@ void SMESHGUI_BaseComputeOp::computeMesh()
       // SHOW MESH
       // NPAL16631: if ( getSMESHGUI()->automaticUpdate() )
       SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() );
-      long newSize = myMesh->NbElements();
       bool limitExceeded;
+      long limitSize = resMgr->integerValue( "SMESH", "update_limit", 500000 );
+      int entities = SMESH_Actor::eAllEntity;
+      int hidden = 0;
       if ( !memoryLack )
       {
-        if ( getSMESHGUI()->automaticUpdate( newSize, &limitExceeded ) )
+        if ( getSMESHGUI()->automaticUpdate( myMesh, &entities, &limitExceeded, &hidden ) )
         {
           try {
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
             OCC_CATCH_SIGNALS;
 #endif
+            SMESH_Actor *anActor = SMESH::FindActorByObject( myMesh );
+            if ( !anActor ) anActor = SMESH::CreateActor( aMeshSObj->GetStudy(), aMeshSObj->GetID().c_str(), true );    
+            if ( anActor ) // actor is not created for an empty mesh
+            {
+              anActor->SetEntityMode( entities );
+              SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
+            }
             SMESH::Update(myIObject, true);
+
+            if ( limitExceeded )
+            {
+              QStringList hiddenMsg;
+              if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" );
+              if ( hidden & SMESH_Actor::eEdges )      hiddenMsg << tr( "SMESH_EDGES" );
+              if ( hidden & SMESH_Actor::eFaces )      hiddenMsg << tr( "SMESH_FACES" );
+              if ( hidden & SMESH_Actor::eVolumes )    hiddenMsg << tr( "SMESH_VOLUMES" );
+              if ( hidden & SMESH_Actor::eBallElem )   hiddenMsg << tr( "SMESH_BALLS" );
+              SUIT_MessageBox::warning( desktop(),
+                                        tr( "SMESH_WRN_WARNING" ),
+                                        tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ).arg( myMesh->NbElements() ).arg( limitSize ).arg( hiddenMsg.join(", ") ) );
+            }
           }
           catch (...) {
 #ifdef _DEBUG_
@@ -898,10 +947,9 @@ void SMESHGUI_BaseComputeOp::computeMesh()
         }
         else if ( limitExceeded )
         {
-          long limitSize = resMgr->integerValue( "SMESH", "update_limit", 500000 );
           SUIT_MessageBox::warning( desktop(),
                                     tr( "SMESH_WRN_WARNING" ),
-                                    tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( newSize ).arg( limitSize ) );
+                                    tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ).arg( myMesh->NbElements() ).arg( limitSize ) );
         }
       }
       LightApp_SelectionMgr *Sel = selectionMgr();
@@ -1072,11 +1120,14 @@ void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack,
       tbl->resizeColumnToContents( COL_SHAPE );
       tbl->setWordWrap( true );
 
-      if ( hasBadMesh )
+      if ( hasBadMesh ) {
         aCompDlg->myBadMeshBtn->show();
-      else
+        aCompDlg->myBadMeshToGroupBtn->show();
+      }
+      else {
         aCompDlg->myBadMeshBtn->hide();
-
+        aCompDlg->myBadMeshToGroupBtn->hide();
+      }
       tbl->setCurrentCell(0,0);
       currentCellChanged(); // to update buttons
     }
@@ -1180,8 +1231,8 @@ void SMESHGUI_BaseComputeOp::onShowBadMesh()
       if ( myBadMeshDisplayer ) delete myBadMeshDisplayer;
       myBadMeshDisplayer = new SMESHGUI_MeshEditPreview( view );
       SMESH::MeshPreviewStruct_var aMeshData = gen->GetBadInputElements(myMesh,curSub);
-      vtkFloatingPointType aPointSize = SMESH::GetFloat("SMESH:node_size",3);
-      vtkFloatingPointType aLineWidth = SMESH::GetFloat("SMESH:element_width",1);
+      double aPointSize = SMESH::GetFloat("SMESH:node_size",3);
+      double aLineWidth = SMESH::GetFloat("SMESH:element_width",1);
       vtkProperty* prop = vtkProperty::New();
       prop->SetLineWidth( aLineWidth * 3 );
       prop->SetPointSize( aPointSize * 3 );
@@ -1193,6 +1244,43 @@ void SMESHGUI_BaseComputeOp::onShowBadMesh()
   }
 }
 
+//================================================================================
+/*!
+ * \brief create groups of bad mesh elements preventing computation of a submesh of current row
+ */
+//================================================================================
+
+void SMESHGUI_BaseComputeOp::onGroupOfBadMesh()
+{
+  QList<int> rows;
+  SMESH::getSelectedRows( table(), rows );
+  int row;
+  foreach ( row, rows )
+  {
+    bool hasBadMesh = ( !table()->item(row, COL_BAD_MESH)->text().isEmpty() );
+    if ( hasBadMesh ) {
+      int     curSub = table()->item(rows.front(), COL_SHAPEID)->text().toInt();
+      QString grName = table()->item(rows.front(), COL_SHAPE)->text();
+      if ( grName.isEmpty() ) grName = "bad mesh";
+      else                    grName = "bad mesh of " + grName;
+      SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen();
+      SMESH::ListOfGroups_var groups
+        ( gen->MakeGroupsOfBadInputElements(myMesh,curSub,grName.toLatin1().data()) );
+      update( UF_ObjBrowser | UF_Model );
+      if( LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( application() ))
+      {
+        QStringList anEntryList;
+        for ( size_t i = 0; i < groups->length(); ++i )
+          if ( _PTR(SObject) so = SMESH::FindSObject( groups[i] ))
+            anEntryList.append( so->GetID().c_str() );
+
+        if ( !anEntryList.isEmpty())
+          anApp->browseObjects( anEntryList, true, false );
+      }
+    }
+  }
+}
+
 //================================================================================
 /*!
  * \brief SLOT called when a selected cell in table() changed
@@ -1232,6 +1320,7 @@ void SMESHGUI_BaseComputeOp::currentCellChanged()
   myCompDlg->myPublishBtn->setEnabled( publishEnable );
   myCompDlg->myShowBtn   ->setEnabled( showEnable );
   myCompDlg->myBadMeshBtn->setEnabled( hasBadMesh && ( nbSelected == 1 ));
+  myCompDlg->myBadMeshToGroupBtn->setEnabled( hasBadMesh && ( nbSelected == 1 ));
 }
 
 //================================================================================
@@ -1291,9 +1380,10 @@ SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::computeDlg() const
     SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this;
     me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), false );
     // connect signals and slots
-    connect(myCompDlg->myShowBtn,    SIGNAL (clicked()), SLOT(onPreviewShape()));
-    connect(myCompDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape()));
-    connect(myCompDlg->myBadMeshBtn, SIGNAL (clicked()), SLOT(onShowBadMesh()));
+    connect(myCompDlg->myShowBtn,           SIGNAL (clicked()), SLOT(onPreviewShape()));
+    connect(myCompDlg->myPublishBtn,        SIGNAL (clicked()), SLOT(onPublishShape()));
+    connect(myCompDlg->myBadMeshBtn,        SIGNAL (clicked()), SLOT(onShowBadMesh()));
+    connect(myCompDlg->myBadMeshToGroupBtn, SIGNAL (clicked()), SLOT(onGroupOfBadMesh()));
 
     QTableWidget* aTable = me->table();
     connect(aTable, SIGNAL(itemSelectionChanged()), SLOT(currentCellChanged()));
@@ -2127,10 +2217,15 @@ void SMESHGUI_BaseComputeOp::showEvaluateResult(const SMESH::long_array& theRes,
       tbl->setWordWrap( true );
 
       if ( hasBadMesh )
+      {
         aCompDlg->myBadMeshBtn->show();
+        aCompDlg->myBadMeshToGroupBtn->show();
+      }
       else
+      {
         aCompDlg->myBadMeshBtn->hide();
-
+        aCompDlg->myBadMeshToGroupBtn->hide();
+      }
       tbl->setCurrentCell(0,0);
       currentCellChanged(); // to update buttons
     }