From 4b9725e701864a6b59195f92a1de6b4baa2b1da8 Mon Sep 17 00:00:00 2001 From: eap Date: Thu, 12 Jan 2017 15:13:47 +0300 Subject: [PATCH] 23404: EDF 14011 - Problem with Quadrangle (Medial Axis projection) algorithm (SMESH_MAT2d.cxx) + IPAL53878: Quadrangle: Medial Axis Projection algorithm fails (StdMeshers_QuadFromMedialAxis_1D2D.cxx) --- resources/CMakeLists.txt | 1 + resources/mesh_tree_hypo_quadratic.png | Bin 0 -> 349 bytes src/SMESHUtils/SMESH_MAT2d.cxx | 51 ++++++++++++++++-- .../StdMeshers_QuadFromMedialAxis_1D2D.cxx | 39 ++++++++------ src/StdMeshersGUI/StdMeshers_images.ts | 2 +- 5 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 resources/mesh_tree_hypo_quadratic.png diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 9975b95b2..b7208534e 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -192,6 +192,7 @@ SET(SMESH_RESOURCES_FILES mesh_tree_hypo_source_3d_shape.png mesh_tree_hypo_projection_3d.png mesh_tree_hypo_projection_2d.png + mesh_tree_hypo_quadratic.png mesh_build_compound.png copy_mesh.png mesh_node_to_point.png diff --git a/resources/mesh_tree_hypo_quadratic.png b/resources/mesh_tree_hypo_quadratic.png new file mode 100644 index 0000000000000000000000000000000000000000..6516bf8b9d4c1928772f0215b36efe0776ec9c54 GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xawj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&pIsM@~SMQ)&J7JwTyXo-U3d8t0ErGW2pW6mdN-&Fm;q z67=VgTaFs{h0-0&8_SsW9Cg;*X~|33Ah2<>XKv#3Q;Cbt?KczrBq{o{cYD>IYJUAE zwv&%Y_)4tgJdn+C&CI*w*Sd8#54vpioj-Z1Kt`L`$i-a4@VxKcD#q~h2X>!d`TynbT0f>=rl;8%Cb!JwbeQya r+itVxQICHleSB`b>A&Sp!(S}_XGRo9UEk*d^fiO0tDnm{r-UW|nKO>v literal 0 HcmV?d00001 diff --git a/src/SMESHUtils/SMESH_MAT2d.cxx b/src/SMESHUtils/SMESH_MAT2d.cxx index 2c20eb815..aad6899d3 100644 --- a/src/SMESHUtils/SMESH_MAT2d.cxx +++ b/src/SMESHUtils/SMESH_MAT2d.cxx @@ -340,7 +340,7 @@ namespace return ( _inSeg->getGeomEdge( _edge->twin()->cell() ) != theNoEdgeID ); } - // check a next segment in CW order + // check a next segment in CCW order bool isSameBranch( const BndSeg& seg2 ) { if ( !_edge || !seg2._edge ) @@ -1011,6 +1011,8 @@ namespace int branchID = 1; // we code orientation as branchID sign branchEdges.resize( branchID ); + vector< std::pair< int, const TVDVertex* > > branchesToCheckEnd; + for ( size_t iE = 0; iE < bndSegsPerEdge.size(); ++iE ) { vector< BndSeg >& bndSegs = bndSegsPerEdge[ iE ]; @@ -1039,7 +1041,13 @@ namespace { branchEdges.resize(( branchID = branchEdges.size()) + 1 ); if ( bndSegs[i]._edge && bndSegs[i]._prev ) + { endType.insert( make_pair( bndSegs[i]._edge->vertex1(), SMESH_MAT2d::BE_BRANCH_POINT )); + if ( bndSegs[i]._prev->_branchID < 0 ) + // 0023404: a branch-point is inside a branch + branchesToCheckEnd.push_back( make_pair( bndSegs[i]._prev->branchID(), + bndSegs[i]._edge->vertex1() )); + } } else if ( bndSegs[i]._prev->_branchID ) { @@ -1063,6 +1071,37 @@ namespace } } + if ( !ignoreCorners && !branchesToCheckEnd.empty() ) + { + // split branches having branch-point inside + // (a branch-point was not detected since another branch is joined at the opposite side) + for ( size_t i = 0; i < branchesToCheckEnd.size(); ++i ) + { + vector & branch = branchEdges[ branchesToCheckEnd[i].first ]; + const TVDVertex* branchPoint = branchesToCheckEnd[i].second; + if ( branch.front()->vertex1() == branchPoint || + branch.back ()->vertex0() == branchPoint ) + continue; // OK - branchPoint is at a branch end + + // find a MA edge where another branch begins + size_t iE; + for ( iE = 0; iE < branch.size(); ++iE ) + if ( branch[iE]->vertex1() == branchPoint ) + break; + if ( iE < branch.size() ) + { + // split the branch + branchEdges.resize(( branchID = branchEdges.size()) + 1 ); + vector & branch2 = branchEdges[ branchID ]; + branch2.assign( branch.begin()+iE, branch.end() ); + branch.resize( iE ); + for ( iE = 0; iE < branch2.size(); ++iE ) + if ( BndSeg* bs = BndSeg::getBndSegOfEdge( branch2[iE], bndSegsPerEdge )) + bs->setBranch( branchID, bndSegsPerEdge ); + } + } + } + // join the 1st and the last branch edges if it is the same branch // if ( bndSegs.back().branchID() != bndSegs.front().branchID() && // bndSegs.back().isSameBranch( bndSegs.front() )) @@ -1073,10 +1112,14 @@ namespace // br2.clear(); // } - // remove branches ending at BE_ON_VERTEX + // remove branches ending at BE_ON_VERTEX and BE_END vector isBranchRemoved( branchEdges.size(), false ); + std::set< SMESH_MAT2d::BranchEndType > endTypeToRm; + endTypeToRm.insert( SMESH_MAT2d::BE_ON_VERTEX ); + endTypeToRm.insert( SMESH_MAT2d::BE_END ); + if ( ignoreCorners && branchEdges.size() > 2 && !branchEdges[2].empty() ) { // find branches to remove @@ -1088,10 +1131,10 @@ namespace const TVDVertex* v0 = branchEdges[iB][0]->vertex1(); const TVDVertex* v1 = branchEdges[iB].back()->vertex0(); v2et = endType.find( v0 ); - if ( v2et != endType.end() && v2et->second == SMESH_MAT2d::BE_ON_VERTEX ) + if ( v2et != endType.end() && endTypeToRm.count( v2et->second )) isBranchRemoved[ iB ] = true; v2et = endType.find( v1 ); - if ( v2et != endType.end() && v2et->second == SMESH_MAT2d::BE_ON_VERTEX ) + if ( v2et != endType.end() && endTypeToRm.count( v2et->second )) isBranchRemoved[ iB ] = true; } // try to join not removed branches into one diff --git a/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx b/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx index 76f3a31f2..c7df8a3f7 100644 --- a/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx @@ -1072,7 +1072,7 @@ namespace if ( ! ( theDivPoints[0]._iEdge == 0 && theDivPoints[0]._edgeParam == 0. )) // recursive call { - SMESH_MAT2d::BranchPoint brp( &branch, 0, 0 ); + SMESH_MAT2d::BranchPoint brp( &branch, 0, 0. ); vector< SMESH_MAT2d::BranchPoint > divPoint( 1, brp ); vector< std::size_t > edgeIDs1(2), edgeIDs2(2); edgeIDs1[0] = theEdgeIDs1.back(); @@ -1084,9 +1084,10 @@ namespace } } - // project theDivPoints + // project theDivPoints and keep projections to merge TMAPar2NPoints::iterator u2NP; + vector< TMAPar2NPoints::iterator > projToMerge; for ( size_t i = 0; i < theDivPoints.size(); ++i ) { if ( !branch.getParameter( theDivPoints[i], uMA )) @@ -1129,9 +1130,18 @@ namespace if ( isVertex[0] && isVertex[1] ) continue; - bool isOppComputed = theIsEdgeComputed[ np[ iNode ]._edgeInd ]; - if ( !isOppComputed ) - continue; + // bool isOppComputed = theIsEdgeComputed[ np[ iNode ]._edgeInd ]; + // if ( isOppComputed ) + projToMerge.push_back( u2NP ); + } + + // merge projections + + for ( size_t i = 0; i < projToMerge.size(); ++i ) + { + u2NP = projToMerge[i]; + const size_t iVert = get( u2NP->second, 0 )._node ? 0 : 1; // side with a VERTEX + const size_t iNode = 1 - iVert; // opposite (meshed?) side // a VERTEX is projected on a meshed EDGE; there are two options: // 1) a projected point is joined with a closet node if a strip between this and neighbor @@ -1145,10 +1155,6 @@ namespace bool isShortPrev[2], isShortNext[2], isPrevCloser[2]; TMAPar2NPoints::iterator u2NPPrev = u2NP, u2NPNext = u2NP; --u2NPPrev; ++u2NPNext; - // bool hasPrev = ( u2NP != thePointsOnE.begin() ); - // bool hasNext = ( u2NPNext != thePointsOnE.end() ); - // if ( !hasPrev ) u2NPPrev = u2NP0; - // if ( !hasNext ) u2NPNext = u2NP1; for ( int iS = 0; iS < 2; ++iS ) // side with Vertex and side with Nodes { NodePoint np = get( u2NP->second, iS ); @@ -1161,11 +1167,9 @@ namespace double distNext = p.Distance( pNext ); double r = distPrev / ( distPrev + distNext ); isShortPrev [iS] = ( r < rShort ); - isShortNext [iS] = (( 1 - r ) > ( 1 - rShort )); - isPrevCloser[iS] = (( r < 0.5 ) && ( u2NPPrev->first > 0 )); + isShortNext [iS] = (( 1 - r ) < rShort ); + isPrevCloser[iS] = (( r < 0.5 ) && ( theSinuFace.IsRing() || u2NPPrev->first > 0 )); } - // if ( !hasPrev ) isShortPrev[0] = isShortPrev[1] = false; - // if ( !hasNext ) isShortNext[0] = isShortNext[1] = false; TMAPar2NPoints::iterator u2NPClose; @@ -1174,17 +1178,18 @@ namespace { u2NPClose = isPrevCloser[0] ? u2NPPrev : u2NPNext; NodePoint& npProj = get( u2NP->second, iNode ); // NP of VERTEX projection + NodePoint& npVert = get( u2NP->second, iVert ); // NP of VERTEX NodePoint npCloseN = get( u2NPClose->second, iNode ); // NP close to npProj - NodePoint npCloseV = get( u2NPClose->second, iVert ); // NP close to VERTEX - if ( !npCloseV._node ) + NodePoint npCloseV = get( u2NPClose->second, iVert ); // NP close to npVert + if ( !npCloseV._node || npCloseV._node == npVert._node ) { npProj = npCloseN; - thePointsOnE.erase( isPrevCloser[0] ? u2NPPrev : u2NPNext ); + thePointsOnE.erase( u2NPClose ); continue; } else { - // can't remove the neighbor projection as it is also from VERTEX, -> option 1) + // can't remove the neighbor projection as it is also from VERTEX -> option 1) } } // else: option 1) - wide enough -> "duplicate" existing node diff --git a/src/StdMeshersGUI/StdMeshers_images.ts b/src/StdMeshersGUI/StdMeshers_images.ts index 4bfcece28..fc618a74f 100644 --- a/src/StdMeshersGUI/StdMeshers_images.ts +++ b/src/StdMeshersGUI/StdMeshers_images.ts @@ -265,7 +265,7 @@ ICON_SMESH_TREE_HYPO_QuadraticMesh - mesh_tree_hypo_length.png + mesh_tree_hypo_quadratic.png ICON_SMESH_TREE_HYPO_SegmentLengthAroundVertex -- 2.30.2