-
Notifications
You must be signed in to change notification settings - Fork 704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mark edge segments with interpolated match points #3670
Changes from 7 commits
0a71dce
26b55fa
31c2269
79676ce
faf7868
f01b71e
ef28f74
354888f
0524544
881af5f
322ca4a
cea174c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,11 +75,16 @@ EdgeSegment::EdgeSegment(baldr::GraphId the_edgeid, | |
* Here we return the vector of edge segments between the source and target states. If its a node to | ||
* node route (meaning no realy edge is traversed) then we use the target_result to say what edge the | ||
* segment should use | ||
* | ||
* TODO: we should modify this function to take the range of MatchResults between the source and | ||
* target. we should then use those to property initialize the segments source/target/indices to | ||
* match those of the MatchResults that lie on them rather than doing it downstream in an otherwise | ||
* superfluous operation | ||
* @param source source state to use to find the route | ||
* @param target target state which candidate in the next column to fetch the route for | ||
* @param route a place to put the edge segments as we create them | ||
* @param target_result in case we have a node to node route we have a no-op edge segment to return | ||
* @return the vector of segments reprsenting the route between source and target | ||
* @return the vector of segments representing the route between source and target | ||
*/ | ||
bool MergeRoute(const State& source, | ||
const State& target, | ||
|
@@ -129,38 +134,47 @@ bool MergeRoute(const State& source, | |
void cut_segments(const std::vector<MatchResult>& match_results, | ||
int first_idx, | ||
int last_idx, | ||
const std::vector<EdgeSegment>& segments, | ||
std::vector<EdgeSegment>& segments, | ||
std::vector<EdgeSegment>& new_segments) { | ||
auto first_segment = segments.begin(); | ||
auto search_segment = first_segment; | ||
int prev_idx = first_idx; | ||
for (int curr_idx = first_idx + 1; curr_idx <= last_idx; ++curr_idx) { | ||
const MatchResult& curr_match = match_results[curr_idx]; | ||
const MatchResult& prev_match = match_results[prev_idx]; | ||
|
||
// skip if we do not need to cut | ||
if (!curr_match.is_break_point && curr_idx != last_idx) { | ||
continue; | ||
} | ||
|
||
// Allow for some fp-fuzz in this gt comparison | ||
// does the previous match point look further along its edge than the current | ||
bool prev_gt_curr = prev_match.distance_along > curr_match.distance_along + 1e-3; | ||
|
||
// we want to handle to loop by locating the correct target edge by comparing the distance alone | ||
// if they are on the same edge and previous comes after then its a loop | ||
bool loop = (prev_match.edgeid == curr_match.edgeid) && prev_gt_curr; | ||
|
||
// if it is a loop, we start the search after the first edge | ||
auto last_segment = std::find_if(first_segment + static_cast<size_t>(loop), segments.end(), | ||
[&curr_match](const EdgeSegment& segment) { | ||
return (segment.edgeid == curr_match.edgeid); | ||
}); | ||
for (search_segment += static_cast<size_t>(loop); search_segment != segments.end(); | ||
++search_segment) { | ||
if (search_segment->edgeid == curr_match.edgeid) | ||
break; | ||
} | ||
|
||
if (last_segment == segments.cend()) { | ||
if (search_segment == segments.cend()) { | ||
throw std::logic_error("In meili::cutsegments(), unexpectedly unable to locate target edge."); | ||
} | ||
|
||
// if its not a break point nor the last segment, then we dont need to split it into two | ||
if (!curr_match.is_break_point && curr_idx != last_idx) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so the main trick is we moved this continue down past where we did the loop to find the segment upon which the current match point lies. this way we have access to it, even if we arent going to cut it below. because i keep the |
||
// but if it isnt a breakpoint and its not the last stateful match point then its interpolated | ||
// and we still need to mark the segments in such a way that we which match points lie on them | ||
if (search_segment->first_match_idx < 0) | ||
search_segment->first_match_idx = curr_idx; | ||
if (search_segment->last_match_idx < 0) | ||
search_segment->last_match_idx = curr_idx; | ||
Comment on lines
+167
to
+170
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'll admit that i didnt think too hard about how correct this is but rather did the conservative thing, that is only set the index if unset. its possible that i should just always set both of them because they will be corrected below and wont have been set up to this point (ie we can probably remove the |
||
// we are done marking it no need to split this one | ||
continue; | ||
} | ||
|
||
// we need to close the previous edge | ||
size_t old_size = new_segments.size(); | ||
new_segments.insert(new_segments.cend(), first_segment, last_segment + 1); | ||
new_segments.insert(new_segments.cend(), first_segment, search_segment + 1); | ||
new_segments[old_size].first_match_idx = prev_idx; | ||
// when the points got interpolated, we want to use the match results' distance along | ||
// otherwise, we use the segment's source or target because if it is a node snap, the | ||
|
@@ -169,9 +183,9 @@ void cut_segments(const std::vector<MatchResult>& match_results, | |
prev_match.HasState() ? first_segment->source : prev_match.distance_along; | ||
new_segments.back().last_match_idx = curr_idx; | ||
new_segments.back().target = | ||
curr_match.HasState() ? last_segment->target : curr_match.distance_along; | ||
curr_match.HasState() ? search_segment->target : curr_match.distance_along; | ||
|
||
first_segment = last_segment; | ||
first_segment = search_segment; | ||
prev_idx = curr_idx; | ||
} | ||
} | ||
|
@@ -201,6 +215,7 @@ std::vector<EdgeSegment> ConstructRoute(const MapMatcher& mapmatcher, | |
for (int curr_idx = 0, n = static_cast<int>(match_results.size()); curr_idx < n; ++curr_idx) { | ||
const MatchResult& match = match_results[curr_idx]; | ||
|
||
// unmatched or interpolated | ||
if (!match.edgeid.Is_Valid() || !match.HasState()) { | ||
continue; | ||
} | ||
|
@@ -214,7 +229,7 @@ std::vector<EdgeSegment> ConstructRoute(const MapMatcher& mapmatcher, | |
// minimum number of segments. in this case we could at minimum end up with 1 segment | ||
segments.clear(); | ||
if (!MergeRoute(prev_state, state, segments, match)) { | ||
// we are only discontinuous but only if this isnt the beginning of the route | ||
// we are only discontinuous if this isnt the beginning of the route | ||
if (!route.empty()) | ||
route.back().discontinuity = true; | ||
// next pair | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah so we have a bug on geos 3.9*. and in a previous pr we patched it without really checking it. the best thing that we can do here is to not exit if its 3.9. ill change this script to do that. @nilsnolde are you cool if this comes along for the ride? im kind of sick of having to deal with it and have been too lazy to pr it seprately
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure!