Prevent merging of circular-shaped roads

This commit is contained in:
Michael Krasnyk
2017-10-16 10:47:14 +02:00
parent bf03dcd1e6
commit 088d4edc6b
5 changed files with 102 additions and 3 deletions
@@ -297,7 +297,7 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
// many roads only do short parallel segments. To get a good impression of how `parallel` two
// roads are, we look 100 meters down the road (wich can be quite short for very broad roads).
const double constexpr distance_to_extract = 100;
const double constexpr distance_to_extract = 150;
std::tie(distance_traversed_to_the_left, coordinates_to_the_left) =
getCoordinatesAlongWay(lhs.eid, distance_to_extract);
@@ -317,6 +317,36 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
const auto connect_again = (coordinates_to_the_left.back() == coordinates_to_the_right.back());
// Tuning parameter to detect and don't merge roads close to circular shapes
// if the area to squared circumference ratio is between the lower bound and 1/(4π)
// that correspond to isoperimetric inequality 4πA ≤ L² or lower bound ≤ A/L² ≤ 1/(4π).
// The lower bound must be larger enough to allow merging of square-shaped intersections
// with A/L² = 1/16 or 78.6%
// The condition suppresses roads merging for intersections like
// . .
// . .
// ---- ----
// . .
// . .
// but will allow roads merging for intersections like
// -------
// / \ 
// ---- ----
// \ /
// -------
const auto constexpr CIRCULAR_POLYGON_ISOPERIMETRIC_LOWER_BOUND = 0.85 / (4 * M_PI);
if (connect_again && coordinates_to_the_left.front() == coordinates_to_the_left.back())
{ // if the left and right roads connect again and are closed polygons ...
const auto area = util::coordinate_calculation::computeArea(coordinates_to_the_left);
const auto perimeter = distance_traversed_to_the_left;
const auto area_to_squared_perimeter_ratio = std::abs(area) / (perimeter * perimeter);
// then don't merge roads if A/L² is greater than the lower bound
BOOST_ASSERT(area_to_squared_perimeter_ratio <= 1. / (4 * M_PI));
if (area_to_squared_perimeter_ratio >= CIRCULAR_POLYGON_ISOPERIMETRIC_LOWER_BOUND)
return false;
}
// sampling to correctly weight longer segments in regression calculations
const auto constexpr SAMPLE_INTERVAL = 5;
coordinates_to_the_left = coordinate_extractor.SampleCoordinates(