| 177 | } |
| 178 | |
| 179 | Expected<UnionFind<VertId>> getUnionFindStructureVerts( const PointCloud& pointCloud, float maxDist, const VertBitSet* region /*= nullptr*/, ProgressCallback pc /*= {}*/ ) |
| 180 | { |
| 181 | MR_TIMER; |
| 182 | |
| 183 | const VertBitSet& vertsRegion = region ? *region : pointCloud.validPoints; |
| 184 | |
| 185 | if ( !vertsRegion.any() ) |
| 186 | return unexpected( std::string( "Chosen region empty" ) ); |
| 187 | |
| 188 | const VertBitSet* lastPassVerts = &vertsRegion; |
| 189 | const auto numVerts = vertsRegion.find_last() + 1; |
| 190 | UnionFind<VertId> unionFindStructure( numVerts ); |
| 191 | const auto numThreads = int( tbb::global_control::active_value( tbb::global_control::max_allowed_parallelism ) ); |
| 192 | |
| 193 | VertBitSet bdVerts; |
| 194 | ProgressCallback subPc = subprogress( pc, 0.f, 1.0f ); |
| 195 | const auto maxDistSq = sqr( maxDist ); |
| 196 | if ( numThreads > 1 ) |
| 197 | { |
| 198 | bdVerts.resize( numVerts ); |
| 199 | lastPassVerts = &bdVerts; |
| 200 | subPc = subprogress( pc, 0.f, 0.7f ); |
| 201 | BitSetParallelForAllRanged( vertsRegion, [&] ( VertId v0, const auto & range ) |
| 202 | { |
| 203 | if ( !contains( vertsRegion, v0 ) ) |
| 204 | return; |
| 205 | findPointsInBall( pointCloud.getAABBTree(), { pointCloud.points[v0], maxDistSq }, |
| 206 | [&] ( const PointsProjectionResult & found, const Vector3f &, Ball3f & ) |
| 207 | { |
| 208 | const auto v1 = found.vId; |
| 209 | if ( v0 < v1 && contains( vertsRegion, v1 ) ) |
| 210 | { |
| 211 | if ( v1 >= range.end ) |
| 212 | bdVerts.set( v0 ); |
| 213 | else |
| 214 | unionFindStructure.unite( v0, v1 ); |
| 215 | } |
| 216 | return Processing::Continue; |
| 217 | } ); |
| 218 | }, subPc ); |
| 219 | if ( !reportProgress( subPc, 1.f ) ) |
| 220 | return unexpectedOperationCanceled(); |
| 221 | subPc = subprogress( pc, 0.7f, 1.f ); |
| 222 | } |
| 223 | |
| 224 | int counterProcessedVerts = 0; |
| 225 | const float counterMax = float( lastPassVerts->count() ); |
| 226 | const int counterDivider = std::max( 1, int( lastPassVerts->count() ) / 100 ); |
| 227 | for ( auto v0 : *lastPassVerts ) |
| 228 | { |
| 229 | findPointsInBall( pointCloud.getAABBTree(), { pointCloud.points[v0], maxDistSq }, |
| 230 | [&] ( const PointsProjectionResult & found, const Vector3f &, Ball3f & ) |
| 231 | { |
| 232 | const auto v1 = found.vId; |
| 233 | if ( v0 < v1 && contains( vertsRegion, v1 ) ) |
| 234 | { |
| 235 | unionFindStructure.unite( v0, v1 ); |
| 236 | } |
no test coverage detected