using strong Distance types in many more places

This commit is contained in:
Dustin Carlino 2019-01-30 15:10:05 -08:00
parent 3e00789960
commit 7519fdf584
35 changed files with 180 additions and 149 deletions

View File

@ -165,9 +165,7 @@ fn use_parking_hints(map: &mut raw_data::Map, shapes: ExtraShapes, gps_bounds: &
// TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within // TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within
// the threshold distance? // the threshold distance?
let middle = PolyLine::new(pts).middle(); let middle = PolyLine::new(pts).middle();
if let Some(((r, fwds), _)) = if let Some(((r, fwds), _)) = closest.closest_pt(middle, LANE_THICKNESS * 5.0) {
closest.closest_pt(middle, Distance::meters(5.0 * LANE_THICKNESS))
{
let category = s.attributes.get("PARKING_CATEGORY"); let category = s.attributes.get("PARKING_CATEGORY");
let has_parking = category != Some(&"None".to_string()) let has_parking = category != Some(&"None".to_string())
&& category != Some(&"No Parking Allowed".to_string()); && category != Some(&"No Parking Allowed".to_string());

View File

@ -3,9 +3,6 @@
## Geometry ## Geometry
- try fixed pt again, for determinism purposes mostly - try fixed pt again, for determinism purposes mostly
- go through and use less f64's... like LANE_THICKNESS, make_polygons, Circle::new, project_away
- audit inner_foo()'s
- change internal pt2d representation to int. JUST get that working first. - change internal pt2d representation to int. JUST get that working first.
- clamp distances first, not points? - clamp distances first, not points?
- note contains_pt needs to use 2 or 3 * epsilon, because of the error that may accumulate... - note contains_pt needs to use 2 or 3 * epsilon, because of the error that may accumulate...

View File

@ -1,10 +1,10 @@
use crate::objects::Ctx; use crate::objects::Ctx;
use crate::plugins::{load_neighborhood_builder, Plugin, PluginCtx}; use crate::plugins::{load_neighborhood_builder, Plugin, PluginCtx};
use ezgui::{Color, GfxCtx, Key, Wizard, WrappedWizard}; use ezgui::{Color, GfxCtx, Key, Wizard, WrappedWizard};
use geom::{Circle, Line, Polygon, Pt2D}; use geom::{Circle, Distance, Line, Polygon, Pt2D};
use map_model::{Map, NeighborhoodBuilder}; use map_model::{Map, NeighborhoodBuilder};
const POINT_RADIUS: f64 = 2.0; const POINT_RADIUS: Distance = Distance::const_meters(2.0);
pub enum DrawNeighborhoodState { pub enum DrawNeighborhoodState {
PickNeighborhood(Wizard), PickNeighborhood(Wizard),

View File

@ -1,10 +1,10 @@
use crate::objects::{Ctx, ID}; use crate::objects::{Ctx, ID};
use crate::render::{RenderOptions, Renderable}; use crate::render::{RenderOptions, Renderable};
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Bounds, Polygon, Pt2D}; use geom::{Bounds, Distance, Polygon, Pt2D};
use sim::{CarID, CarState, DrawCarInput}; use sim::{CarID, CarState, DrawCarInput};
const BIKE_WIDTH: f64 = 0.8; const BIKE_WIDTH: Distance = Distance::const_meters(0.8);
pub struct DrawBike { pub struct DrawBike {
pub id: CarID, pub id: CarID,

View File

@ -19,7 +19,7 @@ impl DrawBuilding {
// overlap. For now, this cleanup is visual; it doesn't belong in the map_model layer. // overlap. For now, this cleanup is visual; it doesn't belong in the map_model layer.
let mut front_path_line = bldg.front_path.line.clone(); let mut front_path_line = bldg.front_path.line.clone();
let len = front_path_line.length(); let len = front_path_line.length();
let trim_back = Distance::meters(LANE_THICKNESS / 2.0); let trim_back = LANE_THICKNESS / 2.0;
if len > trim_back && len - trim_back > geom::EPSILON_DIST { if len > trim_back && len - trim_back > geom::EPSILON_DIST {
front_path_line = Line::new( front_path_line = Line::new(
front_path_line.pt1(), front_path_line.pt1(),
@ -27,7 +27,7 @@ impl DrawBuilding {
); );
} }
let fill_polygon = Polygon::new(&bldg.points); let fill_polygon = Polygon::new(&bldg.points);
let front_path = front_path_line.make_polygons(1.0); let front_path = front_path_line.make_polygons(Distance::meters(1.0));
let default_draw = prerender.upload_borrowed(vec![ let default_draw = prerender.upload_borrowed(vec![
( (

View File

@ -27,7 +27,7 @@ impl DrawBusStop {
.map(|(pt, _)| pt) .map(|(pt, _)| pt)
.unwrap_or_else(|| lane.last_pt()), .unwrap_or_else(|| lane.last_pt()),
]) ])
.make_polygons(0.8 * LANE_THICKNESS); .make_polygons(LANE_THICKNESS * 0.8);
DrawBusStop { DrawBusStop {
id: stop.id, id: stop.id,
polygon, polygon,

View File

@ -6,7 +6,7 @@ use map_model::{Map, TurnType};
use sim::{CarID, CarState, DrawCarInput, MIN_CAR_LENGTH}; use sim::{CarID, CarState, DrawCarInput, MIN_CAR_LENGTH};
use std; use std;
const CAR_WIDTH: f64 = 2.0; const CAR_WIDTH: Distance = Distance::const_meters(2.0);
pub struct DrawCar { pub struct DrawCar {
pub id: CarID, pub id: CarID,
@ -57,17 +57,17 @@ impl DrawCar {
.body .body
.dist_along(input.body.length() - Distance::meters(0.5)); .dist_along(input.body.length() - Distance::meters(0.5));
let (back_blinker_pos, back_blinker_angle) = input.body.dist_along(Distance::meters(0.5)); let (back_blinker_pos, back_blinker_angle) = input.body.dist_along(Distance::meters(0.5));
let blinker_radius = 0.3; let blinker_radius = Distance::meters(0.3);
let window_length_gap = 0.2; let window_length_gap = Distance::meters(0.2);
let window_thickness = 0.3; let window_thickness = Distance::meters(0.3);
let front_window = { let front_window = {
let (pos, angle) = input let (pos, angle) = input
.body .body
.dist_along(input.body.length() - Distance::meters(1.0)); .dist_along(input.body.length() - Distance::meters(1.0));
thick_line_from_angle( thick_line_from_angle(
window_thickness, window_thickness,
CAR_WIDTH - 2.0 * window_length_gap, CAR_WIDTH - window_length_gap * 2.0,
pos.project_away( pos.project_away(
CAR_WIDTH / 2.0 - window_length_gap, CAR_WIDTH / 2.0 - window_length_gap,
angle.rotate_degs(-90.0), angle.rotate_degs(-90.0),
@ -79,7 +79,7 @@ impl DrawCar {
let (pos, angle) = input.body.dist_along(Distance::meters(1.0)); let (pos, angle) = input.body.dist_along(Distance::meters(1.0));
thick_line_from_angle( thick_line_from_angle(
window_thickness * 0.8, window_thickness * 0.8,
CAR_WIDTH - 2.0 * window_length_gap, CAR_WIDTH - window_length_gap * 2.0,
pos.project_away( pos.project_away(
CAR_WIDTH / 2.0 - window_length_gap, CAR_WIDTH / 2.0 - window_length_gap,
angle.rotate_degs(-90.0), angle.rotate_degs(-90.0),
@ -95,26 +95,32 @@ impl DrawCar {
left_blinkers: Some(( left_blinkers: Some((
Circle::new( Circle::new(
front_blinker_pos.project_away( front_blinker_pos.project_away(
CAR_WIDTH / 2.0 - 0.5, CAR_WIDTH / 2.0 - Distance::meters(0.5),
front_blinker_angle.rotate_degs(-90.0), front_blinker_angle.rotate_degs(-90.0),
), ),
blinker_radius, blinker_radius,
), ),
Circle::new( Circle::new(
back_blinker_pos back_blinker_pos.project_away(
.project_away(CAR_WIDTH / 2.0 - 0.5, back_blinker_angle.rotate_degs(-90.0)), CAR_WIDTH / 2.0 - Distance::meters(0.5),
back_blinker_angle.rotate_degs(-90.0),
),
blinker_radius, blinker_radius,
), ),
)), )),
right_blinkers: Some(( right_blinkers: Some((
Circle::new( Circle::new(
front_blinker_pos front_blinker_pos.project_away(
.project_away(CAR_WIDTH / 2.0 - 0.5, front_blinker_angle.rotate_degs(90.0)), CAR_WIDTH / 2.0 - Distance::meters(0.5),
front_blinker_angle.rotate_degs(90.0),
),
blinker_radius, blinker_radius,
), ),
Circle::new( Circle::new(
back_blinker_pos back_blinker_pos.project_away(
.project_away(CAR_WIDTH / 2.0 - 0.5, back_blinker_angle.rotate_degs(90.0)), CAR_WIDTH / 2.0 - Distance::meters(0.5),
back_blinker_angle.rotate_degs(90.0),
),
blinker_radius, blinker_radius,
), ),
)), )),
@ -216,7 +222,12 @@ impl Renderable for DrawCar {
} }
} }
fn thick_line_from_angle(thickness: f64, line_length: f64, pt: Pt2D, angle: Angle) -> Polygon { fn thick_line_from_angle(
thickness: Distance,
line_length: Distance,
pt: Pt2D,
angle: Angle,
) -> Polygon {
let pt2 = pt.project_away(line_length, angle); let pt2 = pt.project_away(line_length, angle);
// Shouldn't ever fail for a single line // Shouldn't ever fail for a single line
PolyLine::new(vec![pt, pt2]).make_polygons(thickness) PolyLine::new(vec![pt, pt2]).make_polygons(thickness)

View File

@ -50,19 +50,18 @@ impl DrawExtraShape {
road: None, road: None,
}) })
} else { } else {
let width = get_sidewalk_width(&s.attributes) let width = get_sidewalk_width(&s.attributes).unwrap_or(EXTRA_SHAPE_THICKNESS);
.unwrap_or_else(|| Distance::meters(EXTRA_SHAPE_THICKNESS));
let pl = PolyLine::new(pts); let pl = PolyLine::new(pts);
// The blockface line endpoints will be close to other roads, so match based on the // The blockface line endpoints will be close to other roads, so match based on the
// middle of the blockface. // middle of the blockface.
// TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within // TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within
// the threshold distance? // the threshold distance?
let road = closest let road = closest
.closest_pt(pl.middle(), Distance::meters(5.0 * LANE_THICKNESS)) .closest_pt(pl.middle(), LANE_THICKNESS * 5.0)
.map(|(r, _)| r); .map(|(r, _)| r);
Some(DrawExtraShape { Some(DrawExtraShape {
id, id,
shape: Shape::Polygon(pl.make_polygons(width.inner_meters())), shape: Shape::Polygon(pl.make_polygons(width)),
attributes: s.attributes, attributes: s.attributes,
road, road,
}) })

View File

@ -224,7 +224,7 @@ fn draw_signal_cycle_with_icons(cycle: &Cycle, g: &mut GfxCtx, ctx: &Ctx) {
}; };
} }
let radius = Distance::meters(LANE_THICKNESS / 2.0); let radius = LANE_THICKNESS / 2.0;
// TODO Ignore right_ok... // TODO Ignore right_ok...
{ {
@ -234,7 +234,7 @@ fn draw_signal_cycle_with_icons(cycle: &Cycle, g: &mut GfxCtx, ctx: &Ctx) {
} else { } else {
ctx.cs.get_def("traffic light stop", Color::RED) ctx.cs.get_def("traffic light stop", Color::RED)
}; };
g.draw_circle(color, &Circle::new(center1, radius.inner_meters())); g.draw_circle(color, &Circle::new(center1, radius));
} }
if let Some(pri) = left_priority { if let Some(pri) = left_priority {
@ -248,16 +248,14 @@ fn draw_signal_cycle_with_icons(cycle: &Cycle, g: &mut GfxCtx, ctx: &Ctx) {
}; };
g.draw_circle( g.draw_circle(
ctx.cs.get_def("traffic light box", Color::BLACK), ctx.cs.get_def("traffic light box", Color::BLACK),
&Circle::new(center2, radius.inner_meters()), &Circle::new(center2, radius),
); );
g.draw_arrow( g.draw_arrow(
color, color,
0.1, Distance::meters(0.1),
&Line::new( &Line::new(
center2 center2.project_away(radius, lane_line.angle().rotate_degs(90.0)),
.project_away(radius.inner_meters(), lane_line.angle().rotate_degs(90.0)), center2.project_away(radius, lane_line.angle().rotate_degs(-90.0)),
center2
.project_away(radius.inner_meters(), lane_line.angle().rotate_degs(-90.0)),
), ),
); );
} }

View File

@ -81,8 +81,8 @@ impl DrawLane {
PARCEL_BOUNDARY_THICKNESS / 2.0, PARCEL_BOUNDARY_THICKNESS / 2.0,
&l, &l,
); );
g.draw_circle(circle_color, &Circle::new(l.pt1(), 0.4)); g.draw_circle(circle_color, &Circle::new(l.pt1(), Distance::meters(0.4)));
g.draw_circle(circle_color, &Circle::new(l.pt2(), 0.8)); g.draw_circle(circle_color, &Circle::new(l.pt2(), Distance::meters(0.8)));
} }
} }
} }
@ -122,14 +122,14 @@ impl Renderable for DrawLane {
} }
// TODO this always does it at pt1 // TODO this always does it at pt1
fn perp_line(l: Line, length: f64) -> Line { fn perp_line(l: Line, length: Distance) -> Line {
let pt1 = l.shift_right(length / 2.0).pt1(); let pt1 = l.shift_right(length / 2.0).pt1();
let pt2 = l.shift_left(length / 2.0).pt1(); let pt2 = l.shift_left(length / 2.0).pt1();
Line::new(pt1, pt2) Line::new(pt1, pt2)
} }
fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> { fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> {
let tile_every = Distance::meters(LANE_THICKNESS); let tile_every = LANE_THICKNESS;
let color = cs.get_def("sidewalk lines", Color::grey(0.7)); let color = cs.get_def("sidewalk lines", Color::grey(0.7));
let length = lane.length(); let length = lane.length();
@ -140,10 +140,10 @@ fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygo
while dist_along < length - tile_every { while dist_along < length - tile_every {
let (pt, angle) = lane.dist_along(dist_along); let (pt, angle) = lane.dist_along(dist_along);
// Reuse perp_line. Project away an arbitrary amount // Reuse perp_line. Project away an arbitrary amount
let pt2 = pt.project_away(1.0, angle); let pt2 = pt.project_away(Distance::meters(1.0), angle);
result.push(( result.push((
color, color,
perp_line(Line::new(pt, pt2), LANE_THICKNESS).make_polygons(0.25), perp_line(Line::new(pt, pt2), LANE_THICKNESS).make_polygons(Distance::meters(0.25)),
)); ));
dist_along += tile_every; dist_along += tile_every;
} }
@ -153,8 +153,7 @@ fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygo
fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> { fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> {
// meters, but the dims get annoying below to remove // meters, but the dims get annoying below to remove
// TODO make Pt2D natively understand meters, projecting away by an angle let leg_length = Distance::meters(1.0);
let leg_length = 1.0;
let color = cs.get_def("parking lines", Color::WHITE); let color = cs.get_def("parking lines", Color::WHITE);
let mut result = Vec::new(); let mut result = Vec::new();
@ -168,13 +167,22 @@ fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon
let t_pt = pt.project_away(LANE_THICKNESS * 0.4, perp_angle); let t_pt = pt.project_away(LANE_THICKNESS * 0.4, perp_angle);
// The perp leg // The perp leg
let p1 = t_pt.project_away(leg_length, perp_angle.opposite()); let p1 = t_pt.project_away(leg_length, perp_angle.opposite());
result.push((color, Line::new(t_pt, p1).make_polygons(0.25))); result.push((
color,
Line::new(t_pt, p1).make_polygons(Distance::meters(0.25)),
));
// Upper leg // Upper leg
let p2 = t_pt.project_away(leg_length, lane_angle); let p2 = t_pt.project_away(leg_length, lane_angle);
result.push((color, Line::new(t_pt, p2).make_polygons(0.25))); result.push((
color,
Line::new(t_pt, p2).make_polygons(Distance::meters(0.25)),
));
// Lower leg // Lower leg
let p3 = t_pt.project_away(leg_length, lane_angle.opposite()); let p3 = t_pt.project_away(leg_length, lane_angle.opposite());
result.push((color, Line::new(t_pt, p3).make_polygons(0.25))); result.push((
color,
Line::new(t_pt, p3).make_polygons(Distance::meters(0.25)),
));
} }
} }
@ -199,7 +207,7 @@ fn calculate_driving_lines(lane: &Lane, parent: &Road, cs: &ColorScheme) -> Vec<
.slice(dash_separation, lane_edge_pts.length() - dash_separation) .slice(dash_separation, lane_edge_pts.length() - dash_separation)
.unwrap() .unwrap()
.0 .0
.dashed_polygons(0.25, dash_len, dash_separation); .dashed_polygons(Distance::meters(0.25), dash_len, dash_separation);
polygons polygons
.into_iter() .into_iter()
.map(|p| (cs.get_def("dashed lane line", Color::WHITE), p)) .map(|p| (cs.get_def("dashed lane line", Color::WHITE), p))
@ -220,7 +228,7 @@ fn calculate_stop_sign_line(
let (pt1, angle) = lane.safe_dist_along(lane.length() - Distance::meters(1.0))?; let (pt1, angle) = lane.safe_dist_along(lane.length() - Distance::meters(1.0))?;
// Reuse perp_line. Project away an arbitrary amount // Reuse perp_line. Project away an arbitrary amount
let pt2 = pt1.project_away(1.0, angle); let pt2 = pt1.project_away(Distance::meters(1.0), angle);
// Don't clobber the yellow line. // Don't clobber the yellow line.
let line = if road.is_canonical_lane(lane.id) { let line = if road.is_canonical_lane(lane.id) {
perp_line( perp_line(
@ -233,7 +241,7 @@ fn calculate_stop_sign_line(
Some(( Some((
cs.get_def("stop line for lane", Color::RED), cs.get_def("stop line for lane", Color::RED),
line.make_polygons(0.45), line.make_polygons(Distance::meters(0.45)),
)) ))
} }
@ -266,7 +274,7 @@ fn turn_markings(turn: &Turn, map: &Map, cs: &ColorScheme) -> Vec<(Color, Polygo
.slice(len - Distance::meters(7.0), len - Distance::meters(5.0)) .slice(len - Distance::meters(7.0), len - Distance::meters(5.0))
.unwrap() .unwrap()
.0; .0;
let base_polygon = common_base.make_polygons(0.1); let base_polygon = common_base.make_polygons(Distance::meters(0.1));
let turn_line = Line::new( let turn_line = Line::new(
common_base.last_pt(), common_base.last_pt(),
common_base common_base
@ -276,6 +284,11 @@ fn turn_markings(turn: &Turn, map: &Map, cs: &ColorScheme) -> Vec<(Color, Polygo
let color = cs.get_def("turn restrictions on lane", Color::WHITE); let color = cs.get_def("turn restrictions on lane", Color::WHITE);
let mut result = vec![(color, base_polygon)]; let mut result = vec![(color, base_polygon)];
result.extend(turn_line.make_arrow(0.05).into_iter().map(|p| (color, p))); result.extend(
turn_line
.make_arrow(Distance::meters(0.05))
.into_iter()
.map(|p| (color, p)),
);
result result
} }

View File

@ -22,21 +22,20 @@ pub use crate::render::map::{DrawMap, RenderOrder};
pub use crate::render::pedestrian::DrawPedestrian; pub use crate::render::pedestrian::DrawPedestrian;
pub use crate::render::turn::{DrawCrosswalk, DrawTurn}; pub use crate::render::turn::{DrawCrosswalk, DrawTurn};
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Bounds, Pt2D}; use geom::{Bounds, Distance, Pt2D};
use map_model::Map; use map_model::Map;
use sim::{DrawCarInput, VehicleType}; use sim::{DrawCarInput, VehicleType};
use std::f64; use std::f64;
// These are all in meters const PARCEL_BOUNDARY_THICKNESS: Distance = Distance::const_meters(0.5);
const PARCEL_BOUNDARY_THICKNESS: f64 = 0.5; const EXTRA_SHAPE_THICKNESS: Distance = Distance::const_meters(1.0);
const EXTRA_SHAPE_THICKNESS: f64 = 1.0; const EXTRA_SHAPE_POINT_RADIUS: Distance = Distance::const_meters(1.0);
const EXTRA_SHAPE_POINT_RADIUS: f64 = 1.0;
const BIG_ARROW_THICKNESS: f64 = 0.5; const BIG_ARROW_THICKNESS: Distance = Distance::const_meters(0.5);
const TURN_ICON_ARROW_THICKNESS: f64 = 0.15; const TURN_ICON_ARROW_THICKNESS: Distance = Distance::const_meters(0.15);
const TURN_ICON_ARROW_LENGTH: f64 = 2.0; const TURN_ICON_ARROW_LENGTH: Distance = Distance::const_meters(2.0);
pub const CROSSWALK_LINE_THICKNESS: f64 = 0.25; pub const CROSSWALK_LINE_THICKNESS: Distance = Distance::const_meters(0.25);
pub const MIN_ZOOM_FOR_MARKINGS: f64 = 5.0; pub const MIN_ZOOM_FOR_MARKINGS: f64 = 5.0;

View File

@ -1,11 +1,11 @@
use crate::objects::{Ctx, ID}; use crate::objects::{Ctx, ID};
use crate::render::{RenderOptions, Renderable}; use crate::render::{RenderOptions, Renderable};
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Bounds, Circle, Line, Pt2D}; use geom::{Bounds, Circle, Distance, Line, Pt2D};
use map_model::Map; use map_model::Map;
use sim::{DrawPedestrianInput, PedestrianID}; use sim::{DrawPedestrianInput, PedestrianID};
const RADIUS: f64 = 1.0; const RADIUS: Distance = Distance::const_meters(1.0);
pub struct DrawPedestrian { pub struct DrawPedestrian {
pub id: PedestrianID, pub id: PedestrianID,
@ -59,7 +59,7 @@ impl Renderable for DrawPedestrian {
if let Some(ref a) = self.turn_arrow { if let Some(ref a) = self.turn_arrow {
g.draw_arrow( g.draw_arrow(
ctx.cs.get_def("pedestrian turn arrow", Color::CYAN), ctx.cs.get_def("pedestrian turn arrow", Color::CYAN),
0.25, Distance::meters(0.25),
a, a,
); );
} }

View File

@ -6,7 +6,6 @@ use crate::render::{
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Bounds, Circle, Distance, Line, Polygon, Pt2D}; use geom::{Bounds, Circle, Distance, Line, Polygon, Pt2D};
use map_model::{Map, Turn, TurnID, LANE_THICKNESS}; use map_model::{Map, Turn, TurnID, LANE_THICKNESS};
use std::f64;
#[derive(Debug)] #[derive(Debug)]
pub struct DrawTurn { pub struct DrawTurn {
@ -22,9 +21,9 @@ impl DrawTurn {
let end_line = map.get_l(turn.id.src).end_line(turn.id.parent); let end_line = map.get_l(turn.id.src).end_line(turn.id.parent);
// Start the distance from the intersection // Start the distance from the intersection
let icon_center = end_line.reverse().unbounded_dist_along(Distance::meters( let icon_center = end_line
(offset_along_lane + 0.5) * TURN_ICON_ARROW_LENGTH, .reverse()
)); .unbounded_dist_along(TURN_ICON_ARROW_LENGTH * (offset_along_lane + 0.5));
let icon_circle = Circle::new(icon_center, TURN_ICON_ARROW_LENGTH / 2.0); let icon_circle = Circle::new(icon_center, TURN_ICON_ARROW_LENGTH / 2.0);
@ -43,10 +42,10 @@ impl DrawTurn {
// TODO This is hiding a real problem... some composite turns probably need to have their // TODO This is hiding a real problem... some composite turns probably need to have their
// geometry simplified a bit. // geometry simplified a bit.
if let Some(pl) = t.geom.without_last_line() { if let Some(pl) = t.geom.without_last_line() {
g.draw_polygon(color, &pl.make_polygons(2.0 * BIG_ARROW_THICKNESS)); g.draw_polygon(color, &pl.make_polygons(BIG_ARROW_THICKNESS * 2.0));
} }
// And a cap on the arrow // And a cap on the arrow
g.draw_arrow(color, 2.0 * BIG_ARROW_THICKNESS, &t.geom.last_line()); g.draw_arrow(color, BIG_ARROW_THICKNESS * 2.0, &t.geom.last_line());
} }
pub fn draw_dashed(turn: &Turn, g: &mut GfxCtx, color: Color) { pub fn draw_dashed(turn: &Turn, g: &mut GfxCtx, color: Color) {
@ -118,8 +117,8 @@ impl DrawCrosswalk {
// Start at least LANE_THICKNESS out to not hit sidewalk corners. Also account for // Start at least LANE_THICKNESS out to not hit sidewalk corners. Also account for
// the thickness of the crosswalk line itself. Center the lines inside these two // the thickness of the crosswalk line itself. Center the lines inside these two
// boundaries. // boundaries.
let boundary = Distance::meters(LANE_THICKNESS + CROSSWALK_LINE_THICKNESS); let boundary = LANE_THICKNESS + CROSSWALK_LINE_THICKNESS;
let tile_every = Distance::meters(0.6 * LANE_THICKNESS); let tile_every = LANE_THICKNESS * 0.6;
let line = { let line = {
// The middle line in the crosswalk geometry is the main crossing line. // The middle line in the crosswalk geometry is the main crossing line.
let pts = turn.geom.points(); let pts = turn.geom.points();
@ -136,7 +135,7 @@ impl DrawCrosswalk {
for _ in 0..=num_markings { for _ in 0..=num_markings {
let pt1 = line.dist_along(dist_along); let pt1 = line.dist_along(dist_along);
// Reuse perp_line. Project away an arbitrary amount // Reuse perp_line. Project away an arbitrary amount
let pt2 = pt1.project_away(1.0, turn.angle()); let pt2 = pt1.project_away(Distance::meters(1.0), turn.angle());
draw.push( draw.push(
perp_line(Line::new(pt1, pt2), LANE_THICKNESS) perp_line(Line::new(pt1, pt2), LANE_THICKNESS)
.make_polygons(CROSSWALK_LINE_THICKNESS), .make_polygons(CROSSWALK_LINE_THICKNESS),
@ -154,7 +153,7 @@ impl DrawCrosswalk {
} }
// TODO copied from DrawLane // TODO copied from DrawLane
fn perp_line(l: Line, length: f64) -> Line { fn perp_line(l: Line, length: Distance) -> Line {
let pt1 = l.shift_right(length / 2.0).pt1(); let pt1 = l.shift_right(length / 2.0).pt1();
let pt2 = l.shift_left(length / 2.0).pt1(); let pt2 = l.shift_left(length / 2.0).pt1();
Line::new(pt1, pt2) Line::new(pt1, pt2)

View File

@ -1,5 +1,5 @@
use crate::{Canvas, Color, ScreenPt}; use crate::{Canvas, Color, ScreenPt};
use geom::{Circle, Line, Polygon, Pt2D}; use geom::{Circle, Distance, Line, Polygon, Pt2D};
use glium::{implement_vertex, uniform, Surface}; use glium::{implement_vertex, uniform, Surface};
const TRIANGLES_PER_CIRCLE: usize = 60; const TRIANGLES_PER_CIRCLE: usize = 60;
@ -100,11 +100,11 @@ impl<'a> GfxCtx<'a> {
// Use graphics::Line internally for now, but make it easy to switch to something else by // Use graphics::Line internally for now, but make it easy to switch to something else by
// picking this API now. // picking this API now.
pub fn draw_line(&mut self, color: Color, thickness: f64, line: &Line) { pub fn draw_line(&mut self, color: Color, thickness: Distance, line: &Line) {
self.draw_polygon(color, &line.make_polygons(thickness)); self.draw_polygon(color, &line.make_polygons(thickness));
} }
pub fn draw_rounded_line(&mut self, color: Color, thickness: f64, line: &Line) { pub fn draw_rounded_line(&mut self, color: Color, thickness: Distance, line: &Line) {
self.draw_polygon_batch(vec![ self.draw_polygon_batch(vec![
(color, &line.make_polygons(thickness)), (color, &line.make_polygons(thickness)),
( (
@ -118,7 +118,7 @@ impl<'a> GfxCtx<'a> {
]); ]);
} }
pub fn draw_arrow(&mut self, color: Color, thickness: f64, line: &Line) { pub fn draw_arrow(&mut self, color: Color, thickness: Distance, line: &Line) {
let polygons = line.make_arrow(thickness); let polygons = line.make_arrow(thickness);
self.draw_polygon_batch(polygons.iter().map(|poly| (color, poly)).collect()); self.draw_polygon_batch(polygons.iter().map(|poly| (color, poly)).collect());
} }

View File

@ -1,30 +1,30 @@
use crate::{Angle, Bounds, Polygon, Pt2D}; use crate::{Angle, Bounds, Distance, Polygon, Pt2D};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::fmt; use std::fmt;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct Circle { pub struct Circle {
pub center: Pt2D, pub center: Pt2D,
pub radius: f64, pub radius: Distance,
} }
impl Circle { impl Circle {
pub fn new(center: Pt2D, radius: f64) -> Circle { pub fn new(center: Pt2D, radius: Distance) -> Circle {
Circle { center, radius } Circle { center, radius }
} }
pub fn contains_pt(&self, pt: Pt2D) -> bool { pub fn contains_pt(&self, pt: Pt2D) -> bool {
// avoid sqrt by squaring radius instead // avoid sqrt by squaring radius instead
(pt.x() - self.center.x()).powi(2) + (pt.y() - self.center.y()).powi(2) (pt.x() - self.center.x()).powi(2) + (pt.y() - self.center.y()).powi(2)
< self.radius.powi(2) < self.radius.inner_meters().powi(2)
} }
pub fn get_bounds(&self) -> Bounds { pub fn get_bounds(&self) -> Bounds {
Bounds { Bounds {
min_x: self.center.x() - self.radius, min_x: self.center.x() - self.radius.inner_meters(),
max_x: self.center.x() + self.radius, max_x: self.center.x() + self.radius.inner_meters(),
min_y: self.center.y() - self.radius, min_y: self.center.y() - self.radius.inner_meters(),
max_y: self.center.y() + self.radius, max_y: self.center.y() + self.radius.inner_meters(),
} }
} }

View File

@ -36,15 +36,15 @@ impl Line {
PolyLine::new(self.points()) PolyLine::new(self.points())
} }
pub fn make_polygons(&self, thickness: f64) -> Polygon { pub fn make_polygons(&self, thickness: Distance) -> Polygon {
self.to_polyline().make_polygons(thickness) self.to_polyline().make_polygons(thickness)
} }
// TODO One polygon, please :) // TODO One polygon, please :)
pub fn make_arrow(&self, thickness: f64) -> Vec<Polygon> { pub fn make_arrow(&self, thickness: Distance) -> Vec<Polygon> {
let head_size = 2.0 * thickness; let head_size = thickness * 2.0;
let angle = self.angle(); let angle = self.angle();
let triangle_height = Distance::meters((head_size / 2.0).sqrt()); let triangle_height = (head_size / 2.0).sqrt();
vec![ vec![
Polygon::new(&vec![ Polygon::new(&vec![
//self.pt2(), //self.pt2(),
@ -107,8 +107,8 @@ impl Line {
} }
} }
pub fn shift_right(&self, width: f64) -> Line { pub fn shift_right(&self, width: Distance) -> Line {
assert!(width >= 0.0); assert!(width >= Distance::ZERO);
let angle = self.angle().rotate_degs(90.0); let angle = self.angle().rotate_degs(90.0);
Line( Line(
self.pt1().project_away(width, angle), self.pt1().project_away(width, angle),
@ -116,8 +116,8 @@ impl Line {
) )
} }
pub fn shift_left(&self, width: f64) -> Line { pub fn shift_left(&self, width: Distance) -> Line {
assert!(width >= 0.0); assert!(width >= Distance::ZERO);
let angle = self.angle().rotate_degs(-90.0); let angle = self.angle().rotate_degs(-90.0);
Line( Line(
self.pt1().project_away(width, angle), self.pt1().project_away(width, angle),
@ -125,8 +125,8 @@ impl Line {
) )
} }
pub(crate) fn shift_either_direction(&self, width: f64) -> Line { pub(crate) fn shift_either_direction(&self, width: Distance) -> Line {
if width >= 0.0 { if width >= Distance::ZERO {
self.shift_right(width) self.shift_right(width)
} else { } else {
self.shift_left(-width) self.shift_left(-width)

View File

@ -3,7 +3,6 @@ use crate::{
}; };
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::collections::HashSet; use std::collections::HashSet;
use std::f64;
use std::fmt; use std::fmt;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -51,7 +50,7 @@ impl PolyLine {
PolyLine { pts, length } PolyLine { pts, length }
} }
pub fn make_polygons_for_boundary(pts: Vec<Pt2D>, thickness: f64) -> Polygon { pub fn make_polygons_for_boundary(pts: Vec<Pt2D>, thickness: Distance) -> Polygon {
// Points WILL repeat -- fast-path some stuff. // Points WILL repeat -- fast-path some stuff.
let pl = PolyLine { let pl = PolyLine {
pts, pts,
@ -222,18 +221,18 @@ impl PolyLine {
Some(PolyLine::new(self.pts[0..self.pts.len() - 1].to_vec())) Some(PolyLine::new(self.pts[0..self.pts.len() - 1].to_vec()))
} }
pub fn shift_right(&self, width: f64) -> PolyLine { pub fn shift_right(&self, width: Distance) -> PolyLine {
self.shift_with_corrections(width) self.shift_with_corrections(width)
} }
pub fn shift_left(&self, width: f64) -> PolyLine { pub fn shift_left(&self, width: Distance) -> PolyLine {
self.shift_with_corrections(-width) self.shift_with_corrections(-width)
} }
// Things to remember about shifting polylines: // Things to remember about shifting polylines:
// - the length before and after probably don't match up // - the length before and after probably don't match up
// - the number of points will match // - the number of points will match
fn shift_with_corrections(&self, width: f64) -> PolyLine { fn shift_with_corrections(&self, width: Distance) -> PolyLine {
let result = PolyLine::new(Pt2D::approx_dedupe( let result = PolyLine::new(Pt2D::approx_dedupe(
self.shift_with_sharp_angles(width), self.shift_with_sharp_angles(width),
EPSILON_DIST, EPSILON_DIST,
@ -247,7 +246,7 @@ impl PolyLine {
fixed fixed
} }
fn shift_with_sharp_angles(&self, width: f64) -> Vec<Pt2D> { fn shift_with_sharp_angles(&self, width: Distance) -> Vec<Pt2D> {
if self.pts.len() == 2 { if self.pts.len() == 2 {
let l = Line::new(self.pts[0], self.pts[1]).shift_either_direction(width); let l = Line::new(self.pts[0], self.pts[1]).shift_either_direction(width);
return vec![l.pt1(), l.pt2()]; return vec![l.pt1(), l.pt2()];
@ -290,7 +289,7 @@ impl PolyLine {
result result
} }
pub fn make_polygons(&self, width: f64) -> Polygon { pub fn make_polygons(&self, width: Distance) -> Polygon {
// TODO Don't use the angle corrections yet -- they seem to do weird things. // TODO Don't use the angle corrections yet -- they seem to do weird things.
let side1 = self.shift_with_sharp_angles(width / 2.0); let side1 = self.shift_with_sharp_angles(width / 2.0);
let side2 = self.shift_with_sharp_angles(-width / 2.0); let side2 = self.shift_with_sharp_angles(-width / 2.0);
@ -315,7 +314,7 @@ impl PolyLine {
pub fn dashed_polygons( pub fn dashed_polygons(
&self, &self,
width: f64, width: Distance,
dash_len: Distance, dash_len: Distance,
dash_separation: Distance, dash_separation: Distance,
) -> Vec<Polygon> { ) -> Vec<Polygon> {

View File

@ -86,12 +86,15 @@ impl Pt2D {
// TODO better name // TODO better name
// TODO Meters for dist? // TODO Meters for dist?
pub fn project_away(self, dist: f64, theta: Angle) -> Pt2D { pub fn project_away(self, dist: Distance, theta: Angle) -> Pt2D {
// If negative, caller should use theta.opposite() // If negative, caller should use theta.opposite()
assert!(dist >= 0.0); assert!(dist >= Distance::ZERO);
let (sin, cos) = theta.normalized_radians().sin_cos(); let (sin, cos) = theta.normalized_radians().sin_cos();
Pt2D::new(self.x() + dist * cos, self.y() + dist * sin) Pt2D::new(
self.x() + dist.inner_meters() * cos,
self.y() + dist.inner_meters() * sin,
)
} }
// TODO valid to do euclidean distance on world-space points that're formed from // TODO valid to do euclidean distance on world-space points that're formed from

View File

@ -35,6 +35,10 @@ impl Distance {
} }
} }
pub fn sqrt(self) -> Distance {
Distance::meters(self.0.sqrt())
}
// TODO Remove by making Distance itself Ord. // TODO Remove by making Distance itself Ord.
pub fn as_ordered(self) -> NotNan<f64> { pub fn as_ordered(self) -> NotNan<f64> {
NotNan::new(self.0).unwrap() NotNan::new(self.0).unwrap()
@ -75,6 +79,14 @@ impl ops::Sub for Distance {
} }
} }
impl ops::Neg for Distance {
type Output = Distance;
fn neg(self) -> Distance {
Distance::meters(-self.0)
}
}
impl ops::SubAssign for Distance { impl ops::SubAssign for Distance {
fn sub_assign(&mut self, other: Distance) { fn sub_assign(&mut self, other: Distance) {
*self = *self - other; *self = *self - other;

View File

@ -1,6 +1,6 @@
use aabb_quadtree::QuadTree; use aabb_quadtree::QuadTree;
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Bounds, Line, Polygon, Pt2D}; use geom::{Bounds, Distance, Line, Polygon, Pt2D};
use map_model::{Building, BuildingID, Map, Road, RoadID, LANE_THICKNESS}; use map_model::{Building, BuildingID, Map, Road, RoadID, LANE_THICKNESS};
// black // black
@ -12,7 +12,7 @@ const BUILDING: Color = Color::rgb_f(136.0 / 255.0, 30.0 / 255.0, 228.0 / 255.0)
// dark orange / red // dark orange / red
const PATH: Color = Color::rgb_f(247.0 / 255.0, 95.0 / 255.0, 28.0 / 255.0); const PATH: Color = Color::rgb_f(247.0 / 255.0, 95.0 / 255.0, 28.0 / 255.0);
const LINE_WIDTH: f64 = 1.0; const LINE_WIDTH: Distance = Distance::const_meters(1.0);
pub struct DrawMap { pub struct DrawMap {
roads: Vec<DrawRoad>, roads: Vec<DrawRoad>,

View File

@ -38,8 +38,9 @@ pub use crate::traffic_signals::{ControlTrafficSignal, Cycle};
pub use crate::traversable::{Position, Traversable}; pub use crate::traversable::{Position, Traversable};
pub use crate::turn::{Turn, TurnID, TurnPriority, TurnType}; pub use crate::turn::{Turn, TurnID, TurnPriority, TurnType};
use abstutil::Cloneable; use abstutil::Cloneable;
use geom::Distance;
pub const LANE_THICKNESS: f64 = 2.5; pub const LANE_THICKNESS: Distance = Distance::const_meters(2.5);
impl Cloneable for ControlTrafficSignal {} impl Cloneable for ControlTrafficSignal {}
impl Cloneable for IntersectionID {} impl Cloneable for IntersectionID {}

View File

@ -114,8 +114,11 @@ fn generalized_trim_back(
if let Some((hit, angle)) = use_pl1.intersection(&use_pl2) { if let Some((hit, angle)) = use_pl1.intersection(&use_pl2) {
// Find where the perpendicular hits the original road line // Find where the perpendicular hits the original road line
let perp = let perp = Line::new(
Line::new(hit, hit.project_away(1.0, angle.rotate_degs(90.0))).infinite(); hit,
hit.project_away(Distance::meters(1.0), angle.rotate_degs(90.0)),
)
.infinite();
// How could something perpendicular to a shifted polyline never hit the original // How could something perpendicular to a shifted polyline never hit the original
// polyline? // polyline?
let trim_to = road_center.intersection_infinite(&perp).unwrap(); let trim_to = road_center.intersection_infinite(&perp).unwrap();

View File

@ -5,7 +5,7 @@ mod merge;
use crate::raw_data::{StableIntersectionID, StableRoadID}; use crate::raw_data::{StableIntersectionID, StableRoadID};
use crate::{raw_data, MapEdits, LANE_THICKNESS}; use crate::{raw_data, MapEdits, LANE_THICKNESS};
use abstutil::Timer; use abstutil::Timer;
use geom::{GPSBounds, PolyLine, Pt2D}; use geom::{Distance, GPSBounds, PolyLine, Pt2D};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
@ -25,8 +25,8 @@ pub struct Road {
pub dst_i: StableIntersectionID, pub dst_i: StableIntersectionID,
pub original_center_pts: PolyLine, pub original_center_pts: PolyLine,
pub trimmed_center_pts: PolyLine, pub trimmed_center_pts: PolyLine,
pub fwd_width: f64, pub fwd_width: Distance,
pub back_width: f64, pub back_width: Distance,
pub lane_specs: Vec<lane_specs::LaneSpec>, pub lane_specs: Vec<lane_specs::LaneSpec>,
} }
@ -90,8 +90,8 @@ impl InitialMap {
); );
let lane_specs = lane_specs::get_lane_specs(r, *stable_id, edits); let lane_specs = lane_specs::get_lane_specs(r, *stable_id, edits);
let mut fwd_width = 0.0; let mut fwd_width = Distance::ZERO;
let mut back_width = 0.0; let mut back_width = Distance::ZERO;
for l in &lane_specs { for l in &lane_specs {
if l.reverse_pts { if l.reverse_pts {
back_width += LANE_THICKNESS; back_width += LANE_THICKNESS;

View File

@ -482,5 +482,5 @@ fn validate(map: &Map, steps: &Vec<PathStep>) {
// Negate since BinaryHeap is a max-heap. // Negate since BinaryHeap is a max-heap.
fn dist_to_pri_queue(dist: Distance) -> NotNan<f64> { fn dist_to_pri_queue(dist: Distance) -> NotNan<f64> {
(dist * -1.0).as_ordered() -dist.as_ordered()
} }

View File

@ -1,5 +1,5 @@
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{Circle, PolyLine}; use geom::{Circle, Distance, PolyLine};
// TODO Don't just use ezgui constants in this crate, since we want the slight transparency by // TODO Don't just use ezgui constants in this crate, since we want the slight transparency by
// default. // default.
@ -11,11 +11,11 @@ pub const BLACK: Color = Color::BLACK.alpha(0.3);
pub const SOLID_BLACK: Color = Color::BLACK.alpha(0.9); pub const SOLID_BLACK: Color = Color::BLACK.alpha(0.9);
pub const YELLOW: Color = Color::YELLOW.alpha(0.8); pub const YELLOW: Color = Color::YELLOW.alpha(0.8);
pub fn draw_polyline(g: &mut GfxCtx, pl: &PolyLine, thickness: f64, color: Color) { pub fn draw_polyline(g: &mut GfxCtx, pl: &PolyLine, thickness: Distance, color: Color) {
for l in pl.lines() { for l in pl.lines() {
g.draw_line(color, thickness, &l); g.draw_line(color, thickness, &l);
} }
let radius = 0.5; let radius = Distance::meters(0.5);
let pts = pl.points(); let pts = pl.points();
assert!(pts.len() >= 2); assert!(pts.len() >= 2);
for pt in pts { for pt in pts {

View File

@ -1,13 +1,13 @@
use crate::common::{draw_polyline, SOLID_BLACK, YELLOW}; use crate::common::{draw_polyline, SOLID_BLACK, YELLOW};
use ezgui::{Color, GfxCtx}; use ezgui::{Color, GfxCtx};
use geom::{PolyLine, Pt2D}; use geom::{Distance, PolyLine, Pt2D};
// Copied from map_model; no need to have to rebuild that crate // Copied from map_model; no need to have to rebuild that crate
const LANE_THICKNESS: f64 = 2.5; const LANE_THICKNESS: Distance = Distance::const_meters(2.5);
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
pub fn run(g: &mut GfxCtx) { pub fn run(g: &mut GfxCtx) {
let thin = 0.25; let thin = Distance::meters(0.25);
let shift1_width = LANE_THICKNESS * 0.5; let shift1_width = LANE_THICKNESS * 0.5;
let shift2_width = LANE_THICKNESS * 1.5; let shift2_width = LANE_THICKNESS * 1.5;
@ -80,5 +80,5 @@ pub fn draw_lane(g: &mut GfxCtx, pl: &PolyLine, color: Color) {
g.draw_polygon(color, &pl.make_polygons(LANE_THICKNESS)); g.draw_polygon(color, &pl.make_polygons(LANE_THICKNESS));
// Debug the center points // Debug the center points
draw_polyline(g, pl, 0.25, SOLID_BLACK); draw_polyline(g, pl, Distance::meters(0.25), SOLID_BLACK);
} }

View File

@ -1,11 +1,11 @@
use crate::common::{draw_polyline, BLACK, RED}; use crate::common::{draw_polyline, BLACK, RED};
use ezgui::GfxCtx; use ezgui::GfxCtx;
use geom::{PolyLine, Pt2D}; use geom::{Distance, PolyLine, Pt2D};
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
pub fn run(g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) { pub fn run(g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) {
let thin = 1.0; let thin = Distance::meters(1.0);
let width = 50.0; let width = Distance::meters(50.0);
// TODO retain this as a regression test // TODO retain this as a regression test
let center_pts = PolyLine::new( let center_pts = PolyLine::new(

View File

@ -7,7 +7,6 @@ mod trim_polyline;
use ezgui::{Canvas, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, GUI}; use ezgui::{Canvas, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, GUI};
use geom::Pt2D; use geom::Pt2D;
use std::f64;
use std::process; use std::process;
pub struct UI { pub struct UI {

View File

@ -1,6 +1,6 @@
use crate::common::{draw_polyline, BLACK, BLUE, GREEN, RED}; use crate::common::{draw_polyline, BLACK, BLUE, GREEN, RED};
use ezgui::GfxCtx; use ezgui::GfxCtx;
use geom::{PolyLine, Pt2D}; use geom::{Distance, PolyLine, Pt2D};
pub fn run(p3_offset: (f64, f64), g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) { pub fn run(p3_offset: (f64, f64), g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) {
macro_rules! point { macro_rules! point {
@ -17,9 +17,9 @@ pub fn run(p3_offset: (f64, f64), g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String
}; };
}*/ }*/
let thin = 1.0; let thin = Distance::meters(1.0);
let thick = 5.0; let thick = Distance::meters(5.0);
let shift_away = 50.0; let shift_away = Distance::meters(50.0);
point!(p1, Pt2D::new(100.0, 100.0)); point!(p1, Pt2D::new(100.0, 100.0));
point!(p2, Pt2D::new(110.0, 200.0)); point!(p2, Pt2D::new(110.0, 200.0));

View File

@ -1,6 +1,6 @@
use crate::common::{draw_polyline, BLUE, GREEN, RED}; use crate::common::{draw_polyline, BLUE, GREEN, RED};
use ezgui::GfxCtx; use ezgui::GfxCtx;
use geom::{Circle, PolyLine, Pt2D}; use geom::{Circle, Distance, PolyLine, Pt2D};
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
pub fn run(g: &mut GfxCtx) { pub fn run(g: &mut GfxCtx) {
@ -20,12 +20,12 @@ pub fn run(g: &mut GfxCtx) {
let (hit, _) = vertical_pl.intersection(&horiz_pl).unwrap(); let (hit, _) = vertical_pl.intersection(&horiz_pl).unwrap();
if false { if false {
g.draw_circle(BLUE, &Circle::new(hit, 1.0)); g.draw_circle(BLUE, &Circle::new(hit, Distance::meters(1.0)));
} else { } else {
vertical_pl = vertical_pl.get_slice_ending_at(hit).unwrap(); vertical_pl = vertical_pl.get_slice_ending_at(hit).unwrap();
horiz_pl = horiz_pl.get_slice_ending_at(hit).unwrap(); horiz_pl = horiz_pl.get_slice_ending_at(hit).unwrap();
} }
draw_polyline(g, &vertical_pl, 0.25, RED); draw_polyline(g, &vertical_pl, Distance::meters(0.25), RED);
draw_polyline(g, &horiz_pl, 0.25, GREEN); draw_polyline(g, &horiz_pl, Distance::meters(0.25), GREEN);
} }

View File

@ -859,7 +859,7 @@ impl DrivingSimState {
1.0 - progress 1.0 - progress
}; };
// TODO we're assuming the parking lane is to the right of us! // TODO we're assuming the parking lane is to the right of us!
base_body.shift_right(project_away_ratio * LANE_THICKNESS) base_body.shift_right(LANE_THICKNESS * project_away_ratio)
} else { } else {
base_body base_body
}; };

View File

@ -142,7 +142,7 @@ impl Vehicle {
speed: Speed, speed: Speed,
dist: Distance, dist: Distance,
) -> Result<Acceleration, Error> { ) -> Result<Acceleration, Error> {
if dist < EPSILON_DIST * -1.0 { if dist < -EPSILON_DIST {
return Err(Error::new(format!( return Err(Error::new(format!(
"{} called accel_to_stop_in_dist({}, {}) with negative distance", "{} called accel_to_stop_in_dist({}, {}) with negative distance",
self.id, speed, dist self.id, speed, dist

View File

@ -3,7 +3,7 @@ mod model;
use crate::model::{BuildingID, Direction, Model, ID}; use crate::model::{BuildingID, Direction, Model, ID};
use aabb_quadtree::QuadTree; use aabb_quadtree::QuadTree;
use ezgui::{Canvas, Color, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, Wizard, GUI}; use ezgui::{Canvas, Color, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, Wizard, GUI};
use geom::Line; use geom::{Distance, Line};
use map_model::raw_data::{StableIntersectionID, StableRoadID}; use map_model::raw_data::{StableIntersectionID, StableRoadID};
use std::{env, process}; use std::{env, process};
@ -210,7 +210,7 @@ impl GUI<Text> for UI {
if let Some(cursor) = self.canvas.get_cursor_in_map_space() { if let Some(cursor) = self.canvas.get_cursor_in_map_space() {
g.draw_line( g.draw_line(
Color::GREEN, Color::GREEN,
5.0, Distance::meters(5.0),
&Line::new(self.model.get_i_center(i1), cursor), &Line::new(self.model.get_i_center(i1), cursor),
); );
} }

View File

@ -8,9 +8,9 @@ use serde_derive::{Deserialize, Serialize};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::mem; use std::mem;
const INTERSECTION_RADIUS: f64 = 5.0; const INTERSECTION_RADIUS: Distance = Distance::const_meters(5.0);
const BUILDING_LENGTH: f64 = 30.0; const BUILDING_LENGTH: f64 = 30.0;
const CENTER_LINE_THICKNESS: f64 = 0.5; const CENTER_LINE_THICKNESS: Distance = Distance::const_meters(0.5);
const HIGHLIGHT_COLOR: Color = Color::CYAN; const HIGHLIGHT_COLOR: Color = Color::CYAN;
@ -99,7 +99,7 @@ impl Road {
for (idx, lt) in self.lanes.fwd.iter().enumerate() { for (idx, lt) in self.lanes.fwd.iter().enumerate() {
let polygon = base let polygon = base
.shift_right(((idx as f64) + 0.5) * LANE_THICKNESS) .shift_right(LANE_THICKNESS * ((idx as f64) + 0.5))
.make_polygons(LANE_THICKNESS); .make_polygons(LANE_THICKNESS);
g.draw_polygon( g.draw_polygon(
if highlight_fwd { if highlight_fwd {
@ -112,7 +112,7 @@ impl Road {
} }
for (idx, lt) in self.lanes.back.iter().enumerate() { for (idx, lt) in self.lanes.back.iter().enumerate() {
let polygon = base let polygon = base
.shift_left(((idx as f64) + 0.5) * LANE_THICKNESS) .shift_left(LANE_THICKNESS * ((idx as f64) + 0.5))
.make_polygons(LANE_THICKNESS); .make_polygons(LANE_THICKNESS);
g.draw_polygon( g.draw_polygon(
if highlight_back { if highlight_back {

View File

@ -80,7 +80,7 @@ fn test_accel_to_stop_in_dist(vehicle: Vehicle, orig_dist_left: Distance, orig_s
speed = new_speed; speed = new_speed;
dist_left -= dist_covered; dist_left -= dist_covered;
if dist_left < EPSILON_DIST * -1.0 { if dist_left < -EPSILON_DIST {
println!(" Result: speed {}, dist_left {}", speed, dist_left); println!(" Result: speed {}, dist_left {}", speed, dist_left);
panic!("We overshot too much!"); panic!("We overshot too much!");
} }