| 526 | |
| 527 | template <typename It> |
| 528 | double Router::GetCoverage(m2::PointD const & u, m2::PointD const & v, It b, It e) |
| 529 | { |
| 530 | double const kEps = 1e-5; |
| 531 | double const kLengthThresholdM = 1; |
| 532 | |
| 533 | m2::PointD const uv = v - u; |
| 534 | double const sqlen = u.SquaredLength(v); |
| 535 | |
| 536 | if (mercator::DistanceOnEarth(u, v) < kLengthThresholdM) |
| 537 | return 0; |
| 538 | |
| 539 | std::vector<std::pair<double, double>> covs; |
| 540 | for (; b != e; ++b) |
| 541 | { |
| 542 | auto const s = b->m_u.m_junction.GetPoint(); |
| 543 | auto const t = b->m_v.m_junction.GetPoint(); |
| 544 | if (!m2::IsPointOnSegmentEps(s, u, v, kEps) || !m2::IsPointOnSegmentEps(t, u, v, kEps)) |
| 545 | continue; |
| 546 | |
| 547 | if (DotProduct(uv, t - s) < -kEps) |
| 548 | continue; |
| 549 | |
| 550 | double const sp = DotProduct(uv, s - u) / sqlen; |
| 551 | double const tp = DotProduct(uv, t - u) / sqlen; |
| 552 | |
| 553 | double const start = math::Clamp(std::min(sp, tp), 0.0, 1.0); |
| 554 | double const finish = math::Clamp(std::max(sp, tp), 0.0, 1.0); |
| 555 | covs.emplace_back(start, finish); |
| 556 | } |
| 557 | |
| 558 | sort(covs.begin(), covs.end()); |
| 559 | |
| 560 | double coverage = 0; |
| 561 | |
| 562 | size_t i = 0; |
| 563 | while (i != covs.size()) |
| 564 | { |
| 565 | size_t j = i; |
| 566 | |
| 567 | double const first = covs[i].first; |
| 568 | double last = covs[i].second; |
| 569 | while (j != covs.size() && covs[j].first <= last) |
| 570 | { |
| 571 | last = std::max(last, covs[j].second); |
| 572 | ++j; |
| 573 | } |
| 574 | |
| 575 | coverage += last - first; |
| 576 | i = j; |
| 577 | } |
| 578 | |
| 579 | CHECK_LESS_OR_EQUAL(coverage, 1.0 + kEps, ()); |
| 580 | |
| 581 | return coverage; |
| 582 | } |
| 583 | |
| 584 | template <typename It> |
| 585 | double Router::GetMatchingScore(m2::PointD const & u, m2::PointD const & v, It b, It e) |
nothing calls this directly
no test coverage detected