From 4a8521d5db0878f4e4f50bd94cf6e5200d2ec777 Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 29 Apr 2014 16:09:10 +0400 Subject: [PATCH] SALOME_TESTS/Grids/smesh/mesh_Projection_2D_00/A0 Attempts to mesh a difficult shape --- src/StdMeshers/StdMeshers_FaceSide.hxx | 2 +- src/StdMeshers/StdMeshers_Prism_3D.cxx | 144 ++++++++++++++---- src/StdMeshers/StdMeshers_Prism_3D.hxx | 4 +- src/StdMeshers/StdMeshers_ProjectionUtils.cxx | 9 +- 4 files changed, 128 insertions(+), 31 deletions(-) diff --git a/src/StdMeshers/StdMeshers_FaceSide.hxx b/src/StdMeshers/StdMeshers_FaceSide.hxx index 9ef5960fb..4b8bf1d33 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.hxx +++ b/src/StdMeshers/StdMeshers_FaceSide.hxx @@ -220,7 +220,7 @@ public: */ int NbEdges() const { return myEdge.size(); } /*! - * \brief Return i-th wrapped edge (count starts from zero) + * \brief Return i-th edge (count starts from zero) */ const TopoDS_Edge& Edge(int i) const { return myEdge[i]; } /*! diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index 9eea019c6..3b6cf6481 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -231,7 +231,7 @@ namespace { quad->face = TopoDS::Face( face ); - return isComposite; + return !isComposite; } //================================================================================ @@ -655,6 +655,7 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh meshedFaces.splice( meshedFaces.begin(), notQuadMeshedFaces ); Prism_3D::TPrismTopo prism; + myPropagChains = 0; if ( nbSolids == 1 ) { @@ -906,8 +907,15 @@ bool StdMeshers_Prism_3D::getWallFaces( Prism_3D::TPrismTopo & thePrism, if ( !quadList.back() ) return toSM( error(TCom("Side face #") << shapeID( face ) << " not meshable with quadrangles")); - if ( ! setBottomEdge( *edge, quadList.back(), face )) - ; //return toSM( error(TCom("Composite 'horizontal' edges are not supported"))); + bool isCompositeBase = ! setBottomEdge( *edge, quadList.back(), face ); + if ( isCompositeBase ) + { + // it's OK if all EDGEs of the bottom side belongs to the bottom FACE + StdMeshers_FaceSidePtr botSide = quadList.back()->side[ QUAD_BOTTOM_SIDE ]; + for ( int iE = 0; iE < botSide->NbEdges(); ++iE ) + if ( !myHelper->IsSubShape( botSide->Edge(iE), thePrism.myBottom )) + return toSM( error(TCom("Composite 'horizontal' edges are not supported"))); + } if ( faceMap.Add( face )) thePrism.myWallQuads.push_back( quadList ); break; @@ -1077,7 +1085,7 @@ bool StdMeshers_Prism_3D::compute(const Prism_3D::TPrismTopo& thePrism) // Projections on the top and bottom faces are taken from nodes existing // on these faces; find correspondence between bottom and top nodes myBotToColumnMap.clear(); - if ( !assocOrProjBottom2Top( bottomToTopTrsf ) ) // it also fills myBotToColumnMap + if ( !assocOrProjBottom2Top( bottomToTopTrsf, thePrism ) ) // it also fills myBotToColumnMap return false; @@ -1443,10 +1451,13 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism) Prism_3D::TQuadList::const_iterator quad = thePrism.myWallQuads[iW].begin(); for ( ; quad != thePrism.myWallQuads[iW].end(); ++quad ) { - // Top EDGEs must be projections from the bottom ones - // to compute stuctured quad mesh on wall FACEs - // --------------------------------------------------- + const TopoDS_Face& face = (*quad)->face; + SMESH_subMesh* fSM = mesh->GetSubMesh( face ); + if ( ! fSM->IsMeshComputed() ) { + // Top EDGEs must be projections from the bottom ones + // to compute stuctured quad mesh on wall FACEs + // --------------------------------------------------- const TopoDS_Edge& botE = (*quad)->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0); const TopoDS_Edge& topE = (*quad)->side[ QUAD_TOP_SIDE ].grid->Edge(0); SMESH_subMesh* botSM = mesh->GetSubMesh( botE ); @@ -1503,14 +1514,11 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism) } } tgtSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); - } - // Compute quad mesh on wall FACEs - // ------------------------------- - const TopoDS_Face& face = (*quad)->face; - SMESH_subMesh* fSM = mesh->GetSubMesh( face ); - if ( ! fSM->IsMeshComputed() ) - { + + // Compute quad mesh on wall FACEs + // ------------------------------- + // make all EDGES meshed fSM->ComputeSubMeshStateEngine( SMESH_subMesh::COMPUTE ); if ( !fSM->SubMeshesComputed() ) @@ -1546,9 +1554,10 @@ bool StdMeshers_Prism_3D::computeWalls(const Prism_3D::TPrismTopo& thePrism) TopoDS_Edge StdMeshers_Prism_3D::findPropagationSource( const TopoDS_Edge& E ) { - for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i ) - if ( myPropagChains[i].Contains( E )) - return TopoDS::Edge( myPropagChains[i].FindKey( 1 )); + if ( myPropagChains ) + for ( size_t i = 0; !myPropagChains[i].IsEmpty(); ++i ) + if ( myPropagChains[i].Contains( E )) + return TopoDS::Edge( myPropagChains[i].FindKey( 1 )); return TopoDS_Edge(); } @@ -1802,7 +1811,8 @@ void StdMeshers_Prism_3D::AddPrisms( vector & columns, */ //================================================================================ -bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf ) +bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf, + const Prism_3D::TPrismTopo& thePrism) { SMESH_subMesh * botSM = myBlock.SubMesh( ID_BOT_FACE ); SMESH_subMesh * topSM = myBlock.SubMesh( ID_TOP_FACE ); @@ -1819,7 +1829,7 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf } bool needProject = !topSM->IsMeshComputed(); - if ( !needProject && + if ( !needProject && (botSMDS->NbElements() != topSMDS->NbElements() || botSMDS->NbNodes() != topSMDS->NbNodes())) { @@ -1845,19 +1855,70 @@ bool StdMeshers_Prism_3D::assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf TopoDS_Face topFace = TopoDS::Face( myBlock.Shape( ID_TOP_FACE )); // associate top and bottom faces TAssocTool::TShapeShapeMap shape2ShapeMap; - if ( !TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(), - topFace, myBlock.Mesh(), - shape2ShapeMap) ) - return toSM( error(TCom("Topology of faces #") << botSM->GetId() - <<" and #"<< topSM->GetId() << " seems different" )); + const bool sameTopo = + TAssocTool::FindSubShapeAssociation( botFace, myBlock.Mesh(), + topFace, myBlock.Mesh(), + shape2ShapeMap); + if ( !sameTopo ) + for ( size_t iQ = 0; iQ < thePrism.myWallQuads.size(); ++iQ ) + { + const Prism_3D::TQuadList& quadList = thePrism.myWallQuads[iQ]; + StdMeshers_FaceSidePtr botSide = quadList.front()->side[ QUAD_BOTTOM_SIDE ]; + StdMeshers_FaceSidePtr topSide = quadList.back ()->side[ QUAD_TOP_SIDE ]; + if ( botSide->NbEdges() == topSide->NbEdges() ) + { + for ( int iE = 0; iE < botSide->NbEdges(); ++iE ) + { + TAssocTool::InsertAssociation( botSide->Edge( iE ), + topSide->Edge( iE ), shape2ShapeMap ); + TAssocTool::InsertAssociation( myHelper->IthVertex( 0, botSide->Edge( iE )), + myHelper->IthVertex( 0, topSide->Edge( iE )), + shape2ShapeMap ); + } + } + else + { + TopoDS_Vertex vb, vt; + StdMeshers_FaceSidePtr sideB, sideT; + vb = myHelper->IthVertex( 0, botSide->Edge( 0 )); + vt = myHelper->IthVertex( 0, topSide->Edge( 0 )); + sideB = quadList.front()->side[ QUAD_LEFT_SIDE ]; + sideT = quadList.back ()->side[ QUAD_LEFT_SIDE ]; + if ( vb.IsSame( sideB->FirstVertex() ) && + vt.IsSame( sideT->LastVertex() )) + { + TAssocTool::InsertAssociation( botSide->Edge( 0 ), + topSide->Edge( 0 ), shape2ShapeMap ); + TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap ); + } + vb = myHelper->IthVertex( 1, botSide->Edge( botSide->NbEdges()-1 )); + vt = myHelper->IthVertex( 1, topSide->Edge( topSide->NbEdges()-1 )); + sideB = quadList.front()->side[ QUAD_RIGHT_SIDE ]; + sideT = quadList.back ()->side[ QUAD_RIGHT_SIDE ]; + if ( vb.IsSame( sideB->FirstVertex() ) && + vt.IsSame( sideT->LastVertex() )) + { + TAssocTool::InsertAssociation( botSide->Edge( botSide->NbEdges()-1 ), + topSide->Edge( topSide->NbEdges()-1 ), + shape2ShapeMap ); + TAssocTool::InsertAssociation( vb, vt, shape2ShapeMap ); + } + } + } // Find matching nodes of top and bottom faces TNodeNodeMap n2nMap; if ( ! TAssocTool::FindMatchingNodesOnFaces( botFace, myBlock.Mesh(), topFace, myBlock.Mesh(), shape2ShapeMap, n2nMap )) - return toSM( error(TCom("Mesh on faces #") << botSM->GetId() - <<" and #"<< topSM->GetId() << " seems different" )); + { + if ( sameTopo ) + return toSM( error(TCom("Mesh on faces #") << botSM->GetId() + <<" and #"<< topSM->GetId() << " seems different" )); + else + return toSM( error(TCom("Topology of faces #") << botSM->GetId() + <<" and #"<< topSM->GetId() << " seems different" )); + } // Fill myBotToColumnMap @@ -2497,6 +2558,29 @@ namespace Prism_3D myWallQuads.clear(); } + //================================================================================ + /*! + * \brief Set upside-down + */ + //================================================================================ + + void TPrismTopo::SetUpsideDown() + { + std::swap( myBottom, myTop ); + myBottomEdges.clear(); + std::reverse( myBottomEdges.begin(), myBottomEdges.end() ); + for ( size_t i = 0; i < myWallQuads.size(); ++i ) + { + myWallQuads[i].reverse(); + TQuadList::iterator q = myWallQuads[i].begin(); + for ( ; q != myWallQuads[i].end(); ++q ) + { + (*q)->shift( 2, /*keepUnitOri=*/true ); + } + myBottomEdges.push_back( myWallQuads[i].front()->side[ QUAD_BOTTOM_SIDE ].grid->Edge(0) ); + } + } + } // namespace Prism_3D //================================================================================ @@ -2603,7 +2687,7 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, SMESH_subMesh * botSM = 0; SMESH_subMesh * topSM = 0; - if ( hasNotQuad ) // can chose a bottom FACE + if ( hasNotQuad ) // can choose a bottom FACE { if ( nbNotQuadMeshed > 0 ) botSM = notQuadElemSubMesh.front(); else botSM = notQuadGeomSubMesh.front(); @@ -2711,6 +2795,12 @@ bool StdMeshers_Prism_3D::initPrism(Prism_3D::TPrismTopo& thePrism, "Non-quadrilateral faces are not opposite")); } + if ( thePrism.myBottomEdges.size() > thePrism.myWallQuads.size() ) + { + // composite bottom sides => set thePrism upside-down + thePrism.SetUpsideDown(); + } + return true; } diff --git a/src/StdMeshers/StdMeshers_Prism_3D.hxx b/src/StdMeshers/StdMeshers_Prism_3D.hxx index f4e49ce63..f2929c31a 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.hxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.hxx @@ -109,6 +109,7 @@ namespace Prism_3D bool myNotQuadOnTop; void Clear(); + void SetUpsideDown(); }; } @@ -471,7 +472,8 @@ public: * and projection is possible and allowed, perform the projection * \retval bool - is a success or not */ - bool assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf ); + bool assocOrProjBottom2Top( const gp_Trsf & bottomToTopTrsf, + const Prism_3D::TPrismTopo& thePrism); /*! * \brief Remove quadrangles from the top face and diff --git a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx index 8d4e172ad..18c6f27d2 100644 --- a/src/StdMeshers/StdMeshers_ProjectionUtils.cxx +++ b/src/StdMeshers/StdMeshers_ProjectionUtils.cxx @@ -1800,7 +1800,8 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, eE.Next(); // edge 1 if ( !assocMap.IsBound( e2, /*is2nd=*/true )) - RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( e2 )); + continue; + //RETURN_BAD_RESULT("Association not found for edge " << meshDS2->ShapeToIndex( e2 )); TopoDS_Edge e1 = TopoDS::Edge( assocMap( e2, /*is2nd=*/true )); if ( !helper1.IsSubShape( e1, face1 )) RETURN_BAD_RESULT("Wrong association, edge " << meshDS1->ShapeToIndex( e1 ) << @@ -1844,7 +1845,11 @@ FindMatchingNodesOnFaces( const TopoDS_Face& face1, // get 2 matching vertices TopoDS_Vertex V2 = TopExp::FirstVertex( TopoDS::Edge( edge2 )); if ( !assocMap.IsBound( V2, /*is2nd=*/true )) - RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 )); + { + V2 = TopExp::LastVertex( TopoDS::Edge( edge2 )); + if ( !assocMap.IsBound( V2, /*is2nd=*/true )) + RETURN_BAD_RESULT("Association not found for vertex " << meshDS2->ShapeToIndex( V2 )); + } TopoDS_Vertex V1 = TopoDS::Vertex( assocMap( V2, /*is2nd=*/true )); // nodes on vertices -- 2.30.2