From 4bb0c233facf7cc47356a2ebcaa34320918c6fb2 Mon Sep 17 00:00:00 2001 From: Grant Karapetyan Date: Thu, 8 Jun 2023 17:50:43 +0300 Subject: [PATCH] Add cut mesh convert function for not closed MeshTriPoints (#1299) * Add cut mesh converert function for not closed MeshTriPoints * erase invalid commenterase invalid comment --- source/MRMesh/MRContoursCut.cpp | 81 ++++++++++++++++++++++++--------- source/MRMesh/MRContoursCut.h | 10 +++- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/source/MRMesh/MRContoursCut.cpp b/source/MRMesh/MRContoursCut.cpp index eddc4ec5388b..0f292f45bc41 100644 --- a/source/MRMesh/MRContoursCut.cpp +++ b/source/MRMesh/MRContoursCut.cpp @@ -909,14 +909,29 @@ OneMeshIntersection intersectionFromMeshTriPoint( const Mesh& mesh, const MeshTr return res; } -OneMeshContour convertMeshTriPointsToClosedContour( const Mesh& mesh, const std::vector& meshTriPointsOrg ) + +OneMeshContour convertMeshTriPointsToMeshContour( const Mesh& mesh, const std::vector& meshTriPointsOrg ) { MR_TIMER; + if ( meshTriPointsOrg.size() < 2 ) + return {}; + bool closed = + meshTriPointsOrg.front().e == meshTriPointsOrg.back().e && + meshTriPointsOrg.front().bary.a == meshTriPointsOrg.back().bary.a && + meshTriPointsOrg.front().bary.b == meshTriPointsOrg.back().bary.b; + + if ( closed && meshTriPointsOrg.size() < 4 ) + return {}; + // clear duplicates auto meshTriPoints = meshTriPointsOrg; + if ( closed ) + meshTriPoints.resize( meshTriPoints.size() - 1 ); + size_t sizeMTP = closed ? meshTriPoints.size() : meshTriPoints.size() - 1; + std::vector sameEdgeMTPs; Box3f box; - for ( int i = 0; i < meshTriPoints.size(); ++i ) + for ( int i = 0; i < sizeMTP; ++i ) { box.include( mesh.triPoint( meshTriPoints[i] ) ); auto e1 = meshTriPoints[i].onEdge( mesh.topology ); @@ -943,11 +958,11 @@ OneMeshContour convertMeshTriPointsToClosedContour( const Mesh& mesh, const std: if ( meshTriPoints.size() < 2 ) return {}; OneMeshContour res; - std::vector surfacePaths( meshTriPoints.size() ); - for ( int i = 0; i < meshTriPoints.size(); ++i ) + std::vector surfacePaths( sizeMTP ); + for ( int i = 0; i < sizeMTP; ++i ) { // using DijkstraAStar here might be faster, in most case points are close to each other - auto sp = computeGeodesicPath( mesh, meshTriPoints[i], meshTriPoints[( i + 1 ) % meshTriPoints.size()],GeodesicPathApprox::DijkstraAStar ); + auto sp = computeGeodesicPath( mesh, meshTriPoints[i], meshTriPoints[( i + 1 ) % meshTriPoints.size()], GeodesicPathApprox::DijkstraAStar ); if ( !sp.has_value() ) continue; auto partContours = convertSurfacePathsToMeshContours( mesh, { std::move( sp.value() ) } ); @@ -991,25 +1006,36 @@ OneMeshContour convertMeshTriPointsToClosedContour( const Mesh& mesh, const std: // add interjacent for ( int i = 0; i < meshTriPoints.size(); ++i ) { - auto& prevInter = surfacePaths[( i + int( meshTriPoints.size() ) - 1 ) % meshTriPoints.size()].intersections; - auto& nextInter = surfacePaths[i].intersections; + std::vector* prevInter = ( closed || i > 0 ) ? &surfacePaths[( i + int( meshTriPoints.size() ) - 1 ) % meshTriPoints.size()].intersections : nullptr; + const std::vector* nextInter = ( i < sizeMTP ) ? &surfacePaths[i].intersections : nullptr; OneMeshIntersection lastPrev; OneMeshIntersection firstNext; - if ( prevInter.empty() ) + if ( prevInter ) { - if ( !res.intersections.empty() ) - lastPrev = res.intersections.back(); + if ( prevInter->empty() ) + { + if ( !res.intersections.empty() ) + lastPrev = res.intersections.back(); + else + lastPrev = intersectionFromMeshTriPoint( mesh, meshTriPoints[( i + int( meshTriPoints.size() ) - 1 ) % meshTriPoints.size()] ); + } else - lastPrev = intersectionFromMeshTriPoint( mesh, meshTriPoints[( i + int( meshTriPoints.size() ) - 1 ) % meshTriPoints.size()] ); + lastPrev = prevInter->back(); } else - lastPrev = prevInter.back(); - if ( nextInter.empty() ) + lastPrev = intersectionFromMeshTriPoint( mesh, meshTriPoints[i] ); + if ( nextInter ) { - firstNext = intersectionFromMeshTriPoint( mesh, meshTriPoints[( i + 1 ) % meshTriPoints.size()] ); + if ( nextInter->empty() ) + { + firstNext = intersectionFromMeshTriPoint( mesh, meshTriPoints[( i + 1 ) % meshTriPoints.size()] ); + } + else + firstNext = nextInter->front(); } else - firstNext = nextInter.front(); + firstNext = intersectionFromMeshTriPoint( mesh, meshTriPoints[i] ); + CenterInterType type; auto centerInterOp = centralIntersection( mesh, lastPrev, meshTriPoints[i], firstNext, closeEdgeEps, type ); if ( centerInterOp ) @@ -1019,25 +1045,38 @@ OneMeshContour convertMeshTriPointsToClosedContour( const Mesh& mesh, const std: else { if ( res.intersections.empty() ) - prevInter.back() = *centerInterOp; + { + if ( prevInter ) + prevInter->back() = *centerInterOp; + } else res.intersections.back() = *centerInterOp; } } - if ( !surfacePaths[i].intersections.empty() ) + if ( nextInter && !nextInter->empty() ) { if ( type == CenterInterType::Common ) - res.intersections.insert( res.intersections.end(), surfacePaths[i].intersections.begin(), surfacePaths[i].intersections.end() ); + res.intersections.insert( res.intersections.end(), nextInter->begin(), nextInter->end() ); else - res.intersections.insert( res.intersections.end(), surfacePaths[i].intersections.begin() + 1, surfacePaths[i].intersections.end() ); + res.intersections.insert( res.intersections.end(), nextInter->begin() + 1, nextInter->end() ); } } - res.intersections.push_back( res.intersections.front() ); - res.closed = true; + if ( closed && !res.intersections.empty() ) + { + res.intersections.push_back( res.intersections.front() ); + res.closed = true; + } return res; } +OneMeshContour convertMeshTriPointsToClosedContour( const Mesh& mesh, const std::vector& meshTriPointsOrg ) +{ + auto conts = meshTriPointsOrg; + conts.push_back( meshTriPointsOrg.front() ); + return convertMeshTriPointsToMeshContour( mesh, meshTriPointsOrg ); +} + OneMeshContour convertSurfacePathWithEndsToMeshContour( const MR::Mesh& mesh, const MeshTriPoint& start, const MR::SurfacePath& surfacePath, const MeshTriPoint& end ) { if ( surfacePath.empty() ) diff --git a/source/MRMesh/MRContoursCut.h b/source/MRMesh/MRContoursCut.h index d5c71f236b5c..414f8c2c45f6 100644 --- a/source/MRMesh/MRContoursCut.h +++ b/source/MRMesh/MRContoursCut.h @@ -57,10 +57,18 @@ MRMESH_API OneMeshContours getOneMeshIntersectionContours( const Mesh& meshA, co const CoordinateConverters& converters, const AffineXf3f* rigidB2A = nullptr ); /** \ingroup BooleanGroup - * \brief Makes closed continuous contour by mesh tri points + * \brief Makes continuous contour by mesh tri points, if first and last meshTriPoint is the same, makes closed contour + * + * Finds shortest paths between neighbor \p meshTriPoints and build contour MR::cutMesh input + */ +MRMESH_API OneMeshContour convertMeshTriPointsToMeshContour( const Mesh& mesh, const std::vector& meshTriPoints ); + +/** \ingroup BooleanGroup + * \brief Makes closed continuous contour by mesh tri points, note that first and last meshTriPoint should not be same * * Finds shortest paths between neighbor \p meshTriPoints and build closed contour MR::cutMesh input */ +[[deprecated( "use convertMeshTriPointsToMeshContour(...) instead, note that it requires same front and back MeshTriPoints for closed contour" )]] MRMESH_API OneMeshContour convertMeshTriPointsToClosedContour( const Mesh& mesh, const std::vector& meshTriPoints ); /** \ingroup BooleanGroup