diff --git a/osm2streets/src/lib.rs b/osm2streets/src/lib.rs index 862f8322..06b87226 100644 --- a/osm2streets/src/lib.rs +++ b/osm2streets/src/lib.rs @@ -156,7 +156,7 @@ impl StreetNetwork { for road in self.roads_per_intersection(endpts[0]) { // trimmed_center_line hasn't been initialized yet, so override this let mut input = road.to_input_road(); - input.center_pts = road.untrimmed_road_geometry().0; + input.center_pts = road.untrimmed_road_geometry(self.config.driving_side).0; input_roads.push(input); } let mut results = intersection_polygon( @@ -176,7 +176,7 @@ impl StreetNetwork { if road.id == road_id { input.center_pts = trimmed_center_pts.clone(); } else { - input.center_pts = road.untrimmed_road_geometry().0; + input.center_pts = road.untrimmed_road_geometry(self.config.driving_side).0; } input_roads.push(input); } @@ -228,7 +228,7 @@ impl StreetNetwork { pub(crate) fn debug_road>(&self, r: RoadID, label: I) { if let Some(step) = self.debug_steps.borrow_mut().last_mut() { step.polylines - .push((self.roads[&r].untrimmed_road_geometry().0, label.into())); + .push((self.roads[&r].center_line.clone(), label.into())); } } } diff --git a/osm2streets/src/road.rs b/osm2streets/src/road.rs index 35e9c320..5a971072 100644 --- a/osm2streets/src/road.rs +++ b/osm2streets/src/road.rs @@ -221,38 +221,23 @@ impl Road { self.reference_line.length() } - /// Returns the corrected (but untrimmed) center and total width for a road - pub fn untrimmed_road_geometry(&self) -> (PolyLine, Distance) { - let mut total_width = Distance::ZERO; - let mut sidewalk_right = None; - let mut sidewalk_left = None; - for l in &self.lane_specs_ltr { - total_width += l.width; - if l.lt.is_walkable() { - if l.dir == Direction::Back { - sidewalk_left = Some(l.width); - } else { - sidewalk_right = Some(l.width); - } - } - } - - // If there's a sidewalk on only one side, adjust the true center of the road. - // TODO I don't remember the rationale for doing this in the first place. What if there's a - // shoulder and a sidewalk of different widths? We don't do anything then - //TODO use self.left_edge_offset_of(RoadPosition::Center) or something? - let mut true_center = self.reference_line.clone(); - match (sidewalk_right, sidewalk_left) { - (Some(w), None) => { - true_center = true_center.must_shift_right(w / 2.0); - } - (None, Some(w)) => { - true_center = true_center.must_shift_right(w / 2.0); - } - _ => {} - } - - (true_center, total_width) + /// Returns a line along `RoadPosition::Center` (but untrimmed) and total width for ALL lanes. + pub fn untrimmed_road_geometry(&self, driving_side: DrivingSide) -> (PolyLine, Distance) { + let total_width = self.total_width(); + let ref_position = match self.reference_line_placement { + Placement::Consistent(p) => p, + Placement::Varying(p, _) => p, + Placement::Transition => RoadPosition::Center, // Best we can do for now. + }; + let ref_offset = self.left_edge_offset_of(ref_position, driving_side); + let center_offset = self.left_edge_offset_of(RoadPosition::Center, driving_side); + + ( + self.reference_line + .shift_either_direction(center_offset - ref_offset) + .unwrap(), + total_width, + ) } pub fn total_width(&self) -> Distance { @@ -416,10 +401,21 @@ impl Road { /// Returns the untrimmed left and right side of the road, oriented in the same direction of /// the road - pub fn get_untrimmed_sides(&self) -> Result<(PolyLine, PolyLine)> { - let (center, total_width) = self.untrimmed_road_geometry(); - let left = center.shift_from_center(total_width, -total_width / 2.0)?; - let right = center.shift_from_center(total_width, total_width / 2.0)?; + pub fn get_untrimmed_sides(&self, driving_side: DrivingSide) -> Result<(PolyLine, PolyLine)> { + let total_width = self.total_width(); + let ref_position = match self.reference_line_placement { + Placement::Consistent(p) => p, + Placement::Varying(p, _) => p, + Placement::Transition => RoadPosition::Center, // Best we can do for now. + }; + let ref_offset = self.left_edge_offset_of(ref_position, driving_side); + + let left = self + .reference_line + .shift_from_center(total_width, ref_offset - total_width)?; + let right = self + .reference_line + .shift_from_center(total_width, total_width - ref_offset)?; Ok((left, right)) } diff --git a/osm2streets/src/transform/dual_carriageways.rs b/osm2streets/src/transform/dual_carriageways.rs index 53322960..00d73cf6 100644 --- a/osm2streets/src/transform/dual_carriageways.rs +++ b/osm2streets/src/transform/dual_carriageways.rs @@ -263,12 +263,22 @@ impl DualCarriagewayPt2 { side1_length: orig .side1 .iter() - .map(|r| streets.roads[&r.road].untrimmed_road_geometry().0.length()) + .map(|r| { + streets.roads[&r.road] + .untrimmed_road_geometry(streets.config.driving_side) + .0 + .length() + }) .sum(), side2_length: orig .side2 .iter() - .map(|r| streets.roads[&r.road].untrimmed_road_geometry().0.length()) + .map(|r| { + streets.roads[&r.road] + .untrimmed_road_geometry(streets.config.driving_side) + .0 + .length() + }) .sum(), }) } @@ -294,7 +304,7 @@ impl DualCarriagewayPt2 { for pair in side.windows(2) { dist += streets.roads[&pair[0].road] - .untrimmed_road_geometry() + .untrimmed_road_geometry(streets.config.driving_side) .0 .length(); let i = pair[0].dst_i; diff --git a/osm2streets/src/transform/find_short_roads.rs b/osm2streets/src/transform/find_short_roads.rs index 8c05a1c8..7f64c7f2 100644 --- a/osm2streets/src/transform/find_short_roads.rs +++ b/osm2streets/src/transform/find_short_roads.rs @@ -88,7 +88,12 @@ impl StreetNetwork { { continue; } - if road.untrimmed_road_geometry().0.length() <= threshold { + if road + .untrimmed_road_geometry(self.config.driving_side) + .0 + .length() + <= threshold + { results.push(road.id); } } diff --git a/osm2streets/src/transform/separate_cycletracks.rs b/osm2streets/src/transform/separate_cycletracks.rs index 2bbd303e..23ca8130 100644 --- a/osm2streets/src/transform/separate_cycletracks.rs +++ b/osm2streets/src/transform/separate_cycletracks.rs @@ -83,7 +83,7 @@ fn find_cycleways(streets: &StreetNetwork) -> Vec { { cycleways.push(Cycleway { cycleway: cycleway_road.id, - cycleway_center: cycleway_road.untrimmed_road_geometry().0, + cycleway_center: cycleway_road.center_line.clone(), debug_idx: cycleways.len(), main_road_src_i, main_road_dst_i, @@ -135,7 +135,9 @@ fn snap(streets: &mut StreetNetwork, input: Cycleway) { for r in input.main_roads { let main_road = &streets.roads[&r]; // Which side is closer to the cycleway? - let (left, right) = main_road.get_untrimmed_sides().unwrap(); + let (left, right) = main_road + .get_untrimmed_sides(streets.config.driving_side) + .unwrap(); // TODO georust has a way to check distance of linestrings. But for now, just check the // middles let snap_to_left = input.cycleway_center.middle().dist_to(left.middle()) diff --git a/osm2streets/src/transform/shrink_roads.rs b/osm2streets/src/transform/shrink_roads.rs index 620fa9ed..b7510dea 100644 --- a/osm2streets/src/transform/shrink_roads.rs +++ b/osm2streets/src/transform/shrink_roads.rs @@ -23,7 +23,8 @@ pub fn shrink(streets: &mut StreetNetwork, timer: &mut Timer) { continue; } - let (center, total_width) = road.untrimmed_road_geometry(); + let center = road.center_line.clone(); + let total_width = road.total_width(); let polygon = center.make_polygons(total_width); // Any conflicts with existing?