-// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
#include <Bnd_B2d.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopoDS.hxx>
#include <gp_Ax2.hxx>
#define RETURN_BAD_RESULT(msg) { MESSAGE(")-: Error: " << msg); return false; }
-typedef StdMeshers_ProjectionUtils TAssocTool;
+namespace TAssocTool = StdMeshers_ProjectionUtils;
+//typedef StdMeshers_ProjectionUtils TAssocTool;
//=======================================================================
//function : StdMeshers_Projection_2D
:SMESH_2D_Algo(hypId, studyId, gen)
{
_name = "Projection_2D";
- _shapeType = (1 << TopAbs_FACE); // 1 bit per shape type
-
_compatibleHypothesis.push_back("ProjectionSource2D");
_sourceHypo = 0;
}
/*!
* \brief find new nodes belonging to one free border of mesh on face
* \param sm - submesh on edge or vertex containg nodes to choose from
- * \param face - the face bound the submesh
+ * \param face - the face bound by the submesh
* \param u2nodes - map to fill with nodes
* \param seamNodes - set of found nodes
* \retval bool - is a success
if ( !smV1->IsMeshComputed() || !smV2->IsMeshComputed() )
RETURN_BAD_RESULT("Empty vertex submeshes");
- // Look for a new node on V1
- nIt = smV1->GetSubMeshDS()->GetNodes();
const SMDS_MeshNode* nV1 = 0;
- while ( nIt->more() && !nV1 ) {
- const SMDS_MeshNode* node = nIt->next();
- if ( !isOldNode( node ) ) nV1 = node;
- }
- if ( !nV1 )
- RETURN_BAD_RESULT("No new node found on V1");
-
- // Find a new node connected to nV1 and belonging to edge submesh;
const SMDS_MeshNode* nE = 0;
- SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
- SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(SMDSAbs_Face);
- while ( vElems->more() && !nE ) {
- const SMDS_MeshElement* elem = vElems->next();
- int nbNodes = elem->NbNodes();
- if ( elem->IsQuadratic() )
- nbNodes /= 2;
- int iV1 = elem->GetNodeIndex( nV1 );
- // try next after nV1
- int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
- if ( smDS->Contains( elem->GetNode( iE ) ))
- nE = elem->GetNode( iE );
- if ( !nE ) {
- // try node before nV1
- iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
- if ( smDS->Contains( elem->GetNode( iE )))
+
+ // Look for nV1 - a new node on V1
+ nIt = smV1->GetSubMeshDS()->GetNodes();
+ while ( nIt->more() && !nE ) {
+ const SMDS_MeshNode* node = nIt->next();
+ if ( isOldNode( node ) ) continue;
+ nV1 = node;
+
+ // Find nE - a new node connected to nV1 and belonging to edge submesh;
+ SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
+ SMDS_ElemIteratorPtr vElems = nV1->GetInverseElementIterator(SMDSAbs_Face);
+ while ( vElems->more() && !nE ) {
+ const SMDS_MeshElement* elem = vElems->next();
+ int nbNodes = elem->NbNodes();
+ if ( elem->IsQuadratic() )
+ nbNodes /= 2;
+ int iV1 = elem->GetNodeIndex( nV1 );
+ // try next after nV1
+ int iE = SMESH_MesherHelper::WrapIndex( iV1 + 1, nbNodes );
+ if ( smDS->Contains( elem->GetNode( iE ) ))
nE = elem->GetNode( iE );
- }
- if ( nE && elem->IsQuadratic() ) { // find medium node between nV1 and nE
- if ( Abs( iV1 - iE ) == 1 )
- nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
- else
- nE = elem->GetNode( elem->NbNodes() - 1 );
+ if ( !nE ) {
+ // try node before nV1
+ iE = SMESH_MesherHelper::WrapIndex( iV1 - 1, nbNodes );
+ if ( smDS->Contains( elem->GetNode( iE )))
+ nE = elem->GetNode( iE );
+ }
+ if ( nE && elem->IsQuadratic() ) { // find medium node between nV1 and nE
+ if ( Abs( iV1 - iE ) == 1 )
+ nE = elem->GetNode( Min ( iV1, iE ) + nbNodes );
+ else
+ nE = elem->GetNode( elem->NbNodes() - 1 );
+ }
}
}
+ if ( !nV1 )
+ RETURN_BAD_RESULT("No new node found on V1");
if ( !nE )
RETURN_BAD_RESULT("new node on edge not found");
// make any local coord systems of src and tgt faces
vector<gp_Pnt> srcPP, tgtPP; // 3 points on face boundaries to make axes of CS
- SMESH_subMesh * srcSM = srcMesh->GetSubMesh( srcFace );
+ int tgtNbVert = SMESH_MesherHelper::Count( tgtFace, TopAbs_VERTEX, /*ignoreSame=*/true );
+ int srcNbVert = SMESH_MesherHelper::Count( srcFace, TopAbs_VERTEX, /*ignoreSame=*/true );
+ SMESH_subMesh * srcSM = srcMesh->GetSubMesh( srcFace );
SMESH_subMeshIteratorPtr smIt = srcSM->getDependsOnIterator(/*includeSelf=*/false,false);
srcSM = smIt->next(); // sm of a vertex
while ( smIt->more() && srcPP.size() < 3 )
// find corresponding point on target shape
pOK = false;
gp_Pnt tgtP;
- const TopoDS_Shape& tgtShape = shape2ShapeMap( srcSM->GetSubShape() );
+ const TopoDS_Shape& tgtShape = shape2ShapeMap( srcSM->GetSubShape(), /*isSrc=*/true );
if ( tgtShape.ShapeType() == TopAbs_VERTEX )
{
tgtP = BRep_Tool::Pnt( TopoDS::Vertex( tgtShape ));
- pOK = true;
+ if ( srcNbVert == tgtNbVert || tgtPP.empty() )
+ pOK = true;
+ else
+ pOK = (( tgtP.Distance( tgtPP[0] ) > tol*tol ) &&
+ ( tgtPP.size() == 1 || tgtP.Distance( tgtPP[1] ) > tol*tol ));
//cout << "V - nS " << p._node->GetID() << " - nT " << SMESH_Algo::VertexNode(TopoDS::Vertex( tgtShape),tgtMesh->GetMeshDS())->GetID() << endl;
}
else if ( tgtPP.size() > 0 )
for ( TopExp_Explorer srcEdge( srcFace, TopAbs_EDGE); srcEdge.More(); srcEdge.Next() )
{
- const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current() );
+ const TopoDS_Shape& tgtEdge = shape2ShapeMap( srcEdge.Current(), /*isSrc=*/true );
map< double, const SMDS_MeshNode* > srcNodes, tgtNodes;
if ( !SMESH_Algo::GetSortedNodesOnEdge( srcMesh->GetMeshDS(),
{
list< TopoDS_Edge > tgtEdges;
StdMeshers_FaceSidePtr srcWire = srcWires[iW];
+ TopTools_IndexedMapOfShape edgeMap; // to detect seam edges
for ( int iE = 0; iE < srcWire->NbEdges(); ++iE )
- tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ))));
-
+ {
+ tgtEdges.push_back( TopoDS::Edge( shape2ShapeMap( srcWire->Edge( iE ), /*isSrc=*/true)));
+ // reverse a seam edge encountered for the second time
+ const int oldExtent = edgeMap.Extent();
+ edgeMap.Add( tgtEdges.back() );
+ if ( oldExtent == edgeMap.Extent() )
+ tgtEdges.back().Reverse();
+ }
tgtWires[ iW ].reset( new StdMeshers_FaceSide( tgtFace, tgtEdges, tgtMesh,
/*theIsForward = */ true,
/*theIgnoreMediumNodes = */false));
}
case SMDS_TOP_EDGE: {
TopoDS_Shape srcEdge = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() );
- TopoDS_Shape tgtEdge = shape2ShapeMap( srcEdge );
+ TopoDS_Edge tgtEdge = TopoDS::Edge( shape2ShapeMap( srcEdge, /*isSrc=*/true ));
+ tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ));
double U = srcHelper.GetNodeU( TopoDS::Edge( srcEdge ), srcNode );
- tgtMeshDS->SetNodeOnEdge( n, TopoDS::Edge( tgtEdge ), U);
+ helper.CheckNodeU( tgtEdge, n, U, Precision::PConfusion());
+ n->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition( U )));
break;
}
case SMDS_TOP_VERTEX: {
TopoDS_Shape srcV = srcHelper.GetSubShapeByNode( srcNode, srcHelper.GetMeshDS() );
- TopoDS_Shape tgtV = shape2ShapeMap( srcV );
+ TopoDS_Shape tgtV = shape2ShapeMap( srcV, /*isSrc=*/true );
tgtMeshDS->SetNodeOnVertex( n, TopoDS::Vertex( tgtV ));
break;
}
// Make sub-shapes association
// ---------------------------
- TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
+ TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD));
TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
TAssocTool::TShapeShapeMap shape2ShapeMap;
- TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace );
+ TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh,
shape2ShapeMap) ||
!shape2ShapeMap.IsBound( tgtFace ))
+ {
+ if ( srcShape.ShapeType() == TopAbs_FACE )
+ {
+ int nbE1 = SMESH_MesherHelper::Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true );
+ int nbE2 = SMESH_MesherHelper::Count( srcShape, TopAbs_EDGE, /*ignoreSame=*/true );
+ if ( nbE1 != nbE2 )
+ return error(COMPERR_BAD_SHAPE,
+ SMESH_Comment("Different number of edges in source and target faces: ")
+ << nbE2 << " and " << nbE1 );
+ }
return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" );
-
+ }
TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD));
// ----------------------------------------------
SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace );
SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace );
+ string srcMeshError;
if ( tgtMesh == srcMesh ) {
if ( !TAssocTool::MakeComputed( srcSubMesh ))
- return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
+ srcMeshError = TAssocTool::SourceNotComputedError( srcSubMesh, this );
}
else {
if ( !srcSubMesh->IsMeshComputed() )
- return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed");
+ srcMeshError = TAssocTool::SourceNotComputedError();
}
+ if ( !srcMeshError.empty() )
+ return error(COMPERR_BAD_INPUT_MESH, srcMeshError );
- // --------------------------
- // Simple cases of projection
- // --------------------------
+ // ===========
+ // Projection
+ // ===========
// find out if EDGEs are meshed or not
bool is1DComputed = false;
is1DComputed = sm->IsMeshComputed();
}
- // try to project from same face with different location
- if ( projectPartner( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap ))
- return true;
-
- if ( projectBy2DSimilarity( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap, is1DComputed ))
- return true;
+ bool done = false;
- // --------------------
- // Prepare to mapping
- // --------------------
+ if ( !done )
+ {
+ // try to project from the same face with different location
+ done = projectPartner( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap );
+ }
+ if ( !done )
+ {
+ // projection in case if the faces are similar in 2D space
+ done = projectBy2DSimilarity( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap, is1DComputed);
+ }
SMESH_MesherHelper helper( theMesh );
helper.SetSubShape( tgtFace );
- // Check if node projection to a face is needed
- Bnd_B2d uvBox;
- SMDS_ElemIteratorPtr faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
- int nbFaceNodes = 0;
- for ( ; nbFaceNodes < 3 && faceIt->more(); ) {
- const SMDS_MeshElement* face = faceIt->next();
- SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
- while ( nodeIt->more() ) {
- const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
- if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
- nbFaceNodes++;
- uvBox.Add( helper.GetNodeUV( srcFace, node ));
+ if ( !done )
+ {
+ // --------------------
+ // Prepare to mapping
+ // --------------------
+
+ // Check if node projection to a face is needed
+ Bnd_B2d uvBox;
+ SMDS_ElemIteratorPtr faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
+ int nbFaceNodes = 0;
+ for ( ; nbFaceNodes < 3 && faceIt->more(); ) {
+ const SMDS_MeshElement* face = faceIt->next();
+ SMDS_ElemIteratorPtr nodeIt = face->nodesIterator();
+ while ( nodeIt->more() ) {
+ const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+ if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) {
+ nbFaceNodes++;
+ uvBox.Add( helper.GetNodeUV( srcFace, node ));
+ }
}
}
- }
- const bool toProjectNodes =
- ( nbFaceNodes > 0 && ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN ));
-
- // Load pattern from the source face
- SMESH_Pattern mapper;
- mapper.Load( srcMesh, srcFace, toProjectNodes );
- if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
- return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
-
- // Find the first target vertex corresponding to first vertex of the <mapper>
- // and <theReverse> flag needed to call mapper.Apply()
-
- TopoDS_Vertex srcV1 = TopoDS::Vertex( mapper.GetSubShape( 1 ));
- if ( srcV1.IsNull() )
- RETURN_BAD_RESULT("Mesh is not bound to the face");
- if ( !shape2ShapeMap.IsBound( srcV1 ))
- RETURN_BAD_RESULT("Not associated vertices, srcV1 " << srcV1.TShape().operator->() );
- TopoDS_Vertex tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1 ));
-
- if ( !SMESH_MesherHelper::IsSubShape( srcV1, srcFace ))
- RETURN_BAD_RESULT("Wrong srcV1 " << srcV1.TShape().operator->());
- if ( !SMESH_MesherHelper::IsSubShape( tgtV1, tgtFace ))
- RETURN_BAD_RESULT("Wrong tgtV1 " << tgtV1.TShape().operator->());
-
- // try to find out orientation by order of edges
- bool reverse = false;
- list< TopoDS_Edge > tgtEdges, srcEdges;
- list< int > nbEdgesInWires;
- SMESH_Block::GetOrderedEdges( tgtFace, tgtV1, tgtEdges, nbEdgesInWires);
- SMESH_Block::GetOrderedEdges( srcFace, srcV1, srcEdges, nbEdgesInWires);
- if ( nbEdgesInWires.front() > 1 ) // possible to find out
- {
- TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
- TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 );
- reverse = ( ! srcE1.IsSame( srcE1bis ));
- }
- else if ( nbEdgesInWires.front() == 1 )
- {
- // TODO::Compare orientation of curves in a sole edge
- //RETURN_BAD_RESULT("Not implemented case");
- }
- else
- {
- RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()");
- }
+ const bool toProjectNodes =
+ ( nbFaceNodes > 0 && ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN ));
- // --------------------
- // Perform 2D mapping
- // --------------------
+ // Find the corresponding source and target vertex
+ // and <theReverse> flag needed to call mapper.Apply()
- // Compute mesh on a target face
+ TopoDS_Vertex srcV1, tgtV1;
+ bool reverse = false;
- mapper.Apply( tgtFace, tgtV1, reverse );
- if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
- return error("Can't apply source mesh pattern to the face");
-
- // Create the mesh
+ if ( _sourceHypo->HasVertexAssociation() ) {
+ srcV1 = _sourceHypo->GetSourceVertex(1);
+ tgtV1 = _sourceHypo->GetTargetVertex(1);
+ } else {
+ srcV1 = TopoDS::Vertex( TopExp_Explorer( srcFace, TopAbs_VERTEX ).Current() );
+ tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1, /*isSrc=*/true ));
+ }
+ list< TopoDS_Edge > tgtEdges, srcEdges;
+ list< int > nbEdgesInWires;
+ SMESH_Block::GetOrderedEdges( tgtFace, tgtEdges, nbEdgesInWires, tgtV1 );
+ SMESH_Block::GetOrderedEdges( srcFace, srcEdges, nbEdgesInWires, srcV1 );
- const bool toCreatePolygons = false, toCreatePolyedrs = false;
- mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs );
- if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
- return error("Can't make mesh by source mesh pattern");
+ if ( nbEdgesInWires.front() > 1 ) // possible to find out orientation
+ {
+ TopoDS_Edge srcE1 = srcEdges.front(), tgtE1 = tgtEdges.front();
+ TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 );
+ reverse = ( ! srcE1.IsSame( srcE1bis ));
+ if ( reverse &&
+ _sourceHypo->HasVertexAssociation() &&
+ nbEdgesInWires.front() > 2 &&
+ helper.IsRealSeam( tgtEdges.front() ))
+ {
+ // projection to a face with seam EDGE; pb is that GetOrderedEdges()
+ // always puts a seam EDGE first (if possible) and as a result
+ // we can't use only theReverse flag to correctly associate source
+ // and target faces in the mapper. Thus we select srcV1 so that
+ // GetOrderedEdges() to return EDGEs in a needed order
+ list< TopoDS_Edge >::iterator edge = srcEdges.begin();
+ for ( ; edge != srcEdges.end(); ++edge ) {
+ if ( srcE1bis.IsSame( *edge )) {
+ srcV1 = helper.IthVertex( 0, *edge );
+ break;
+ }
+ }
+ }
+ }
+ else if ( nbEdgesInWires.front() == 1 )
+ {
+ // TODO::Compare orientation of curves in a sole edge
+ //RETURN_BAD_RESULT("Not implemented case");
+ }
+ else
+ {
+ RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()");
+ }
- // it will remove mesh built by pattern mapper on edges and vertices
- // in failure case
- MeshCleaner cleaner( tgtSubMesh );
+ // Load pattern from the source face
+ SMESH_Pattern mapper;
+ mapper.Load( srcMesh, srcFace, toProjectNodes, srcV1 );
+ if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+ return error(COMPERR_BAD_INPUT_MESH,"Can't load mesh pattern from the source face");
- SMESH_MeshEditor editor( tgtMesh );
+ // --------------------
+ // Perform 2D mapping
+ // --------------------
- // -------------------------------------------------------------------------
- // mapper doesn't take care of nodes already existing on edges and vertices,
- // so we must merge nodes created by it with existing ones
- // -------------------------------------------------------------------------
+ // Compute mesh on a target face
- SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
+ mapper.Apply( tgtFace, tgtV1, reverse );
+ if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+ return error("Can't apply source mesh pattern to the face");
- // Make groups of nodes to merge
+ // Create the mesh
- // loop on edge and vertex submeshes of a target face
- smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,/*complexShapeFirst=*/false);
- while ( smIt->more() )
- {
- SMESH_subMesh* sm = smIt->next();
- SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
- if ( !sm->IsMeshComputed() )
- break;
- //if ( !is1DComputed && sm->GetSubShape().ShapeType() == TopAbs_EDGE )
- //break;
+ const bool toCreatePolygons = false, toCreatePolyedrs = false;
+ mapper.MakeMesh( tgtMesh, toCreatePolygons, toCreatePolyedrs );
+ if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK )
+ return error("Can't make mesh by source mesh pattern");
- // Sort new and old nodes of a submesh separately
+ // it will remove mesh built by pattern mapper on edges and vertices
+ // in failure case
+ MeshCleaner cleaner( tgtSubMesh );
- bool isSeam = helper.IsRealSeam( sm->GetId() );
+ // -------------------------------------------------------------------------
+ // mapper doesn't take care of nodes already existing on edges and vertices,
+ // so we must merge nodes created by it with existing ones
+ // -------------------------------------------------------------------------
- enum { NEW_NODES = 0, OLD_NODES };
- map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam;
- map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
- set< const SMDS_MeshNode* > seamNodes;
+ SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
- // mapper puts on a seam edge nodes from 2 edges
- if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
- RETURN_BAD_RESULT("getBoundaryNodes() failed");
+ // Make groups of nodes to merge
- SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
- while ( nIt->more() )
+ // loop on EDGE and VERTEX sub-meshes of a target FACE
+ smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,/*complexShapeFirst=*/false);
+ while ( smIt->more() )
{
- const SMDS_MeshNode* node = nIt->next();
- bool isOld = isOldNode( node );
+ SMESH_subMesh* sm = smIt->next();
+ SMESHDS_SubMesh* smDS = sm->GetSubMeshDS();
+ if ( !smDS || smDS->NbNodes() == 0 )
+ continue;
+ //if ( !is1DComputed && sm->GetSubShape().ShapeType() == TopAbs_EDGE )
+ //break;
- if ( !isOld && isSeam ) { // new node on a seam edge
- if ( seamNodes.find( node ) != seamNodes.end())
- continue; // node is already in the map
+ if ( helper.IsDegenShape( sm->GetId() ) ) // to merge all nodes on degenerated
+ {
+ if ( sm->GetSubShape().ShapeType() == TopAbs_EDGE )
+ {
+ groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
+ SMESH_subMeshIteratorPtr smDegenIt
+ = sm->getDependsOnIterator(/*includeSelf=*/true,/*complexShapeFirst=*/false);
+ while ( smDegenIt->more() )
+ if (( smDS = smDegenIt->next()->GetSubMeshDS() ))
+ {
+ SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+ while ( nIt->more() )
+ groupsOfNodes.back().push_back( nIt->next() );
+ }
+ }
+ continue; // do not treat sm of degen VERTEX
}
- // sort nodes on edges by their position
- map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES];
- switch ( node->GetPosition()->GetTypeOfPosition() )
+ // Sort new and old nodes of a submesh separately
+
+ bool isSeam = helper.IsRealSeam( sm->GetId() );
+
+ enum { NEW_NODES = 0, OLD_NODES };
+ map< double, const SMDS_MeshNode* > u2nodesMaps[2], u2nodesOnSeam;
+ map< double, const SMDS_MeshNode* >::iterator u_oldNode, u_newNode, u_newOnSeam, newEnd;
+ set< const SMDS_MeshNode* > seamNodes;
+
+ // mapper puts on a seam edge nodes from 2 edges
+ if ( isSeam && ! getBoundaryNodes ( sm, tgtFace, u2nodesOnSeam, seamNodes ))
+ RETURN_BAD_RESULT("getBoundaryNodes() failed");
+
+ SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+ while ( nIt->more() )
{
- case SMDS_TOP_VERTEX: {
- if ( !is1DComputed && !pos2nodes.empty() )
- u2nodesMaps[isOld ? NEW_NODES : OLD_NODES].insert( make_pair( 0, node ));
- else
- pos2nodes.insert( make_pair( 0, node ));
- break;
- }
- case SMDS_TOP_EDGE: {
- const SMDS_EdgePosition* pos =
- static_cast<const SMDS_EdgePosition*>(node->GetPosition());
- pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
- break;
+ const SMDS_MeshNode* node = nIt->next();
+ bool isOld = isOldNode( node );
+
+ if ( !isOld && isSeam ) { // new node on a seam edge
+ if ( seamNodes.count( node ) )
+ continue; // node is already in the map
+ }
+
+ // sort nodes on edges by their position
+ map< double, const SMDS_MeshNode* > & pos2nodes = u2nodesMaps[isOld ? OLD_NODES : NEW_NODES];
+ switch ( node->GetPosition()->GetTypeOfPosition() )
+ {
+ case SMDS_TOP_VERTEX: {
+ if ( !is1DComputed && !pos2nodes.empty() )
+ u2nodesMaps[isOld ? NEW_NODES : OLD_NODES].insert( make_pair( 0, node ));
+ else
+ pos2nodes.insert( make_pair( 0, node ));
+ break;
+ }
+ case SMDS_TOP_EDGE: {
+ const SMDS_EdgePosition* pos =
+ static_cast<const SMDS_EdgePosition*>(node->GetPosition());
+ pos2nodes.insert( make_pair( pos->GetUParameter(), node ));
+ break;
+ }
+ default:
+ RETURN_BAD_RESULT("Wrong node position type: "<<
+ node->GetPosition()->GetTypeOfPosition());
+ }
}
- default:
- RETURN_BAD_RESULT("Wrong node position type: "<<
- node->GetPosition()->GetTypeOfPosition());
+ const bool mergeNewToOld =
+ ( u2nodesMaps[ NEW_NODES ].size() == u2nodesMaps[ OLD_NODES ].size() );
+ const bool mergeSeamToNew =
+ ( u2nodesMaps[ NEW_NODES ].size() == u2nodesOnSeam.size() );
+
+ if ( !mergeNewToOld )
+ if ( u2nodesMaps[ NEW_NODES ].size() > 0 &&
+ u2nodesMaps[ OLD_NODES ].size() > 0 )
+ {
+ u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
+ newEnd = u2nodesMaps[ OLD_NODES ].end();
+ for ( ; u_oldNode != newEnd; ++u_oldNode )
+ SMESH_Algo::addBadInputElement( u_oldNode->second );
+ return error( COMPERR_BAD_INPUT_MESH,
+ SMESH_Comment( "Existing mesh mismatches the projected 2D mesh on " )
+ << ( sm->GetSubShape().ShapeType() == TopAbs_EDGE ? "edge" : "vertex" )
+ << " #" << sm->GetId() );
+ }
+ if ( isSeam && !mergeSeamToNew ) {
+ const TopoDS_Shape& seam = sm->GetSubShape();
+ if ( u2nodesMaps[ NEW_NODES ].size() > 0 &&
+ u2nodesOnSeam.size() > 0 &&
+ seam.ShapeType() == TopAbs_EDGE )
+ {
+ int nbE1 = SMESH_MesherHelper::Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true );
+ int nbE2 = SMESH_MesherHelper::Count( srcFace, TopAbs_EDGE, /*ignoreSame=*/true );
+ if ( nbE1 != nbE2 ) // 2 EDGEs are mapped to a seam EDGE
+ {
+ // find the 2 EDGEs of srcFace
+ TopTools_DataMapIteratorOfDataMapOfShapeShape src2tgtIt( shape2ShapeMap._map2to1 );
+ for ( ; src2tgtIt.More(); src2tgtIt.Next() )
+ if ( seam.IsSame( src2tgtIt.Value() ))
+ SMESH_Algo::addBadInputElements
+ ( srcMesh->GetMeshDS()->MeshElements( src2tgtIt.Key() ));
+ return error( COMPERR_BAD_INPUT_MESH,
+ "Different number of nodes on two edges projected to a seam edge" );
+ }
+ }
}
- }
- if ( u2nodesMaps[ NEW_NODES ].size() != u2nodesMaps[ OLD_NODES ].size() )
- {
- if ( u2nodesMaps[ NEW_NODES ].size() == 0 &&
- sm->GetSubShape().ShapeType() == TopAbs_EDGE &&
- helper.IsDegenShape( sm->GetId() ) )
- // NPAL15894 (tt88bis.py) - project mesh built by NETGEN_1d_2D that
- // does not make segments/nodes on degenerated edges
- continue;
- if ( u2nodesMaps[ OLD_NODES ].size() == 0 &&
- sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
- // old nodes are optional on vertices in the case of 1D-2D projection
- continue;
+ // Make groups of nodes to merge
- RETURN_BAD_RESULT("Different nb of old and new nodes on shape #"<< sm->GetId() <<" "<<
- u2nodesMaps[ OLD_NODES ].size() << " != " <<
- u2nodesMaps[ NEW_NODES ].size());
- }
- if ( isSeam && u2nodesMaps[ OLD_NODES ].size() != u2nodesOnSeam.size() ) {
- RETURN_BAD_RESULT("Different nb of old and seam nodes " <<
- u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size());
- }
- // Make groups of nodes to merge
- u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
- u_newNode = u2nodesMaps[ NEW_NODES ].begin();
- newEnd = u2nodesMaps[ NEW_NODES ].end();
- u_newOnSeam = u2nodesOnSeam.begin();
- for ( ; u_newNode != newEnd; ++u_newNode, ++u_oldNode ) {
- groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
- groupsOfNodes.back().push_back( u_oldNode->second );
- groupsOfNodes.back().push_back( u_newNode->second );
- if ( isSeam )
- groupsOfNodes.back().push_back( (u_newOnSeam++)->second );
- }
- }
+ u_oldNode = u2nodesMaps[ OLD_NODES ].begin();
+ u_newNode = u2nodesMaps[ NEW_NODES ].begin();
+ newEnd = u2nodesMaps[ NEW_NODES ].end();
+ u_newOnSeam = u2nodesOnSeam.begin();
+ if ( mergeNewToOld )
+ for ( ; u_newNode != newEnd; ++u_newNode, ++u_oldNode )
+ {
+ groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
+ groupsOfNodes.back().push_back( u_oldNode->second );
+ groupsOfNodes.back().push_back( u_newNode->second );
+ if ( mergeSeamToNew )
+ groupsOfNodes.back().push_back( (u_newOnSeam++)->second );
+ }
+ else if ( mergeSeamToNew )
+ for ( ; u_newNode != newEnd; ++u_newNode, ++u_newOnSeam )
+ {
+ groupsOfNodes.push_back( list< const SMDS_MeshNode* >() );
+ groupsOfNodes.back().push_back( u_newNode->second );
+ groupsOfNodes.back().push_back( u_newOnSeam->second );
+ }
- // Merge
+ } // loop on EDGE and VERTEX submeshes of a target FACE
- int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
- editor.MergeNodes( groupsOfNodes );
- int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
- if ( nbFaceBeforeMerge != nbFaceAtferMerge )
- return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
+ // Merge
- // ----------------------------------------------------------------
- // The mapper can't create quadratic elements, so convert if needed
- // ----------------------------------------------------------------
+ SMESH_MeshEditor editor( tgtMesh );
+ int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
+ editor.MergeNodes( groupsOfNodes );
+ int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements();
+ if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() )
+ return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces");
- faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
- bool srcIsQuad = faceIt->next()->IsQuadratic();
- faceIt = tgtSubMesh->GetSubMeshDS()->GetElements();
- bool tgtIsQuad = faceIt->next()->IsQuadratic();
- if ( srcIsQuad && !tgtIsQuad )
- {
- TIDSortedElemSet tgtFaces;
- faceIt = tgtSubMesh->GetSubMeshDS()->GetElements();
- while ( faceIt->more() )
- tgtFaces.insert( tgtFaces.end(), faceIt->next() );
+ // ----------------------------------------------------------------
+ // The mapper can't create quadratic elements, so convert if needed
+ // ----------------------------------------------------------------
+
+ faceIt = srcSubMesh->GetSubMeshDS()->GetElements();
+ bool srcIsQuad = faceIt->next()->IsQuadratic();
+ faceIt = tgtSubMesh->GetSubMeshDS()->GetElements();
+ bool tgtIsQuad = faceIt->next()->IsQuadratic();
+ if ( srcIsQuad && !tgtIsQuad )
+ {
+ TIDSortedElemSet tgtFaces;
+ faceIt = tgtSubMesh->GetSubMeshDS()->GetElements();
+ while ( faceIt->more() )
+ tgtFaces.insert( tgtFaces.end(), faceIt->next() );
+
+ editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false);
+ }
+
+ cleaner.Release(); // not to remove mesh
+
+ } // end of projection using Pattern mapping
- editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces);
- }
// ---------------------------
// Check elements orientation
// ---------------------------
- TopoDS_Face face = tgtFace;
+ TopoDS_Face face = TopoDS::Face( theShape );
if ( !theMesh.IsMainShape( tgtFace ))
{
// find the main shape
}
}
// Fix orientation
- if ( SMESH_Algo::IsReversedSubMesh( face, meshDS ))
+ if ( helper.IsReversedSubMesh( face ))
{
+ SMESH_MeshEditor editor( tgtMesh );
SMDS_ElemIteratorPtr eIt = meshDS->MeshElements( face )->GetElements();
while ( eIt->more() ) {
const SMDS_MeshElement* e = eIt->next();
}
}
- cleaner.Release(); // do not remove mesh
-
return true;
}
TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD);
TAssocTool::TShapeShapeMap shape2ShapeMap;
- TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace );
+ TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap );
if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh,
shape2ShapeMap) ||
!shape2ShapeMap.IsBound( tgtFace ))