X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_Projection_2D.cxx;h=2db02b2ce110fcd767728e8109252e6da13e4bcb;hp=f8dd7501666ac0edcbb18001285b135c2e1469b3;hb=80e28740d3fd1b3debb41e25c7fe515cc1305eef;hpb=324d433f277a1ec6552c93db878504f447f8fbad diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index f8dd75016..2db02b2ce 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2015 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 @@ -427,15 +427,44 @@ namespace { // get ordered src EDGEs TError err; srcWires = StdMeshers_FaceSide::GetFaceWires( srcFace, *srcMesh,/*skipMediumNodes=*/0, err); - if ( err && !err->IsOK() ) + if ( err && !err->IsOK() || srcWires.empty() ) return err; + SMESH_MesherHelper srcHelper( *srcMesh ); + srcHelper.SetSubShape( srcFace ); + // make corresponding sequence of tgt EDGEs tgtWires.resize( srcWires.size() ); for ( size_t iW = 0; iW < srcWires.size(); ++iW ) { - list< TopoDS_Edge > tgtEdges; + // check ori + bool reverse = false; StdMeshers_FaceSidePtr srcWire = srcWires[iW]; + // for ( int iE = 0; iE < srcWire->NbEdges(); ++iE ) + // { + // if ( srcHelper.IsRealSeam( srcWire->EdgeID( iE ))) + // continue; + // TopoDS_Shape srcE = srcWire->Edge( iE ); + // TopoDS_Shape tgtE = shape2ShapeMap( srcE, /*isSrc=*/true); + // if ( shape2ShapeMap._assocType == TShapeShapeMap::PROPAGATION || + // shape2ShapeMap._assocType == TShapeShapeMap::PROPAGATION) + // { + // reverse = false; + // } + // else if ( tgtMesh == srcMesh ) + // { + // reverse = (( srcE.Orientation() == srcHelper.GetSubShapeOri( srcFace, srcE )) != + // ( tgtE.Orientation() == srcHelper.GetSubShapeOri( tgtFace, tgtE ))); + // } + // else + // { + // TopoDS_Shape srcEbis = shape2ShapeMap( tgtE, /*isSrc=*/false ); + // reverse = ( srcE.Orientation() != srcEbis.Orientation() ); + // } + // break; + // } + + list< TopoDS_Edge > tgtEdges; TopTools_IndexedMapOfShape edgeMap; // to detect seam edges for ( int iE = 0; iE < srcWire->NbEdges(); ++iE ) { @@ -443,6 +472,7 @@ namespace { TopoDS_Edge tgtE = TopoDS::Edge( shape2ShapeMap( srcE, /*isSrc=*/true)); TopoDS_Shape srcEbis = shape2ShapeMap( tgtE, /*isSrc=*/false ); if ( srcE.Orientation() != srcEbis.Orientation() ) + //if ( reverse ) tgtE.Reverse(); // reverse a seam edge encountered for the second time const int index = edgeMap.Add( tgtE ); @@ -568,6 +598,7 @@ namespace { 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; @@ -584,6 +615,8 @@ namespace { tgtPnts.push_back( tgtWires[iW]->Value3d( tgtU ).XYZ() ); srcU += srcDu; tgtU += tgtDu; + srcBC += srcPnts.back(); + tgtBC += tgtPnts.back(); } } } @@ -596,6 +629,8 @@ namespace { 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] ); @@ -606,8 +641,8 @@ namespace { { 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 ); @@ -721,13 +756,13 @@ namespace { { case SMDS_TOP_FACE: { - if ( nbOkPos < 10 ) break; + if ( nbOkPos > 10 ) break; gp_XY uv = helper.GetNodeUV( tgtFace, n ), uvBis = uv; if (( helper.CheckNodeUV( tgtFace, n, uv, tol )) && (( uv - uvBis ).SquareModulus() < tol2d )) ++nbOkPos; else - nbOkPos = 0; + nbOkPos = -((int) src2tgtNodes.size() ); break; } case SMDS_TOP_EDGE: @@ -888,10 +923,9 @@ namespace { 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: { @@ -922,12 +956,12 @@ namespace { */ //================================================================================ - 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(); @@ -965,7 +999,12 @@ namespace { set 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 @@ -990,6 +1029,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& srcMesh = tgtMesh; SMESHDS_Mesh * meshDS = theMesh.GetMeshDS(); + SMESH_MesherHelper helper( theMesh ); // --------------------------- // Make sub-shapes association @@ -1006,8 +1046,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& { 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 ); + int nbE1 = helper.Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true ); + int nbE2 = helper.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: ") @@ -1017,6 +1057,23 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& } TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD)); + // orient faces + // if ( srcMesh == tgtMesh ) + // { + // TopoDS_Shape solid = + // helper.GetCommonAncestor( srcFace, tgtFace, *tgtMesh, TopAbs_SOLID ); + // if ( !solid.IsNull() ) + // { + // srcFace.Orientation( helper.GetSubShapeOri( solid, srcFace )); + // tgtFace.Orientation( helper.GetSubShapeOri( solid, tgtFace )); + // } + // else if ( helper.NbAncestors( srcFace, *tgtMesh, TopAbs_SOLID ) == 1 && + // helper.NbAncestors( tgtFace, *tgtMesh, TopAbs_SOLID ) == 1 ) + // { + // srcFace.Orientation( helper.GetSubShapeOri( tgtMesh->GetShapeToMesh(), srcFace )); + // tgtFace.Orientation( helper.GetSubShapeOri( tgtMesh->GetShapeToMesh(), tgtFace )); + // } + // } // ---------------------------------------------- // Assure that mesh on a source Face is computed // ---------------------------------------------- @@ -1048,25 +1105,27 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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(); // -------------------- @@ -1076,20 +1135,22 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // 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(); ) { + set< const SMDS_MeshNode* > faceNodes; + for ( ; faceNodes.size() < 3 && faceIt->more(); ) { const SMDS_MeshElement* face = faceIt->next(); SMDS_ElemIteratorPtr nodeIt = face->nodesIterator(); while ( nodeIt->more() ) { const SMDS_MeshNode* node = static_cast( nodeIt->next() ); - if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE ) { - nbFaceNodes++; + if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE && + faceNodes.insert( node ).second ) uvBox.Add( helper.GetNodeUV( srcFace, node )); - } } } - const bool toProjectNodes = - ( nbFaceNodes > 0 && ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN )); + bool toProjectNodes = false; + if ( faceNodes.size() == 1 ) + toProjectNodes = ( uvBox.IsVoid() || uvBox.CornerMin().IsEqual( gp_XY(0,0), 1e-12 )); + else if ( faceNodes.size() > 1 ) + toProjectNodes = ( uvBox.IsVoid() || uvBox.SquareExtent() < DBL_MIN ); // Find the corresponding source and target vertex // and flag needed to call mapper.Apply() @@ -1097,13 +1158,10 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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 )); - } + TopExp_Explorer vSrcExp( srcFace, TopAbs_VERTEX ); + srcV1 = TopoDS::Vertex( vSrcExp.Current() ); + tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1, /*isSrc=*/true )); + list< TopoDS_Edge > tgtEdges, srcEdges; list< int > nbEdgesInWires; SMESH_Block::GetOrderedEdges( tgtFace, tgtEdges, nbEdgesInWires, tgtV1 ); @@ -1115,7 +1173,7 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& TopoDS_Shape srcE1bis = shape2ShapeMap( tgtE1 ); reverse = ( ! srcE1.IsSame( srcE1bis )); if ( reverse && - _sourceHypo->HasVertexAssociation() && + //_sourceHypo->HasVertexAssociation() && nbEdgesInWires.front() > 2 && helper.IsRealSeam( tgtEdges.front() )) { @@ -1124,11 +1182,30 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // 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; + TopoDS_Face tgtFaceBis = tgtFace; + for ( vSrcExp.Next(); vSrcExp.More(); ) + { + tgtFaceBis.Reverse(); + tgtEdges.clear(); + SMESH_Block::GetOrderedEdges( tgtFaceBis, tgtEdges, nbEdgesInWires, tgtV1 ); + bool ok = true; + list< TopoDS_Edge >::iterator edgeS = srcEdges.begin(), edgeT = tgtEdges.begin(); + for ( ; edgeS != srcEdges.end() && ok ; ++edgeS, ++edgeT ) + ok = edgeS->IsSame( shape2ShapeMap( *edgeT )); + if ( ok ) + break; // FOUND! + + reverse = !reverse; + if ( reverse ) + { + vSrcExp.Next(); + } + else + { + srcV1 = TopoDS::Vertex( vSrcExp.Current() ); + tgtV1 = TopoDS::Vertex( shape2ShapeMap( srcV1, /*isSrc=*/true )); + srcEdges.clear(); + SMESH_Block::GetOrderedEdges( srcFace, srcEdges, nbEdgesInWires, srcV1 ); } } } @@ -1156,8 +1233,11 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& // Compute mesh on a target face mapper.Apply( tgtFace, tgtV1, reverse ); - if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) + if ( mapper.GetErrorCode() != SMESH_Pattern::ERR_OK ) { + // std::ofstream file("/tmp/Pattern.smp" ); + // mapper.Save( file ); return error("Can't apply source mesh pattern to the face"); + } // Create the mesh @@ -1166,10 +1246,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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 @@ -1279,8 +1355,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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 ); + int nbE1 = helper.Count( tgtFace, TopAbs_EDGE, /*ignoreSame=*/true ); + int nbE2 = helper.Count( srcFace, TopAbs_EDGE, /*ignoreSame=*/true ); if ( nbE1 != nbE2 ) // 2 EDGEs are mapped to a seam EDGE { // find the 2 EDGEs of srcFace @@ -1329,14 +1405,6 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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 // ---------------------------------------------------------------- @@ -1355,11 +1423,18 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& 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 // --------------------------- @@ -1405,6 +1480,8 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& } } + cleaner.Release(); // not to remove mesh + return true; }