prepare solution

This commit is contained in:
Moritz Kobitzsch 2016-08-11 12:44:10 +02:00
parent b6c3d1d5bf
commit 5a9eb6ef72
2 changed files with 108 additions and 18 deletions

View File

@ -50,6 +50,12 @@ class IntersectionGenerator
OSRM_ATTR_WARN_UNUSED OSRM_ATTR_WARN_UNUSED
Intersection getConnectedRoads(const NodeID from_node, const EdgeID via_eid) const; Intersection getConnectedRoads(const NodeID from_node, const EdgeID via_eid) const;
// check if two indices in an intersection can be seen as a single road in the perceived
// intersection representation
bool canMerge(const Intersection &intersection,
std::size_t first_index,
std::size_t second_index) const;
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as // Merge segregated roads to omit invalid turns in favor of treating segregated roads as
// one. // one.
// This function combines roads the following way: // This function combines roads the following way:
@ -63,6 +69,20 @@ class IntersectionGenerator
// 160 // 160
OSRM_ATTR_WARN_UNUSED OSRM_ATTR_WARN_UNUSED
Intersection mergeSegregatedRoads(Intersection intersection) const; Intersection mergeSegregatedRoads(Intersection intersection) const;
// The counterpiece to mergeSegregatedRoads. While we can adjust roads that split up at the
// intersection itself, it can also happen that intersections are connected to joining roads.
//
// * *
// * is converted to *
// v a --- a ---
// v ^ +
// v ^ +
// b
//
// for the local view of b at a.
Intersection adjustForJoiningRoads(const NodeID node_at_intersection,
Intersection intersection) const;
}; };
} // namespace guidance } // namespace guidance

View File

@ -30,7 +30,9 @@ IntersectionGenerator::IntersectionGenerator(
Intersection IntersectionGenerator::operator()(const NodeID from_node, const EdgeID via_eid) const Intersection IntersectionGenerator::operator()(const NodeID from_node, const EdgeID via_eid) const
{ {
return getConnectedRoads(from_node, via_eid); auto intersection = getConnectedRoads(from_node, via_eid);
return adjustForJoiningRoads(node_based_graph.GetTarget(via_eid),
mergeSegregatedRoads(std::move(intersection)));
} }
// a // a
@ -161,6 +163,40 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
return mergeSegregatedRoads(std::move(intersection)); return mergeSegregatedRoads(std::move(intersection));
} }
bool IntersectionGenerator::canMerge(const Intersection &intersection,
std::size_t first_index,
std::size_t second_index) const
{
const auto &first_data = node_based_graph.GetEdgeData(intersection[first_index].turn.eid);
const auto &second_data = node_based_graph.GetEdgeData(intersection[second_index].turn.eid);
// only merge named ids
if (first_data.name_id == EMPTY_NAMEID)
return false;
// need to be same name
if (first_data.name_id != second_data.name_id)
return false;
// compatibility is required
if (first_data.travel_mode != second_data.travel_mode)
return false;
if (first_data.road_classification != second_data.road_classification)
return false;
//may not be on a roundabout
if( first_data.roundabout || second_data.roundabout)
return false;
// exactly one of them has to be reversed
if (first_data.reversed == second_data.reversed)
return false;
// mergeable if the angle is not too big
return angularDeviation(intersection[first_index].turn.angle,
intersection[second_index].turn.angle) < 60;
}
/* /*
* Segregated Roads often merge onto a single intersection. * Segregated Roads often merge onto a single intersection.
* While technically representing different roads, they are * While technically representing different roads, they are
@ -190,20 +226,6 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
return (index + intersection.size() - 1) % intersection.size(); return (index + intersection.size() - 1) % intersection.size();
}; };
const auto mergable = [&](std::size_t first, std::size_t second) -> bool {
const auto &first_data = node_based_graph.GetEdgeData(intersection[first].turn.eid);
const auto &second_data = node_based_graph.GetEdgeData(intersection[second].turn.eid);
return first_data.name_id != EMPTY_NAMEID && first_data.name_id == second_data.name_id &&
!first_data.roundabout && !second_data.roundabout &&
first_data.travel_mode == second_data.travel_mode &&
first_data.road_classification == second_data.road_classification &&
// compatible threshold
angularDeviation(intersection[first].turn.angle, intersection[second].turn.angle) <
60 &&
first_data.reversed != second_data.reversed;
};
const auto merge = [](const ConnectedRoad &first, const auto merge = [](const ConnectedRoad &first,
const ConnectedRoad &second) -> ConnectedRoad { const ConnectedRoad &second) -> ConnectedRoad {
if (!first.entry_allowed) if (!first.entry_allowed)
@ -275,7 +297,8 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
// with respect to the now changed perceived location of a. If we move (a) to the left, we add // with respect to the now changed perceived location of a. If we move (a) to the left, we add
// the difference to all angles. Otherwise we subtract it. // the difference to all angles. Otherwise we subtract it.
bool merged_first = false; bool merged_first = false;
if (mergable(0, intersection.size() - 1)) // these result in an adjustment of all other angles
if (canMerge(intersection, 0, intersection.size() - 1))
{ {
merged_first = true; merged_first = true;
// moving `a` to the left // moving `a` to the left
@ -290,7 +313,7 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
intersection.pop_back(); intersection.pop_back();
} }
else if (mergable(0, 1)) else if (canMerge(intersection, 0, 1))
{ {
merged_first = true; merged_first = true;
// moving `a` to the right // moving `a` to the right
@ -321,7 +344,7 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
// therefore these are handled prior to this step // therefore these are handled prior to this step
for (std::size_t index = 2; index < intersection.size(); ++index) for (std::size_t index = 2; index < intersection.size(); ++index)
{ {
if (mergable(index, getRight(index))) if (canMerge(intersection, index, getRight(index)))
{ {
intersection[getRight(index)] = intersection[getRight(index)] =
merge(intersection[getRight(index)], intersection[index]); merge(intersection[getRight(index)], intersection[index]);
@ -337,6 +360,53 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
return intersection; return intersection;
} }
// OSM can have some very steep angles for joining roads. Considering the following intersection:
// x
// |__________c
// /
// a ---d
// \ __________b
//
// with c->d as a oneway
// and d->b as a oneway, the turn von x->d is actually a turn from x->a. So when looking at the
// intersection coming from x, we want to interpret the situation as
// x
// a __ d __ |__________c
// |
// |_______________b
//
// Where we see the turn to `d` as a right turn, rather than going straight.
// We do this by adjusting the local turn angle at `x` to turn onto `d` to be reflective of this
// situation.
Intersection IntersectionGenerator::adjustForJoiningRoads(const NodeID node_at_intersection,
Intersection intersection) const
{
for (auto &road : intersection)
{
// prune to short intersections to save on compute overhead
if (node_based_graph.GetEdgeData(road.turn.eid).distance > 10)
continue;
// to find out about the above situation, we need to look at the next intersection (at d in
// the example). If the initial road can be merged to the left/right, we are about to adjust
// the angle.
const auto next_intersection_along_road =
getConnectedRoads(node_at_intersection, road.turn.eid);
if (next_intersection_along_road.size() <= 1)
continue;
if (canMerge(next_intersection_along_road, 0, 1))
{
std::cout << "Merge at next intersection" << std::endl;
}
else if (canMerge(next_intersection_along_road, 0, next_intersection_along_road.size() - 1))
{
std::cout << "Merge at next intersection (2)" << std::endl;
}
}
return intersection;
}
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor
} // namespace osrm } // namespace osrm