| 11 | { |
| 12 | |
| 13 | std::optional<VertBitSet> pointUniformSampling( const PointCloud& pointCloud, const UniformSamplingSettings & settings ) |
| 14 | { |
| 15 | MR_TIMER; |
| 16 | |
| 17 | auto cb = settings.progress; |
| 18 | |
| 19 | const VertNormals * pNormals = settings.pNormals; |
| 20 | if ( !pNormals && pointCloud.hasNormals() ) |
| 21 | pNormals = &pointCloud.normals; |
| 22 | |
| 23 | VertBitSet visited( pointCloud.validPoints.size() ); |
| 24 | VertBitSet sampled( pointCloud.validPoints.size() ); |
| 25 | |
| 26 | struct NearVert |
| 27 | { |
| 28 | VertId v; |
| 29 | float distSq = 0; |
| 30 | }; |
| 31 | std::vector<NearVert> nearVerts; |
| 32 | |
| 33 | auto processOne = [&]( VertId v ) |
| 34 | { |
| 35 | if ( visited.test( v ) ) |
| 36 | return; |
| 37 | sampled.set( v ); |
| 38 | const auto c = pointCloud.points[v]; |
| 39 | float localMaxDistSq = sqr( settings.distance ); |
| 40 | findPointsInBall( pointCloud, { c, localMaxDistSq }, [&] ( const PointsProjectionResult & found, const Vector3f&, Ball3f & ) |
| 41 | { |
| 42 | const auto u = found.vId; |
| 43 | if ( pNormals && std::abs( dot( (*pNormals)[v], (*pNormals)[u] ) ) < settings.minNormalDot ) |
| 44 | localMaxDistSq = std::min( localMaxDistSq, found.distSq ); |
| 45 | else |
| 46 | nearVerts.push_back( { u, found.distSq } ); |
| 47 | return Processing::Continue; |
| 48 | } ); |
| 49 | for ( const auto & [ u, distSq ] : nearVerts ) |
| 50 | { |
| 51 | if ( distSq >= localMaxDistSq ) |
| 52 | continue; |
| 53 | visited.set( u ); |
| 54 | } |
| 55 | nearVerts.clear(); |
| 56 | }; |
| 57 | |
| 58 | size_t progressCount = 0; |
| 59 | if ( settings.lexicographicalOrder ) |
| 60 | { |
| 61 | std::vector<VertId> searchQueue = pointCloud.getLexicographicalOrder(); |
| 62 | if ( !reportProgress( cb, 0.3f ) ) |
| 63 | return {}; |
| 64 | cb = subprogress( cb, 0.3f, 1.0f ); |
| 65 | size_t totalCount = searchQueue.size(); |
| 66 | for ( auto v : searchQueue ) |
| 67 | { |
| 68 | if ( cb && !( ( ++progressCount ) & 0x3ff ) && !cb( float( progressCount ) / float( totalCount ) ) ) |
| 69 | return {}; |
| 70 | processOne( v ); |
no test coverage detected