| 141 | |
| 142 | template <typename V> |
| 143 | std::vector<UndirectedEdgeBitSet> getNLargeByLengthComponents( const Polyline<V>& polyline, const LargeByLengthComponentsSettings& settings ) |
| 144 | { |
| 145 | MR_TIMER; |
| 146 | std::vector<UndirectedEdgeBitSet> res; |
| 147 | |
| 148 | assert( settings.maxLargeComponents > 0 ); |
| 149 | if ( settings.maxLargeComponents <= 0 ) |
| 150 | { |
| 151 | if ( settings.numSmallerComponents ) |
| 152 | *settings.numSmallerComponents = -1; //unknown |
| 153 | return res; |
| 154 | } |
| 155 | if ( settings.maxLargeComponents == 1 ) |
| 156 | { |
| 157 | res.push_back( getLargestComponent( polyline, settings.minLength, settings.numSmallerComponents ) ); |
| 158 | return res; |
| 159 | } |
| 160 | |
| 161 | auto unionFind = getUnionFindStructure( polyline.topology ); |
| 162 | const auto& roots = unionFind.roots(); |
| 163 | |
| 164 | HashMap<UndirectedEdgeId, float> root2length; |
| 165 | for ( auto ue : undirectedEdges( polyline.topology ) ) |
| 166 | root2length[roots[ue]] += polyline.edgeLength( EdgeId( ue ) ); |
| 167 | |
| 168 | struct LengthRoot |
| 169 | { |
| 170 | float length = 0; |
| 171 | UndirectedEdgeId root; |
| 172 | constexpr auto operator <=>( const LengthRoot& ) const = default; |
| 173 | }; |
| 174 | |
| 175 | std::vector<LengthRoot> lengthRootVec; |
| 176 | lengthRootVec.reserve( root2length.size() ); |
| 177 | // fill it with not too small components |
| 178 | for ( const auto& [root, length] : root2length ) |
| 179 | { |
| 180 | if ( length >= settings.minLength ) |
| 181 | lengthRootVec.push_back( { length, root } ); |
| 182 | } |
| 183 | |
| 184 | // leave at most given number of roots sorted in descending by area order |
| 185 | if ( lengthRootVec.size() <= settings.maxLargeComponents ) |
| 186 | { |
| 187 | if ( settings.numSmallerComponents ) |
| 188 | *settings.numSmallerComponents = 0; |
| 189 | std::sort( lengthRootVec.begin(), lengthRootVec.end(), std::greater() ); |
| 190 | } |
| 191 | else |
| 192 | { |
| 193 | if ( settings.numSmallerComponents ) |
| 194 | *settings.numSmallerComponents = int( lengthRootVec.size() - settings.maxLargeComponents ); |
| 195 | std::partial_sort( lengthRootVec.begin(), lengthRootVec.begin() + settings.maxLargeComponents, lengthRootVec.end(), std::greater() ); |
| 196 | lengthRootVec.resize( settings.maxLargeComponents ); |
| 197 | } |
| 198 | |
| 199 | res.resize( lengthRootVec.size() ); |
| 200 | ParallelFor( res, [&] ( size_t i ) |
nothing calls this directly
no test coverage detected