Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 56 additions & 35 deletions source/MRMesh/MRMeshComponents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ namespace MR
namespace MeshComponents
{

std::pair<std::vector<int>, int> getUniqueRoots( const FaceMap& allRoots, const FaceBitSet& region )
{
constexpr int InvalidRoot = -1;
std::vector<int> uniqueRootsMap( allRoots.size(), InvalidRoot );
int k = 0;
int curRoot;
for ( auto f : region )
{
curRoot = allRoots[f];
auto& uniqIndex = uniqueRootsMap[curRoot];
if ( uniqIndex == InvalidRoot )
{
uniqIndex = k;
++k;
}
}
return { std::move( uniqueRootsMap ),k };
}

FaceBitSet getComponent( const MeshPart& meshPart, FaceId id, FaceIncidence incidence/* = FaceIncidence::PerEdge*/ )
{
MR_TIMER;
Expand Down Expand Up @@ -57,31 +76,36 @@ FaceBitSet getLargestComponent( const MeshPart& meshPart, FaceIncidence incidenc
{
MR_TIMER;

auto allComponents = getAllComponents( meshPart, incidence );

if ( allComponents.empty() )
return {};
auto unionFindStruct = getUnionFindStructureFaces( meshPart, incidence );
const auto& mesh = meshPart.mesh;
const FaceBitSet& region = mesh.topology.getFaceIds( meshPart.region );

struct PerThreadArea
{
float area{0.0f};
};
const auto& allRoots = unionFindStruct.roots();
auto [uniqueRootsMap, k] = getUniqueRoots( allRoots, region );

std::vector<float> areas( allComponents.size(), 0.0f );
for ( int i = 0; i < areas.size(); ++i )
double maxArea = -DBL_MAX;
int maxI = 0;
std::vector<double> areas( k, 0.0 );
for ( auto f : region )
{
const auto& component = allComponents[i];

tbb::enumerable_thread_specific<PerThreadArea> perTreadAreas;
BitSetParallelFor( component, [&]( FaceId f )
auto index = uniqueRootsMap[allRoots[f]];
auto& area = areas[index];
area += meshPart.mesh.dblArea( f );
if ( area > maxArea )
{
perTreadAreas.local().area += meshPart.mesh.dblArea( f );
} );
for ( const auto& pta : perTreadAreas )
areas[i] += pta.area;
maxI = index;
maxArea = area;
}
}

return allComponents[std::distance( areas.begin(), std::max_element( areas.begin(), areas.end() ) )];
FaceBitSet maxAreaComponent( region.find_last() + 1 );
for ( auto f : region )
{
auto index = uniqueRootsMap[allRoots[f]];
if ( index != maxI )
continue;
maxAreaComponent.set( f );
}
return maxAreaComponent;
}

VertBitSet getLargestComponentVerts( const Mesh& mesh, const VertBitSet* region /*= nullptr */ )
Expand Down Expand Up @@ -184,25 +208,22 @@ std::vector<FaceBitSet> getAllComponents( const MeshPart& meshPart, FaceIncidenc
const FaceBitSet& region = mesh.topology.getFaceIds( meshPart.region );

const auto& allRoots = unionFindStruct.roots();
constexpr int InvalidRoot = -1;
std::vector<int> uniqueRootsMap( allRoots.size(), InvalidRoot );
int k = 0;
int curRoot;
auto [uniqueRootsMap, k] = getUniqueRoots( allRoots, region );
std::vector<FaceBitSet> res( k );
// this block is needed to limit allocations for not packed meshes
std::vector<int> resSizes( k, 0 );
for ( auto f : region )
{
curRoot = allRoots[f];
auto& uniqIndex = uniqueRootsMap[curRoot];
if ( uniqIndex == InvalidRoot )
{
uniqIndex = k;
++k;
}
int index = uniqueRootsMap[allRoots[f]];
if ( f > resSizes[index] )
resSizes[index] = f;
}
std::vector<FaceBitSet> res( k, FaceBitSet( allRoots.size() ) );
for ( int i = 0; i < k; ++i )
res[i].resize( resSizes[i] + 1 );
// end of allocation block
for ( auto f : region )
{
curRoot = allRoots[f];
res[uniqueRootsMap[curRoot]].set( f );
res[uniqueRootsMap[allRoots[f]]].set( f );
}
return res;
}
Expand Down Expand Up @@ -304,7 +325,7 @@ UnionFind<FaceId> getUnionFindStructureFaces( const MeshPart& meshPart, FaceInci

FaceId f1;
EdgeId e;
UnionFind<FaceId> unionFindStructure( edgesPerFaces.size() );
UnionFind<FaceId> unionFindStructure( region.find_last() + 1 );
for ( auto f0 : region )
{
e = edgesPerFaces[f0];
Expand Down