| 1443 | } |
| 1444 | |
| 1445 | RouterResultCode IndexRouter::ProcessLeapsJoints(vector<Segment> const & input, IndexGraphStarter & starter, |
| 1446 | shared_ptr<AStarProgress> const & progress, |
| 1447 | RoutesCalculator & calculator, RoutingResultT & result) |
| 1448 | { |
| 1449 | LOG(LDEBUG, ("Process input:", input)); |
| 1450 | |
| 1451 | // { fake, mwmId1, mwmId2, mwmId2, mwmId3, .. pairs of ids .. , fake }. |
| 1452 | ASSERT_GREATER_OR_EQUAL(input.size(), 4, ()); |
| 1453 | ASSERT(input.size() % 2 == 0, ()); |
| 1454 | |
| 1455 | WorldGraph & worldGraph = starter.GetGraph(); |
| 1456 | |
| 1457 | // For all leaps except the first leap which connects start to mwm exit in LeapsOnly mode we need |
| 1458 | // to drop first segment of the leap because we already have its twin from the previous mwm. |
| 1459 | bool dropFirstSegment = false; |
| 1460 | |
| 1461 | // While route building in LeapOnly mode we estimate start to mwm exit distance. This estimation may |
| 1462 | // be incorrect and it causes appearance of unneeded loops: route goes from start to wrongly selected mwm exit, |
| 1463 | // then we have small unneeded leap in other mwm which returns us to start mwm, then we have leap in start mwm |
| 1464 | // to the correct start mwm exit and then we have normal route. |
| 1465 | // |input| mwm ids for such case look like |
| 1466 | // { fake, startId, otherId, otherId, startId, startId, .. pairs of ids for other leaps .. , finishId, fake }. |
| 1467 | |
| 1468 | // Stable solution here is to calculate all routes with and without loops, and choose the best one. |
| 1469 | // https://github.com/organicmaps/organicmaps/issues/821 |
| 1470 | // https://github.com/organicmaps/organicmaps/issues/2085 |
| 1471 | // https://github.com/organicmaps/organicmaps/issues/5069 |
| 1472 | |
| 1473 | buffer_vector<size_t, 4> arrBeg, arrEnd; |
| 1474 | size_t const begIdx = 1; |
| 1475 | size_t const endIdx = input.size() - 2; |
| 1476 | |
| 1477 | auto const firstMwmId = input[begIdx].GetMwmId(); |
| 1478 | for (size_t i = begIdx; i < endIdx; ++i) |
| 1479 | if (input[i].GetMwmId() == firstMwmId && (i % 2 == 1)) |
| 1480 | arrBeg.push_back(i); |
| 1481 | |
| 1482 | auto const lastMwmId = input[endIdx].GetMwmId(); |
| 1483 | for (size_t i = endIdx; i > begIdx; --i) |
| 1484 | if (input[i].GetMwmId() == lastMwmId && (i % 2 == 0)) |
| 1485 | arrEnd.push_back(i); |
| 1486 | |
| 1487 | size_t const variantsCount = arrBeg.size() * arrEnd.size(); |
| 1488 | ASSERT(variantsCount > 0, ()); |
| 1489 | |
| 1490 | for (size_t startLeapEnd : arrBeg) |
| 1491 | for (size_t finishLeapStart : arrEnd) |
| 1492 | { |
| 1493 | size_t maxStart = 0; |
| 1494 | |
| 1495 | auto const runAStarAlgorithm = [&](size_t start, size_t end, WorldGraphMode mode) |
| 1496 | { |
| 1497 | ASSERT_LESS(start, input.size(), ()); |
| 1498 | ASSERT_LESS(end, input.size(), ()); |
| 1499 | |
| 1500 | maxStart = max(maxStart, start); |
| 1501 | auto const contribCoef = static_cast<double>(end - maxStart + 1) / input.size() / variantsCount; |
| 1502 |
nothing calls this directly
no test coverage detected