To compute mesh in SALOME_TESTS/Grids/geom/bugs_15/R7

and other tests of "Extrusion 3D" mesher
This commit is contained in:
eap 2014-11-12 18:35:28 +03:00
parent d6b7cb735f
commit 3ddacb9798
6 changed files with 253 additions and 166 deletions

View File

@ -941,7 +941,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
int shapeID = n->getshapeId(); int shapeID = n->getshapeId();
bool infinit = Precision::IsInfinite( u ); bool infinit = Precision::IsInfinite( u );
bool zero = ( u == 0. ); bool zero = ( u == 0. );
if ( force || toCheckPosOnShape( shapeID ) || infinit || zero ) if ( force || infinit || zero || toCheckPosOnShape( shapeID ))
{ {
TopLoc_Location loc; double f,l; TopLoc_Location loc; double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( E,loc,f,l ); Handle(Geom_Curve) curve = BRep_Tool::Curve( E,loc,f,l );
@ -958,7 +958,7 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge& E,
gp_Pnt nodePnt = SMESH_TNodeXYZ( n ); gp_Pnt nodePnt = SMESH_TNodeXYZ( n );
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() ); if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
gp_Pnt curvPnt; gp_Pnt curvPnt;
double dist = u; double dist = 2*tol;
if ( !infinit ) if ( !infinit )
{ {
curvPnt = curve->Value( u ); curvPnt = curve->Value( u );
@ -2559,7 +2559,8 @@ bool SMESH_MesherHelper::IsStructured( SMESH_subMesh* faceSM )
//purpose : Return true if 2D mesh on FACE is ditorted //purpose : Return true if 2D mesh on FACE is ditorted
//======================================================================= //=======================================================================
bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM ) bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM,
bool checkUV)
{ {
if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE ) if ( !faceSM || faceSM->GetSubShape().ShapeType() != TopAbs_FACE )
return false; return false;
@ -2577,6 +2578,7 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM )
double prevArea2D = 0; double prevArea2D = 0;
vector< const SMDS_MeshNode* > nodes; vector< const SMDS_MeshNode* > nodes;
vector< gp_XY > uv; vector< gp_XY > uv;
bool* toCheckUV = checkUV ? & checkUV : 0;
while ( faceIt->more() && !haveBadFaces ) while ( faceIt->more() && !haveBadFaces )
{ {
const SMDS_MeshElement* face = faceIt->next(); const SMDS_MeshElement* face = faceIt->next();
@ -2608,7 +2610,7 @@ bool SMESH_MesherHelper::IsDistorted2D( SMESH_subMesh* faceSM )
// get UVs // get UVs
uv.resize( nodes.size() ); uv.resize( nodes.size() );
for ( size_t i = 0; i < nodes.size(); ++i ) for ( size_t i = 0; i < nodes.size(); ++i )
uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode ); uv[ i ] = helper.GetNodeUV( F, nodes[ i ], inFaceNode, toCheckUV );
// compare orientation of triangles // compare orientation of triangles
for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT ) for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )

View File

@ -120,7 +120,7 @@ class SMESH_EXPORT SMESH_MesherHelper
/*! /*!
* \brief Return true if 2D mesh on FACE is distored * \brief Return true if 2D mesh on FACE is distored
*/ */
static bool IsDistorted2D( SMESH_subMesh* faceSM ); static bool IsDistorted2D( SMESH_subMesh* faceSM, bool checkUV=false );
/*! /*!
* \brief Returns true if given node is medium * \brief Returns true if given node is medium

View File

@ -689,6 +689,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
list< Prism_3D::TPrismTopo > meshedPrism; list< Prism_3D::TPrismTopo > meshedPrism;
list< TopoDS_Face > suspectSourceFaces; list< TopoDS_Face > suspectSourceFaces;
TopTools_ListIteratorOfListOfShape solidIt; TopTools_ListIteratorOfListOfShape solidIt;
bool selectBottom = false;
while ( meshedSolids.Extent() < nbSolids ) while ( meshedSolids.Extent() < nbSolids )
{ {
@ -709,7 +710,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
{ {
prism.Clear(); prism.Clear();
prism.myBottom = face; prism.myBottom = face;
if ( !initPrism( prism, solid ) || if ( !initPrism( prism, solid, selectBottom ) ||
!compute( prism )) !compute( prism ))
return false; return false;
@ -762,15 +763,24 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
while ( const TopoDS_Shape* f = faceIt->next() ) while ( const TopoDS_Shape* f = faceIt->next() )
{ {
const TopoDS_Face& candidateF = TopoDS::Face( *f ); const TopoDS_Face& candidateF = TopoDS::Face( *f );
if ( candidateF.IsSame( wFace )) continue;
// select a source FACE: prismIt->myBottom or prismIt->myTop
TopoDS_Face sourceF = prismIt->myBottom;
for ( TopExp_Explorer v( prismIt->myTop, TopAbs_VERTEX ); v.More(); v.Next() )
if ( myHelper->IsSubShape( v.Current(), candidateF )) {
sourceF = prismIt->myTop;
break;
}
prism.Clear(); prism.Clear();
prism.myBottom = candidateF; prism.myBottom = candidateF;
mySetErrorToSM = false; mySetErrorToSM = false;
if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) && if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) &&
myHelper->IsSubShape( candidateF, solid ) && myHelper ->IsSubShape( candidateF, solid ) &&
!myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() && !myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() &&
initPrism( prism, solid ) && initPrism( prism, solid, /*selectBottom=*/false ) &&
!myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() && !myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() &&
project2dMesh( prismIt->myBottom, candidateF)) !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() &&
project2dMesh( sourceF, prism.myBottom ))
{ {
mySetErrorToSM = true; mySetErrorToSM = true;
if ( !compute( prism )) if ( !compute( prism ))
@ -780,6 +790,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
{ {
meshedFaces.push_front( prism.myTop ); meshedFaces.push_front( prism.myTop );
meshedFaces.push_front( prism.myBottom ); meshedFaces.push_front( prism.myBottom );
selectBottom = false;
} }
meshedPrism.push_back( prism ); meshedPrism.push_back( prism );
meshedSolids.Add( solid ); meshedSolids.Add( solid );
@ -802,6 +813,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
if ( meshedFaces.empty() ) if ( meshedFaces.empty() )
{ {
meshedFaces.splice( meshedFaces.end(), suspectSourceFaces ); meshedFaces.splice( meshedFaces.end(), suspectSourceFaces );
selectBottom = true;
} }
// find FACEs with local 1D hyps, which has to be computed by now, // find FACEs with local 1D hyps, which has to be computed by now,
@ -822,6 +834,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
{ {
if ( !meshedFaces.empty() ) meshedFaces.pop_back(); if ( !meshedFaces.empty() ) meshedFaces.pop_back();
meshedFaces.push_back( face ); // lower priority meshedFaces.push_back( face ); // lower priority
selectBottom = true;
prevNbFaces = nbFaces; prevNbFaces = nbFaces;
} }
} }
@ -836,6 +849,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE ); faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
if ( !faceSM->IsEmpty() ) { if ( !faceSM->IsEmpty() ) {
meshedFaces.push_front( face ); // higher priority meshedFaces.push_front( face ); // higher priority
selectBottom = true;
break; break;
} }
else { else {
@ -867,6 +881,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh
meshedFaces.push_front( prism.myBottom ); meshedFaces.push_front( prism.myBottom );
meshedPrism.push_back( prism ); meshedPrism.push_back( prism );
meshedSolids.Add( solid.Current() ); meshedSolids.Add( solid.Current() );
selectBottom = true;
} }
mySetErrorToSM = true; mySetErrorToSM = true;
} }
@ -1071,7 +1086,7 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism,
StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ]; StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
const TopoDS_Edge & topE = topSide->Edge( 0 ); const TopoDS_Edge & topE = topSide->Edge( 0 );
if ( !myHelper->IsSubShape( topE, thePrism.myTop )) if ( !myHelper->IsSubShape( topE, thePrism.myTop ))
return toSM( error( TCom("Wrong source face (#") << shapeID( thePrism.myBottom ))); return toSM( error( TCom("Wrong source face: #") << shapeID( thePrism.myBottom )));
} }
return true; return true;
@ -1088,13 +1103,21 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
if ( _computeCanceled ) if ( _computeCanceled )
return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED))); return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
// Assure the bottom is meshed
SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
if ( ! NSProjUtils::MakeComputed( botSM ))
return error( COMPERR_BAD_INPUT_MESH,
TCom( "No mesher defined to compute the face #")
<< shapeID( thePrism.myBottom ));
// Make all side FACEs of thePrism meshed with quads // Make all side FACEs of thePrism meshed with quads
if ( !computeWalls( thePrism )) if ( !computeWalls( thePrism ))
return false; return false;
// Analyse mesh and geometry to find all block sub-shapes and submeshes // Analyse mesh and geometry to find all block sub-shapes and submeshes
// (after fixing IPAL52499 myBlock is used only as a holder of boundary nodes // (after fixing IPAL52499 myBlock is used as a holder of boundary nodes
// and location of internal nodes is computed by StdMeshers_Sweeper) // and for 2D projection in hard cases where StdMeshers_Projection_2D fails;
// location of internal nodes is usually computed by StdMeshers_Sweeper)
if ( !myBlock.Init( myHelper, thePrism )) if ( !myBlock.Init( myHelper, thePrism ))
return toSM( error( myBlock.GetError())); return toSM( error( myBlock.GetError()));
@ -1123,6 +1146,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// Projections on the top and bottom faces are taken from nodes existing // Projections on the top and bottom faces are taken from nodes existing
// on these faces; find correspondence between bottom and top nodes // on these faces; find correspondence between bottom and top nodes
myUseBlock = false;
myBotToColumnMap.clear(); myBotToColumnMap.clear();
if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
return false; return false;
@ -1132,27 +1156,31 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism)
// use transformation (issue 0020680, IPAL0052499) // use transformation (issue 0020680, IPAL0052499)
StdMeshers_Sweeper sweeper; StdMeshers_Sweeper sweeper;
double tol;
// load boundary nodes if ( !myUseBlock )
bool dummy;
list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
{ {
int edgeID = meshDS->ShapeToIndex( *edge ); // load boundary nodes into sweeper
TParam2ColumnMap* u2col = const_cast<TParam2ColumnMap*> bool dummy;
( myBlock.GetParam2ColumnMap( edgeID, dummy )); list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
TParam2ColumnMap::iterator u2colIt = u2col->begin(); for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
for ( ; u2colIt != u2col->end(); ++u2colIt ) {
sweeper.myBndColumns.push_back( & u2colIt->second ); int edgeID = meshDS->ShapeToIndex( *edge );
TParam2ColumnMap* u2col = const_cast<TParam2ColumnMap*>
( myBlock.GetParam2ColumnMap( edgeID, dummy ));
TParam2ColumnMap::iterator u2colIt = u2col->begin();
for ( ; u2colIt != u2col->end(); ++u2colIt )
sweeper.myBndColumns.push_back( & u2colIt->second );
}
// load node columns inside the bottom face
TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
sweeper.myIntColumns.push_back( & bot_column->second );
tol = getSweepTolerance( thePrism );
} }
// load node columns inside the bottom face
TNode2ColumnMap::iterator bot_column = myBotToColumnMap.begin();
for ( ; bot_column != myBotToColumnMap.end(); ++bot_column )
sweeper.myIntColumns.push_back( & bot_column->second );
const double tol = getSweepTolerance( thePrism ); if ( !myUseBlock && sweeper.ComputeNodes( *myHelper, tol ))
if ( sweeper.ComputeNodes( *myHelper, tol ))
{ {
} }
else // use block approach else // use block approach
@ -1528,7 +1556,7 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism)
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad ) for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{ {
const TopoDS_Face& face = (*quad)->face; const TopoDS_Face& face = (*quad)->face;
SMESH_subMesh* fSM = mesh->GetSubMesh( face ); SMESH_subMesh* fSM = mesh->GetSubMesh( face );
if ( ! fSM->IsMeshComputed() ) if ( ! fSM->IsMeshComputed() )
{ {
// Top EDGEs must be projections from the bottom ones // Top EDGEs must be projections from the bottom ones
@ -1938,8 +1966,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
NSProjUtils::TShapeShapeMap shape2ShapeMap; NSProjUtils::TShapeShapeMap shape2ShapeMap;
const bool sameTopo = const bool sameTopo =
NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(), NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(),
thePrism.myTop, myHelper->GetMesh(), thePrism.myTop, myHelper->GetMesh(),
shape2ShapeMap); shape2ShapeMap);
if ( !sameTopo ) if ( !sameTopo )
for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ ) for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
{ {
@ -1951,10 +1979,10 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
for ( int iE = 0; iE < botSide->NbEdges(); ++iE ) for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
{ {
NSProjUtils::InsertAssociation( botSide->Edge( iE ), NSProjUtils::InsertAssociation( botSide->Edge( iE ),
topSide->Edge( iE ), shape2ShapeMap ); topSide->Edge( iE ), shape2ShapeMap );
NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )), NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
myHelper->IthVertex( 0, topSide->Edge( iE )), myHelper->IthVertex( 0, topSide->Edge( iE )),
shape2ShapeMap ); shape2ShapeMap );
} }
} }
else else
@ -1969,7 +1997,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
vt.IsSame( sideT->LastVertex() )) vt.IsSame( sideT->LastVertex() ))
{ {
NSProjUtils::InsertAssociation( botSide->Edge( 0 ), NSProjUtils::InsertAssociation( botSide->Edge( 0 ),
topSide->Edge( 0 ), shape2ShapeMap ); topSide->Edge( 0 ), shape2ShapeMap );
NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap ); NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
} }
vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 )); vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
@ -1980,8 +2008,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
vt.IsSame( sideT->LastVertex() )) vt.IsSame( sideT->LastVertex() ))
{ {
NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ), NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
topSide->Edge( topSide->NbEdges()-1 ), topSide->Edge( topSide->NbEdges()-1 ),
shape2ShapeMap ); shape2ShapeMap );
NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap ); NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
} }
} }
@ -1990,8 +2018,8 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
// Find matching nodes of top and bottom faces // Find matching nodes of top and bottom faces
n2nMapPtr = & n2nMap; n2nMapPtr = & n2nMap;
if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(), if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(),
thePrism.myTop, myHelper->GetMesh(), thePrism.myTop, myHelper->GetMesh(),
shape2ShapeMap, n2nMap )) shape2ShapeMap, n2nMap ))
{ {
if ( sameTopo ) if ( sameTopo )
return toSM( error(TCom("Mesh on faces #") << botSM->GetId() return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
@ -2014,7 +2042,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf
continue; // wall columns are contained in myBlock continue; // wall columns are contained in myBlock
// create node column // create node column
Prism_3D::TNode bN( botNode ); Prism_3D::TNode bN( botNode );
TNode2ColumnMap::iterator bN_col = TNode2ColumnMap::iterator bN_col =
myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first; myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
TNodeColumn & column = bN_col->second; TNodeColumn & column = bN_col->second;
column.resize( zSize ); column.resize( zSize );
@ -2038,6 +2066,11 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom
{ {
return true; return true;
} }
NSProjUtils::TNodeNodeMap& n2nMap =
(NSProjUtils::TNodeNodeMap&) TProjction2dAlgo::instance( this )->GetNodesMap();
n2nMap.clear();
myUseBlock = true;
SMESHDS_Mesh* meshDS = myHelper->GetMeshDS(); SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom ); SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
@ -2047,7 +2080,13 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS(); SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
if ( topSMDS && topSMDS->NbElements() > 0 ) if ( topSMDS && topSMDS->NbElements() > 0 )
topSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); {
//topSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
for ( SMDS_ElemIteratorPtr eIt = topSMDS->GetElements(); eIt->more(); )
meshDS->RemoveFreeElement( eIt->next(), topSMDS, /*fromGroups=*/false );
for ( SMDS_NodeIteratorPtr nIt = topSMDS->GetNodes(); nIt->more(); )
meshDS->RemoveFreeNode( nIt->next(), topSMDS, /*fromGroups=*/false );
}
const TopoDS_Face& botFace = thePrism.myBottom; // oriented within const TopoDS_Face& botFace = thePrism.myBottom; // oriented within
const TopoDS_Face& topFace = thePrism.myTop; // the 3D SHAPE const TopoDS_Face& topFace = thePrism.myTop; // the 3D SHAPE
@ -2119,6 +2158,8 @@ bool StdMeshers_Prism_3D::projectBottomToTop( const gp_Trsf & bottom
column.front() = botNode; column.front() = botNode;
column.back() = topNode; column.back() = topNode;
n2nMap.insert( n2nMap.end(), make_pair( botNode, topNode ));
if ( _computeCanceled ) if ( _computeCanceled )
return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED))); return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
} }
@ -2270,6 +2311,15 @@ bool StdMeshers_Prism_3D::project2dMesh(const TopoDS_Face& theSrcFace,
bool ok = projector2D->Compute( *myHelper->GetMesh(), theTgtFace ); bool ok = projector2D->Compute( *myHelper->GetMesh(), theTgtFace );
SMESH_subMesh* tgtSM = myHelper->GetMesh()->GetSubMesh( theTgtFace ); SMESH_subMesh* tgtSM = myHelper->GetMesh()->GetSubMesh( theTgtFace );
if ( !ok && tgtSM->GetSubMeshDS() ) {
//tgtSM->ComputeStateEngine( SMESH_subMesh::CLEAN ); -- avoid propagation of events
SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
SMESHDS_SubMesh* tgtSMDS = tgtSM->GetSubMeshDS();
for ( SMDS_ElemIteratorPtr eIt = tgtSMDS->GetElements(); eIt->more(); )
meshDS->RemoveFreeElement( eIt->next(), tgtSMDS, /*fromGroups=*/false );
for ( SMDS_NodeIteratorPtr nIt = tgtSMDS->GetNodes(); nIt->more(); )
meshDS->RemoveFreeNode( nIt->next(), tgtSMDS, /*fromGroups=*/false );
}
tgtSM->ComputeStateEngine ( SMESH_subMesh::CHECK_COMPUTE_STATE ); tgtSM->ComputeStateEngine ( SMESH_subMesh::CHECK_COMPUTE_STATE );
tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); tgtSM->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
@ -2785,7 +2835,8 @@ void StdMeshers_PrismAsBlock::Clear()
//======================================================================= //=======================================================================
bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
const TopoDS_Shape& shape3D) const TopoDS_Shape& shape3D,
const bool selectBottom)
{ {
myHelper->SetSubShape( shape3D ); myHelper->SetSubShape( shape3D );
@ -2884,19 +2935,23 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
// use thePrism.myBottom // use thePrism.myBottom
if ( !thePrism.myBottom.IsNull() ) if ( !thePrism.myBottom.IsNull() )
{ {
if ( botSM ) { if ( botSM ) { // <-- not quad geom or mesh on botSM
if ( ! botSM->GetSubShape().IsSame( thePrism.myBottom )) { if ( ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
std::swap( botSM, topSM ); std::swap( botSM, topSM );
if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom )) if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
return toSM( error( COMPERR_BAD_INPUT_MESH, if ( !selectBottom )
"Incompatible non-structured sub-meshes")); return toSM( error( COMPERR_BAD_INPUT_MESH,
"Incompatible non-structured sub-meshes"));
std::swap( botSM, topSM );
thePrism.myBottom = TopoDS::Face( botSM->GetSubShape() );
}
} }
} }
else { else if ( !selectBottom ) {
botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom ); botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
} }
} }
else if ( !botSM ) // find a proper bottom if ( !botSM ) // find a proper bottom
{ {
// composite walls or not prism shape // composite walls or not prism shape
for ( TopExp_Explorer f( shape3D, TopAbs_FACE ); f.More(); f.Next() ) for ( TopExp_Explorer f( shape3D, TopAbs_FACE ); f.More(); f.Next() )
@ -2906,11 +2961,17 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
{ {
thePrism.Clear(); thePrism.Clear();
thePrism.myBottom = TopoDS::Face( f.Current() ); thePrism.myBottom = TopoDS::Face( f.Current() );
if ( initPrism( thePrism, shape3D )) if ( initPrism( thePrism, shape3D, /*selectBottom=*/false ))
{
botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
topSM = myHelper->GetMesh()->GetSubMesh( thePrism.myTop );
if ( botSM->IsEmpty() && !topSM->IsEmpty() )
thePrism.SetUpsideDown();
return true; return true;
}
} }
return toSM( error( COMPERR_BAD_SHAPE ));
} }
return toSM( error( COMPERR_BAD_SHAPE ));
} }
// find vertex 000 - the one with smallest coordinates (for easy DEBUG :-) // find vertex 000 - the one with smallest coordinates (for easy DEBUG :-)
@ -2943,7 +3004,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
thePrism.myNbEdgesInWires, V000 ); thePrism.myNbEdgesInWires, V000 );
// Get Wall faces corresponding to the ordered bottom edges and the top FACE // Get Wall faces corresponding to the ordered bottom edges and the top FACE
if ( !getWallFaces( thePrism, nbFaces )) if ( !getWallFaces( thePrism, nbFaces )) // it also sets thePrism.myTop
return false; //toSM( error(COMPERR_BAD_SHAPE, "Can't find side faces")); return false; //toSM( error(COMPERR_BAD_SHAPE, "Can't find side faces"));
if ( topSM ) if ( topSM )
@ -3887,7 +3948,7 @@ gp_Pnt StdMeshers_PrismAsBlock::TSideFace::Value(const Standard_Real U,
TopoDS_Shape s = myHelper.GetSubShapeByNode( nn[0], myHelper.GetMeshDS() ); TopoDS_Shape s = myHelper.GetSubShapeByNode( nn[0], myHelper.GetMeshDS() );
if ( s.ShapeType() != TopAbs_EDGE ) if ( s.ShapeType() != TopAbs_EDGE )
s = myHelper.GetSubShapeByNode( nn[2], myHelper.GetMeshDS() ); s = myHelper.GetSubShapeByNode( nn[2], myHelper.GetMeshDS() );
if ( s.ShapeType() == TopAbs_EDGE ) if ( !s.IsNull() && s.ShapeType() == TopAbs_EDGE )
edge = TopoDS::Edge( s ); edge = TopoDS::Edge( s );
} }
if ( !edge.IsNull() ) if ( !edge.IsNull() )

View File

@ -482,7 +482,9 @@ public:
* \brief Analyse shape geometry and mesh. * \brief Analyse shape geometry and mesh.
* If there are triangles on one of faces, it becomes 'bottom' * If there are triangles on one of faces, it becomes 'bottom'
*/ */
bool initPrism(Prism_3D::TPrismTopo& thePrism, const TopoDS_Shape& theSolid); bool initPrism(Prism_3D::TPrismTopo& thePrism,
const TopoDS_Shape& theSolid,
const bool selectBottom = true);
/*! /*!
* \brief Fill thePrism.myWallQuads and thePrism.myTopEdges * \brief Fill thePrism.myWallQuads and thePrism.myTopEdges
@ -556,6 +558,7 @@ private:
bool myProjectTriangles; bool myProjectTriangles;
bool mySetErrorToSM; bool mySetErrorToSM;
bool myUseBlock;
StdMeshers_PrismAsBlock myBlock; StdMeshers_PrismAsBlock myBlock;
SMESH_MesherHelper* myHelper; SMESH_MesherHelper* myHelper;

View File

@ -1942,97 +1942,109 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1,
// 2. face sets // 2. face sets
set<const SMDS_MeshElement*> Elems1, Elems2; int assocRes;
for ( int is2 = 0; is2 < 2; ++is2 ) for ( int iAttempt = 0; iAttempt < 2; ++iAttempt )
{ {
set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1; set<const SMDS_MeshElement*> Elems1, Elems2;
SMESHDS_SubMesh* sm = is2 ? SM2 : SM1; for ( int is2 = 0; is2 < 2; ++is2 )
SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
const TopoDS_Face & face = is2 ? face2 : face1;
SMDS_ElemIteratorPtr eIt = sm->GetElements();
if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
{ {
while ( eIt->more() ) elems.insert( eIt->next() ); set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
} SMESHDS_SubMesh* sm = is2 ? SM2 : SM1;
else SMESH_MesherHelper* helper = is2 ? &helper2 : &helper1;
{ const TopoDS_Face & face = is2 ? face2 : face1;
// the only suitable edge is seam, i.e. it is a sphere. SMDS_ElemIteratorPtr eIt = sm->GetElements();
// FindMatchingNodes() will not know which way to go from any edge.
// So we ignore all faces having nodes on edges or vertices except
// one of faces sharing current start nodes
// find a face to keep if ( !helper->IsRealSeam( is2 ? edge2 : edge1 ))
const SMDS_MeshElement* faceToKeep = 0; {
const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1; while ( eIt->more() ) elems.insert( elems.end(), eIt->next() );
const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
TIDSortedElemSet inSet, notInSet;
const SMDS_MeshElement* f1 =
SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
notInSet.insert( f1 );
const SMDS_MeshElement* f2 =
SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
// select a face with less UV of vNode
const SMDS_MeshNode* notSeamNode[2] = {0, 0};
for ( int iF = 0; iF < 2; ++iF ) {
const SMDS_MeshElement* f = ( iF ? f2 : f1 );
for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
const SMDS_MeshNode* node = f->GetNode( i );
if ( !helper->IsSeamShape( node->getshapeId() ))
notSeamNode[ iF ] = node;
}
} }
gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
faceToKeep = f2;
else else
faceToKeep = f1; {
// the only suitable edge is seam, i.e. it is a sphere.
// FindMatchingNodes() will not know which way to go from any edge.
// So we ignore all faces having nodes on edges or vertices except
// one of faces sharing current start nodes
// fill elem set // find a face to keep
elems.insert( faceToKeep ); const SMDS_MeshElement* faceToKeep = 0;
while ( eIt->more() ) { const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
const SMDS_MeshElement* f = eIt->next(); const SMDS_MeshNode* eNode = is2 ? eNode2[0] : eNode1[0];
int nbNodes = f->NbNodes(); TIDSortedElemSet inSet, notInSet;
if ( f->IsQuadratic() )
nbNodes /= 2; const SMDS_MeshElement* f1 =
bool onBnd = false; SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
for ( int i = 0; !onBnd && i < nbNodes; ++i ) { if ( !f1 ) RETURN_BAD_RESULT("The first face on seam not found");
const SMDS_MeshNode* node = f->GetNode( i ); notInSet.insert( f1 );
onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
const SMDS_MeshElement* f2 =
SMESH_MeshAlgos::FindFaceInSet( vNode, eNode, inSet, notInSet );
if ( !f2 ) RETURN_BAD_RESULT("The second face on seam not found");
// select a face with less UV of vNode
const SMDS_MeshNode* notSeamNode[2] = {0, 0};
for ( int iF = 0; iF < 2; ++iF ) {
const SMDS_MeshElement* f = ( iF ? f2 : f1 );
for ( int i = 0; !notSeamNode[ iF ] && i < f->NbNodes(); ++i ) {
const SMDS_MeshNode* node = f->GetNode( i );
if ( !helper->IsSeamShape( node->getshapeId() ))
notSeamNode[ iF ] = node;
}
} }
if ( !onBnd ) gp_Pnt2d uv1 = helper->GetNodeUV( face, vNode, notSeamNode[0] );
elems.insert( f ); gp_Pnt2d uv2 = helper->GetNodeUV( face, vNode, notSeamNode[1] );
} if ( uv1.X() + uv1.Y() > uv2.X() + uv2.Y() )
// add also faces adjacent to faceToKeep faceToKeep = f2;
int nbNodes = faceToKeep->NbNodes(); else
if ( faceToKeep->IsQuadratic() ) nbNodes /= 2; faceToKeep = f1;
notInSet.insert( f1 );
notInSet.insert( f2 );
for ( int i = 0; i < nbNodes; ++i ) {
const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
if ( f1 )
elems.insert( f1 );
}
} // case on a sphere
} // loop on 2 faces
// int quadFactor = (*Elems1.begin())->IsQuadratic() ? 2 : 1; // fill elem set
elems.insert( faceToKeep );
while ( eIt->more() ) {
const SMDS_MeshElement* f = eIt->next();
int nbNodes = f->NbNodes();
if ( f->IsQuadratic() )
nbNodes /= 2;
bool onBnd = false;
for ( int i = 0; !onBnd && i < nbNodes; ++i ) {
const SMDS_MeshNode* node = f->GetNode( i );
onBnd = ( node->GetPosition()->GetTypeOfPosition() != SMDS_TOP_FACE);
}
if ( !onBnd )
elems.insert( f );
}
// add also faces adjacent to faceToKeep
int nbNodes = faceToKeep->NbNodes();
if ( faceToKeep->IsQuadratic() ) nbNodes /= 2;
notInSet.insert( f1 );
notInSet.insert( f2 );
for ( int i = 0; i < nbNodes; ++i ) {
const SMDS_MeshNode* n1 = faceToKeep->GetNode( i );
const SMDS_MeshNode* n2 = faceToKeep->GetNode(( i+1 ) % nbNodes );
f1 = SMESH_MeshAlgos::FindFaceInSet( n1, n2, inSet, notInSet );
if ( f1 )
elems.insert( f1 );
}
} // case on a sphere
} // loop on 2 faces
node1To2Map.clear(); node1To2Map.clear();
int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2, assocRes = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
vNode1, vNode2, vNode1, vNode2,
eNode1[0], eNode2[0], eNode1[0], eNode2[0],
node1To2Map); node1To2Map);
if ( res != SMESH_MeshEditor::SEW_OK ) if (( assocRes != SMESH_MeshEditor::SEW_OK ) &&
RETURN_BAD_RESULT("FindMatchingNodes() result " << res ); ( eNode1[1] || eNode2[1] )) // there is another node to try (on a closed EDGE)
{
node1To2Map.clear();
if ( eNode1[1] ) std::swap( eNode1[0], eNode1[1] );
else std::swap( eNode2[0], eNode2[1] );
continue; // one more attempt
}
break;
}
if ( assocRes != SMESH_MeshEditor::SEW_OK )
RETURN_BAD_RESULT("FindMatchingNodes() result " << assocRes );
// On a sphere, add matching nodes on the edge // On a sphere, add matching nodes on the edge

View File

@ -568,6 +568,7 @@ namespace {
vector< gp_XYZ > srcPnts, tgtPnts; vector< gp_XYZ > srcPnts, tgtPnts;
srcPnts.reserve( totNbSeg ); srcPnts.reserve( totNbSeg );
tgtPnts.reserve( totNbSeg ); tgtPnts.reserve( totNbSeg );
gp_XYZ srcBC( 0,0,0 ), tgtBC( 0,0,0 );
for ( size_t iW = 0; iW < srcWires.size(); ++iW ) for ( size_t iW = 0; iW < srcWires.size(); ++iW )
{ {
const double minSegLen = srcWires[iW]->Length() / totNbSeg; const double minSegLen = srcWires[iW]->Length() / totNbSeg;
@ -584,6 +585,8 @@ namespace {
tgtPnts.push_back( tgtWires[iW]->Value3d( tgtU ).XYZ() ); tgtPnts.push_back( tgtWires[iW]->Value3d( tgtU ).XYZ() );
srcU += srcDu; srcU += srcDu;
tgtU += tgtDu; tgtU += tgtDu;
srcBC += srcPnts.back();
tgtBC += tgtPnts.back();
} }
} }
} }
@ -596,6 +599,8 @@ namespace {
const int nbTestPnt = 20; const int nbTestPnt = 20;
const size_t iStep = Max( 1, int( srcPnts.size() / nbTestPnt )); const size_t iStep = Max( 1, int( srcPnts.size() / nbTestPnt ));
// check boundary // check boundary
gp_Pnt trsfTgt = trsf.Transform( srcBC / srcPnts.size() );
trsfIsOK = ( trsfTgt.SquareDistance( tgtBC / tgtPnts.size() ) < tol*tol );
for ( size_t i = 0; ( i < srcPnts.size() && trsfIsOK ); i += iStep ) for ( size_t i = 0; ( i < srcPnts.size() && trsfIsOK ); i += iStep )
{ {
gp_Pnt trsfTgt = trsf.Transform( srcPnts[i] ); gp_Pnt trsfTgt = trsf.Transform( srcPnts[i] );
@ -606,8 +611,8 @@ namespace {
{ {
BRepAdaptor_Surface srcSurf( srcFace ); BRepAdaptor_Surface srcSurf( srcFace );
gp_Pnt srcP = gp_Pnt srcP =
srcSurf.Value( 0.5 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ), srcSurf.Value( 0.321 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ),
0.5 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() )); 0.123 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() ));
gp_Pnt tgtTrsfP = trsf.Transform( srcP ); gp_Pnt tgtTrsfP = trsf.Transform( srcP );
TopLoc_Location loc; TopLoc_Location loc;
GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( tgtFace, loc, 0.1*tol ); GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( tgtFace, loc, 0.1*tol );
@ -888,10 +893,9 @@ namespace {
case SMDS_TOP_EDGE: { case SMDS_TOP_EDGE: {
TopoDS_Shape srcEdge = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() ); TopoDS_Shape srcEdge = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() );
TopoDS_Edge tgtEdge = TopoDS::Edge( shape2ShapeMap( srcEdge, /*isSrc=*/true )); TopoDS_Edge tgtEdge = TopoDS::Edge( shape2ShapeMap( srcEdge, /*isSrc=*/true ));
tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge )); double U = Precision::Infinite();
double U = srcHelper.GetNodeU( TopoDS::Edge( srcEdge ), srcNode );
helper.CheckNodeU( tgtEdge, n, U, Precision::PConfusion()); helper.CheckNodeU( tgtEdge, n, U, Precision::PConfusion());
n->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition( U ))); tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ), U );
break; break;
} }
case SMDS_TOP_VERTEX: { case SMDS_TOP_VERTEX: {
@ -922,12 +926,12 @@ namespace {
*/ */
//================================================================================ //================================================================================
void fixDistortedFaces( SMESH_MesherHelper& helper, bool fixDistortedFaces( SMESH_MesherHelper& helper,
TSideVector& tgtWires ) TSideVector& tgtWires )
{ {
SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() ); SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() );
if ( helper.IsDistorted2D( faceSM )) if ( helper.IsDistorted2D( faceSM, /*checkUV=*/false ))
{ {
SMESH_MeshEditor editor( helper.GetMesh() ); SMESH_MeshEditor editor( helper.GetMesh() );
SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS(); SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS();
@ -965,7 +969,12 @@ namespace {
set<const SMDS_MeshNode*> fixedNodes; set<const SMDS_MeshNode*> fixedNodes;
editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10, editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
/*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar); /*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
helper.ToFixNodeParameters( true );
return !helper.IsDistorted2D( faceSM, /*checkUV=*/true );
} }
return true;
} }
} // namespace } // namespace
@ -1048,25 +1057,28 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
if ( err && !err->IsOK() ) if ( err && !err->IsOK() )
return error( err ); return error( err );
bool done = false; bool projDone = false;
if ( !done ) if ( !projDone )
{ {
// try to project from the same face with different location // try to project from the same face with different location
done = projectPartner( tgtFace, srcFace, tgtWires, srcWires, projDone = projectPartner( tgtFace, srcFace, tgtWires, srcWires,
shape2ShapeMap, _src2tgtNodes, is1DComputed ); shape2ShapeMap, _src2tgtNodes, is1DComputed );
} }
if ( !done ) if ( !projDone )
{ {
// projection in case if the faces are similar in 2D space // projection in case if the faces are similar in 2D space
done = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires, projDone = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires,
shape2ShapeMap, _src2tgtNodes, is1DComputed); shape2ShapeMap, _src2tgtNodes, is1DComputed);
} }
SMESH_MesherHelper helper( theMesh ); SMESH_MesherHelper helper( theMesh );
helper.SetSubShape( tgtFace ); helper.SetSubShape( tgtFace );
if ( !done ) // it will remove mesh built on edges and vertices in failure case
MeshCleaner cleaner( tgtSubMesh );
if ( !projDone )
{ {
_src2tgtNodes.clear(); _src2tgtNodes.clear();
// -------------------- // --------------------
@ -1166,10 +1178,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
return error("Can't make mesh by source mesh pattern"); return error("Can't make mesh by source mesh pattern");
// it will remove mesh built by pattern mapper on edges and vertices
// in failure case
MeshCleaner cleaner( tgtSubMesh );
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// mapper doesn't take care of nodes already existing on edges and vertices, // mapper doesn't take care of nodes already existing on edges and vertices,
// so we must merge nodes created by it with existing ones // so we must merge nodes created by it with existing ones
@ -1329,14 +1337,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() ) if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() )
return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces"); return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
// ----------------------------------------------------------------
// The mapper can create distorted faces by placing nodes out of the FACE
// boundary -- fix bad faces by smoothing
// ----------------------------------------------------------------
fixDistortedFaces( helper, tgtWires );
// ---------------------------------------------------------------- // ----------------------------------------------------------------
// The mapper can't create quadratic elements, so convert if needed // The mapper can't create quadratic elements, so convert if needed
// ---------------------------------------------------------------- // ----------------------------------------------------------------
@ -1355,11 +1355,18 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false); editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false);
} }
cleaner.Release(); // not to remove mesh
} // end of projection using Pattern mapping } // end of projection using Pattern mapping
if ( !projDone || is1DComputed )
// ----------------------------------------------------------------
// The mapper can create distorted faces by placing nodes out of the FACE
// boundary, also bad face can be created if EDGEs already discretized
// --> fix bad faces by smoothing
// ----------------------------------------------------------------
if ( !fixDistortedFaces( helper, tgtWires ))
return error("Invalid mesh generated");
// --------------------------- // ---------------------------
// Check elements orientation // Check elements orientation
// --------------------------- // ---------------------------
@ -1405,6 +1412,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape&
} }
} }
cleaner.Release(); // not to remove mesh
return true; return true;
} }