From 466da2436e3a2de79c6c79edafc0d4cac819f839 Mon Sep 17 00:00:00 2001 From: eap Date: Thu, 16 Jun 2016 16:23:35 +0300 Subject: [PATCH] Fix test SALOME_TESTS/Grids/smesh/2D_mesh_QuadranglePreference_01/B6 Case of a ring with sub-meshes on both wires --- .../SMESH/images/quad_from_ma_ring_mesh.png | Bin 0 -> 8751 bytes .../gui/SMESH/input/basic_meshing_algos.doc | 2 +- .../gui/SMESH/input/quad_from_ma_algo.doc | 1 + src/SMESH/SMESH_Algo.cxx | 2 +- src/SMESH_SWIG/smeshBuilder.py | 6 + src/StdMeshers/StdMeshers_FaceSide.cxx | 25 +- .../StdMeshers_QuadFromMedialAxis_1D2D.cxx | 496 +++++++++++------- src/StdMeshers/StdMeshers_Quadrangle_2D.cxx | 11 +- 8 files changed, 343 insertions(+), 200 deletions(-) create mode 100644 doc/salome/gui/SMESH/images/quad_from_ma_ring_mesh.png diff --git a/doc/salome/gui/SMESH/images/quad_from_ma_ring_mesh.png b/doc/salome/gui/SMESH/images/quad_from_ma_ring_mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..9a43e6db7719463f041fd5293e60fe3e32a68f68 GIT binary patch literal 8751 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 BN811Z literal 0 HcmV?d00001 diff --git a/doc/salome/gui/SMESH/input/basic_meshing_algos.doc b/doc/salome/gui/SMESH/input/basic_meshing_algos.doc index 080727462..b4a99c41f 100644 --- a/doc/salome/gui/SMESH/input/basic_meshing_algos.doc +++ b/doc/salome/gui/SMESH/input/basic_meshing_algos.doc @@ -66,7 +66,7 @@ objects. There is also a number of more specific algorithms:
  • \subpage prism_3d_algo_page "for meshing prismatic 3D shapes with hexahedra and prisms"
  • -
  • \subpage quad_from_ma_algo_page "for quadrangle meshing of faces with sinuous borders"
  • +
  • \subpage quad_from_ma_algo_page "for quadrangle meshing of faces with sinuous borders and rings"
  • Polygon per Face meshing algorithm - generates one mesh face (either a triangle, a quadrangle or a polygon) per a geometrical face using all nodes from the face boundary.
  • diff --git a/doc/salome/gui/SMESH/input/quad_from_ma_algo.doc b/doc/salome/gui/SMESH/input/quad_from_ma_algo.doc index e3df9e4a5..f7312ee12 100644 --- a/doc/salome/gui/SMESH/input/quad_from_ma_algo.doc +++ b/doc/salome/gui/SMESH/input/quad_from_ma_algo.doc @@ -32,4 +32,5 @@ The Medial Axis is used in two ways: borders to find positions of nodes. +\image html quad_from_ma_ring_mesh.png "Mesh depends on defined sub-meshes: to the left - sub-meshes on both wires, to the right - a sub-mesh on internal wire only" */ diff --git a/src/SMESH/SMESH_Algo.cxx b/src/SMESH/SMESH_Algo.cxx index 9541f249e..e31bf02d9 100644 --- a/src/SMESH/SMESH_Algo.cxx +++ b/src/SMESH/SMESH_Algo.cxx @@ -412,7 +412,7 @@ bool SMESH_Algo::GetSortedNodesOnEdge(const SMESHDS_Mesh* theM return false; SMESHDS_SubMesh * eSubMesh = theMesh->MeshElements( theEdge ); - if ( !eSubMesh || ( eSubMesh->NbElements()==0 && eSubMesh->NbNodes() == 0)) + if ( !eSubMesh || ( eSubMesh->NbElements() == 0 && eSubMesh->NbNodes() == 0)) return false; // edge is not meshed int nbNodes = 0; diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 1baa0400d..f56f9551c 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -1504,6 +1504,12 @@ class Mesh: pass return ok + ## Return a list of error messages (SMESH.ComputeError) of the last Compute() + def GetComputeErrors(self, shape=0 ): + if shape == 0: + shape = self.mesh.GetShapeToMesh() + return self.smeshpyD.GetComputeErrors( self.mesh, shape ) + ## Return a name of a sub-shape by its ID # @param subShapeID a unique ID of a sub-shape # @return a string describing the sub-shape; possible variants: diff --git a/src/StdMeshers/StdMeshers_FaceSide.cxx b/src/StdMeshers/StdMeshers_FaceSide.cxx index ab76ddf93..53a8d5dc2 100644 --- a/src/StdMeshers/StdMeshers_FaceSide.cxx +++ b/src/StdMeshers/StdMeshers_FaceSide.cxx @@ -548,8 +548,8 @@ const vector& StdMeshers_FaceSide::SimulateUVPtStruct(int nbSeg, bool isXConst, double constValue) const { - if ( myFalsePoints.empty() ) { - + if ( myFalsePoints.empty() ) + { if ( NbEdges() == 0 ) return myFalsePoints; vector* points = const_cast*>( &myFalsePoints ); @@ -557,28 +557,29 @@ const vector& StdMeshers_FaceSide::SimulateUVPtStruct(int nbSeg, int EdgeIndex = 0; double prevNormPar = 0, paramSize = myNormPar[ EdgeIndex ]; - for ( size_t i = 0 ; i < myFalsePoints.size(); ++i ) { + gp_Pnt2d p; + for ( size_t i = 0 ; i < myFalsePoints.size(); ++i ) + { double normPar = double(i) / double(nbSeg); UVPtStruct & uvPt = (*points)[i]; uvPt.node = 0; uvPt.x = uvPt.y = uvPt.param = uvPt.normParam = normPar; if ( isXConst ) uvPt.x = constValue; else uvPt.y = constValue; - if ( myNormPar[ EdgeIndex ] < normPar ) { + if ( myNormPar[ EdgeIndex ] < normPar ) + { prevNormPar = myNormPar[ EdgeIndex ]; ++EdgeIndex; paramSize = myNormPar[ EdgeIndex ] - prevNormPar; } double r = ( normPar - prevNormPar )/ paramSize; uvPt.param = myFirst[EdgeIndex] * ( 1 - r ) + myLast[EdgeIndex] * r; - if ( !myC2d[ EdgeIndex ].IsNull() ) { - gp_Pnt2d p = myC2d[ EdgeIndex ]->Value( uvPt.param ); - uvPt.u = p.X(); - uvPt.v = p.Y(); - } - else { - uvPt.u = uvPt.v = 1e+100; - } + if ( !myC2d[ EdgeIndex ].IsNull() ) + p = myC2d[ EdgeIndex ]->Value( uvPt.param ); + else + p = Value2d( normPar ); + uvPt.u = p.X(); + uvPt.v = p.Y(); } } return myFalsePoints; diff --git a/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx b/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx index 46d661191..fb0749452 100644 --- a/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx @@ -160,7 +160,7 @@ StdMeshers_QuadFromMedialAxis_1D2D::StdMeshers_QuadFromMedialAxis_1D2D(int _shapeType = (1 << TopAbs_FACE); _onlyUnaryInput = true; // FACE by FACE so far _requireDiscreteBoundary = false; // make 1D by myself - _supportSubmeshes = true; // make 1D by myself + _supportSubmeshes = true; // make 1D by myself _neededLowerHyps[ 1 ] = true; // suppress warning on hiding a global 1D algo _neededLowerHyps[ 2 ] = true; // suppress warning on hiding a global 2D algo _compatibleHypothesis.clear(); @@ -1363,6 +1363,116 @@ namespace return; } // separateNodes() + + //================================================================================ + /*! + * \brief Find association of nodes existing on the sinuous sides of a ring + * + * TMAPar2NPoints filled here is used in setQuadSides() only if theSinuFace.IsRing() + * to find most distant nodes of the inner and the outer wires + */ + //================================================================================ + + void assocNodes( SMESH_MesherHelper& theHelper, + SinuousFace& theSinuFace, + const SMESH_MAT2d::MedialAxis& theMA, + TMAPar2NPoints & thePointsOnE ) + { + list< TopoDS_Edge > ee1( theSinuFace._sinuSide [0].begin(), theSinuFace._sinuSide [0].end() ); + list< TopoDS_Edge > ee2( theSinuFace._sinuSide [1].begin(), theSinuFace._sinuSide [1].end() ); + StdMeshers_FaceSide sideOut( theSinuFace.Face(), ee1, theHelper.GetMesh(), true, true ); + StdMeshers_FaceSide sideIn ( theSinuFace.Face(), ee2, theHelper.GetMesh(), true, true ); + const UVPtStructVec& uvsOut = sideOut.GetUVPtStruct(); + const UVPtStructVec& uvsIn = sideIn.GetUVPtStruct(); + // if ( uvs1.size() != uvs2.size() ) + // return; + + const SMESH_MAT2d::Branch& branch = *theMA.getBranch(0); + SMESH_MAT2d::BoundaryPoint bp[2]; + SMESH_MAT2d::BranchPoint brp; + SMESHDS_Mesh* meshDS = theHelper.GetMeshDS(); + + map< double, const SMDS_MeshNode* > nodeParams; // params of existing nodes + map< double, const SMDS_MeshNode* >::iterator u2n; + + // find a node of sideOut most distant from sideIn + + vector< BRepAdaptor_Curve > curvesIn( theSinuFace._sinuSide[1].size() ); + for ( size_t iE = 0; iE < theSinuFace._sinuSide[1].size(); ++iE ) + curvesIn[ iE ].Initialize( theSinuFace._sinuSide[1][iE] ); + + double maxDist = 0; + SMESH_MAT2d::BoundaryPoint bpIn; // closest IN point + const SMDS_MeshNode* nOut = 0; + const size_t nbEOut = theSinuFace._sinuSide[0].size(); + for ( size_t iE = 0; iE < nbEOut; ++iE ) + { + const TopoDS_Edge& E = theSinuFace._sinuSide[0][iE]; + + if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, E, /*skipMedium=*/true, nodeParams )) + return; + for ( u2n = nodeParams.begin(); u2n != nodeParams.end(); ++u2n ) + { + // point on EDGE (u2n) --> MA point (brp) + if ( !theMA.getBoundary().getBranchPoint( iE, u2n->first, brp ) || + !branch.getBoundaryPoints( brp, bp[0], bp[1] )) + return; + gp_Pnt pOut = SMESH_TNodeXYZ( u2n->second ); + gp_Pnt pIn = curvesIn[ bp[1]._edgeIndex - nbEOut ].Value( bp[1]._param ); + double dist = pOut.SquareDistance( pIn ); + if ( dist > maxDist ) + { + maxDist = dist; + nOut = u2n->second; + bpIn = bp[1]; + } + } + } + const SMDS_MeshNode* nIn = 0; + if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, + theSinuFace._sinuEdges[ bpIn._edgeIndex ], + /*skipMedium=*/true, + nodeParams )) + return; + u2n = nodeParams.lower_bound( bpIn._param ); + if ( u2n == nodeParams.end() ) + nIn = nodeParams.rbegin()->second; + else + nIn = u2n->second; + + // find position of distant nodes in uvsOut and uvsIn + size_t iDistOut, iDistIn; + for ( iDistOut = 0; iDistOut < uvsOut.size(); ++iDistOut ) + { + if ( uvsOut[iDistOut].node == nOut ) + break; + } + for ( iDistIn = 0; iDistIn < uvsIn.size(); ++iDistIn ) + { + if ( uvsIn[iDistIn].node == nIn ) + break; + } + if ( iDistOut == uvsOut.size() || iDistIn == uvsIn.size() ) + return; + + // store opposite nodes in thePointsOnE (param and EDGE have no sense) + pair< NodePoint, NodePoint > oppNodes( NodePoint( nOut, 0, 0 ), NodePoint( nIn, 0, 0)); + thePointsOnE.insert( make_pair( uvsOut[ iDistOut ].normParam, oppNodes )); + int iOut = iDistOut, iIn = iDistIn; + int i, nbNodes = std::min( uvsOut.size(), uvsIn.size() ); + if ( nbNodes > 5 ) nbNodes = 5; + for ( i = 0, ++iOut, --iIn; i < nbNodes; ++iOut, --iIn, ++i ) + { + iOut = theHelper.WrapIndex( iOut, uvsOut.size() ); + iIn = theHelper.WrapIndex( iIn, uvsIn.size() ); + oppNodes.first._node = uvsOut[ iOut ].node; + oppNodes.second._node = uvsIn[ iIn ].node; + thePointsOnE.insert( make_pair( uvsOut[ iOut ].normParam, oppNodes )); + } + + return; + } // assocNodes() + //================================================================================ /*! * \brief Setup sides of SinuousFace::_quad @@ -1387,9 +1497,9 @@ namespace list< TopoDS_Edge > side[4]; side[0].insert( side[0].end(), theFace._shortSide[0].begin(), theFace._shortSide[0].end() ); - side[1].insert( side[1].end(), theFace._sinuSide[1].begin(), theFace._sinuSide[1].end() ); + side[1].insert( side[1].end(), theFace._sinuSide [1].begin(), theFace._sinuSide [1].end() ); side[2].insert( side[2].end(), theFace._shortSide[1].begin(), theFace._shortSide[1].end() ); - side[3].insert( side[3].end(), theFace._sinuSide[0].begin(), theFace._sinuSide[0].end() ); + side[3].insert( side[3].end(), theFace._sinuSide [0].begin(), theFace._sinuSide [0].end() ); for ( int i = 0; i < 4; ++i ) { @@ -1406,6 +1516,11 @@ namespace if ( thePointsOnEdges.size() < 4 ) return false; + int nbOut = theFace._quad->side[ 1 ].GetUVPtStruct().size(); + int nbIn = theFace._quad->side[ 3 ].GetUVPtStruct().size(); + if ( nbOut == 0 || nbIn == 0 ) + return false; + // find most distant opposite nodes double maxDist = 0, dist; TMAPar2NPoints::const_iterator u2NPdist, u2NP = thePointsOnEdges.begin(); @@ -1416,7 +1531,7 @@ namespace if ( dist > maxDist ) { u2NPdist = u2NP; - maxDist = dist; + maxDist = dist; } } // compute distribution of radial nodes @@ -1428,6 +1543,8 @@ namespace params ); // add a radial quad side + + theHelper.SetElementsOnShape( true ); u2NP = thePointsOnEdges.begin(); const SMDS_MeshNode* nOut = u2NP->second.first._node; const SMDS_MeshNode* nIn = u2NP->second.second._node; @@ -1457,13 +1574,10 @@ namespace theFace._quad->side[ 0 ] = StdMeshers_FaceSide::New( uvsNew ); theFace._quad->side[ 2 ] = theFace._quad->side[ 0 ]; - - if ( theFace._quad->side[ 1 ].GetUVPtStruct().empty() || - theFace._quad->side[ 3 ].GetUVPtStruct().empty() ) - return false; + if ( nbIn != nbOut ) + theFace._quad->side[ 2 ] = StdMeshers_FaceSide::New( uvsNew ); // assure that the outer sinuous side starts at nOut - if ( theFace._sinuSide[0].size() > 1 ) { const UVPtStructVec& uvsOut = theFace._quad->side[ 3 ].GetUVPtStruct(); // _sinuSide[0] size_t i; // find UVPtStruct holding nOut @@ -1485,6 +1599,7 @@ namespace } // rotate the IN side if opposite nodes of IN and OUT sides don't match + const SMDS_MeshNode * nIn0 = theFace._quad->side[ 1 ].First().node; if ( nIn0 != nIn ) { @@ -1571,208 +1686,223 @@ namespace const SMESH_MAT2d::Branch& branch = *theMA.getBranch(0); SMESH_MAT2d::BoundaryPoint bp[2]; - vector< std::size_t > edgeIDs1, edgeIDs2; // indices in theSinuEdges - vector< SMESH_MAT2d::BranchPoint > divPoints; - if ( !allComputed ) - branch.getOppositeGeomEdges( edgeIDs1, edgeIDs2, divPoints ); - - for ( size_t i = 0; i < edgeIDs1.size(); ++i ) - if ( isComputed[ edgeIDs1[i]] && - isComputed[ edgeIDs2[i]] ) - { - int nbNodes1 = meshDS->MeshElements(edgeIDs[ edgeIDs1[i]] )->NbNodes(); - int nbNodes2 = meshDS->MeshElements(edgeIDs[ edgeIDs2[i]] )->NbNodes(); - if ( nbNodes1 != nbNodes2 ) - return false; - if (( i-1 >= 0 ) && - ( edgeIDs1[i-1] == edgeIDs1[i] || - edgeIDs2[i-1] == edgeIDs2[i] )) - return false; - if (( i+1 < edgeIDs1.size() ) && - ( edgeIDs1[i+1] == edgeIDs1[i] || - edgeIDs2[i+1] == edgeIDs2[i] )) - return false; - } - - // map (param on MA) to (parameters of nodes on a pair of theSinuEdges) TMAPar2NPoints pointsOnE; - vector maParams; - set projectedEdges; // treated EDGEs which 'isComputed' + // check that computed EDGEs are opposite and equally meshed + if ( allComputed ) + { + // int nbNodes[2] = { 0, 0 }; + // for ( int iSide = 0; iSide < 2; ++iSide ) // loop on two sinuous sides + // nbNodes[ iSide ] += meshDS->MeshElements( theSinuFace._sinuSide[ iSide ])->NbNodes() - 1; - // compute params of nodes on EDGEs by projecting division points from MA + // if ( nbNodes[0] != nbNodes[1] ) + // return false; - for ( size_t iEdgePair = 0; iEdgePair < edgeIDs1.size(); ++iEdgePair ) - // loop on pairs of opposite EDGEs + if ( theSinuFace.IsRing() ) + assocNodes( theHelper, theSinuFace, theMA, pointsOnE ); + } + else { - if ( projectedEdges.count( edgeIDs1[ iEdgePair ]) || - projectedEdges.count( edgeIDs2[ iEdgePair ]) ) - continue; + vector< std::size_t > edgeIDs1, edgeIDs2; // indices in theSinuEdges + vector< SMESH_MAT2d::BranchPoint > divPoints; + branch.getOppositeGeomEdges( edgeIDs1, edgeIDs2, divPoints ); - // -------------------------------------------------------------------------------- - if ( isComputed[ edgeIDs1[ iEdgePair ]] != // one EDGE is meshed - isComputed[ edgeIDs2[ iEdgePair ]]) + for ( size_t i = 0; i < edgeIDs1.size(); ++i ) + if ( isComputed[ edgeIDs1[i]] && + isComputed[ edgeIDs2[i]] ) + { + int nbNodes1 = meshDS->MeshElements(edgeIDs[ edgeIDs1[i]] )->NbNodes(); + int nbNodes2 = meshDS->MeshElements(edgeIDs[ edgeIDs2[i]] )->NbNodes(); + if ( nbNodes1 != nbNodes2 ) + return false; + if (( int(i)-1 >= 0 ) && + ( edgeIDs1[i-1] == edgeIDs1[i] || + edgeIDs2[i-1] == edgeIDs2[i] )) + return false; + if (( i+1 < edgeIDs1.size() ) && + ( edgeIDs1[i+1] == edgeIDs1[i] || + edgeIDs2[i+1] == edgeIDs2[i] )) + return false; + } + + // map (param on MA) to (parameters of nodes on a pair of theSinuEdges) + vector maParams; + set projectedEdges; // treated EDGEs which 'isComputed' + + // compute params of nodes on EDGEs by projecting division points from MA + + for ( size_t iEdgePair = 0; iEdgePair < edgeIDs1.size(); ++iEdgePair ) + // loop on pairs of opposite EDGEs { - // "projection" from one side to the other + if ( projectedEdges.count( edgeIDs1[ iEdgePair ]) || + projectedEdges.count( edgeIDs2[ iEdgePair ]) ) + continue; - size_t iEdgeComputed = edgeIDs1[iEdgePair], iSideComputed = 0; - if ( !isComputed[ iEdgeComputed ]) - ++iSideComputed, iEdgeComputed = edgeIDs2[iEdgePair]; + // -------------------------------------------------------------------------------- + if ( isComputed[ edgeIDs1[ iEdgePair ]] != // one EDGE is meshed + isComputed[ edgeIDs2[ iEdgePair ]]) + { + // "projection" from one side to the other - map< double, const SMDS_MeshNode* > nodeParams; // params of existing nodes - if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iEdgeComputed ], /*skipMedium=*/true, nodeParams )) - return false; + size_t iEdgeComputed = edgeIDs1[iEdgePair], iSideComputed = 0; + if ( !isComputed[ iEdgeComputed ]) + ++iSideComputed, iEdgeComputed = edgeIDs2[iEdgePair]; - projectedEdges.insert( iEdgeComputed ); + map< double, const SMDS_MeshNode* > nodeParams; // params of existing nodes + if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iEdgeComputed ], /*skipMedium=*/true, nodeParams )) + return false; - SMESH_MAT2d::BoundaryPoint& bndPnt = bp[ 1-iSideComputed ]; - SMESH_MAT2d::BranchPoint brp; - NodePoint npN, npB; // NodePoint's initialized by node and BoundaryPoint - NodePoint& np0 = iSideComputed ? npB : npN; - NodePoint& np1 = iSideComputed ? npN : npB; + projectedEdges.insert( iEdgeComputed ); - double maParam1st, maParamLast, maParam; - if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, nodeParams.begin()->first, brp )) - return false; - branch.getParameter( brp, maParam1st ); - if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, nodeParams.rbegin()->first, brp )) - return false; - branch.getParameter( brp, maParamLast ); + SMESH_MAT2d::BoundaryPoint& bndPnt = bp[ 1-iSideComputed ]; + SMESH_MAT2d::BranchPoint brp; + NodePoint npN, npB; // NodePoint's initialized by node and BoundaryPoint + NodePoint& np0 = iSideComputed ? npB : npN; + NodePoint& np1 = iSideComputed ? npN : npB; - map< double, const SMDS_MeshNode* >::iterator u2n = nodeParams.begin(), u2nEnd = nodeParams.end(); - TMAPar2NPoints::iterator end = pointsOnE.end(), pos = end; - TMAPar2NPoints::iterator & hint = (maParamLast > maParam1st) ? end : pos; - for ( ++u2n, --u2nEnd; u2n != u2nEnd; ++u2n ) - { - // point on EDGE (u2n) --> MA point (brp) - if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, u2n->first, brp )) + double maParam1st, maParamLast, maParam; + if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, nodeParams.begin()->first, brp )) return false; - // MA point --> points on 2 EDGEs (bp) - if ( !branch.getBoundaryPoints( brp, bp[0], bp[1] ) || - !branch.getParameter( brp, maParam )) + branch.getParameter( brp, maParam1st ); + if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, nodeParams.rbegin()->first, brp )) return false; + branch.getParameter( brp, maParamLast ); - npN = NodePoint( u2n->second, u2n->first, iEdgeComputed ); - npB = NodePoint( bndPnt ); - pos = pointsOnE.insert( hint, make_pair( maParam, make_pair( np0, np1 ))); + map< double, const SMDS_MeshNode* >::iterator u2n = nodeParams.begin(), u2nEnd = nodeParams.end(); + TMAPar2NPoints::iterator end = pointsOnE.end(), pos = end; + TMAPar2NPoints::iterator & hint = (maParamLast > maParam1st) ? end : pos; + for ( ++u2n, --u2nEnd; u2n != u2nEnd; ++u2n ) + { + // point on EDGE (u2n) --> MA point (brp) + if ( !theMA.getBoundary().getBranchPoint( iEdgeComputed, u2n->first, brp )) + return false; + // MA point --> points on 2 EDGEs (bp) + if ( !branch.getBoundaryPoints( brp, bp[0], bp[1] ) || + !branch.getParameter( brp, maParam )) + return false; + + npN = NodePoint( u2n->second, u2n->first, iEdgeComputed ); + npB = NodePoint( bndPnt ); + pos = pointsOnE.insert( hint, make_pair( maParam, make_pair( np0, np1 ))); + } } - } - // -------------------------------------------------------------------------------- - else if ( !isComputed[ edgeIDs1[ iEdgePair ]] && // none of EDGEs is meshed - !isComputed[ edgeIDs2[ iEdgePair ]]) - { - // "projection" from MA - maParams.clear(); - if ( !getParamsForEdgePair( iEdgePair, divPoints, theMAParams, maParams )) - return false; - - for ( size_t i = 1; i < maParams.size()-1; ++i ) + // -------------------------------------------------------------------------------- + else if ( !isComputed[ edgeIDs1[ iEdgePair ]] && // none of EDGEs is meshed + !isComputed[ edgeIDs2[ iEdgePair ]]) { - if ( !branch.getBoundaryPoints( maParams[i], bp[0], bp[1] )) + // "projection" from MA + maParams.clear(); + if ( !getParamsForEdgePair( iEdgePair, divPoints, theMAParams, maParams )) return false; - pointsOnE.insert( pointsOnE.end(), make_pair( maParams[i], make_pair( NodePoint(bp[0]), - NodePoint(bp[1])))); - } - } - // -------------------------------------------------------------------------------- - else if ( isComputed[ edgeIDs1[ iEdgePair ]] && // equally meshed EDGES - isComputed[ edgeIDs2[ iEdgePair ]]) - { - // add existing nodes - - size_t iE0 = edgeIDs1[ iEdgePair ]; - size_t iE1 = edgeIDs2[ iEdgePair ]; - map< double, const SMDS_MeshNode* > nodeParams[2]; // params of existing nodes - if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iE0 ], - /*skipMedium=*/false, nodeParams[0] ) || - !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iE1 ], - /*skipMedium=*/false, nodeParams[1] ) || - nodeParams[0].size() != nodeParams[1].size() ) - return false; - - if ( nodeParams[0].size() <= 2 ) - continue; // nodes on VERTEXes only + for ( size_t i = 1; i < maParams.size()-1; ++i ) + { + if ( !branch.getBoundaryPoints( maParams[i], bp[0], bp[1] )) + return false; - bool reverse = ( theSinuEdges[0].Orientation() == theSinuEdges[1].Orientation() ); - double maParam; - SMESH_MAT2d::BranchPoint brp; - std::pair< NodePoint, NodePoint > npPair; - - map< double, const SMDS_MeshNode* >::iterator - u2n0F = ++nodeParams[0].begin(), - u2n1F = ++nodeParams[1].begin(); - map< double, const SMDS_MeshNode* >::reverse_iterator - u2n1R = ++nodeParams[1].rbegin(); - for ( ; u2n0F != nodeParams[0].end(); ++u2n0F ) + pointsOnE.insert( pointsOnE.end(), make_pair( maParams[i], make_pair( NodePoint(bp[0]), + NodePoint(bp[1])))); + } + } + // -------------------------------------------------------------------------------- + else if ( isComputed[ edgeIDs1[ iEdgePair ]] && // equally meshed EDGES + isComputed[ edgeIDs2[ iEdgePair ]]) { - if ( !theMA.getBoundary().getBranchPoint( iE0, u2n0F->first, brp ) || - !branch.getParameter( brp, maParam )) + // add existing nodes + + size_t iE0 = edgeIDs1[ iEdgePair ]; + size_t iE1 = edgeIDs2[ iEdgePair ]; + map< double, const SMDS_MeshNode* > nodeParams[2]; // params of existing nodes + if ( !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iE0 ], + /*skipMedium=*/false, nodeParams[0] ) || + !SMESH_Algo::GetSortedNodesOnEdge( meshDS, theSinuEdges[ iE1 ], + /*skipMedium=*/false, nodeParams[1] ) || + nodeParams[0].size() != nodeParams[1].size() ) return false; - npPair.first = NodePoint( u2n0F->second, u2n0F->first, iE0 ); - if ( reverse ) - { - npPair.second = NodePoint( u2n1R->second, u2n1R->first, iE1 ); - ++u2n1R; - } - else + if ( nodeParams[0].size() <= 2 ) + continue; // nodes on VERTEXes only + + bool reverse = ( theSinuEdges[0].Orientation() == theSinuEdges[1].Orientation() ); + double maParam; + SMESH_MAT2d::BranchPoint brp; + std::pair< NodePoint, NodePoint > npPair; + + map< double, const SMDS_MeshNode* >::iterator + u2n0F = ++nodeParams[0].begin(), + u2n1F = ++nodeParams[1].begin(); + map< double, const SMDS_MeshNode* >::reverse_iterator + u2n1R = ++nodeParams[1].rbegin(); + for ( ; u2n0F != nodeParams[0].end(); ++u2n0F ) { - npPair.second = NodePoint( u2n1F->second, u2n1F->first, iE1 ); - ++u2n1F; + if ( !theMA.getBoundary().getBranchPoint( iE0, u2n0F->first, brp ) || + !branch.getParameter( brp, maParam )) + return false; + + npPair.first = NodePoint( u2n0F->second, u2n0F->first, iE0 ); + if ( reverse ) + { + npPair.second = NodePoint( u2n1R->second, u2n1R->first, iE1 ); + ++u2n1R; + } + else + { + npPair.second = NodePoint( u2n1F->second, u2n1F->first, iE1 ); + ++u2n1F; + } + pointsOnE.insert( make_pair( maParam, npPair )); } - pointsOnE.insert( make_pair( maParam, npPair )); } - } - } // loop on pairs of opposite EDGEs + } // loop on pairs of opposite EDGEs - if ( !projectVertices( theHelper, theMA, divPoints, edgeIDs1, edgeIDs2, - isComputed, pointsOnE, theSinuFace )) - return false; + if ( !projectVertices( theHelper, theMA, divPoints, edgeIDs1, edgeIDs2, + isComputed, pointsOnE, theSinuFace )) + return false; - separateNodes( theHelper, theMA, pointsOnE, theSinuFace, isComputed ); + separateNodes( theHelper, theMA, pointsOnE, theSinuFace, isComputed ); - // create nodes - TMAPar2NPoints::iterator u2np = pointsOnE.begin(); - for ( ; u2np != pointsOnE.end(); ++u2np ) - { - NodePoint* np[2] = { & u2np->second.first, & u2np->second.second }; - for ( int iSide = 0; iSide < 2; ++iSide ) + // create nodes + TMAPar2NPoints::iterator u2np = pointsOnE.begin(); + for ( ; u2np != pointsOnE.end(); ++u2np ) { - if ( np[ iSide ]->_node ) continue; - size_t iEdge = np[ iSide ]->_edgeInd; - double u = np[ iSide ]->_u; - gp_Pnt p = curves[ iEdge ]->Value( u ); - np[ iSide ]->_node = meshDS->AddNode( p.X(), p.Y(), p.Z() ); - meshDS->SetNodeOnEdge( np[ iSide ]->_node, edgeIDs[ iEdge ], u ); + NodePoint* np[2] = { & u2np->second.first, & u2np->second.second }; + for ( int iSide = 0; iSide < 2; ++iSide ) + { + if ( np[ iSide ]->_node ) continue; + size_t iEdge = np[ iSide ]->_edgeInd; + double u = np[ iSide ]->_u; + gp_Pnt p = curves[ iEdge ]->Value( u ); + np[ iSide ]->_node = meshDS->AddNode( p.X(), p.Y(), p.Z() ); + meshDS->SetNodeOnEdge( np[ iSide ]->_node, edgeIDs[ iEdge ], u ); + } } - } - - // create mesh segments on EDGEs - theHelper.SetElementsOnShape( false ); - TopoDS_Face face = TopoDS::Face( theHelper.GetSubShape() ); - for ( size_t i = 0; i < theSinuEdges.size(); ++i ) - { - SMESH_subMesh* sm = mesh->GetSubMesh( theSinuEdges[i] ); - if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->NbElements() > 0 ) - continue; - StdMeshers_FaceSide side( face, theSinuEdges[i], mesh, - /*isFwd=*/true, /*skipMediumNodes=*/true ); - vector nodes = side.GetOrderedNodes(); - for ( size_t in = 1; in < nodes.size(); ++in ) + // create mesh segments on EDGEs + theHelper.SetElementsOnShape( false ); + TopoDS_Face face = TopoDS::Face( theHelper.GetSubShape() ); + for ( size_t i = 0; i < theSinuEdges.size(); ++i ) { - const SMDS_MeshElement* seg = theHelper.AddEdge( nodes[in-1], nodes[in], 0, false ); - meshDS->SetMeshElementOnShape( seg, edgeIDs[ i ] ); + SMESH_subMesh* sm = mesh->GetSubMesh( theSinuEdges[i] ); + if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->NbElements() > 0 ) + continue; + + StdMeshers_FaceSide side( face, theSinuEdges[i], mesh, + /*isFwd=*/true, /*skipMediumNodes=*/true ); + vector nodes = side.GetOrderedNodes(); + for ( size_t in = 1; in < nodes.size(); ++in ) + { + const SMDS_MeshElement* seg = theHelper.AddEdge( nodes[in-1], nodes[in], 0, false ); + meshDS->SetMeshElementOnShape( seg, edgeIDs[ i ] ); + } } - } - // update sub-meshes on VERTEXes - for ( size_t i = 0; i < theSinuEdges.size(); ++i ) - { - mesh->GetSubMesh( theHelper.IthVertex( 0, theSinuEdges[i] )) - ->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); - mesh->GetSubMesh( theHelper.IthVertex( 1, theSinuEdges[i] )) - ->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + // update sub-meshes on VERTEXes + for ( size_t i = 0; i < theSinuEdges.size(); ++i ) + { + mesh->GetSubMesh( theHelper.IthVertex( 0, theSinuEdges[i] )) + ->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + mesh->GetSubMesh( theHelper.IthVertex( 1, theSinuEdges[i] )) + ->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + } } // Setup sides of a quadrangle @@ -1969,21 +2099,25 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::computeQuads( SMESH_MesherHelper& theHe int nbNodesShort0 = theQuad->side[0].NbPoints(); int nbNodesShort1 = theQuad->side[2].NbPoints(); + int nbNodesSinu0 = theQuad->side[1].NbPoints(); + int nbNodesSinu1 = theQuad->side[3].NbPoints(); // compute UV of internal points myQuadList.push_back( theQuad ); - if ( !StdMeshers_Quadrangle_2D::setNormalizedGrid( theQuad )) - return false; + // if ( !StdMeshers_Quadrangle_2D::setNormalizedGrid( theQuad )) + // return false; // elliptic smooth of internal points to get boundary cell normal to the boundary bool isRing = theQuad->side[0].grid->Edge(0).IsNull(); - if ( !isRing ) + if ( !isRing ) { + if ( !StdMeshers_Quadrangle_2D::setNormalizedGrid( theQuad )) + return false; ellipticSmooth( theQuad, 1 ); - + } // create quadrangles bool ok; theHelper.SetElementsOnShape( true ); - if ( nbNodesShort0 == nbNodesShort1 ) + if ( nbNodesShort0 == nbNodesShort1 && nbNodesSinu0 == nbNodesSinu1 ) ok = StdMeshers_Quadrangle_2D::computeQuadDominant( *theHelper.GetMesh(), theQuad->face, theQuad ); else diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index e9e6ad827..fc25bf7bb 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -609,8 +609,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh, int stop = 0; if ( quad->side[3].grid->Edge(0).IsNull() ) // left side is simulated one { - // quad divided at I but not at J, as nbvertic==nbright==2 - stop++; // we stop at a second node + if ( nbright == 2 ) // quad divided at I but not at J (2D_mesh_QuadranglePreference_01/B1) + stop++; // we stop at a second node } else { @@ -657,7 +657,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh, } // for each node of the up edge find nearest node // in the first row of the regular grid and link them - for ( ; i > stop; i--) { + for ( ; i > stop; i--) + { a = uv_e2[i].node; b = uv_e2[i - 1].node; gp_Pnt pb = SMESH_TNodeXYZ( b ); @@ -791,8 +792,8 @@ bool StdMeshers_Quadrangle_2D::computeQuadDominant(SMESH_Mesh& aMesh, } } } else { - if (quad->nbNodeOut(3) && nbhoriz == 2) { -// MESSAGE("left edge is out"); + if (quad->nbNodeOut(3) && nbhoriz == 2) + { int g = nbvertic - 1; // last processed node in the grid int stop = 0; i = quad->side[ QUAD_LEFT_SIDE ].to-1; // nbleft - 1; -- 2.39.2