Skip to content

Commit b948641

Browse files
authored
getOneMeshIntersectionContours can output two contours (#4623)
1 parent 55f3144 commit b948641

File tree

5 files changed

+67
-78
lines changed

5 files changed

+67
-78
lines changed

source/MRMesh/MRContoursCut.cpp

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,12 @@ void subdivideLoneContours( Mesh& mesh, const OneMeshContours& contours, FaceHas
493493
}
494494
}
495495

496-
OneMeshContours getOneMeshIntersectionContours( const Mesh& meshA, const Mesh& meshB, const ContinuousContours& contours, bool getMeshAIntersections,
496+
void getOneMeshIntersectionContours( const Mesh& meshA, const Mesh& meshB, const ContinuousContours& contours,
497+
OneMeshContours* outA, OneMeshContours* outB,
497498
const CoordinateConverters& converters, const AffineXf3f* rigidB2A /*= nullptr */ )
498499
{
499500
MR_TIMER;
500-
OneMeshContours res;
501+
assert( outA || outB );
501502

502503
std::function<Vector3f( const Vector3f& coord, bool meshA )> getCoord;
503504

@@ -518,52 +519,63 @@ OneMeshContours getOneMeshIntersectionContours( const Mesh& meshA, const Mesh& m
518519
AffineXf3f inverseXf;
519520
if ( rigidB2A )
520521
inverseXf = rigidB2A->inverse();
521-
const auto& mainMesh = getMeshAIntersections ? meshA : meshB;
522-
const auto& otherMesh = getMeshAIntersections ? meshB : meshA;
523-
res.resize( contours.size() );
522+
if ( outA )
523+
outA->resize( contours.size() );
524+
if ( outB )
525+
outB->resize( contours.size() );
524526
ParallelFor( contours, [&]( size_t j )
525527
{
526-
OneMeshContour cur;
527-
auto& curOutContour = cur.intersections;
528+
OneMeshContour curA, curB;
528529
const auto& curInContour = contours[j];
529-
curOutContour.resize( curInContour.size() );
530+
curA.closed = curB.closed = isClosed( curInContour );
531+
if ( outA )
532+
curA.intersections.resize( curInContour.size() );
533+
if ( outB )
534+
curB.intersections.resize( curInContour.size() );
530535

531-
ParallelFor( curOutContour, [&]( size_t i )
536+
ParallelFor( curInContour, [&]( size_t i )
532537
{
533538
Vector3f a, b, c, d, e;
534539
const auto& inIntersection = curInContour[i];
535-
auto& outIntersection = curOutContour[i];
540+
OneMeshIntersection pntA, pntB;
536541

537-
bool edgeMain = getMeshAIntersections == inIntersection.isEdgeATriB;
538-
if ( edgeMain )
542+
if ( inIntersection.isEdgeATriB )
539543
{
540-
outIntersection.primitiveId = inIntersection.edge;
541-
otherMesh.getTriPoints( inIntersection.tri, a, b, c );
542-
d = mainMesh.orgPnt( inIntersection.edge );
543-
e = mainMesh.destPnt( inIntersection.edge );
544+
pntA.primitiveId = inIntersection.edge;
545+
pntB.primitiveId = inIntersection.tri;
546+
meshB.getTriPoints( inIntersection.tri, a, b, c );
547+
d = meshA.orgPnt( inIntersection.edge );
548+
e = meshA.destPnt( inIntersection.edge );
544549
}
545550
else
546551
{
547-
outIntersection.primitiveId = inIntersection.tri;
548-
mainMesh.getTriPoints( inIntersection.tri, a, b, c );
549-
d = otherMesh.orgPnt( inIntersection.edge );
550-
e = otherMesh.destPnt( inIntersection.edge );
552+
pntB.primitiveId = inIntersection.edge;
553+
pntA.primitiveId = inIntersection.tri;
554+
meshA.getTriPoints( inIntersection.tri, a, b, c );
555+
d = meshB.orgPnt( inIntersection.edge );
556+
e = meshB.destPnt( inIntersection.edge );
551557
}
552558
// always calculate in mesh A space
553-
outIntersection.coordinate = findTriangleSegmentIntersectionPrecise(
559+
pntA.coordinate = findTriangleSegmentIntersectionPrecise(
554560
getCoord( a, !inIntersection.isEdgeATriB ),
555561
getCoord( b, !inIntersection.isEdgeATriB ),
556562
getCoord( c, !inIntersection.isEdgeATriB ),
557563
getCoord( d, inIntersection.isEdgeATriB ),
558564
getCoord( e, inIntersection.isEdgeATriB ), converters );
559565

560-
if ( !getMeshAIntersections && rigidB2A )
561-
outIntersection.coordinate = inverseXf( outIntersection.coordinate );
566+
if ( outA )
567+
curA.intersections[i] = pntA;
568+
if ( outB )
569+
{
570+
pntB.coordinate = rigidB2A ? inverseXf( pntA.coordinate ) : pntA.coordinate;
571+
curB.intersections[i] = pntB;
572+
}
562573
} );
563-
cur.closed = isClosed( curInContour );
564-
res[j] = std::move( cur );
574+
if ( outA )
575+
(*outA)[j] = std::move( curA );
576+
if ( outB )
577+
(*outB)[j] = std::move( curB );
565578
} );
566-
return res;
567579
}
568580

569581
OneMeshContours getOneMeshSelfIntersectionContours( const Mesh& mesh, const ContinuousContours& contours, const CoordinateConverters& converters, const AffineXf3f* rigidB2A /*= nullptr */ )
@@ -2311,8 +2323,8 @@ TEST( MRMesh, BooleanIntersectionsSort )
23112323
auto converters = getVectorConverters( meshA, meshB );
23122324
auto intersections = findCollidingEdgeTrisPrecise( meshA, meshB, converters.toInt );
23132325
auto contours = orderIntersectionContours( meshA.topology, meshB.topology, intersections );
2314-
auto meshAContours = getOneMeshIntersectionContours( meshA, meshB, contours, true, converters );
2315-
auto meshBContours = getOneMeshIntersectionContours( meshA, meshB, contours, false, converters );
2326+
OneMeshContours meshAContours, meshBContours;
2327+
getOneMeshIntersectionContours( meshA, meshB, contours, &meshAContours, &meshBContours, converters );
23162328

23172329
SortIntersectionsData dataForA{meshB,contours,converters.toInt,nullptr,meshA.topology.vertSize(),false};
23182330

@@ -2349,8 +2361,8 @@ TEST( MRMesh, MeshCollidePrecise )
23492361
//EXPECT_EQ( contours[2].size(), 7 );
23502362
//EXPECT_EQ( contours[3].size(), 7 );
23512363

2352-
const auto meshAContours = getOneMeshIntersectionContours( meshA, meshB, contours, true, conv );
2353-
const auto meshBContours = getOneMeshIntersectionContours( meshA, meshB, contours, false, conv );
2364+
OneMeshContours meshAContours, meshBContours;
2365+
getOneMeshIntersectionContours( meshA, meshB, contours, &meshAContours, &meshBContours, conv );
23542366
EXPECT_EQ( meshAContours.size(), 4 );
23552367
EXPECT_EQ( meshBContours.size(), 4 );
23562368

source/MRMesh/MRContoursCut.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ using OneMeshContours = std::vector<OneMeshContour>;
5252
// if there is more than one contour on face it guarantee to subdivide at least one lone contour on this face
5353
MRMESH_API void subdivideLoneContours( Mesh& mesh, const OneMeshContours& contours, FaceHashMap* new2oldMap = nullptr );
5454

55-
// Converts ordered continuous contours of two meshes to OneMeshContours
56-
// converters are required for better precision in case of degenerations
57-
// note that contours should not have intersections
58-
[[nodiscard]]
59-
MRMESH_API OneMeshContours getOneMeshIntersectionContours( const Mesh& meshA, const Mesh& meshB, const ContinuousContours& contours, bool getMeshAIntersections,
55+
/// Converts contours given in topological terms as the intersections of one mesh's edge and another mesh's triangle (ContinuousContours),
56+
/// into contours of meshA and/or meshB given as a sequence of (primitiveId and euclidean coordinate);
57+
/// converters are required for better precision in case of degenerations;
58+
/// note that contours should not have intersections
59+
MRMESH_API void getOneMeshIntersectionContours( const Mesh& meshA, const Mesh& meshB, const ContinuousContours& contours,
60+
OneMeshContours* outA, OneMeshContours* outB,
6061
const CoordinateConverters& converters, const AffineXf3f* rigidB2A = nullptr );
6162

6263
// Converts ordered continuous self contours of single meshes to OneMeshContours

source/MRMesh/MRMeshBoolean.cpp

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -78,33 +78,6 @@ void gatherEdgeInfo( const MeshTopology& topology, EdgeId e, FaceBitSet& faces,
7878
dests.set( topology.dest( e ) );
7979
}
8080

81-
OneMeshContours getOtherMeshContoursByHint( const OneMeshContours& aContours, const ContinuousContours& contours,
82-
const AffineXf3f* rigidB2A = nullptr )
83-
{
84-
MR_TIMER;
85-
AffineXf3f inverseXf;
86-
if ( rigidB2A )
87-
inverseXf = rigidB2A->inverse();
88-
OneMeshContours bMeshContours = aContours;
89-
for ( int j = 0; j < bMeshContours.size(); ++j )
90-
{
91-
const auto& inCont = contours[j];
92-
auto& outCont = bMeshContours[j].intersections;
93-
assert( inCont.size() == outCont.size() );
94-
ParallelFor( inCont, [&] ( size_t i )
95-
{
96-
const auto& inInter = inCont[i];
97-
auto& outInter = outCont[i];
98-
outInter.primitiveId = inInter.isEdgeATriB ?
99-
std::variant<FaceId, EdgeId, VertId>( inInter.tri ) :
100-
std::variant<FaceId, EdgeId, VertId>( inInter.edge );
101-
if ( rigidB2A )
102-
outInter.coordinate = inverseXf( outCont[i].coordinate );
103-
} );
104-
}
105-
return bMeshContours;
106-
}
107-
10881
}
10982

11083
namespace MR
@@ -474,16 +447,16 @@ BooleanResult booleanImpl( Mesh&& meshA, Mesh&& meshB, BooleanOperation operatio
474447
if ( !loneA.empty() && needCutMeshA )
475448
{
476449
aSubdivided = true;
477-
auto loneIntsA = getOneMeshIntersectionContours( meshA, meshB, loneA, true, converters, params.rigidB2A );
478-
auto loneIntsAonB = getOneMeshIntersectionContours( meshA, meshB, loneA, false, converters, params.rigidB2A );
450+
OneMeshContours loneIntsA, loneIntsAonB;
451+
getOneMeshIntersectionContours( meshA, meshB, loneA, &loneIntsA, &loneIntsAonB, converters, params.rigidB2A );
479452
removeLoneDegeneratedContours( meshB.topology, loneIntsA, loneIntsAonB );
480453
subdivideLoneContours( meshA, loneIntsA, &new2orgSubdivideMapA );
481454
}
482455
if ( !loneB.empty() && needCutMeshB )
483456
{
484457
bSubdivided = true;
485-
auto loneIntsB = getOneMeshIntersectionContours( meshA, meshB, loneB, false, converters, params.rigidB2A );
486-
auto loneIntsBonA = getOneMeshIntersectionContours( meshA, meshB, loneB, true, converters, params.rigidB2A );
458+
OneMeshContours loneIntsB, loneIntsBonA;
459+
getOneMeshIntersectionContours( meshA, meshB, loneB, &loneIntsBonA, &loneIntsB, converters, params.rigidB2A );
487460
removeLoneDegeneratedContours( meshA.topology, loneIntsB, loneIntsBonA );
488461
subdivideLoneContours( meshB, loneIntsB, &new2orgSubdivideMapB );
489462
}
@@ -557,15 +530,11 @@ BooleanResult booleanImpl( Mesh&& meshA, Mesh&& meshB, BooleanOperation operatio
557530
}
558531
taskGroup.wait();
559532

560-
if ( needCutMeshA )
561-
meshAContours = getOneMeshIntersectionContours( meshA, meshB, contours, true, converters, params.rigidB2A );
562-
if ( needCutMeshB )
563-
{
564-
if ( needCutMeshA )
565-
meshBContours = getOtherMeshContoursByHint( meshAContours, contours, params.rigidB2A );
566-
else
567-
meshBContours = getOneMeshIntersectionContours( meshA, meshB, contours, false, converters, params.rigidB2A );
568-
}
533+
if ( needCutMeshA || needCutMeshB )
534+
getOneMeshIntersectionContours( meshA, meshB, contours,
535+
needCutMeshA ? &meshAContours : nullptr,
536+
needCutMeshB ? &meshBContours : nullptr,
537+
converters, params.rigidB2A );
569538

570539
if ( mainCb && !mainCb( 0.33f ) )
571540
return { .errorString = stringOperationCanceled() };

source/MRMeshC/MRContoursCut.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,10 @@ MROneMeshContours* mrGetOneMeshIntersectionContours( const MRMesh* meshA_, const
4545
.toInt = *auto_cast( converters_->toInt ),
4646
.toFloat = *auto_cast( converters_->toFloat ),
4747
};
48-
RETURN_NEW( getOneMeshIntersectionContours( meshA, meshB, contours, getMeshAIntersections, converters, rigidB2A ) );
48+
OneMeshContours res;
49+
getOneMeshIntersectionContours( meshA, meshB, contours,
50+
getMeshAIntersections ? &res : nullptr,
51+
getMeshAIntersections ? nullptr : &res,
52+
converters, rigidB2A );
53+
RETURN_NEW( res );
4954
}

test_python/test_booleanExposing.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,10 @@ def test_intersection_contours():
8686
else:
8787
intersections = mrmesh.findCollidingEdgeTrisPrecise(meshA,meshB,conv)
8888
orderedIntersections = mrmesh.orderIntersectionContours(meshA.topology,meshA.topology,intersections)
89-
aConts = mrmesh.getOneMeshIntersectionContours(meshA,meshB,orderedIntersections,True,conv)
90-
bConts = mrmesh.getOneMeshIntersectionContours(meshA,meshB,orderedIntersections,False,conv)
89+
90+
aConts = mrmesh.OneMeshContours()
91+
bConts = mrmesh.OneMeshContours()
92+
mrmesh.getOneMeshIntersectionContours(meshA,meshB,orderedIntersections,aConts,bConts,conv)
9193
assert aConts[0].intersections.size() > 0
9294
assert aConts[0].closed
9395
assert aConts[0].intersections.size() == bConts[0].intersections.size()

0 commit comments

Comments
 (0)