+//================================================================================
+/*!
+ * \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()
+