X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_ProjectionUtils.cxx;h=924eba9bf39bba644c6748ec5d0093e8ed5c9b56;hp=c4b082adcc93c72d16d06cb72c166f5698a06ac7;hb=ccb5e3c25bf204e839c0094f50f543eacedba5e6;hpb=ac96f997ef6d5e09b407a5363a3c69415e2442dc diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index c4b082adc..924eba9bf 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -28,6 +28,7 @@ #include "StdMeshers_ProjectionUtils.hxx" #include "SMDS_EdgePosition.hxx" +#include "SMDS_FacePosition.hxx" #include "SMESHDS_Mesh.hxx" #include "SMESH_Algo.hxx" #include "SMESH_Block.hxx" @@ -46,6 +47,7 @@ #include "utilities.h" #include +#include #include #include #include @@ -476,6 +478,26 @@ namespace { return !allBndEdges.empty(); } + /*! + * \brief Convertor used in Delaunay constructor + */ + struct SideVector2UVPtStructVec + { + std::vector< const UVPtStructVec* > _uvVecs; + + SideVector2UVPtStructVec( const TSideVector& wires ) + { + _uvVecs.resize( wires.size() ); + for ( size_t i = 0; i < wires.size(); ++i ) + _uvVecs[ i ] = & wires[i]->GetUVPtStruct(); + } + + operator const std::vector< const UVPtStructVec* > & () const + { + return _uvVecs; + } + }; + } // namespace //======================================================================= @@ -679,7 +701,7 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the RETURN_BAD_RESULT("edge2 does not belong to theShape2"); } // - // Look for 2 corresponing faces: + // Look for 2 corresponding faces: // TopoDS_Shape F1, F2; @@ -742,8 +764,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the int nbE = FindFaceAssociation( face1, VV1, face2, VV2, edges1, edges2, isVCloseness ); if ( !nbE ) RETURN_BAD_RESULT("FindFaceAssociation() failed"); InsertAssociation( face1, face2, theMap ); // assoc faces - MESSAGE("Assoc FACE " << theMesh1->GetMeshDS()->ShapeToIndex( face1 )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( face2 )); + // MESSAGE("Assoc FACE " << theMesh1->GetMeshDS()->ShapeToIndex( face1 )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( face2 )); if ( nbE == 2 && (edge1.IsSame( edges1.front())) != (edge2.IsSame( edges2.front()))) { reverseEdges( edges2, nbE ); @@ -847,8 +869,8 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the } // Associate shells // - int nbFaces1 = SMESH_MesherHelper:: Count( shell1, TopAbs_FACE, 0 ); - int nbFaces2 = SMESH_MesherHelper:: Count( shell2, TopAbs_FACE, 0 ); + int nbFaces1 = SMESH_MesherHelper::Count( shell1, TopAbs_FACE, 0 ); + int nbFaces2 = SMESH_MesherHelper::Count( shell2, TopAbs_FACE, 0 ); if ( nbFaces1 != nbFaces2 ) RETURN_BAD_RESULT("Different nb of faces found for shells"); if ( nbFaces1 > 0 ) { @@ -954,14 +976,14 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the v2e[0].UnBind( V[0] ); v2e[1].UnBind( V[1] ); InsertAssociation( e0, e1, theMap ); - MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0 )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( e1 )); + // MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0 )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( e1 )); V[0] = GetNextVertex( e0, V[0] ); V[1] = GetNextVertex( e1, V[1] ); if ( !V[0].IsNull() ) { InsertAssociation( V[0], V[1], theMap ); - MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( V[0] )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( V[1] )); + // MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( V[0] )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( V[1] )); } } else if ( nbE0 == 2 ) @@ -988,12 +1010,12 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the InsertAssociation( e0b, e1b, theMap ); InsertAssociation( e0n, e1n, theMap ); InsertAssociation( v0n, v1n, theMap ); - MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0b )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( e1b )); - MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0n )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( e1n )); - MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( v0n )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( v1n )); + // MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0b )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( e1b )); + // MESSAGE("Assoc edge " << theMesh1->GetMeshDS()->ShapeToIndex( e0n )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( e1n )); + // MESSAGE("Assoc vertex " << theMesh1->GetMeshDS()->ShapeToIndex( v0n )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( v1n )); v2e[0].UnBind( V[0] ); v2e[1].UnBind( V[1] ); V[0] = v0n; @@ -1098,6 +1120,11 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the // take care of proper association of propagated edges bool same1 = edge1.IsSame( edges1.front() ); bool same2 = edge2.IsSame( edges2.front() ); + if ( !same1 && !same2 ) + { + same1 = ( edges1.back().Orientation() == edge1.Orientation() ); + same2 = ( edges2.back().Orientation() == edge2.Orientation() ); + } if ( same1 != same2 ) { reverseEdges(edges2, nbE); @@ -1342,10 +1369,10 @@ bool StdMeshers_ProjectionUtils::FindSubShapeAssociation(const TopoDS_Shape& the InsertAssociation( VV1[ 0 ], VV2[ 0 ], theMap ); InsertAssociation( VV1[ 1 ], VV2[ 1 ], theMap ); - MESSAGE("Initial assoc VERT " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[ 0 ] )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( VV2[ 0 ] )<< - "\nand VERT " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[ 1 ] )<< - " to " << theMesh2->GetMeshDS()->ShapeToIndex( VV2[ 1 ] )); + // MESSAGE("Initial assoc VERT " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[ 0 ] )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( VV2[ 0 ] )<< + // "\nand VERT " << theMesh1->GetMeshDS()->ShapeToIndex( VV1[ 1 ] )<< + // " to " << theMesh2->GetMeshDS()->ShapeToIndex( VV2[ 1 ] )); if ( theShape1.ShapeType() == TopAbs_EDGE ) { InsertAssociation( theShape1, theShape2, theMap ); return true; @@ -1589,7 +1616,7 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, std::advance( edge2End, *nbE2 ); if ( *nbE1 == *nbE2 && iW2 >= iW1 ) { - // rotate edge2 untill coincidence with edge1 in 2D + // rotate edge2 until coincides with edge1 in 2D int i = *nbE2; bool sameUV = false; while ( !( sameUV = sameVertexUV( *edge2Beg, face2, 0, v0f1UV, vTolUV )) && --i > 0 ) @@ -1638,7 +1665,7 @@ int StdMeshers_ProjectionUtils::FindFaceAssociation(const TopoDS_Face& face1, break; } } - // prepare to the next wire loop + // prepare for the next wire loop edge2Beg = edge2End; } edge1Beg = edge1End; @@ -2324,7 +2351,7 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter string algoType = algo->GetName(); if ( algoType.substr(0, 11) != "Projection_") - return gen->Compute( *mesh, shape, /*shapeOnly=*/true ); + return gen->Compute( *mesh, shape, SMESH_Gen::SHAPE_ONLY ); // try to compute source mesh @@ -2365,7 +2392,7 @@ bool StdMeshers_ProjectionUtils::MakeComputed(SMESH_subMesh * sm, const int iter srcMesh = mesh; if ( MakeComputed( srcMesh->GetSubMesh( srcShape ), iterationNb + 1 ) && - gen->Compute( *mesh, shape, /*shapeOnly=*/true )) + gen->Compute( *mesh, shape, SMESH_Gen::SHAPE_ONLY )) return sm->IsMeshComputed(); return false; @@ -2387,7 +2414,7 @@ std::string StdMeshers_ProjectionUtils::SourceNotComputedError( SMESH_subMesh * if ( !sm || sm->GetAlgoState() != SMESH_subMesh::NO_ALGO ) return usualMessage; // algo is OK, anything else is KO. - // Try to find a type of all-dimentional algorithm that would compute the + // Try to find a type of all-dimensional algorithm that would compute the // given sub-mesh if it could be launched before projection const TopoDS_Shape shape = sm->GetSubShape(); const int shapeDim = SMESH_Gen::GetShapeDim( shape ); @@ -2568,7 +2595,7 @@ namespace StdMeshers_ProjectionUtils //================================================================================ /*! - * \brief Computes transformation beween two sets of 2D points using + * \brief Computes transformation between two sets of 2D points using * a least square approximation * * See "Surface Mesh Projection For Hexahedral Mesh Generation By Sweeping" @@ -2651,7 +2678,7 @@ namespace StdMeshers_ProjectionUtils //================================================================================ /*! - * \brief Computes transformation beween two sets of 3D points using + * \brief Computes transformation between two sets of 3D points using * a least square approximation * * See "Surface Mesh Projection For Hexahedral Mesh Generation By Sweeping" @@ -2787,4 +2814,146 @@ namespace StdMeshers_ProjectionUtils } return true; } -} + + //================================================================================ + /*! + * \brief triangulate the srcFace in 2D + * \param [in] srcWires - boundary of the src FACE + */ + //================================================================================ + + Morph::Morph(const TSideVector& srcWires): + _delaunay( srcWires, /*checkUV=*/true ) + { + _srcSubMesh = srcWires[0]->GetMesh()->GetSubMesh( srcWires[0]->Face() ); + } + + //================================================================================ + /*! + * \brief Move non-marked target nodes + * \param [in,out] tgtHelper - helper + * \param [in] tgtWires - boundary nodes of the target FACE; must be in the + * same order as the nodes in srcWires given in the constructor + * \param [in] src2tgtNodes - map of src -> tgt nodes + * \param [in] moveAll - to move all nodes; if \c false, move only non-marked nodes + * \return bool - Ok or not + */ + //================================================================================ + + bool Morph::Perform(SMESH_MesherHelper& tgtHelper, + const TSideVector& tgtWires, + Handle(ShapeAnalysis_Surface) tgtSurface, + const TNodeNodeMap& src2tgtNodes, + const bool moveAll) + { + // get tgt boundary points corresponding to src boundary nodes + size_t nbP = 0; + for ( size_t iW = 0; iW < tgtWires.size(); ++iW ) + nbP += tgtWires[iW]->NbPoints() - 1; // 1st and last points coincide + if ( nbP != _delaunay.GetBndNodes().size() ) + return false; + + std::vector< gp_XY > tgtUV( nbP ); + for ( size_t iW = 0, iP = 0; iW < tgtWires.size(); ++iW ) + { + const UVPtStructVec& tgtPnt = tgtWires[iW]->GetUVPtStruct(); + for ( int i = 0, nb = tgtPnt.size() - 1; i < nb; ++i, ++iP ) + { + tgtUV[ iP ] = tgtPnt[i].UV(); + } + } + + SMESHDS_Mesh* tgtMesh = tgtHelper.GetMeshDS(); + const SMDS_MeshNode *srcNode, *tgtNode; + + // un-mark internal src nodes in order iterate them using _delaunay + int nbSrcNodes = 0; + SMDS_NodeIteratorPtr nIt = _srcSubMesh->GetSubMeshDS()->GetNodes(); + if ( !nIt || !nIt->more() ) return true; + if ( moveAll ) + { + nbSrcNodes = _srcSubMesh->GetSubMeshDS()->NbNodes(); + while ( nIt->more() ) + nIt->next()->setIsMarked( false ); + } + else + { + while ( nIt->more() ) + nbSrcNodes += int( !nIt->next()->isMarked() ); + } + + // Move tgt nodes + + double bc[3]; // barycentric coordinates + int nodeIDs[3]; // nodes of a delaunay triangle + const SMDS_FacePosition* pos; + + _delaunay.InitTraversal( nbSrcNodes ); + + while (( srcNode = _delaunay.NextNode( bc, nodeIDs ))) + { + // compute new coordinates for a corresponding tgt node + gp_XY uvNew( 0., 0. ), nodeUV; + for ( int i = 0; i < 3; ++i ) + uvNew += bc[i] * tgtUV[ nodeIDs[i]]; + gp_Pnt xyz = tgtSurface->Value( uvNew ); + + // find and move tgt node + TNodeNodeMap::const_iterator n2n = src2tgtNodes.find( srcNode ); + if ( n2n == src2tgtNodes.end() ) continue; + tgtNode = n2n->second; + tgtMesh->MoveNode( tgtNode, xyz.X(), xyz.Y(), xyz.Z() ); + + if (( pos = dynamic_cast< const SMDS_FacePosition* >( tgtNode->GetPosition() ))) + const_cast( pos )->SetParameters( uvNew.X(), uvNew.Y() ); + + --nbSrcNodes; + } + + return nbSrcNodes == 0; + + } // Morph::Perform + + //======================================================================= + //function : Delaunay + //purpose : construct from face sides + //======================================================================= + + Delaunay::Delaunay( const TSideVector& wires, bool checkUV ): + SMESH_Delaunay( SideVector2UVPtStructVec( wires ), + TopoDS::Face( wires[0]->FaceHelper()->GetSubShape() ), + wires[0]->FaceHelper()->GetSubShapeID() ) + { + _wire = wires[0]; // keep a wire to assure _helper to keep alive + _helper = _wire->FaceHelper(); + _checkUVPtr = checkUV ? & _checkUV : 0; + } + + //======================================================================= + //function : Delaunay + //purpose : construct from UVPtStructVec's + //======================================================================= + + Delaunay::Delaunay( const std::vector< const UVPtStructVec* > & boundaryNodes, + SMESH_MesherHelper& faceHelper, + bool checkUV): + SMESH_Delaunay( boundaryNodes, + TopoDS::Face( faceHelper.GetSubShape() ), + faceHelper.GetSubShapeID() ) + { + _helper = & faceHelper; + _checkUVPtr = checkUV ? & _checkUV : 0; + } + + //======================================================================= + //function : getNodeUV + //purpose : + //======================================================================= + + gp_XY Delaunay::getNodeUV( const TopoDS_Face& face, const SMDS_MeshNode* node ) const + { + return _helper->GetNodeUV( face, node, 0, _checkUVPtr ); + } + + +} // namespace StdMeshers_ProjectionUtils