int shapeID = n->getshapeId();
bool infinit = Precision::IsInfinite( u );
bool zero = ( u == 0. );
- if ( force || toCheckPosOnShape( shapeID ) || infinit || zero )
+ if ( force || infinit || zero || toCheckPosOnShape( shapeID ))
{
TopLoc_Location loc; double f,l;
Handle(Geom_Curve) curve = BRep_Tool::Curve( E,loc,f,l );
gp_Pnt nodePnt = SMESH_TNodeXYZ( n );
if ( !loc.IsIdentity() ) nodePnt.Transform( loc.Transformation().Inverted() );
gp_Pnt curvPnt;
- double dist = u;
+ double dist = 2*tol;
if ( !infinit )
{
curvPnt = curve->Value( u );
//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 )
return false;
double prevArea2D = 0;
vector< const SMDS_MeshNode* > nodes;
vector< gp_XY > uv;
+ bool* toCheckUV = checkUV ? & checkUV : 0;
while ( faceIt->more() && !haveBadFaces )
{
const SMDS_MeshElement* face = faceIt->next();
// get UVs
uv.resize( nodes.size() );
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
for ( int iT = 0, nbT = nodes.size()-2; iT < nbT; ++iT )
/*!
* \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
list< Prism_3D::TPrismTopo > meshedPrism;
list< TopoDS_Face > suspectSourceFaces;
TopTools_ListIteratorOfListOfShape solidIt;
+ bool selectBottom = false;
while ( meshedSolids.Extent() < nbSolids )
{
{
prism.Clear();
prism.myBottom = face;
- if ( !initPrism( prism, solid ) ||
+ if ( !initPrism( prism, solid, selectBottom ) ||
!compute( prism ))
return false;
while ( const TopoDS_Shape* f = faceIt->next() )
{
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.myBottom = candidateF;
+ prism.myBottom = candidateF;
mySetErrorToSM = false;
if ( !myHelper->IsSubShape( candidateF, prismIt->myShape3D ) &&
- myHelper->IsSubShape( candidateF, solid ) &&
+ myHelper ->IsSubShape( candidateF, solid ) &&
!myHelper->GetMesh()->GetSubMesh( candidateF )->IsMeshComputed() &&
- initPrism( prism, solid ) &&
+ initPrism( prism, solid, /*selectBottom=*/false ) &&
!myHelper->GetMesh()->GetSubMesh( prism.myTop )->IsMeshComputed() &&
- project2dMesh( prismIt->myBottom, candidateF))
+ !myHelper->GetMesh()->GetSubMesh( prism.myBottom )->IsMeshComputed() &&
+ project2dMesh( sourceF, prism.myBottom ))
{
mySetErrorToSM = true;
if ( !compute( prism ))
{
meshedFaces.push_front( prism.myTop );
meshedFaces.push_front( prism.myBottom );
+ selectBottom = false;
}
meshedPrism.push_back( prism );
meshedSolids.Add( solid );
if ( meshedFaces.empty() )
{
meshedFaces.splice( meshedFaces.end(), suspectSourceFaces );
+ selectBottom = true;
}
// find FACEs with local 1D hyps, which has to be computed by now,
{
if ( !meshedFaces.empty() ) meshedFaces.pop_back();
meshedFaces.push_back( face ); // lower priority
+ selectBottom = true;
prevNbFaces = nbFaces;
}
}
faceSM->ComputeStateEngine( SMESH_subMesh::COMPUTE );
if ( !faceSM->IsEmpty() ) {
meshedFaces.push_front( face ); // higher priority
+ selectBottom = true;
break;
}
else {
meshedFaces.push_front( prism.myBottom );
meshedPrism.push_back( prism );
meshedSolids.Add( solid.Current() );
+ selectBottom = true;
}
mySetErrorToSM = true;
}
StdMeshers_FaceSidePtr topSide = thePrism.myWallQuads[i].back()->side[ QUAD_TOP_SIDE ];
const TopoDS_Edge & topE = topSide->Edge( 0 );
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;
if ( _computeCanceled )
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
if ( !computeWalls( thePrism ))
return false;
// 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
- // and location of internal nodes is computed by StdMeshers_Sweeper)
+ // (after fixing IPAL52499 myBlock is used as a holder of boundary nodes
+ // 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 ))
return toSM( error( myBlock.GetError()));
// Projections on the top and bottom faces are taken from nodes existing
// on these faces; find correspondence between bottom and top nodes
+ myUseBlock = false;
myBotToColumnMap.clear();
if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap
return false;
// use transformation (issue 0020680, IPAL0052499)
StdMeshers_Sweeper sweeper;
+ double tol;
- // load boundary nodes
- bool dummy;
- list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
- for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+ if ( !myUseBlock )
{
- 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 );
+ // load boundary nodes into sweeper
+ bool dummy;
+ list< TopoDS_Edge >::const_iterator edge = thePrism.myBottomEdges.begin();
+ for ( ; edge != thePrism.myBottomEdges.end(); ++edge )
+ {
+ 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 );
- const double tol = getSweepTolerance( thePrism );
+ tol = getSweepTolerance( thePrism );
+ }
- if ( sweeper.ComputeNodes( *myHelper, tol ))
+ if ( !myUseBlock && sweeper.ComputeNodes( *myHelper, tol ))
{
}
else // use block approach
for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad )
{
const TopoDS_Face& face = (*quad)->face;
- SMESH_subMesh* fSM = mesh->GetSubMesh( face );
+ SMESH_subMesh* fSM = mesh->GetSubMesh( face );
if ( ! fSM->IsMeshComputed() )
{
// Top EDGEs must be projections from the bottom ones
NSProjUtils::TShapeShapeMap shape2ShapeMap;
const bool sameTopo =
NSProjUtils::FindSubShapeAssociation( thePrism.myBottom, myHelper->GetMesh(),
- thePrism.myTop, myHelper->GetMesh(),
- shape2ShapeMap);
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap);
if ( !sameTopo )
for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ )
{
for ( int iE = 0; iE < botSide->NbEdges(); ++iE )
{
NSProjUtils::InsertAssociation( botSide->Edge( iE ),
- topSide->Edge( iE ), shape2ShapeMap );
+ topSide->Edge( iE ), shape2ShapeMap );
NSProjUtils::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )),
- myHelper->IthVertex( 0, topSide->Edge( iE )),
- shape2ShapeMap );
+ myHelper->IthVertex( 0, topSide->Edge( iE )),
+ shape2ShapeMap );
}
}
else
vt.IsSame( sideT->LastVertex() ))
{
NSProjUtils::InsertAssociation( botSide->Edge( 0 ),
- topSide->Edge( 0 ), shape2ShapeMap );
+ topSide->Edge( 0 ), shape2ShapeMap );
NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
}
vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 ));
vt.IsSame( sideT->LastVertex() ))
{
NSProjUtils::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ),
- topSide->Edge( topSide->NbEdges()-1 ),
- shape2ShapeMap );
+ topSide->Edge( topSide->NbEdges()-1 ),
+ shape2ShapeMap );
NSProjUtils::InsertAssociation( vb, vt, shape2ShapeMap );
}
}
// Find matching nodes of top and bottom faces
n2nMapPtr = & n2nMap;
if ( ! NSProjUtils::FindMatchingNodesOnFaces( thePrism.myBottom, myHelper->GetMesh(),
- thePrism.myTop, myHelper->GetMesh(),
- shape2ShapeMap, n2nMap ))
+ thePrism.myTop, myHelper->GetMesh(),
+ shape2ShapeMap, n2nMap ))
{
if ( sameTopo )
return toSM( error(TCom("Mesh on faces #") << botSM->GetId()
continue; // wall columns are contained in myBlock
// create node column
Prism_3D::TNode bN( botNode );
- TNode2ColumnMap::iterator bN_col =
+ TNode2ColumnMap::iterator bN_col =
myBotToColumnMap.insert( make_pair ( bN, TNodeColumn() )).first;
TNodeColumn & column = bN_col->second;
column.resize( zSize );
{
return true;
}
+ NSProjUtils::TNodeNodeMap& n2nMap =
+ (NSProjUtils::TNodeNodeMap&) TProjction2dAlgo::instance( this )->GetNodesMap();
+ n2nMap.clear();
+
+ myUseBlock = true;
SMESHDS_Mesh* meshDS = myHelper->GetMeshDS();
SMESH_subMesh * botSM = myHelper->GetMesh()->GetSubMesh( thePrism.myBottom );
SMESHDS_SubMesh * topSMDS = topSM->GetSubMeshDS();
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& topFace = thePrism.myTop; // the 3D SHAPE
column.front() = botNode;
column.back() = topNode;
+ n2nMap.insert( n2nMap.end(), make_pair( botNode, topNode ));
+
if ( _computeCanceled )
return toSM( error( SMESH_ComputeError::New(COMPERR_CANCELED)));
}
bool ok = projector2D->Compute( *myHelper->GetMesh(), 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->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
//=======================================================================
bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism,
- const TopoDS_Shape& shape3D)
+ const TopoDS_Shape& shape3D,
+ const bool selectBottom)
{
myHelper->SetSubShape( shape3D );
// use thePrism.myBottom
if ( !thePrism.myBottom.IsNull() )
{
- if ( botSM ) {
+ if ( botSM ) { // <-- not quad geom or mesh on botSM
if ( ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
std::swap( botSM, topSM );
- if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom ))
- return toSM( error( COMPERR_BAD_INPUT_MESH,
- "Incompatible non-structured sub-meshes"));
+ if ( !botSM || ! botSM->GetSubShape().IsSame( thePrism.myBottom )) {
+ if ( !selectBottom )
+ 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 );
}
}
- else if ( !botSM ) // find a proper bottom
+ if ( !botSM ) // find a proper bottom
{
// composite walls or not prism shape
for ( TopExp_Explorer f( shape3D, TopAbs_FACE ); f.More(); f.Next() )
{
thePrism.Clear();
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 toSM( error( COMPERR_BAD_SHAPE ));
}
+ return toSM( error( COMPERR_BAD_SHAPE ));
}
// find vertex 000 - the one with smallest coordinates (for easy DEBUG :-)
thePrism.myNbEdgesInWires, V000 );
// 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"));
if ( topSM )
TopoDS_Shape s = myHelper.GetSubShapeByNode( nn[0], myHelper.GetMeshDS() );
if ( s.ShapeType() != TopAbs_EDGE )
s = myHelper.GetSubShapeByNode( nn[2], myHelper.GetMeshDS() );
- if ( s.ShapeType() == TopAbs_EDGE )
+ if ( !s.IsNull() && s.ShapeType() == TopAbs_EDGE )
edge = TopoDS::Edge( s );
}
if ( !edge.IsNull() )
* \brief Analyse shape geometry and mesh.
* 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
bool myProjectTriangles;
bool mySetErrorToSM;
+ bool myUseBlock;
StdMeshers_PrismAsBlock myBlock;
SMESH_MesherHelper* myHelper;
// 2. face sets
- set<const SMDS_MeshElement*> Elems1, Elems2;
- for ( int is2 = 0; is2 < 2; ++is2 )
+ int assocRes;
+ for ( int iAttempt = 0; iAttempt < 2; ++iAttempt )
{
- set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
- SMESHDS_SubMesh* sm = is2 ? SM2 : SM1;
- 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() );
- }
- else
+ set<const SMDS_MeshElement*> Elems1, Elems2;
+ for ( int is2 = 0; is2 < 2; ++is2 )
{
- // 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
-
- // find a face to keep
- const SMDS_MeshElement* faceToKeep = 0;
- const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
- 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;
- }
+ set<const SMDS_MeshElement*> & elems = is2 ? Elems2 : Elems1;
+ SMESHDS_SubMesh* sm = is2 ? SM2 : SM1;
+ 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( elems.end(), eIt->next() );
}
- 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
- faceToKeep = f1;
-
- // 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);
+ {
+ // 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
+
+ // find a face to keep
+ const SMDS_MeshElement* faceToKeep = 0;
+ const SMDS_MeshNode* vNode = is2 ? vNode2 : vNode1;
+ 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;
+ }
}
- 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
-
- // int quadFactor = (*Elems1.begin())->IsQuadratic() ? 2 : 1;
-
- node1To2Map.clear();
- int res = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
- vNode1, vNode2,
- eNode1[0], eNode2[0],
- node1To2Map);
- if ( res != SMESH_MeshEditor::SEW_OK )
- RETURN_BAD_RESULT("FindMatchingNodes() result " << res );
+ 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
+ faceToKeep = f1;
+
+ // 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();
+ assocRes = SMESH_MeshEditor::FindMatchingNodes( Elems1, Elems2,
+ vNode1, vNode2,
+ eNode1[0], eNode2[0],
+ node1To2Map);
+ if (( assocRes != SMESH_MeshEditor::SEW_OK ) &&
+ ( 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
vector< gp_XYZ > srcPnts, tgtPnts;
srcPnts.reserve( totNbSeg );
tgtPnts.reserve( totNbSeg );
+ gp_XYZ srcBC( 0,0,0 ), tgtBC( 0,0,0 );
for ( size_t iW = 0; iW < srcWires.size(); ++iW )
{
const double minSegLen = srcWires[iW]->Length() / totNbSeg;
tgtPnts.push_back( tgtWires[iW]->Value3d( tgtU ).XYZ() );
srcU += srcDu;
tgtU += tgtDu;
+ srcBC += srcPnts.back();
+ tgtBC += tgtPnts.back();
}
}
}
const int nbTestPnt = 20;
const size_t iStep = Max( 1, int( srcPnts.size() / nbTestPnt ));
// 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 )
{
gp_Pnt trsfTgt = trsf.Transform( srcPnts[i] );
{
BRepAdaptor_Surface srcSurf( srcFace );
gp_Pnt srcP =
- srcSurf.Value( 0.5 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ),
- 0.5 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() ));
+ srcSurf.Value( 0.321 * ( srcSurf.FirstUParameter() + srcSurf.LastUParameter() ),
+ 0.123 * ( srcSurf.FirstVParameter() + srcSurf.LastVParameter() ));
gp_Pnt tgtTrsfP = trsf.Transform( srcP );
TopLoc_Location loc;
GeomAPI_ProjectPointOnSurf& proj = helper.GetProjector( tgtFace, loc, 0.1*tol );
case SMDS_TOP_EDGE: {
TopoDS_Shape srcEdge = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() );
TopoDS_Edge tgtEdge = TopoDS::Edge( shape2ShapeMap( srcEdge, /*isSrc=*/true ));
- tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ));
- double U = srcHelper.GetNodeU( TopoDS::Edge( srcEdge ), srcNode );
+ double U = Precision::Infinite();
helper.CheckNodeU( tgtEdge, n, U, Precision::PConfusion());
- n->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition( U )));
+ tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ), U );
break;
}
case SMDS_TOP_VERTEX: {
*/
//================================================================================
- void fixDistortedFaces( SMESH_MesherHelper& helper,
+ bool fixDistortedFaces( SMESH_MesherHelper& helper,
TSideVector& tgtWires )
{
SMESH_subMesh* faceSM = helper.GetMesh()->GetSubMesh( helper.GetSubShape() );
- if ( helper.IsDistorted2D( faceSM ))
+ if ( helper.IsDistorted2D( faceSM, /*checkUV=*/false ))
{
SMESH_MeshEditor editor( helper.GetMesh() );
SMESHDS_SubMesh* smDS = faceSM->GetSubMeshDS();
set<const SMDS_MeshNode*> fixedNodes;
editor.Smooth( faces, fixedNodes, algo, /*nbIterations=*/ 10,
/*theTgtAspectRatio=*/1.0, /*the2D=*/!isPlanar);
+
+ helper.ToFixNodeParameters( true );
+
+ return !helper.IsDistorted2D( faceSM, /*checkUV=*/true );
}
+ return true;
}
} // namespace
if ( err && !err->IsOK() )
return error( err );
- bool done = false;
+ bool projDone = false;
- if ( !done )
+ if ( !projDone )
{
// try to project from the same face with different location
- done = projectPartner( tgtFace, srcFace, tgtWires, srcWires,
- shape2ShapeMap, _src2tgtNodes, is1DComputed );
+ projDone = projectPartner( tgtFace, srcFace, tgtWires, srcWires,
+ shape2ShapeMap, _src2tgtNodes, is1DComputed );
}
- if ( !done )
+ if ( !projDone )
{
// projection in case if the faces are similar in 2D space
- done = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires,
- shape2ShapeMap, _src2tgtNodes, is1DComputed);
+ projDone = projectBy2DSimilarity( tgtFace, srcFace, tgtWires, srcWires,
+ shape2ShapeMap, _src2tgtNodes, is1DComputed);
}
SMESH_MesherHelper helper( theMesh );
helper.SetSubShape( tgtFace );
- if ( !done )
+ // it will remove mesh built on edges and vertices in failure case
+ MeshCleaner cleaner( tgtSubMesh );
+
+ if ( !projDone )
{
_src2tgtNodes.clear();
// --------------------
if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
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,
// so we must merge nodes created by it with existing ones
if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() )
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
// ----------------------------------------------------------------
editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false);
}
- cleaner.Release(); // not to remove mesh
-
} // 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
// ---------------------------
}
}
+ cleaner.Release(); // not to remove mesh
+
return true;
}