1717#endif
1818
1919#include < algorithm>
20+ #include < cstdint>
2021
2122#include " boolean3.h"
2223#include " csg_tree.h"
@@ -28,10 +29,14 @@ namespace {
2829using namespace manifold ;
2930
3031struct MeshCompare {
31- bool operator ()(const std::shared_ptr<CsgLeafNode>& a,
32- const std::shared_ptr<CsgLeafNode>& b) {
32+ bool operator ()(const std::pair<std:: shared_ptr<CsgLeafNode>, uint64_t >& a,
33+ const std::pair<std:: shared_ptr<CsgLeafNode>, uint64_t >& b) {
3334 // Use NumVert() which doesn't trigger transform application.
34- return a->NumVert () < b->NumVert ();
35+ const size_t aVert = a.first ->NumVert ();
36+ const size_t bVert = b.first ->NumVert ();
37+ if (aVert != bVert) return aVert < bVert;
38+ // Tie-break by insertion order so heap behavior is deterministic across
39+ return a.second < b.second ;
3540 }
3641};
3742
@@ -384,47 +389,59 @@ std::shared_ptr<CsgLeafNode> BatchBoolean(
384389 if (results.size () == 2 )
385390 return SimpleBoolean (*results[0 ]->GetImpl (), *results[1 ]->GetImpl (),
386391 operation);
392+ std::vector<std::pair<std::shared_ptr<CsgLeafNode>, uint64_t >> heapNodes;
393+ heapNodes.reserve (results.size ());
394+ for (size_t i = 0 ; i < results.size (); ++i) {
395+ heapNodes.emplace_back (std::move (results[i]), i);
396+ }
397+ results.clear ();
398+ uint64_t nextSerial = heapNodes.size ();
399+
387400 // apply boolean operations starting from smaller meshes
388401 // the assumption is that boolean operations on smaller meshes is faster,
389402 // due to less data being copied and processed
390403 auto cmpFn = MeshCompare ();
391- std::make_heap (results .begin (), results .end (), cmpFn);
392- std::vector<std::shared_ptr<CsgLeafNode>> tmp;
404+ std::make_heap (heapNodes .begin (), heapNodes .end (), cmpFn);
405+ std::vector<std::pair<std:: shared_ptr<CsgLeafNode>, uint64_t >> tmp;
393406#if MANIFOLD_PAR == 1
394407 tbb::task_group group;
395408 // make sure the order of result is deterministic
396409 std::vector<std::shared_ptr<CsgLeafNode>> parallelTmp;
410+ std::vector<uint64_t > parallelSerial;
397411 for (int i = 0 ; i < 4 ; i++) parallelTmp.push_back (nullptr );
412+ for (int i = 0 ; i < 4 ; i++) parallelSerial.push_back (0 );
398413#endif
399- while (results .size () > 1 ) {
400- for (size_t i = 0 ; i < 4 && results .size () > 1 ; i++) {
401- std::pop_heap (results .begin (), results .end (), cmpFn);
402- auto a = std::move (results .back ());
403- results .pop_back ();
404- std::pop_heap (results .begin (), results .end (), cmpFn);
405- auto b = std::move (results .back ());
406- results .pop_back ();
414+ while (heapNodes .size () > 1 ) {
415+ for (size_t i = 0 ; i < 4 && heapNodes .size () > 1 ; i++) {
416+ std::pop_heap (heapNodes .begin (), heapNodes .end (), cmpFn);
417+ auto a = std::move (heapNodes .back ());
418+ heapNodes .pop_back ();
419+ std::pop_heap (heapNodes .begin (), heapNodes .end (), cmpFn);
420+ auto b = std::move (heapNodes .back ());
421+ heapNodes .pop_back ();
407422#if MANIFOLD_PAR == 1
408- group.run ([&, i, a, b]() {
423+ parallelSerial[i] = nextSerial++;
424+ group.run ([&, i, a = std::move (a.first ), b = std::move (b.first )]() {
409425 parallelTmp[i] = SimpleBoolean (*a->GetImpl (), *b->GetImpl (), operation);
410426 });
411427#else
412- auto result = SimpleBoolean (*a->GetImpl (), *b->GetImpl (), operation);
413- tmp.push_back (result);
428+ auto result =
429+ SimpleBoolean (*a.first ->GetImpl (), *b.first ->GetImpl (), operation);
430+ tmp.emplace_back (std::move (result), nextSerial++);
414431#endif
415432 }
416433#if MANIFOLD_PAR == 1
417434 group.wait ();
418435 for (int i = 0 ; i < 4 && parallelTmp[i]; i++)
419- tmp.emplace_back (std::move (parallelTmp[i]));
436+ tmp.emplace_back (std::move (parallelTmp[i]), parallelSerial[i] );
420437#endif
421- for (auto result : tmp) {
422- results .push_back (result);
423- std::push_heap (results .begin (), results .end (), cmpFn);
438+ for (auto & result : tmp) {
439+ heapNodes .push_back (std::move ( result) );
440+ std::push_heap (heapNodes .begin (), heapNodes .end (), cmpFn);
424441 }
425442 tmp.clear ();
426443 }
427- return results .front ();
444+ return heapNodes .front (). first ;
428445}
429446
430447/* *
0 commit comments