]> SALOME platform Git repositories - plugins/netgenplugin.git/commitdiff
Salome HOME
0021271: [CEA 473] Implement min size in netgen plugin
authoreap <eap@opencascade.com>
Tue, 5 Jul 2011 08:46:19 +0000 (08:46 +0000)
committereap <eap@opencascade.com>
Tue, 5 Jul 2011 08:46:19 +0000 (08:46 +0000)
12 files changed:
idl/NETGENPlugin_Algorithm.idl
src/GUI/NETGENPluginGUI_HypothesisCreator.cxx
src/GUI/NETGENPluginGUI_HypothesisCreator.h
src/GUI/NETGENPlugin_msg_en.ts
src/NETGENPlugin/NETGENPlugin_Hypothesis.cxx
src/NETGENPlugin/NETGENPlugin_Hypothesis.hxx
src/NETGENPlugin/NETGENPlugin_Hypothesis_i.cxx
src/NETGENPlugin/NETGENPlugin_Hypothesis_i.hxx
src/NETGENPlugin/NETGENPlugin_Mesher.cxx
src/NETGENPlugin/NETGENPlugin_Mesher.hxx
src/NETGENPlugin/NETGENPlugin_NETGEN_2D_ONLY.cxx
src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx

index 344b112ec379f5aa974f26999f2cacd8b5811416..7603725fef718fc3bb05dfadfc142961a32cf22f 100644 (file)
@@ -75,6 +75,9 @@ module NETGENPlugin
     void SetMaxSize(in double value);
     double GetMaxSize();
 
+    void SetMinSize(in double value);
+    double GetMinSize();
+
     void SetSecondOrder(in boolean value);
     boolean GetSecondOrder();
 
index 775c7df6c27228c89bc2d482f24325c1615cebc5..23433fdb2690ef3c844891edde76901bc614f49e 100644 (file)
@@ -110,6 +110,7 @@ bool NETGENPluginGUI_HypothesisCreator::checkParams(QString& msg) const
   storeParamsToHypo( data_old );
   
   res = myMaxSize->isValid(msg,true) && res;
+  res = myMinSize->isValid(msg,true) && res;
   res = myGrowthRate->isValid(msg,true) && res; ;
   if ( myNbSegPerEdge )
     res = myNbSegPerEdge->isValid(msg,true) && res;
@@ -154,6 +155,12 @@ QFrame* NETGENPluginGUI_HypothesisCreator::buildFrame()
   aGroupLayout->addWidget( myMaxSize, row, 1 );
   row++;
 
+  aGroupLayout->addWidget( new QLabel( tr( "NETGEN_MIN_SIZE" ), GroupC1 ), row, 0 );
+  myMinSize = new SMESHGUI_SpinBox( GroupC1 );
+  myMinSize->RangeStepAndValidator( 0.0, 1e+06, 10., "length_precision" );
+  aGroupLayout->addWidget( myMinSize, row, 1 );
+  row++;
+
   mySecondOrder = 0;
   if ( !myIsONLY )
   {
@@ -272,6 +279,11 @@ void NETGENPluginGUI_HypothesisCreator::retrieveParams() const
   else
     myMaxSize->setText( data.myMaxSizeVar );
 
+  if(data.myMinSizeVar.isEmpty())
+    myMinSize->setValue( data.myMinSize );
+  else
+    myMinSize->setText( data.myMinSizeVar );
+
   if ( mySecondOrder )
     mySecondOrder->setChecked( data.mySecondOrder );
   if ( myOptimize )
@@ -339,6 +351,7 @@ QString NETGENPluginGUI_HypothesisCreator::storeParams() const
   storeParamsToHypo( data );
   
   QString valStr = tr("NETGEN_MAX_SIZE") + " = " + QString::number( data.myMaxSize ) + "; ";
+  valStr += tr("NETGEN_MIN_SIZE") + " = " + QString::number( data.myMinSize ) + "; ";
   if ( data.mySecondOrder )
     valStr +=  tr("NETGEN_SECOND_ORDER") + "; ";
   if ( data.myOptimize )
@@ -375,6 +388,8 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromHypo( NetgenHypothesisData
   h_data.myNbSegPerEdgeVar  = (aParameters->length() > 2) ? QString(aParameters[2].in()) : QString("");
   h_data.myNbSegPerRadius = h->GetNbSegPerRadius();
   h_data.myNbSegPerRadiusVar = (aParameters->length() > 3) ? QString(aParameters[3].in()) : QString("");
+  h_data.myMinSize = h->GetMinSize();
+  h_data.myMinSizeVar = (aParameters->length() > 4) ? QString(aParameters[4].in()) : QString("");
 
   if ( myIs2D )
     {
@@ -435,6 +450,8 @@ bool NETGENPluginGUI_HypothesisCreator::storeParamsToHypo( const NetgenHypothesi
         aVariablesList.append(h_data.myNbSegPerEdgeVar);
         aVariablesList.append(h_data.myNbSegPerRadiusVar);
       }
+    h->SetMinSize( h_data.myMinSize );
+    aVariablesList.append(h_data.myMinSizeVar);
     
     if ( myIs2D )
       {
@@ -452,6 +469,7 @@ bool NETGENPluginGUI_HypothesisCreator::storeParamsToHypo( const NetgenHypothesi
         h->SetParameters(aVariablesList.join(":").toLatin1().constData());
         h->SetParameters(aVariablesList.join(":").toLatin1().constData());
       }
+    h->SetParameters(aVariablesList.join(":").toLatin1().constData());
 
     QMapIterator<QString,QString> i(myLocalSizeMap);
     while (i.hasNext()) {
@@ -484,6 +502,8 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromWidgets( NetgenHypothesisD
   h_data.myName           = myName ? myName->text() : "";
   h_data.myMaxSize        = myMaxSize->value();
   h_data.myMaxSizeVar     = myMaxSize->text();
+  h_data.myMinSize        = myMinSize->value();
+  h_data.myMinSizeVar     = myMinSize->text();
   if ( mySecondOrder )
     h_data.mySecondOrder  = mySecondOrder->isChecked();
   if ( myOptimize )
index 61bba9b860532aa25d703318c8097063aca42d95..a4d832a016bd4048a19872e11db39013095744a0 100644 (file)
@@ -44,11 +44,11 @@ class QTableWidget;
 
 typedef struct
 {
-  double              myMaxSize, myGrowthRate, myNbSegPerEdge, myNbSegPerRadius;
+  double              myMaxSize, myMinSize, myGrowthRate, myNbSegPerEdge, myNbSegPerRadius;
   int                 myFineness;
   bool                mySecondOrder, myAllowQuadrangles, myOptimize;
   QString             myName;
-  QString             myMaxSizeVar, myGrowthRateVar, myNbSegPerEdgeVar, myNbSegPerRadiusVar;
+  QString             myMaxSizeVar, myMinSizeVar, myGrowthRateVar, myNbSegPerEdgeVar, myNbSegPerRadiusVar;
 } NetgenHypothesisData;
 
 /*!
@@ -92,6 +92,7 @@ private:
 private:
  QLineEdit*        myName;
  SMESHGUI_SpinBox* myMaxSize;
+ SMESHGUI_SpinBox* myMinSize;
  QCheckBox*        mySecondOrder;
  QCheckBox*        myOptimize;
  QComboBox*        myFineness;
index dd9dd707dafa25da7e82f0df9a136a632b583739..55e4cebec3c31296d4bd504e48be49c4a1a55aca 100644 (file)
         <source>NETGEN_MAX_SIZE</source>
         <translation>Max. Size</translation>
     </message>
+    <message>
+        <source>NETGEN_MIN_SIZE</source>
+        <translation>Min. Size</translation>
+    </message>
     <message>
         <source>NETGEN_MODERATE</source>
         <translation>Moderate</translation>
index 0644102f8f42067de90d4d347b33005eb730ca8e..973906322b05dd6cfd2c9e87a75e6221f7264e38 100644 (file)
 // Project   : SALOME
 //
 #include "NETGENPlugin_Hypothesis.hxx"
+
+#include "NETGENPlugin_Mesher.hxx"
+#include "SMESH_Mesh.hxx"
+
 #include <utilities.h>
 
 using namespace std;
@@ -40,6 +44,7 @@ NETGENPlugin_Hypothesis::NETGENPlugin_Hypothesis (int hypId, int studyId,
                                                   SMESH_Gen * gen)
   : SMESH_Hypothesis(hypId, studyId, gen),
     _maxSize       (GetDefaultMaxSize()),
+    _minSize       (0),
     _growthRate    (GetDefaultGrowthRate()),
     _nbSegPerEdge  (GetDefaultNbSegPerEdge()),
     _nbSegPerRadius(GetDefaultNbSegPerRadius()),
@@ -67,6 +72,20 @@ void NETGENPlugin_Hypothesis::SetMaxSize(double theSize)
   }
 }
 
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+void NETGENPlugin_Hypothesis::SetMinSize(double theSize)
+{
+  if (theSize != _minSize)
+  {
+    _minSize = theSize;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
 //=============================================================================
 /*!
  *  
@@ -248,6 +267,7 @@ ostream & NETGENPlugin_Hypothesis::SaveTo(ostream & save)
     }
     save << " " << "__LOCALSIZE_END__";
   }
+  save << " " << _minSize;
 
   return save;
 }
@@ -332,6 +352,9 @@ istream & NETGENPlugin_Hypothesis::LoadFrom(istream & load)
     }
   }
 
+  if ( !hasLocalSize && !option_or_sm.empty() )
+    _minSize = atof( option_or_sm.c_str() );
+
   return load;
 }
 
@@ -378,10 +401,16 @@ bool NETGENPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh*   theMesh,
 //================================================================================
 
 bool NETGENPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
-                                                      const SMESH_Mesh* /*theMesh*/)
+                                                      const SMESH_Mesh* theMesh)
 {
   _nbSegPerEdge = dflts._nbSegments;
   _maxSize      = dflts._elemLength;
+
+  if ( dflts._shape && !dflts._shape->IsNull() )
+    _minSize    = NETGENPlugin_Mesher::GetDefaultMinSize( *dflts._shape, _maxSize );
+  else if ( theMesh && theMesh->HasShapeToMesh() )
+    _minSize    = NETGENPlugin_Mesher::GetDefaultMinSize( theMesh->GetShapeToMesh(), _maxSize );
+
   return _nbSegPerEdge && _maxSize > 0;
 }
 
index d025bdafc7f01105bfd2a58cb75306f4618a3ee7..ac397320b48a036d9ea896a9ea483ef21e3082b3 100644 (file)
@@ -50,6 +50,9 @@ public:
   void SetMaxSize(double theSize);
   double GetMaxSize() const { return _maxSize; }
 
+  void SetMinSize(double theSize);
+  double GetMinSize() const { return _minSize; }
+
   void SetSecondOrder(bool theVal);
   bool GetSecondOrder() const { return _secondOrder; }
 
@@ -118,7 +121,7 @@ public:
   virtual bool SetParametersByDefaults(const TDefaults& dflts, const SMESH_Mesh* theMesh=0);
 
 private:
-  double        _maxSize;
+  double        _maxSize, _minSize;
   double        _growthRate;
   double        _nbSegPerEdge;
   double        _nbSegPerRadius;
index d5464a990083d278476ecfdc44c5075dda7463a5..cd34d09d12ca1c8a2b85eb5ac356caee3c5f4f99 100644 (file)
@@ -99,6 +99,35 @@ CORBA::Double NETGENPlugin_Hypothesis_i::GetMaxSize()
   return this->GetImpl()->GetMaxSize();
 }
 
+//=============================================================================
+/*!
+ *  NETGENPlugin_Hypothesis_i::SetMinSize
+ *
+ *  Set MinSize
+ */
+//=============================================================================
+void NETGENPlugin_Hypothesis_i::SetMinSize (CORBA::Double theValue)
+{
+  MESSAGE("NETGENPlugin_Hypothesis_i::SetMinSize");
+  ASSERT(myBaseImpl);
+  this->GetImpl()->SetMinSize(theValue);
+  SMESH::TPythonDump() << _this() << ".SetMinSize( " << theValue << " )";
+}
+
+//=============================================================================
+/*!
+ *  NETGENPlugin_Hypothesis_i::GetMinSize
+ *
+ *  Get MinSize
+ */
+//=============================================================================
+CORBA::Double NETGENPlugin_Hypothesis_i::GetMinSize()
+{
+  MESSAGE("NETGENPlugin_Hypothesis_i::GetMinSize");
+  ASSERT(myBaseImpl);
+  return this->GetImpl()->GetMinSize();
+}
+
 //=============================================================================
 /*!
  *  NETGENPlugin_Hypothesis_i::SetSecondOrder
index dc2a911b152e24db9e829c2f29a0ea3e34d332e0..b8737ab99c202147c580372d6bab8eba5a44c6e3 100644 (file)
@@ -25,7 +25,6 @@
 // Author    : Michael Sazonov (OCN)
 // Date      : 03/04/2006
 // Project   : SALOME
-// $Header$
 //=============================================================================
 //
 #ifndef _NETGENPlugin_Hypothesis_i_HXX_
@@ -59,6 +58,9 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Hypothesis_i:
   void SetMaxSize(CORBA::Double theSize);
   CORBA::Double GetMaxSize();
 
+  void SetMinSize(CORBA::Double theSize);
+  CORBA::Double GetMinSize();
+
   void SetSecondOrder(CORBA::Boolean theVal);
   CORBA::Boolean GetSecondOrder();
 
index 28ecc7634f86c0719b7a0ea672528b91948b8db2..f382364a49c74df0ac8917ec005fd77db600536d 100644 (file)
@@ -49,6 +49,9 @@
 #include <limits>
 
 #include <BRep_Tool.hxx>
+#include <Bnd_B3d.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <GeomAdaptor_Curve.hxx>
 #include <NCollection_Map.hxx>
 #include <OSD_File.hxx>
 #include <OSD_Path.hxx>
@@ -64,8 +67,6 @@
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
-#include <GeomAdaptor_Curve.hxx>
-#include <GCPnts_AbscissaPoint.hxx>
 
 // Netgen include files
 #ifndef OCCGEOMETRY
@@ -138,6 +139,7 @@ void NETGENPlugin_Mesher::defaultParameters()
   netgen::MeshingParameters& mparams = netgen::mparam;
   // maximal mesh edge size
   mparams.maxh = NETGENPlugin_Hypothesis::GetDefaultMaxSize();
+  mparams.maxh = 0;
   // minimal number of segments per edge
   mparams.segmentsperedge = NETGENPlugin_Hypothesis::GetDefaultNbSegPerEdge();
   // rate of growth of size between elements
@@ -276,136 +278,6 @@ Standard_Boolean IsEqual(const Link& aLink1, const Link& aLink2)
           aLink1.n1 == aLink2.n2 && aLink1.n2 == aLink2.n1);
 }
 
-//================================================================================
-/*!
- * \brief Initialize netgen::OCCGeometry with OCCT shape
- */
-//================================================================================
-
-void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry&     occgeo,
-                                             const TopoDS_Shape&      shape,
-                                             SMESH_Mesh&              mesh,
-                                             list< SMESH_subMesh* > * meshedSM,
-                                             NETGENPlugin_Internals*  intern)
-{
-  BRepTools::Clean (shape);
-  try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
-    OCC_CATCH_SIGNALS;
-#endif
-    BRepMesh_IncrementalMesh e(shape, 0.01, true);
-  } catch (Standard_Failure) {
-  }
-  Bnd_Box bb;
-  BRepBndLib::Add (shape, bb);
-  double x1,y1,z1,x2,y2,z2;
-  bb.Get (x1,y1,z1,x2,y2,z2);
-  MESSAGE("shape bounding box:\n" <<
-          "(" << x1 << " " << y1 << " " << z1 << ") " <<
-          "(" << x2 << " " << y2 << " " << z2 << ")");
-  netgen::Point<3> p1 = netgen::Point<3> (x1,y1,z1);
-  netgen::Point<3> p2 = netgen::Point<3> (x2,y2,z2);
-  occgeo.boundingbox = netgen::Box<3> (p1,p2);
-
-  occgeo.shape = shape;
-  occgeo.changed = 1;
-
-  // fill maps of shapes of occgeo with not yet meshed subshapes
-
-  // get root submeshes
-  list< SMESH_subMesh* > rootSM;
-  if ( SMESH_subMesh* sm = mesh.GetSubMeshContaining( shape )) {
-    rootSM.push_back( sm );
-  }
-  else {
-    for ( TopoDS_Iterator it( shape ); it.More(); it.Next() )
-      rootSM.push_back( mesh.GetSubMesh( it.Value() ));
-  }
-
-  // add subshapes of empty submeshes
-  list< SMESH_subMesh* >::iterator rootIt = rootSM.begin(), rootEnd = rootSM.end();
-  for ( ; rootIt != rootEnd; ++rootIt ) {
-    SMESH_subMesh * root = *rootIt;
-    SMESH_subMeshIteratorPtr smIt = root->getDependsOnIterator(/*includeSelf=*/true,
-                                                               /*complexShapeFirst=*/true);
-    // to find a right orientation of subshapes (PAL20462)
-    TopTools_IndexedMapOfShape subShapes;
-    TopExp::MapShapes(root->GetSubShape(), subShapes);
-    while ( smIt->more() )
-    {
-      SMESH_subMesh* sm = smIt->next();
-      TopoDS_Shape shape = sm->GetSubShape();
-      if ( intern && intern->isShapeToPrecompute( shape ))
-        continue;
-      if ( !meshedSM || sm->IsEmpty() )
-      {
-        if ( shape.ShapeType() != TopAbs_VERTEX )
-          shape = subShapes( subShapes.FindIndex( shape ));// shape -> index -> oriented shape
-        if ( shape.Orientation() >= TopAbs_INTERNAL )
-          shape.Orientation( TopAbs_FORWARD ); // isuue 0020676
-        switch ( shape.ShapeType() ) {
-        case TopAbs_FACE  : occgeo.fmap.Add( shape ); break;
-        case TopAbs_EDGE  : occgeo.emap.Add( shape ); break;
-        case TopAbs_VERTEX: occgeo.vmap.Add( shape ); break;
-        case TopAbs_SOLID :occgeo.somap.Add( shape ); break;
-        default:;
-        }
-      }
-      // collect submeshes of meshed shapes
-      else if (meshedSM)
-      {
-        const int dim = SMESH_Gen::GetShapeDim( shape );
-        meshedSM[ dim ].push_back( sm );
-      }
-    }
-  }
-  occgeo.facemeshstatus.SetSize (occgeo.fmap.Extent());
-  occgeo.facemeshstatus = 0;
-#ifdef NETGEN_NEW
-  occgeo.face_maxh.SetSize(occgeo.fmap.Extent());
-  occgeo.face_maxh = netgen::mparam.maxh;
-  occgeo.face_maxh_modified.SetSize(occgeo.fmap.Extent());
-  occgeo.face_maxh_modified = 0;
-#endif
-
-  // { // set netgen::mparam.minh
-
-//     TopLoc_Location loc;
-//     int i1, i2, i3;
-//     const int* pi[4] = { &i1, &i2, &i3, &i1 };
-//     double maxh = 1e100;
-//     for ( int i = 0; i < occgeo.fmap.Extent(); ++i )
-//     {
-//       Handle(Poly_Triangulation) triangulation =
-//         BRep_Tool::Triangulation ( TopoDS::Face( occgeo.fmap(i+1) ), loc);
-//       if ( triangulation.IsNull() ) continue;
-//       const TColgp_Array1OfPnt&   points = triangulation->Nodes();
-//       const Poly_Array1OfTriangle& trias = triangulation->Triangles();
-//       for ( int iT = trias.Lower(); iT <= trias.Upper(); ++iT )
-//       {
-//         trias(iT).Get( i1, i2, i3 );
-//         for ( int j = 0; j < 3; ++j )
-//         {
-//           double dist2 = points(*pi[j]).SquareDistance( points( *pi[j+1] ));
-//           if ( dist2 < maxh )
-//             maxh = dist2;
-//         }
-//       }
-//     }
-//     maxh = sqrt( maxh );
-//     if ( maxh > 0.5 * occgeo.boundingbox.Diam() ) // no or too rough triangulation
-//     {
-//       netgen::mparam.minh = occgeo.boundingbox.Diam()*1e-24;
-//       cout << "DEFAULT mparams.minh = " <<netgen::mparam.minh << endl;
-//     }
-//     else
-//     {
-//       netgen::mparam.minh = maxh * 2;
-//       cout << "TRIANGULATION mparams.minh = " <<netgen::mparam.minh << endl;
-//     }
-//   }
-}
-
 namespace
 {
   //================================================================================
@@ -532,6 +404,179 @@ namespace
     }
     return edges;
   }
+
+  //================================================================================
+  /*!
+   * \brief Make triangulation of a shape precise enough
+   */
+  //================================================================================
+
+  void updateTriangulation( const TopoDS_Shape& shape )
+  {
+    static set< Poly_Triangulation* > updated;
+
+    TopLoc_Location loc;
+    TopExp_Explorer fExp( shape, TopAbs_FACE );
+    for ( ; fExp.More(); fExp.Next() )
+    {
+      Handle(Poly_Triangulation) triangulation =
+        BRep_Tool::Triangulation ( TopoDS::Face( fExp.Current() ), loc);
+      if ( triangulation.IsNull() ||
+           updated.insert( triangulation.operator->() ).second )
+      {
+        BRepTools::Clean (shape);
+        try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+          OCC_CATCH_SIGNALS;
+#endif
+          BRepMesh_IncrementalMesh e(shape, 0.01, true);
+        }
+        catch (Standard_Failure)
+        {
+          updated.erase( triangulation.operator->() );
+        }
+      }
+    }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Initialize netgen::OCCGeometry with OCCT shape
+ */
+//================================================================================
+
+void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry&     occgeo,
+                                             const TopoDS_Shape&      shape,
+                                             SMESH_Mesh&              mesh,
+                                             list< SMESH_subMesh* > * meshedSM,
+                                             NETGENPlugin_Internals*  intern)
+{
+  updateTriangulation( shape );
+
+  Bnd_Box bb;
+  BRepBndLib::Add (shape, bb);
+  double x1,y1,z1,x2,y2,z2;
+  bb.Get (x1,y1,z1,x2,y2,z2);
+  MESSAGE("shape bounding box:\n" <<
+          "(" << x1 << " " << y1 << " " << z1 << ") " <<
+          "(" << x2 << " " << y2 << " " << z2 << ")");
+  netgen::Point<3> p1 = netgen::Point<3> (x1,y1,z1);
+  netgen::Point<3> p2 = netgen::Point<3> (x2,y2,z2);
+  occgeo.boundingbox = netgen::Box<3> (p1,p2);
+
+  occgeo.shape = shape;
+  occgeo.changed = 1;
+
+  // fill maps of shapes of occgeo with not yet meshed subshapes
+
+  // get root submeshes
+  list< SMESH_subMesh* > rootSM;
+  if ( SMESH_subMesh* sm = mesh.GetSubMeshContaining( shape )) {
+    rootSM.push_back( sm );
+  }
+  else {
+    for ( TopoDS_Iterator it( shape ); it.More(); it.Next() )
+      rootSM.push_back( mesh.GetSubMesh( it.Value() ));
+  }
+
+  // add subshapes of empty submeshes
+  list< SMESH_subMesh* >::iterator rootIt = rootSM.begin(), rootEnd = rootSM.end();
+  for ( ; rootIt != rootEnd; ++rootIt ) {
+    SMESH_subMesh * root = *rootIt;
+    SMESH_subMeshIteratorPtr smIt = root->getDependsOnIterator(/*includeSelf=*/true,
+                                                               /*complexShapeFirst=*/true);
+    // to find a right orientation of subshapes (PAL20462)
+    TopTools_IndexedMapOfShape subShapes;
+    TopExp::MapShapes(root->GetSubShape(), subShapes);
+    while ( smIt->more() )
+    {
+      SMESH_subMesh* sm = smIt->next();
+      TopoDS_Shape shape = sm->GetSubShape();
+      if ( intern && intern->isShapeToPrecompute( shape ))
+        continue;
+      if ( !meshedSM || sm->IsEmpty() )
+      {
+        if ( shape.ShapeType() != TopAbs_VERTEX )
+          shape = subShapes( subShapes.FindIndex( shape ));// shape -> index -> oriented shape
+        if ( shape.Orientation() >= TopAbs_INTERNAL )
+          shape.Orientation( TopAbs_FORWARD ); // isuue 0020676
+        switch ( shape.ShapeType() ) {
+        case TopAbs_FACE  : occgeo.fmap.Add( shape ); break;
+        case TopAbs_EDGE  : occgeo.emap.Add( shape ); break;
+        case TopAbs_VERTEX: occgeo.vmap.Add( shape ); break;
+        case TopAbs_SOLID :occgeo.somap.Add( shape ); break;
+        default:;
+        }
+      }
+      // collect submeshes of meshed shapes
+      else if (meshedSM)
+      {
+        const int dim = SMESH_Gen::GetShapeDim( shape );
+        meshedSM[ dim ].push_back( sm );
+      }
+    }
+  }
+  occgeo.facemeshstatus.SetSize (occgeo.fmap.Extent());
+  occgeo.facemeshstatus = 0;
+#ifdef NETGEN_NEW
+  occgeo.face_maxh.SetSize(occgeo.fmap.Extent());
+  occgeo.face_maxh = netgen::mparam.maxh;
+  occgeo.face_maxh_modified.SetSize(occgeo.fmap.Extent());
+  occgeo.face_maxh_modified = 0;
+#endif
+}
+
+//================================================================================
+/*!
+ * \brief Return a default min size value suitable for the given geometry.
+ */
+//================================================================================
+
+double NETGENPlugin_Mesher::GetDefaultMinSize(const TopoDS_Shape& geom,
+                                              const double        maxSize)
+{
+  updateTriangulation( geom );
+
+  TopLoc_Location loc;
+  int i1, i2, i3;
+  const int* pi[4] = { &i1, &i2, &i3, &i1 };
+  double minh = 1e100;
+  Bnd_B3d bb;
+  TopExp_Explorer fExp( geom, TopAbs_FACE );
+  for ( ; fExp.More(); fExp.Next() )
+  {
+    Handle(Poly_Triangulation) triangulation =
+      BRep_Tool::Triangulation ( TopoDS::Face( fExp.Current() ), loc);
+    if ( triangulation.IsNull() ) continue;
+    const TColgp_Array1OfPnt&   points = triangulation->Nodes();
+    const Poly_Array1OfTriangle& trias = triangulation->Triangles();
+    for ( int iT = trias.Lower(); iT <= trias.Upper(); ++iT )
+    {
+      trias(iT).Get( i1, i2, i3 );
+      for ( int j = 0; j < 3; ++j )
+      {
+        double dist2 = points(*pi[j]).SquareDistance( points( *pi[j+1] ));
+        if ( dist2 < minh )
+          minh = dist2;
+        bb.Add( points(*pi[j]));
+      }
+    }
+  }
+  if ( minh > 0.25 * bb.SquareExtent() ) // simple geometry, rough triangulation
+  {
+    minh = 1e-3 * sqrt( bb.SquareExtent());
+    //cout << "BND BOX minh = " <<minh << endl;
+  }
+  else
+  {
+    minh = 3 * sqrt( minh ); // triangulation for visualization is rather fine
+    //cout << "TRIANGULATION minh = " <<minh << endl;
+  }
+  if ( minh > 0.5 * maxSize )
+    minh = maxSize / 3.;
+
+  return minh;
 }
 
 //================================================================================
@@ -1761,6 +1806,9 @@ bool NETGENPlugin_Mesher::Compute()
         mparams.maxh = _simpleHyp->GetLocalLength();
     }
 
+    if ( _simpleHyp || mparams.minh == 0.0 )
+      mparams.minh = GetDefaultMinSize( _shape, mparams.maxh );
+
     // Let netgen create ngMesh and calculate element size on not meshed shapes
     char *optstr = 0;
     int startWith = netgen::MESHCONST_ANALYSE;
@@ -2195,6 +2243,7 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap)
       // nb of segments
       mparams.segmentsperedge = nbSeg + 0.1;
       mparams.maxh = occgeo.boundingbox.Diam();
+      mparams.minh = GetDefaultMinSize( _shape, mparams.maxh );
       mparams.grading = 0.01;
     }
     else {
index 65a04f04856ef053192f61052cdb088ee3864e09..70b620f60c650275c82f1e0d9b9e5d2be4318759 100644 (file)
@@ -94,6 +94,9 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
                                  std::list< SMESH_subMesh* > * meshedSM=0,
                                  NETGENPlugin_Internals*       internalShapes=0);
 
+  static double GetDefaultMinSize(const TopoDS_Shape& shape,
+                                  const double        maxSize);
+
   static int FillSMesh(const netgen::OCCGeometry&          occgeom,
                        const netgen::Mesh&                 ngMesh,
                        const NETGENPlugin_ngMeshInfo&      initState,
index c54c8fa0ca123bbad8f6d141250cfb0852a9a7dc..c35e86a563021e8e24f9694659f78d0a5e53c096 100644 (file)
@@ -444,6 +444,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh&         aMesh,
       edgeLength = occgeo.GetBoundingBox().Diam();
 
     netgen::mparam.maxh = edgeLength;
+    netgen::mparam.minh = aMesher.GetDefaultMinSize( aShape, netgen::mparam.maxh );
     netgen::mparam.quad = _hypQuadranglePreference ? 1 : 0;
     netgen::mparam.grading = 0.7; // very coarse mesh by default
   }
index 3b6ff04f7223b9194f6632168caff26c0d806118..cc1ea19ce7f6a14e27142bc9c40264e5c69fd561 100644 (file)
@@ -374,6 +374,11 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
     netgen::mparam.maxh = Dist(pmin, pmax)/2;
   }
 
+  if ( !_hypParameters && aMesh.HasShapeToMesh() )
+  {
+    netgen::mparam.minh = aMesher.GetDefaultMinSize( helper.GetSubShape(), netgen::mparam.maxh );
+  }
+
   try
   {
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100