| 600 | } |
| 601 | |
| 602 | void RoutingManager::CollectFeaturesAlongRoute(vector<RouteSegment> const & segments, |
| 603 | m2::PointD const & startPt, |
| 604 | uint32_t featureType, |
| 605 | vector<std::pair<m2::PointD, FeatureID>> & outFeatures) |
| 606 | { |
| 607 | ASSERT(!segments.empty(), ()); |
| 608 | ASSERT_NOT_EQUAL(featureType, Classificator::INVALID_TYPE, ()); |
| 609 | |
| 610 | double constexpr kSearchRadiusM = 0.3; //radius (in meters) |
| 611 | double const kSearchRadiusMercator = mercator::MetersToMercator(kSearchRadiusM); |
| 612 | double const kChunkSizeMercator = mercator::MetersToMercator(2000.0); |
| 613 | |
| 614 | auto & dataSource = m_callbacks.m_dataSourceGetter(); |
| 615 | |
| 616 | auto processChunk = [&](m2::RectD const & r) |
| 617 | { |
| 618 | m2::RectD queryRect = r; |
| 619 | queryRect.Inflate(kSearchRadiusMercator, kSearchRadiusMercator); |
| 620 | |
| 621 | dataSource.ForEachInRect([&](FeatureType & ft) { |
| 622 | if (ft.GetGeomType() != feature::GeomType::Point) |
| 623 | return; |
| 624 | |
| 625 | feature::TypesHolder types(ft); |
| 626 | // Does this feature match the type we passed in? |
| 627 | if (!types.Has(featureType)) |
| 628 | return; |
| 629 | |
| 630 | m2::PointD const pt = feature::GetCenter(ft); |
| 631 | |
| 632 | double minSqDist = numeric_limits<double>::max(); |
| 633 | m2::PointD prev = startPt; |
| 634 | for (auto const & s : segments) |
| 635 | { |
| 636 | m2::PointD const curr = s.GetJunction().GetPoint(); |
| 637 | m2::ParametrizedSegment<m2::PointD> seg(prev, curr); |
| 638 | minSqDist = min(minSqDist, seg.SquaredDistanceToPoint(pt)); |
| 639 | |
| 640 | // Performance break |
| 641 | if (minSqDist < kSearchRadiusMercator * kSearchRadiusMercator) |
| 642 | break; |
| 643 | |
| 644 | prev = curr; |
| 645 | } |
| 646 | |
| 647 | if (minSqDist < kSearchRadiusMercator * kSearchRadiusMercator) |
| 648 | outFeatures.emplace_back(pt, ft.GetID()); |
| 649 | }, queryRect, scales::GetUpperScale()); |
| 650 | }; |
| 651 | |
| 652 | m2::RectD currentRect; |
| 653 | currentRect.Add(startPt); |
| 654 | |
| 655 | for (auto const & s : segments) |
| 656 | { |
| 657 | currentRect.Add(s.GetJunction().GetPoint()); |
| 658 | if (currentRect.SizeX() > kChunkSizeMercator || currentRect.SizeY() > kChunkSizeMercator) |
| 659 | { |
nothing calls this directly
no test coverage detected