| 68 | } |
| 69 | |
| 70 | virtual void ForEachNodeIdx(uint64_t wayID, uint32_t candidateIdx, m2::PointU pt, |
| 71 | std::function<void(uint32_t, uint32_t)> const & fn) override |
| 72 | { |
| 73 | auto it = m_osm2features.find(base::MakeOsmWay(wayID)); |
| 74 | if (it == m_osm2features.end()) |
| 75 | return; |
| 76 | |
| 77 | auto const & fIDs = it->second; |
| 78 | if (fIDs.size() == 1) |
| 79 | { |
| 80 | // Fast lane when mapped feature wasn't changed. |
| 81 | fn(fIDs[0], candidateIdx); |
| 82 | return; |
| 83 | } |
| 84 | |
| 85 | auto const fullRect = mercator::Bounds::FullRect(); |
| 86 | |
| 87 | for (uint32_t featureID : fIDs) |
| 88 | { |
| 89 | auto ft = m_featureGetter.GetFeatureByIndex(featureID); |
| 90 | CHECK(ft, (featureID)); |
| 91 | |
| 92 | // Skip non-line features (e.g., barriers on area boundaries) |
| 93 | if (ft->GetGeomType() != feature::GeomType::Line) |
| 94 | { |
| 95 | // Use LDEBUG to reduce log spam for features processed multiple times per vehicle type |
| 96 | LOG(LDEBUG, ("Skipping non-line feature", featureID, "for node penalty mapping")); |
| 97 | continue; |
| 98 | } |
| 99 | |
| 100 | // Conversion should work with the same logic as in WayNodesMapper::EncodePoint. |
| 101 | auto const mercatorPt = PointUToPointD(pt, kPointCoordBits, fullRect); |
| 102 | double minSquareDist = 1.0E6; |
| 103 | |
| 104 | ft->ParseGeometry(FeatureType::BEST_GEOMETRY); |
| 105 | |
| 106 | uint32_t const count = ft->GetPointsCount(); |
| 107 | uint32_t resIdx = 0; |
| 108 | for (uint32_t i = 0; i < count; ++i) |
| 109 | { |
| 110 | auto const p = ft->GetPoint(i); |
| 111 | double const d = p.SquaredLength(mercatorPt); |
| 112 | if (d < minSquareDist) |
| 113 | { |
| 114 | minSquareDist = d; |
| 115 | resIdx = i; |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | // Final check to ensure that we have got exact point with Feature coordinates encoding. |
| 120 | if (PointDToPointU(ft->GetPoint(resIdx), kFeatureSorterPointCoordBits, fullRect) == |
| 121 | PointDToPointU(mercatorPt, kFeatureSorterPointCoordBits, fullRect)) |
| 122 | { |
| 123 | fn(featureID, resIdx); |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | }; |
no test coverage detected