| 611 | } |
| 612 | |
| 613 | Polyline2 distanceMapTo2DIsoPolyline( const DistanceMap& distMap, float isoValue ) |
| 614 | { |
| 615 | using namespace MarchingSquaresHelper; |
| 616 | // disambiguate from the same-named types in MRSeparationPoint.h |
| 617 | using MarchingSquaresHelper::NeighborDir; |
| 618 | using MarchingSquaresHelper::SeparationPointSet; |
| 619 | using MarchingSquaresHelper::SeparationPointMap; |
| 620 | MR_NAMED_TIMER( "distanceMapTo2DIsoPolyline" ); |
| 621 | const size_t resX = distMap.resX(); |
| 622 | const size_t resY = distMap.resY(); |
| 623 | if ( resX == 0 || resY == 0 ) |
| 624 | return {}; |
| 625 | |
| 626 | const size_t size = resX * resY; |
| 627 | auto toId = [resX] ( const Vector2i& pos )->size_t |
| 628 | { |
| 629 | return pos.x + pos.y * size_t( resX ); |
| 630 | }; |
| 631 | |
| 632 | size_t threadCount = tbb::global_control::active_value( tbb::global_control::max_allowed_parallelism ); |
| 633 | if ( threadCount == 0 ) |
| 634 | threadCount = std::thread::hardware_concurrency(); |
| 635 | if ( threadCount == 0 ) |
| 636 | threadCount = 1; |
| 637 | |
| 638 | const auto blockCount = threadCount; |
| 639 | const auto blockSize = (size_t)std::ceil( (float)resY / blockCount ); |
| 640 | assert( resY <= blockSize * blockCount ); |
| 641 | |
| 642 | std::vector<SeparationPointMap> hmaps( blockCount ); |
| 643 | auto hmap = [&] ( size_t y ) -> SeparationPointMap& |
| 644 | { |
| 645 | return hmaps[y / blockSize]; |
| 646 | }; |
| 647 | |
| 648 | // find all separate points |
| 649 | // fill map in parallel |
| 650 | struct VertsNumeration |
| 651 | { |
| 652 | // explicit ctor to fix clang build with `vec.emplace_back( ind, 0 )` |
| 653 | VertsNumeration( size_t ind, size_t num ) : initIndex{ ind }, numVerts{ num } {} |
| 654 | size_t initIndex{ 0 }; |
| 655 | size_t numVerts{ 0 }; |
| 656 | }; |
| 657 | using PerThreadVertNumeration = std::vector<VertsNumeration>; |
| 658 | tbb::enumerable_thread_specific<PerThreadVertNumeration> perThreadVertNumeration; |
| 659 | tbb::parallel_for( tbb::blocked_range<size_t>( 0, hmaps.size(), 1 ), [&] ( const tbb::blocked_range<size_t>& range ) |
| 660 | { |
| 661 | assert( range.begin() + 1 == range.end() ); |
| 662 | auto& hmap = hmaps[range.begin()]; |
| 663 | |
| 664 | const auto begin = range.begin() * blockSize; |
| 665 | const auto end = std::min( begin + blockSize, resY ); |
| 666 | |
| 667 | auto& localNumeration = perThreadVertNumeration.local(); |
| 668 | localNumeration.emplace_back( begin * resX, 0 ); |
| 669 | auto& thisRangeNumeration = localNumeration.back().numVerts; |
| 670 | |