| 212 | } |
| 213 | |
| 214 | void ScoreCandidatePathsGetter::GetBestCandidatePaths(vector<shared_ptr<Link>> const & allPaths, |
| 215 | LinearSegmentSource source, bool isLastPoint, |
| 216 | uint32_t requiredBearing, double bearDistM, |
| 217 | m2::PointD const & startPoint, ScorePathVec & candidates) |
| 218 | { |
| 219 | CHECK_NOT_EQUAL(source, LinearSegmentSource::NotValid, ()); |
| 220 | CHECK_LESS_OR_EQUAL(requiredBearing, 255, ()); |
| 221 | |
| 222 | multiset<CandidatePath, greater<>> candidatePaths; |
| 223 | |
| 224 | BearingPointsSelector pointsSelector(static_cast<uint32_t>(bearDistM), isLastPoint); |
| 225 | for (auto const & link : allPaths) |
| 226 | { |
| 227 | auto const bearStartPoint = pointsSelector.GetStartPoint(link->GetStartEdge()); |
| 228 | |
| 229 | // Number of edges counting from the last one to check bearing on. According to OpenLR spec |
| 230 | // we have to check bearing on a point that is no longer than 25 meters traveling down the path. |
| 231 | // But sometimes we may skip the best place to stop and generate a candidate. So we check several |
| 232 | // edges before the last one to avoid such a situation. Number of iterations is taken |
| 233 | // by intuition. |
| 234 | // Example: |
| 235 | // o -------- o { Partners segment. } |
| 236 | // o ------- o --- o { Our candidate. } |
| 237 | // ^ 25m |
| 238 | // ^ This one may be better than |
| 239 | // ^ this one. |
| 240 | // So we want to check them all. |
| 241 | uint32_t traceBackIterationsLeft = 3; |
| 242 | for (auto part = link; part; part = part->m_parent) |
| 243 | { |
| 244 | if (traceBackIterationsLeft == 0) |
| 245 | break; |
| 246 | |
| 247 | --traceBackIterationsLeft; |
| 248 | |
| 249 | // Note. No information about bearing if source == LinearSegmentSource::FromCoordinatesTag. |
| 250 | Score bearingScore = 0; |
| 251 | if (source == LinearSegmentSource::FromLocationReferenceTag) |
| 252 | { |
| 253 | if (!GetBearingScore(pointsSelector, *part, bearStartPoint, requiredBearing, bearingScore)) |
| 254 | continue; |
| 255 | } |
| 256 | candidatePaths.emplace(part, part->m_pointScore, part->m_minRoadScore, bearingScore); |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | size_t constexpr kMaxCandidates = 7; |
| 261 | vector<CandidatePath> paths; |
| 262 | copy_n(candidatePaths.begin(), min(static_cast<size_t>(kMaxCandidates), candidatePaths.size()), back_inserter(paths)); |
| 263 | |
| 264 | for (auto const & path : paths) |
| 265 | { |
| 266 | Graph::EdgeVector edges; |
| 267 | for (auto * p = path.m_path.get(); p; p = p->m_parent.get()) |
| 268 | edges.push_back(p->m_edge); |
| 269 | |
| 270 | if (!isLastPoint) |
| 271 | reverse(edges.begin(), edges.end()); |
nothing calls this directly
no test coverage detected