[traffic] Truncate decoded location to nearby junctions

Signed-off-by: mvglasow <michael -at- vonglasow.com>
This commit is contained in:
mvglasow
2025-11-03 20:16:53 +02:00
parent 05f6dfad7b
commit af20e2b42b
2 changed files with 73 additions and 22 deletions

View File

@@ -958,7 +958,7 @@ void RoutingTraffDecoder::AddDecodedSegment(traffxml::MultiMwmColoring & decoded
} }
void RoutingTraffDecoder::TruncateRoute(std::vector<routing::RouteSegment> & rsegments, void RoutingTraffDecoder::TruncateRoute(std::vector<routing::RouteSegment> & rsegments,
routing::Checkpoints const & checkpoints, bool toJunctions) routing::Checkpoints const & checkpoints, bool backwards)
{ {
double const endWeight = rsegments.back().GetTimeFromBeginningSec(); double const endWeight = rsegments.back().GetTimeFromBeginningSec();
@@ -981,8 +981,10 @@ void RoutingTraffDecoder::TruncateRoute(std::vector<routing::RouteSegment> & rse
// Cost saved by omitting the last `end` segments. // Cost saved by omitting the last `end` segments.
double endSaving = 0; double endSaving = 0;
TruncateStart(rsegments, checkpoints, start, startSaving, toJunctions); TruncateStart(rsegments, checkpoints, start, startSaving,
TruncateEnd(rsegments, checkpoints, end, endSaving, endWeight, toJunctions); backwards ? m_endJunctions : m_startJunctions);
TruncateEnd(rsegments, checkpoints, end, endSaving, endWeight,
backwards ? m_startJunctions : m_endJunctions);
/* /*
* If start <= end, we can truncate both ends at the same time. * If start <= end, we can truncate both ends at the same time.
@@ -1000,7 +1002,8 @@ void RoutingTraffDecoder::TruncateRoute(std::vector<routing::RouteSegment> & rse
rsegments.erase(rsegments.begin(), rsegments.begin() + start); rsegments.erase(rsegments.begin(), rsegments.begin() + start);
end = rsegments.size() - 1; end = rsegments.size() - 1;
endSaving = 0; endSaving = 0;
TruncateEnd(rsegments, checkpoints, end, endSaving, endWeight, toJunctions); TruncateEnd(rsegments, checkpoints, end, endSaving, endWeight,
backwards ? m_startJunctions : m_endJunctions);
rsegments.erase(rsegments.begin() + end + 1, rsegments.end()); rsegments.erase(rsegments.begin() + end + 1, rsegments.end());
} }
else else
@@ -1009,7 +1012,8 @@ void RoutingTraffDecoder::TruncateRoute(std::vector<routing::RouteSegment> & rse
rsegments.erase(rsegments.begin() + end + 1, rsegments.end()); rsegments.erase(rsegments.begin() + end + 1, rsegments.end());
start = 0; start = 0;
startSaving = 0; startSaving = 0;
TruncateStart(rsegments, checkpoints, start, startSaving, toJunctions); TruncateStart(rsegments, checkpoints, start, startSaving,
backwards ? m_endJunctions : m_startJunctions);
rsegments.erase(rsegments.begin(), rsegments.begin() + start); rsegments.erase(rsegments.begin(), rsegments.begin() + start);
} }
} }
@@ -1108,9 +1112,7 @@ void RoutingTraffDecoder::DecodeLocationDirection(traffxml::TraffMessage & messa
{ {
std::vector<routing::RouteSegment> rsegments(route->GetRouteSegments()); std::vector<routing::RouteSegment> rsegments(route->GetRouteSegments());
TruncateRoute(rsegments, checkpoints, TruncateRoute(rsegments, checkpoints, backwards);
message.m_location.value().m_fuzziness
&& (message.m_location.value().m_fuzziness.value() == traffxml::Fuzziness::LowRes));
/* /*
* `m_onRoundabout` is set only for the first segment after the junction. In order to identify * `m_onRoundabout` is set only for the first segment after the junction. In order to identify
@@ -1489,13 +1491,38 @@ std::vector<std::string> ParseRef(std::string const & ref)
void TruncateStart(std::vector<routing::RouteSegment> & rsegments, void TruncateStart(std::vector<routing::RouteSegment> & rsegments,
routing::Checkpoints const & checkpoints, routing::Checkpoints const & checkpoints,
size_t & start, double & startSaving, bool toJunction) size_t & start, double & startSaving,
std::map<m2::PointD, double> const & junctions)
{ {
if (rsegments.empty())
return;
for (size_t i = 0; i < rsegments.size(); i++) for (size_t i = 0; i < rsegments.size(); i++)
{ {
double newStartSaving = rsegments[i].GetTimeFromBeginningSec() double newStartSaving = 0;
- (mercator::DistanceOnEarth(checkpoints.GetStart(), rsegments[i].GetJunction().GetPoint()) /*
* kOffroadPenalty); * Examine end point of segment: for a junction, take weight from table; else calculate it as
* direct distance multiplied with offroad penalty; calculate saving based on that.
*/
auto it = junctions.find(rsegments[i].GetJunction().GetPoint());
if (it != junctions.end())
newStartSaving = rsegments[i].GetTimeFromBeginningSec() - it->second;
else
{
bool matched = false;
// TODO this is likely an inefficient way to return near-matches
for (auto & [point, weight] : junctions)
if (rsegments[i].GetJunction().GetPoint().EqualDxDy(point, kMwmPointAccuracy))
{
newStartSaving = rsegments[i].GetTimeFromBeginningSec() - weight;
matched = true;
break;
}
if (!matched)
newStartSaving = rsegments[i].GetTimeFromBeginningSec()
- (mercator::DistanceOnEarth(checkpoints.GetStart(), rsegments[i].GetJunction().GetPoint())
* kOffroadPenalty);
}
if (newStartSaving > startSaving) if (newStartSaving > startSaving)
{ {
start = i + 1; // add 1 because we are ditching this segment and keeping the next one start = i + 1; // add 1 because we are ditching this segment and keeping the next one
@@ -1506,13 +1533,35 @@ void TruncateStart(std::vector<routing::RouteSegment> & rsegments,
void TruncateEnd(std::vector<routing::RouteSegment> & rsegments, void TruncateEnd(std::vector<routing::RouteSegment> & rsegments,
routing::Checkpoints const & checkpoints, routing::Checkpoints const & checkpoints,
size_t & end, double & endSaving, double const endWeight, bool toJunction) size_t & end, double & endSaving, double const endWeight,
std::map<m2::PointD, double> const & junctions)
{ {
for (size_t i = 0; i < rsegments.size(); i++) for (size_t i = 0; i < rsegments.size(); i++)
{ {
double newEndSaving = endWeight - rsegments[i].GetTimeFromBeginningSec() double newEndSaving = 0;
- (mercator::DistanceOnEarth(rsegments[i].GetJunction().GetPoint(), checkpoints.GetFinish()) /*
* kOffroadPenalty); * Examine end point of segment: for a junction, take weight from table; else calculate it as
* direct distance multiplied with offroad penalty; calculate saving based on that.
*/
auto it = junctions.find(rsegments[i].GetJunction().GetPoint());
if (it != junctions.end())
newEndSaving = endWeight - rsegments[i].GetTimeFromBeginningSec() - it->second;
else
{
bool matched = false;
// TODO this is likely an inefficient way to return near-matches
for (auto & [point, weight] : junctions)
if (rsegments[i].GetJunction().GetPoint().EqualDxDy(point, kMwmPointAccuracy))
{
newEndSaving = endWeight - rsegments[i].GetTimeFromBeginningSec() - weight;
matched = true;
break;
}
if (!matched)
newEndSaving = endWeight - rsegments[i].GetTimeFromBeginningSec()
- (mercator::DistanceOnEarth(rsegments[i].GetJunction().GetPoint(), checkpoints.GetFinish())
* kOffroadPenalty);
}
if (newEndSaving > endSaving) if (newEndSaving > endSaving)
{ {
end = i; end = i;

View File

@@ -471,10 +471,10 @@ protected:
* *
* @param rsegments The segments of the route * @param rsegments The segments of the route
* @param checkpoints The reference points (at least two) * @param checkpoints The reference points (at least two)
* @param toJunctions Whether the truncated route should begin and end at a junction * @param backwards True when decoding the backward direction, false when decodign the forward direction.
*/ */
void TruncateRoute(std::vector<routing::RouteSegment> & rsegments, void TruncateRoute(std::vector<routing::RouteSegment> & rsegments,
routing::Checkpoints const & checkpoints, bool toJunctions); routing::Checkpoints const & checkpoints, bool backwards);
private: private:
static void LogCode(routing::RouterResultCode code, double const elapsedSec); static void LogCode(routing::RouterResultCode code, double const elapsedSec);
@@ -596,11 +596,12 @@ std::vector<std::string> ParseRef(std::string const & ref);
* @param checkpoints The reference points (at least two) * @param checkpoints The reference points (at least two)
* @param start Index of the first segment to keep * @param start Index of the first segment to keep
* @param startSaving Cost saved by truncating * @param startSaving Cost saved by truncating
* @param toJunction Whether the truncated route should start at a junction * @param junctions Junctions with the weight of their leap segment
*/ */
void TruncateStart(std::vector<routing::RouteSegment> & rsegments, void TruncateStart(std::vector<routing::RouteSegment> & rsegments,
routing::Checkpoints const & checkpoints, routing::Checkpoints const & checkpoints,
size_t & start, double & startSaving, bool toJunction); size_t & start, double & startSaving,
std::map<m2::PointD, double> const & junctions);
/** /**
* @brief Calculates the segments to truncate at the start of the route. * @brief Calculates the segments to truncate at the start of the route.
@@ -615,9 +616,10 @@ void TruncateStart(std::vector<routing::RouteSegment> & rsegments,
* @param checkpoints The reference points (at least two) * @param checkpoints The reference points (at least two)
* @param end Index of the last segment to keep * @param end Index of the last segment to keep
* @param endSaving Cost saved by truncating * @param endSaving Cost saved by truncating
* @param toJunction Whether the truncated route should end at a junction * @param junctions Junctions with the weight of their leap segment
*/ */
void TruncateEnd(std::vector<routing::RouteSegment> & rsegments, void TruncateEnd(std::vector<routing::RouteSegment> & rsegments,
routing::Checkpoints const & checkpoints, routing::Checkpoints const & checkpoints,
size_t & end, double & endSaving, double const endWeight, bool ToJunction); size_t & end, double & endSaving, double const endWeight,
std::map<m2::PointD, double> const & junctions);
} // namespace traffxml } // namespace traffxml