Salome HOME
IPAL52861: Netgen 2D fails on a sphere cbr/crowdin_V7_7_BR V7_7_0a1 V7_7_0b1
authoreap <eap@opencascade.com>
Fri, 4 Sep 2015 10:59:33 +0000 (13:59 +0300)
committereap <eap@opencascade.com>
Fri, 4 Sep 2015 10:59:33 +0000 (13:59 +0300)
IPAL22848: Netgen 1D-2D-3D fails on a cone with default Simple parameters
IPAL20479: computation of the mesh (on cone + box) via "NETGEN 1D_2D_3D" is failed.

Fixes:
1) Avoid setting a local size to zero on a degenerated edge
2) Avoid creating coincident NETGEN points (though with different UV) on a seam edge

src/NETGENPlugin/NETGENPlugin_Mesher.cxx
src/NETGENPlugin/NETGENPlugin_Mesher.hxx
src/NETGENPlugin/NETGENPlugin_NETGEN_2D_ONLY.cxx

index b822d1deb6f364493328887010f289bd9ba2db72..69100bd0c2e6b93c1c42e34085178cf1c1adbe1d 100644 (file)
@@ -56,6 +56,7 @@
 #include <NCollection_Map.hxx>
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_ProgramError.hxx>
+#include <TColStd_MapOfInteger.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
@@ -64,8 +65,6 @@
 #include <TopTools_DataMapOfShapeShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
-#include <OSD_File.hxx>
-#include <OSD_Path.hxx>
 
 // Netgen include files
 #ifndef OCCGEOMETRY
@@ -321,6 +320,11 @@ struct Link
   int n1, n2;
   Link(int _n1, int _n2) : n1(_n1), n2(_n2) {}
   Link() : n1(0), n2(0) {}
+  bool Contains( int n ) const { return n == n1 || n == n2; }
+  bool IsConnected( const Link& other ) const
+  {
+    return (( Contains( other.n1 ) || Contains( other.n2 )) && ( this != &other ));
+  }
 };
 
 int HashCode(const Link& aLink, int aLimit)
@@ -699,6 +703,8 @@ void NETGENPlugin_Mesher::RestrictLocalSize(netgen::Mesh& ngMesh,
                                             const double  size,
                                             const bool    overrideMinH)
 {
+  if ( size <= std::numeric_limits<double>::min() )
+    return;
   if ( overrideMinH && netgen::mparam.minh > size )
   {
     ngMesh.SetMinimalH( size );
@@ -1105,6 +1111,115 @@ void NETGENPlugin_Mesher::FixIntFaces(const netgen::OCCGeometry& occgeom,
   }
 }
 
+//================================================================================
+/*!
+ * \brief Tries to heal the mesh on a FACE. The FACE is supposed to be partially
+ *        meshed due to NETGEN failure
+ *  \param [in] occgeom - geometry
+ *  \param [in,out] ngMesh - the mesh to fix
+ *  \param [inout] faceID - ID of the FACE to fix the mesh on
+ *  \return bool - is mesh is or becomes OK
+ */
+//================================================================================
+
+bool NETGENPlugin_Mesher::FixFaceMesh(const netgen::OCCGeometry& occgeom,
+                                      netgen::Mesh&              ngMesh,
+                                      const int                  faceID)
+{
+  // we address a case where the FACE is almost fully meshed except small holes
+  // of usually triangular shape at FACE boundary (IPAL52861)
+
+  // The case appeared to be not simple: holes only look triangular but
+  // indeed are a self intersecting polygon. A reason of the bug was in coincident
+  // NG points on a seam edge. But the code below is very nice, leave it for
+  // another case.
+  return false;
+
+
+  if ( occgeom.fmap.Extent() < faceID )
+    return false;
+  const TopoDS_Face& face = TopoDS::Face( occgeom.fmap( faceID ));
+
+  // find free links on the FACE
+  NCollection_Map<Link> linkMap;
+  for ( int iF = 1; iF <= ngMesh.GetNSE(); ++iF )
+  {
+    const netgen::Element2d& elem = ngMesh.SurfaceElement(iF);
+    if ( faceID != elem.GetIndex() )
+      continue;
+    int n0 = elem[ elem.GetNP() - 1 ];
+    for ( int i = 0; i < elem.GetNP(); ++i )
+    {
+      int n1 = elem[i];
+      Link link( n0, n1 );
+      if ( !linkMap.Add( link ))
+        linkMap.Remove( link );
+      n0 = n1;
+    }
+  }
+  // add/remove boundary links
+  for ( int iSeg = 1; iSeg <= ngMesh.GetNSeg(); ++iSeg )
+  {
+    const netgen::Segment& seg = ngMesh.LineSegment( iSeg );
+    if ( seg.si != faceID ) // !edgeIDs.Contains( seg.edgenr ))
+      continue;
+    Link link( seg[1], seg[0] ); // reverse!!!
+    if ( !linkMap.Add( link ))
+      linkMap.Remove( link );
+  }
+  if ( linkMap.IsEmpty() )
+    return true;
+  if ( linkMap.Extent() < 3 )
+    return false;
+
+  // make triangles of the links
+
+  netgen::Element2d tri(3);
+  tri.SetIndex ( faceID );
+
+  NCollection_Map<Link>::Iterator linkIt( linkMap );
+  Link link1 = linkIt.Value();
+  // look for a link connected to link1
+  NCollection_Map<Link>::Iterator linkIt2 = linkIt;
+  for ( linkIt2.Next(); linkIt2.More(); linkIt2.Next() )
+  {
+    const Link& link2 = linkIt2.Value();
+    if ( link2.IsConnected( link1 ))
+    {
+      // look for a link connected to both link1 and link2
+      NCollection_Map<Link>::Iterator linkIt3 = linkIt2;
+      for ( linkIt3.Next(); linkIt3.More(); linkIt3.Next() )
+      {
+        const Link& link3 = linkIt3.Value();
+        if ( link3.IsConnected( link1 ) &&
+             link3.IsConnected( link2 ) )
+        {
+          // add a triangle
+          tri[0] = link1.n2;
+          tri[1] = link1.n1;
+          tri[2] = ( link2.Contains( link1.n1 ) ? link2.n1 : link3.n1 );
+          if ( tri[0] == tri[2] || tri[1] == tri[2] )
+            return false;
+          ngMesh.AddSurfaceElement( tri );
+
+          // prepare for the next tria search
+          if ( linkMap.Extent() == 3 )
+            return true;
+          linkMap.Remove( link3 );
+          linkMap.Remove( link2 );
+          linkIt.Next();
+          linkMap.Remove( link1 );
+          link1 = linkIt.Value();
+          linkIt2 = linkIt;
+          break;
+        }
+      }
+    }
+  }
+  return false;
+
+} // FixFaceMesh()
+
 namespace
 {
   //================================================================================
@@ -1698,7 +1813,7 @@ NETGENPlugin_Mesher::AddSegmentsToMesh(netgen::Mesh&                    ngMesh,
         continue;
 
       int ngID1 = ngMesh.GetNP() + 1, ngID2 = ngID1+1;
-      if ( onVertex || ( !wasNgMeshEmpty && onEdge ))
+      if ( onVertex || ( !wasNgMeshEmpty && onEdge ) || helper.IsRealSeam( posShapeID ))
         ngID1 = node2ngID.insert( make_pair( n, ngID1 )).first->second;
       if ( ngID1 > ngMesh.GetNP() )
       {
@@ -1810,8 +1925,8 @@ NETGENPlugin_Mesher::AddSegmentsToMesh(netgen::Mesh&                    ngMesh,
         }
       }
       cout << "Segment: " << seg.edgenr << endl
-           << "\tp1: " << seg[0] << endl
-           << "\tp2: " << seg[1] << endl
+           << "\tp1: " << seg[0] << "   n" << nodeVec[ seg[0]]->GetID() << endl
+           << "\tp2: " << seg[1] << "   n" << nodeVec[ seg[1]]->GetID() <<  endl
            << "\tp0 param: " << seg.epgeominfo[ 0 ].dist << endl
            << "\tp0 uv: " << seg.epgeominfo[ 0 ].u <<", "<< seg.epgeominfo[ 0 ].v << endl
            << "\tp0 edge: " << seg.epgeominfo[ 0 ].edgenr << endl
@@ -2146,7 +2261,8 @@ namespace
                     double             size,
                     netgen::Mesh&      mesh)
   {
-    const int nb = 1000;
+    if ( size <= std::numeric_limits<double>::min() )
+      return;
     Standard_Real u1, u2;
     Handle(Geom_Curve) curve = BRep_Tool::Curve(edge, u1, u2);
     if ( curve.IsNull() )
@@ -2158,6 +2274,7 @@ namespace
     }
     else
     {
+      const int nb = (int)( 1.5 * SMESH_Algo::EdgeLength( edge ) / size );
       Standard_Real delta = (u2-u1)/nb;
       for(int i=0; i<nb; i++)
       {
index d7cb39e1017505dd6274a051ee9118b9d650ec8a..52b2b74cc65b42725b5b5c79cdc67cb3848bbda7 100644 (file)
@@ -157,6 +157,10 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
                           netgen::Mesh&              ngMesh,
                           NETGENPlugin_Internals&    internalShapes);
 
+  static bool FixFaceMesh(const netgen::OCCGeometry& occgeom,
+                          netgen::Mesh&              ngMesh,
+                          const int                  faceID);
+
   static void AddIntVerticesInFaces(const netgen::OCCGeometry&          occgeom,
                                     netgen::Mesh&                       ngMesh,
                                     std::vector<const SMDS_MeshNode*>&  nodeVec,
index a8b57bea551d4689d786e2d23d6e2c63b2c98fa1..342d6239d5b9e257669e5a418cad7ae242005e16 100644 (file)
@@ -498,6 +498,8 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh&         aMesh,
       }
       if ( err )
       {
+        if ( aMesher.FixFaceMesh( occgeom, *ngMesh, 1 ))
+          break;
         if ( iLoop == LOC_SIZE )
         {
           netgen::mparam.minh = netgen::mparam.maxh;