diff --git a/data/get_fresh_osm.sh b/data/get_fresh_osm.sh index ff0e223353..f2ec6cf96c 100755 --- a/data/get_fresh_osm.sh +++ b/data/get_fresh_osm.sh @@ -7,4 +7,4 @@ set -e # From http://download.geofabrik.de/north-america/us/washington.html curl -L -O http://download.geofabrik.de/north-america/us/washington-latest.osm.pbf -osmupdate -v washington-latest.osm.pbf updated_wa.osm.pbf +osmupdate -v washington-latest.osm.pbf -B=data/input/seattle/polygons/huge_seattle.poly updated_wa.osm.pbf diff --git a/game/src/edit/traffic_signals.rs b/game/src/edit/traffic_signals.rs index 8936eb63d9..808fb66551 100644 --- a/game/src/edit/traffic_signals.rs +++ b/game/src/edit/traffic_signals.rs @@ -331,18 +331,13 @@ impl State for TrafficSignalEditor { let block_color = match self.group_selected.unwrap().1 { Some(TurnPriority::Protected) => { let green = Color::hex("#72CE36"); - batch.push( - green.alpha(0.5), - signal.turn_groups[&g.id] - .geom - .make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle), - ); - batch.extend( - green, - signal.turn_groups[&g.id] - .geom - .make_arrow_outline(BIG_ARROW_THICKNESS, Distance::meters(0.1)), - ); + let arrow = signal.turn_groups[&g.id] + .geom + .make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle); + batch.push(green.alpha(0.5), arrow.clone()); + if let Ok(p) = arrow.to_outline(Distance::meters(0.1)) { + batch.push(green, p); + } green } Some(TurnPriority::Yield) => { @@ -377,18 +372,13 @@ impl State for TrafficSignalEditor { } Some(TurnPriority::Banned) => { let red = Color::hex("#EB3223"); - batch.push( - red.alpha(0.5), - signal.turn_groups[&g.id] - .geom - .make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle), - ); - batch.extend( - red, - signal.turn_groups[&g.id] - .geom - .make_arrow_outline(BIG_ARROW_THICKNESS, Distance::meters(0.1)), - ); + let arrow = signal.turn_groups[&g.id] + .geom + .make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle); + batch.push(red.alpha(0.5), arrow.clone()); + if let Ok(p) = arrow.to_outline(Distance::meters(0.1)) { + batch.push(red, p); + } red } None => app.cs.signal_turn_block_bg, diff --git a/game/src/render/traffic_signal.rs b/game/src/render/traffic_signal.rs index ab56fa1f82..245e0c2f6a 100644 --- a/game/src/render/traffic_signal.rs +++ b/game/src/render/traffic_signal.rs @@ -127,18 +127,13 @@ pub fn draw_signal_phase( TrafficSignalStyle::GroupArrows => { for g in &phase.yield_groups { assert!(!g.crosswalk); - batch.push( - app.cs.signal_permitted_turn.alpha(0.3), - signal.turn_groups[g] - .geom - .make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle), - ); - batch.extend( - app.cs.signal_permitted_turn, - signal.turn_groups[g] - .geom - .make_arrow_outline(BIG_ARROW_THICKNESS * 2.0, BIG_ARROW_THICKNESS / 2.0), - ); + let arrow = signal.turn_groups[g] + .geom + .make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle); + batch.push(app.cs.signal_permitted_turn.alpha(0.3), arrow.clone()); + if let Ok(p) = arrow.to_outline(BIG_ARROW_THICKNESS / 2.0) { + batch.push(app.cs.signal_permitted_turn, p); + } } let mut dont_walk = BTreeSet::new(); for g in signal.turn_groups.keys() { @@ -178,18 +173,13 @@ pub fn draw_signal_phase( TrafficSignalStyle::Sidewalks => { for g in &phase.yield_groups { assert!(!g.crosswalk); - batch.push( - app.cs.signal_permitted_turn.alpha(0.3), - signal.turn_groups[g] - .geom - .make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle), - ); - batch.extend( - app.cs.signal_permitted_turn, - signal.turn_groups[g] - .geom - .make_arrow_outline(BIG_ARROW_THICKNESS * 2.0, BIG_ARROW_THICKNESS / 2.0), - ); + let arrow = signal.turn_groups[g] + .geom + .make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle); + batch.push(app.cs.signal_permitted_turn.alpha(0.3), arrow.clone()); + if let Ok(p) = arrow.to_outline(BIG_ARROW_THICKNESS / 2.0) { + batch.push(app.cs.signal_permitted_turn, p); + } } for g in &phase.protected_groups { if g.crosswalk { @@ -234,13 +224,14 @@ pub fn draw_signal_phase( ); } TurnPriority::Yield => { - batch.extend( - app.cs.signal_permitted_turn, - turn.geom.make_arrow_outline( - BIG_ARROW_THICKNESS * 2.0, - BIG_ARROW_THICKNESS / 2.0, - ), - ); + let arrow = turn + .geom + .make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle); + if let Ok(p) = arrow.to_outline(BIG_ARROW_THICKNESS / 2.0) { + batch.push(app.cs.signal_permitted_turn, p); + } else { + batch.push(app.cs.signal_permitted_turn, arrow); + } } TurnPriority::Banned => {} } diff --git a/geom/src/polyline.rs b/geom/src/polyline.rs index 22220f2581..60e9391af3 100644 --- a/geom/src/polyline.rs +++ b/geom/src/polyline.rs @@ -9,9 +9,9 @@ use std::fmt; // TODO How to tune this? const MITER_THRESHOLD: f64 = 500.0; +// TODO There used to be a second style that just has extra little hooks going out pub enum ArrowCap { Triangle, - Lines, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -518,6 +518,7 @@ impl PolyLine { return self.make_polygons(thickness); } let slice = self.exact_slice(Distance::ZERO, self.length() - triangle_height); + let angle = slice.last_pt().angle_to(self.last_pt()); let corner1 = self .last_pt() @@ -526,49 +527,20 @@ impl PolyLine { .last_pt() .project_away(head_size, angle.rotate_degs(135.0)); + let mut pts = slice.shift_with_sharp_angles(thickness / 2.0, MITER_THRESHOLD); match cap { - ArrowCap::Triangle => slice.make_polygons(thickness).union(Polygon::new(&vec![ - self.last_pt(), - corner1, - corner2, - ])), - ArrowCap::Lines => self.make_polygons(thickness).union( - PolyLine::must_new(vec![corner1, self.last_pt(), corner2]).make_polygons(thickness), - ), - } - } - - // TODO Refactor - pub fn make_arrow_outline( - &self, - arrow_thickness: Distance, - outline_thickness: Distance, - ) -> Vec { - let head_size = arrow_thickness * 2.0; - let triangle_height = head_size / 2.0_f64.sqrt(); - - if self.length() < triangle_height { - return vec![self.make_polygons(arrow_thickness)]; - } - let slice = self.exact_slice(Distance::ZERO, self.length() - triangle_height); - - if let Some(p) = slice.to_thick_boundary(arrow_thickness, outline_thickness) { - let angle = slice.last_pt().angle_to(self.last_pt()); - vec![ - p, - Ring::must_new(vec![ - self.last_pt(), - self.last_pt() - .project_away(head_size, angle.rotate_degs(-135.0)), - self.last_pt() - .project_away(head_size, angle.rotate_degs(135.0)), - self.last_pt(), - ]) - .make_polygons(outline_thickness), - ] - } else { - vec![self.make_polygons(arrow_thickness)] + ArrowCap::Triangle => { + pts.push(corner2); + pts.push(self.last_pt()); + pts.push(corner1); + } } + let mut side2 = slice.shift_with_sharp_angles(-thickness / 2.0, MITER_THRESHOLD); + side2.reverse(); + pts.extend(side2); + pts.push(pts[0]); + pts.dedup(); + Polygon::new(&pts) } pub fn dashed_arrow(