Improve the dog-leg detection around dual carriageways. Enable this for

Montlake! #654
This commit is contained in:
Dustin Carlino 2022-02-20 16:43:15 +00:00
parent d6508e9376
commit efe5f76bbe
5 changed files with 54 additions and 46 deletions

View File

@ -2911,9 +2911,9 @@
"compressed_size_bytes": 28046882
},
"data/input/us/seattle/screenshots/montlake.zip": {
"checksum": "b49b509993ccbd1666dcf712c8e0ed04",
"uncompressed_size_bytes": 5412207,
"compressed_size_bytes": 5412143
"checksum": "88cadd6ebef45233affc5c3cf29998fb",
"uncompressed_size_bytes": 5460258,
"compressed_size_bytes": 5460211
},
"data/input/us/seattle/trips_2014.csv": {
"checksum": "d4a8e733045b28c0385fb81359d6df03",
@ -4906,9 +4906,9 @@
"compressed_size_bytes": 7386218
},
"data/system/us/seattle/maps/montlake.bin": {
"checksum": "df6f3f66ceaa1327d6ba70f0a993fcc2",
"uncompressed_size_bytes": 3111397,
"compressed_size_bytes": 1184433
"checksum": "b0974b3680feccb5b951238f4b3fd83d",
"uncompressed_size_bytes": 3089847,
"compressed_size_bytes": 1175618
},
"data/system/us/seattle/maps/north_seattle.bin": {
"checksum": "a47d263ff7753acf3ca642d25e5a229a",
@ -4956,14 +4956,14 @@
"compressed_size_bytes": 6427759
},
"data/system/us/seattle/prebaked_results/montlake/car vs bike contention.bin": {
"checksum": "b83549f9dc9f010f1d279d930a89ec5f",
"uncompressed_size_bytes": 4444,
"compressed_size_bytes": 1379
"checksum": "137065d4d899c4670961157d8ce3370d",
"uncompressed_size_bytes": 4288,
"compressed_size_bytes": 1363
},
"data/system/us/seattle/prebaked_results/montlake/weekday.bin": {
"checksum": "d3e38bb47ad5bd4d57a6d1c8fabf62eb",
"uncompressed_size_bytes": 8090114,
"compressed_size_bytes": 3197694
"checksum": "fe1560bcc1fde0794699a2c634751013",
"uncompressed_size_bytes": 8048257,
"compressed_size_bytes": 3187685
},
"data/system/us/seattle/scenarios/arboretum/weekday.bin": {
"checksum": "275e558f75306364cba3d7a038b0c8e1",
@ -4991,9 +4991,9 @@
"compressed_size_bytes": 2404481
},
"data/system/us/seattle/scenarios/montlake/weekday.bin": {
"checksum": "0dcdd05adffbe689f3a65180c7451595",
"checksum": "fbb3641f64d599b7d036d48f809dd991",
"uncompressed_size_bytes": 1334635,
"compressed_size_bytes": 326462
"compressed_size_bytes": 326528
},
"data/system/us/seattle/scenarios/north_seattle/weekday.bin": {
"checksum": "aab330481f4161ba74db9254e867194c",

View File

@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
use abstio::{CityName, MapName};
use abstutil::{deserialize_btreemap, serialize_btreemap, Tags};
use geom::{Distance, GPSBounds, PolyLine, Polygon, Pt2D};
use geom::{Angle, Distance, GPSBounds, PolyLine, Polygon, Pt2D};
pub use self::geometry::intersection_polygon;
pub use self::lane_specs::get_lane_specs_ltr;
@ -410,6 +410,15 @@ impl RawRoad {
.any(|spec| spec.lt == LaneType::Driving)
}
pub fn is_oneway(&self) -> bool {
self.osm_tags.is("oneway", "yes")
}
/// Points from first to last point. Undefined for loops.
pub fn angle(&self) -> Angle {
self.center_points[0].angle_to(*self.center_points.last().unwrap())
}
pub fn length(&self) -> Distance {
PolyLine::unchecked_new(self.center_points.clone()).length()
}

View File

@ -1,15 +1,13 @@
use std::collections::BTreeSet;
use geom::Angle;
use crate::{osm, OriginalRoad, RawMap, RawRoad};
use crate::{osm, OriginalRoad, RawMap};
/// Does this road go between two divided one-ways? Ideally they're tagged explicitly
/// (https://wiki.openstreetmap.org/wiki/Tag:dual_carriageway%3Dyes), but we can also apply simple
/// heuristics to guess this.
#[allow(unused)]
pub fn connects_dual_carriageway(map: &RawMap, id: &OriginalRoad) -> bool {
let connectors_angle = angle(&map.roads[id]);
let connectors_angle = map.roads[id].angle();
// There are false positives like https://www.openstreetmap.org/way/4636259 when we're looking
// at a segment along a marked dual carriageway. Filter out by requiring the intersecting dual
// carriageways to differ by a minimum angle.
@ -19,7 +17,7 @@ pub fn connects_dual_carriageway(map: &RawMap, id: &OriginalRoad) -> bool {
let mut oneway_names_i1: BTreeSet<String> = BTreeSet::new();
for r in map.roads_per_intersection(id.i1) {
let road = &map.roads[&r];
if r == *id || connectors_angle.approx_eq(angle(road), within_degrees) {
if r == *id || connectors_angle.approx_eq(road.angle(), within_degrees) {
continue;
}
if road.osm_tags.is("dual_carriageway", "yes") {
@ -36,7 +34,7 @@ pub fn connects_dual_carriageway(map: &RawMap, id: &OriginalRoad) -> bool {
let mut oneway_names_i2: BTreeSet<String> = BTreeSet::new();
for r in map.roads_per_intersection(id.i2) {
let road = &map.roads[&r];
if r == *id || connectors_angle.approx_eq(angle(road), within_degrees) {
if r == *id || connectors_angle.approx_eq(road.angle(), within_degrees) {
continue;
}
if road.osm_tags.is("dual_carriageway", "yes") {
@ -55,7 +53,3 @@ pub fn connects_dual_carriageway(map: &RawMap, id: &OriginalRoad) -> bool {
.next()
.is_some()
}
fn angle(r: &RawRoad) -> Angle {
r.center_points[0].angle_to(*r.center_points.last().unwrap())
}

View File

@ -24,7 +24,7 @@ pub fn find_short_roads(map: &mut RawMap, consolidate_all: bool) -> Vec<Original
}
// TODO Gradual rollout
if false && map.name == MapName::seattle("montlake") {
if map.name == MapName::seattle("montlake") {
roads.extend(map.find_dog_legs());
}
@ -144,10 +144,9 @@ impl RawMap {
}
}
// TODO Not working yet
// Are these 3 roads nearly parallel? We're near the start of a dual carriageway
// split if so, like https://www.openstreetmap.org/node/496331163
if false && nearly_parallel(self, connections, i).unwrap_or(true) {
// Don't touch the point where dual carriageways split/join, like
// https://www.openstreetmap.org/node/496331163
if dual_carriageway_split(self, connections) {
continue 'ROAD;
}
}
@ -158,21 +157,27 @@ impl RawMap {
}
}
fn nearly_parallel(map: &RawMap, roads: Vec<OriginalRoad>, i: osm::NodeID) -> Option<bool> {
let mut angles = Vec::new();
for id in roads {
let pl = map.trimmed_road_geometry(id)?;
if id.i1 == i {
angles.push(pl.first_line().angle());
} else {
angles.push(pl.last_line().angle());
// TODO Dedupe with find_divided_highways logic in parking_mapper
fn dual_carriageway_split(map: &RawMap, roads: Vec<OriginalRoad>) -> bool {
assert_eq!(roads.len(), 3);
// Look for one-way roads with the same name
for (r1, r2) in [
(roads[0], roads[1]),
(roads[0], roads[2]),
(roads[1], roads[2]),
] {
let road1 = &map.roads[&r1];
let road2 = &map.roads[&r2];
if road1.is_oneway()
&& road2.is_oneway()
&& road1.osm_tags.get(osm::NAME) == road2.osm_tags.get(osm::NAME)
{
// If they're about the same angle, it's probably not a join/split
let within_degrees = 30.0;
if !road1.angle().approx_eq(road2.angle(), within_degrees) {
return true;
}
}
}
let threshold_degrees = 30.0;
Some(
angles[0].approx_parallel(angles[1], threshold_degrees)
&& angles[0].approx_parallel(angles[2], threshold_degrees)
&& angles[1].approx_parallel(angles[2], threshold_degrees),
)
false
}

View File

@ -11,7 +11,7 @@
"scenario": "weekday",
"finished_trips": 36713,
"cancelled_trips": 83,
"total_trip_duration_seconds": 18510320.970200088
"total_trip_duration_seconds": 18485539.44410009
},
{
"map": "parliament (in tehran (ir))",