IPAL52861: Netgen 2D fails on a sphere

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
This commit is contained in:
eap 2015-09-04 13:59:33 +03:00
parent 9a26afa4ea
commit 129557feea
3 changed files with 129 additions and 6 deletions

View 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++)
{

View 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,

View 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;