X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Projection_2D.cxx;h=6bb6adc1fa94d0693d7d55fbf7bf1679d003fc12;hp=60917a9fcd4be63af82cf9d32e1dcbd1de7a2031;hb=bd8f1aee7c78f7d2eb82bd4fec5e08c9e3d280ce;hpb=f5016d85b7b4b88623723027a1585c6414c4dc66 diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index 60917a9fc..6bb6adc1f 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2013 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 @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -61,7 +62,8 @@ using namespace std; #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 @@ -248,7 +250,7 @@ namespace { /*! * \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 @@ -290,43 +292,45 @@ namespace { 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"); @@ -393,7 +397,9 @@ namespace { // make any local coord systems of src and tgt faces vector 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 ) @@ -430,7 +436,11 @@ namespace { 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 ) @@ -786,7 +796,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // 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; @@ -794,8 +804,18 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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)); // ---------------------------------------------- @@ -805,14 +825,17 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace ); SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtFace ); + string srcMeshError; if ( tgtMesh == srcMesh ) { - if ( !TAssocTool::MakeComputed( srcSubMesh ) || !srcSubMesh->IsMeshComputed() ) - return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); + if ( !TAssocTool::MakeComputed( srcSubMesh )) + 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 ); // =========== // Projection @@ -842,15 +865,15 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& done = projectBy2DSimilarity( tgtFace, srcFace, tgtMesh, srcMesh, shape2ShapeMap, is1DComputed); } + SMESH_MesherHelper helper( theMesh ); + helper.SetSubShape( tgtFace ); + if ( !done ) { // -------------------- // Prepare to mapping // -------------------- - 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(); @@ -869,38 +892,47 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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 + // Find the corresponding source and target vertex // and 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, /*isSrc=*/true )) - RETURN_BAD_RESULT("Not associated vertices, srcV1 " << srcV1.TShape().operator->() ); - TopoDS_Vertex tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1, /*isSrc=*/true )); - - 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 + TopoDS_Vertex srcV1, tgtV1; bool reverse = false; + + 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, tgtV1, tgtEdges, nbEdgesInWires); - SMESH_Block::GetOrderedEdges( srcFace, srcV1, srcEdges, nbEdgesInWires); - if ( nbEdgesInWires.front() > 1 ) // possible to find out + SMESH_Block::GetOrderedEdges( tgtFace, tgtEdges, nbEdgesInWires, tgtV1 ); + SMESH_Block::GetOrderedEdges( srcFace, srcEdges, nbEdgesInWires, srcV1 ); + + 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 ) { @@ -912,6 +944,12 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& RETURN_BAD_RESULT("Bad result from SMESH_Block::GetOrderedEdges()"); } + // 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"); + // -------------------- // Perform 2D mapping // -------------------- @@ -942,7 +980,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // Make groups of nodes to merge - // loop on edge and vertex submeshes of a target face + // loop on EDGE and VERTEX sub-meshes of a target FACE smIt = tgtSubMesh->getDependsOnIterator(/*includeSelf=*/false,/*complexShapeFirst=*/false); while ( smIt->more() ) { @@ -953,6 +991,24 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& //if ( !is1DComputed && sm->GetSubShape().ShapeType() == TopAbs_EDGE ) //break; + 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 new and old nodes of a submesh separately bool isSeam = helper.IsRealSeam( sm->GetId() ); @@ -1011,18 +1067,36 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& u_oldNode = u2nodesMaps[ OLD_NODES ].begin(); newEnd = u2nodesMaps[ OLD_NODES ].end(); for ( ; u_oldNode != newEnd; ++u_oldNode ) - _badInputElements.push_back( u_oldNode->second ); + 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 ) { - //RETURN_BAD_RESULT - MESSAGE("Different nb of old and seam nodes " << - u2nodesMaps[ OLD_NODES ].size() << " != " << u2nodesOnSeam.size()); + 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" ); + } + } } + // Make groups of nodes to merge + u_oldNode = u2nodesMaps[ OLD_NODES ].begin(); u_newNode = u2nodesMaps[ NEW_NODES ].begin(); newEnd = u2nodesMaps[ NEW_NODES ].end(); @@ -1043,7 +1117,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& groupsOfNodes.back().push_back( u_newNode->second ); groupsOfNodes.back().push_back( u_newOnSeam->second ); } - } + + } // loop on EDGE and VERTEX submeshes of a target FACE // Merge @@ -1051,7 +1126,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& int nbFaceBeforeMerge = tgtSubMesh->GetSubMeshDS()->NbElements(); editor.MergeNodes( groupsOfNodes ); int nbFaceAtferMerge = tgtSubMesh->GetSubMeshDS()->NbElements(); - if ( nbFaceBeforeMerge != nbFaceAtferMerge ) + if ( nbFaceBeforeMerge != nbFaceAtferMerge && !helper.HasDegeneratedEdges() ) return error(COMPERR_BAD_INPUT_MESH, "Probably invalid node parameters on geom faces"); // ---------------------------------------------------------------- @@ -1069,7 +1144,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& while ( faceIt->more() ) tgtFaces.insert( tgtFaces.end(), faceIt->next() ); - editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces); + editor.ConvertToQuadratic(/*theForce3d=*/false, tgtFaces, false); } cleaner.Release(); // not to remove mesh @@ -1111,7 +1186,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& } } // Fix orientation - if ( SMESH_Algo::IsReversedSubMesh( face, meshDS )) + if ( helper.IsReversedSubMesh( face )) { SMESH_MeshEditor editor( tgtMesh ); SMDS_ElemIteratorPtr eIt = meshDS->MeshElements( face )->GetElements();