mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 00:12:55 +03:00
switching to new units in map_model
This commit is contained in:
parent
976369e7e8
commit
133ec037c9
@ -116,7 +116,7 @@ impl GPSBounds {
|
||||
.gps_dist_meters(LonLat::new(self.max_lon, self.min_lat));
|
||||
let height = LonLat::new(self.min_lon, self.min_lat)
|
||||
.gps_dist_meters(LonLat::new(self.min_lon, self.max_lat));
|
||||
Pt2D::new(width.inner(), height.inner())
|
||||
Pt2D::new(width.inner_meters(), height.inner_meters())
|
||||
}
|
||||
|
||||
pub fn to_bounds(&self) -> Bounds {
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
Angle, Bounds, Distance, HashablePt2D, InfiniteLine, Line, Polygon, Pt2D, EPSILON_DIST,
|
||||
};
|
||||
use ordered_float::NotNan;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use std::f64;
|
||||
@ -357,13 +356,10 @@ impl PolyLine {
|
||||
}
|
||||
|
||||
hits.sort_by_key(|(pt, _)| {
|
||||
NotNan::new(
|
||||
self.get_slice_ending_at(*pt)
|
||||
.map(|pl| pl.length())
|
||||
.unwrap_or(Distance::ZERO)
|
||||
.inner(),
|
||||
)
|
||||
.unwrap()
|
||||
.as_ordered()
|
||||
});
|
||||
if !hits.is_empty() {
|
||||
return Some(hits[0]);
|
||||
|
@ -1,3 +1,4 @@
|
||||
use ordered_float::NotNan;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fmt, ops};
|
||||
|
||||
@ -29,8 +30,13 @@ impl Distance {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Only used within this crate for NotNan construction and GPS->Pt2D.
|
||||
pub(crate) fn inner(self) -> f64 {
|
||||
// TODO Remove by making Distance itself Ord.
|
||||
pub fn as_ordered(self) -> NotNan<f64> {
|
||||
NotNan::new(self.0).unwrap()
|
||||
}
|
||||
|
||||
// TODO Remove if possible.
|
||||
pub fn inner_meters(self) -> f64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@ -70,6 +76,14 @@ impl ops::SubAssign for Distance {
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<f64> for Distance {
|
||||
type Output = Distance;
|
||||
|
||||
fn mul(self, scalar: f64) -> Distance {
|
||||
Distance::meters(self.0 * scalar)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Div<Distance> for Distance {
|
||||
type Output = f64;
|
||||
|
||||
@ -84,11 +98,11 @@ impl ops::Div<Distance> for Distance {
|
||||
impl ops::Div<f64> for Distance {
|
||||
type Output = Distance;
|
||||
|
||||
fn div(self, other: f64) -> Distance {
|
||||
if other == 0.0 {
|
||||
panic!("Can't divide {} / {}", self, other);
|
||||
fn div(self, scalar: f64) -> Distance {
|
||||
if scalar == 0.0 {
|
||||
panic!("Can't divide {} / {}", self, scalar);
|
||||
}
|
||||
Distance::meters(self.0 / other)
|
||||
Distance::meters(self.0 / scalar)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +118,10 @@ impl Duration {
|
||||
|
||||
Duration(value)
|
||||
}
|
||||
|
||||
pub const fn const_seconds(value: f64) -> Duration {
|
||||
Duration(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Duration {
|
||||
@ -112,6 +130,33 @@ impl fmt::Display for Duration {
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn sub(self, other: Duration) -> Duration {
|
||||
Duration::seconds(self.0 - other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<f64> for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn mul(self, other: f64) -> Duration {
|
||||
Duration::seconds(self.0 * other)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Div<Duration> for Duration {
|
||||
type Output = f64;
|
||||
|
||||
fn div(self, other: Duration) -> f64 {
|
||||
if other.0 == 0.0 {
|
||||
panic!("Can't divide {} / {}", self, other);
|
||||
}
|
||||
self.0 / other.0
|
||||
}
|
||||
}
|
||||
|
||||
// In meters per second. Can be negative.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct Speed(f64);
|
||||
@ -124,6 +169,10 @@ impl Speed {
|
||||
|
||||
Speed(value)
|
||||
}
|
||||
|
||||
pub fn miles_per_hour(value: f64) -> Speed {
|
||||
Speed::meters_per_second(0.44704 * value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Speed {
|
||||
|
@ -7,7 +7,6 @@ edition = "2018"
|
||||
[dependencies]
|
||||
aabb-quadtree = "0.1.0"
|
||||
abstutil = { path = "../abstutil" }
|
||||
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
|
||||
geo = "0.11.0"
|
||||
geom = { path = "../geom" }
|
||||
gtfs = { path = "../gtfs" }
|
||||
|
@ -1,10 +1,8 @@
|
||||
use aabb_quadtree::geom::{Point, Rect};
|
||||
use aabb_quadtree::QuadTree;
|
||||
use dimensioned::si;
|
||||
use geo;
|
||||
use geo::prelude::{ClosestPoint, EuclideanDistance};
|
||||
use geom::{Bounds, PolyLine, Pt2D};
|
||||
use ordered_float::NotNan;
|
||||
use geom::{Bounds, Distance, PolyLine, Pt2D};
|
||||
use std::collections::HashMap;
|
||||
|
||||
// TODO Refactor and generalize all of this...
|
||||
@ -33,16 +31,16 @@ where
|
||||
}
|
||||
|
||||
// Finds the closest point on the existing geometry to the query pt.
|
||||
pub fn closest_pt(&self, query_pt: Pt2D, max_dist_away: si::Meter<f64>) -> Option<(K, Pt2D)> {
|
||||
pub fn closest_pt(&self, query_pt: Pt2D, max_dist_away: Distance) -> Option<(K, Pt2D)> {
|
||||
let query_geom = geo::Point::new(query_pt.x(), query_pt.y());
|
||||
let query_bbox = Rect {
|
||||
top_left: Point {
|
||||
x: (query_pt.x() - max_dist_away.value_unsafe) as f32,
|
||||
y: (query_pt.y() - max_dist_away.value_unsafe) as f32,
|
||||
x: (query_pt.x() - max_dist_away.inner_meters()) as f32,
|
||||
y: (query_pt.y() - max_dist_away.inner_meters()) as f32,
|
||||
},
|
||||
bottom_right: Point {
|
||||
x: (query_pt.x() + max_dist_away.value_unsafe) as f32,
|
||||
y: (query_pt.y() + max_dist_away.value_unsafe) as f32,
|
||||
x: (query_pt.x() + max_dist_away.inner_meters()) as f32,
|
||||
y: (query_pt.y() + max_dist_away.inner_meters()) as f32,
|
||||
},
|
||||
};
|
||||
|
||||
@ -53,9 +51,9 @@ where
|
||||
if let geo::Closest::SinglePoint(pt) =
|
||||
self.geometries[&key].closest_point(&query_geom)
|
||||
{
|
||||
let dist = pt.euclidean_distance(&query_geom);
|
||||
if dist * si::M <= max_dist_away {
|
||||
Some((key, pt, NotNan::new(dist).unwrap()))
|
||||
let dist = Distance::meters(pt.euclidean_distance(&query_geom));
|
||||
if dist <= max_dist_away {
|
||||
Some((key, pt, dist.as_ordered()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{raw_data, LaneID, LaneType, Map, RoadID, TurnID};
|
||||
use abstutil;
|
||||
use dimensioned::si;
|
||||
use geom::{Polygon, Pt2D};
|
||||
use geom::{Distance, Polygon, Pt2D};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
@ -30,7 +29,7 @@ pub struct Intersection {
|
||||
// This needs to be in clockwise orientation, or later rendering of sidewalk corners breaks.
|
||||
pub polygon: Polygon,
|
||||
pub turns: Vec<TurnID>,
|
||||
pub elevation: si::Meter<f64>,
|
||||
pub elevation: Distance,
|
||||
|
||||
pub intersection_type: IntersectionType,
|
||||
pub label: Option<String>,
|
||||
|
@ -1,17 +1,11 @@
|
||||
use crate::{BuildingID, BusStopID, IntersectionID, RoadID};
|
||||
use abstutil;
|
||||
use dimensioned::si;
|
||||
use geom::{Angle, Line, PolyLine, Pt2D};
|
||||
use geom::{Angle, Distance, Line, PolyLine, Pt2D};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
|
||||
pub const PARKING_SPOT_LENGTH: si::Meter<f64> = si::Meter {
|
||||
// Bit longer than the longest car.
|
||||
value_unsafe: 8.0,
|
||||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
pub const PARKING_SPOT_LENGTH: Distance = Distance::const_meters(8.0);
|
||||
|
||||
// TODO reconsider pub usize. maybe outside world shouldnt know.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
@ -83,21 +77,21 @@ impl Lane {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dist_along(&self, dist_along: si::Meter<f64>) -> (Pt2D, Angle) {
|
||||
pub fn dist_along(&self, dist_along: Distance) -> (Pt2D, Angle) {
|
||||
self.lane_center_pts.dist_along(dist_along)
|
||||
}
|
||||
|
||||
pub fn safe_dist_along(&self, dist_along: si::Meter<f64>) -> Option<(Pt2D, Angle)> {
|
||||
pub fn safe_dist_along(&self, dist_along: Distance) -> Option<(Pt2D, Angle)> {
|
||||
self.lane_center_pts.safe_dist_along(dist_along)
|
||||
}
|
||||
|
||||
pub fn dist_along_of_point(&self, pt: Pt2D) -> Option<si::Meter<f64>> {
|
||||
pub fn dist_along_of_point(&self, pt: Pt2D) -> Option<Distance> {
|
||||
self.lane_center_pts
|
||||
.dist_along_of_point(pt)
|
||||
.map(|(dist, _)| dist)
|
||||
}
|
||||
|
||||
pub fn length(&self) -> si::Meter<f64> {
|
||||
pub fn length(&self) -> Distance {
|
||||
self.lane_center_pts.length()
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::make::sidewalk_finder::find_sidewalk_points;
|
||||
use crate::{raw_data, Building, BuildingID, FrontPath, Lane};
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, Line, Pt2D};
|
||||
use geom::{Bounds, Distance, GPSBounds, HashablePt2D, Line, Pt2D};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub fn make_all_buildings(
|
||||
@ -34,7 +33,7 @@ pub fn make_all_buildings(
|
||||
}
|
||||
|
||||
// Skip buildings that're too far away from their sidewalk
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, 100.0 * si::M, timer);
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, Distance::meters(100.0), timer);
|
||||
|
||||
timer.start_iter("create building front paths", pts_per_bldg.len());
|
||||
for (idx, points) in pts_per_bldg.into_iter().enumerate() {
|
||||
|
@ -4,11 +4,9 @@ use crate::{
|
||||
Position,
|
||||
};
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, Pt2D};
|
||||
use geom::{Bounds, Distance, GPSBounds, HashablePt2D, Pt2D};
|
||||
use gtfs;
|
||||
use multimap::MultiMap;
|
||||
use ordered_float::NotNan;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::iter;
|
||||
|
||||
@ -32,9 +30,15 @@ pub fn make_bus_stops(
|
||||
}
|
||||
}
|
||||
|
||||
let mut stops_per_sidewalk: MultiMap<LaneID, (si::Meter<f64>, HashablePt2D)> = MultiMap::new();
|
||||
for (pt, pos) in
|
||||
find_sidewalk_points(bounds, bus_stop_pts, map.all_lanes(), 10.0 * si::M, timer).into_iter()
|
||||
let mut stops_per_sidewalk: MultiMap<LaneID, (Distance, HashablePt2D)> = MultiMap::new();
|
||||
for (pt, pos) in find_sidewalk_points(
|
||||
bounds,
|
||||
bus_stop_pts,
|
||||
map.all_lanes(),
|
||||
Distance::meters(10.0),
|
||||
timer,
|
||||
)
|
||||
.into_iter()
|
||||
{
|
||||
stops_per_sidewalk.insert(pos.lane(), (pos.dist_along(), pt));
|
||||
}
|
||||
@ -46,7 +50,7 @@ pub fn make_bus_stops(
|
||||
if let Ok(driving_lane) =
|
||||
road.find_closest_lane(*id, vec![LaneType::Driving, LaneType::Bus])
|
||||
{
|
||||
dists.sort_by_key(|(dist, _)| NotNan::new(dist.value_unsafe).unwrap());
|
||||
dists.sort_by_key(|(dist, _)| dist.as_ordered());
|
||||
for (idx, (dist_along, orig_pt)) in dists.iter().enumerate() {
|
||||
let stop_id = BusStopID { sidewalk: *id, idx };
|
||||
point_to_stop_id.insert(*orig_pt, stop_id);
|
||||
|
@ -4,7 +4,6 @@ use crate::{
|
||||
};
|
||||
use abstutil::Timer;
|
||||
use geom::{Bounds, GPSBounds, Polygon, Pt2D};
|
||||
use ordered_float::NotNan;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct HalfMap {
|
||||
@ -171,14 +170,11 @@ pub fn make_half_map(
|
||||
let mut bldgs = half_map.lanes[lane.0].building_paths.clone();
|
||||
bldgs.push(b.id);
|
||||
bldgs.sort_by_key(|b| {
|
||||
NotNan::new(
|
||||
half_map.buildings[b.0]
|
||||
.front_path
|
||||
.sidewalk
|
||||
.dist_along()
|
||||
.value_unsafe,
|
||||
)
|
||||
.unwrap()
|
||||
.as_ordered()
|
||||
});
|
||||
half_map.lanes[lane.0].building_paths = bldgs;
|
||||
}
|
||||
|
@ -1,15 +1,10 @@
|
||||
use crate::make::initial::{Intersection, Road};
|
||||
use crate::raw_data::{StableIntersectionID, StableRoadID};
|
||||
use abstutil::wraparound_get;
|
||||
use dimensioned::si;
|
||||
use geom::{Angle, HashablePt2D, Line, PolyLine, Pt2D};
|
||||
use geom::{Angle, Distance, HashablePt2D, Line, PolyLine, Pt2D};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::marker;
|
||||
|
||||
const DEGENERATE_INTERSECTION_HALF_LENGTH: si::Meter<f64> = si::Meter {
|
||||
value_unsafe: 5.0,
|
||||
_marker: marker::PhantomData,
|
||||
};
|
||||
const DEGENERATE_INTERSECTION_HALF_LENGTH: Distance = Distance::const_meters(5.0);
|
||||
|
||||
// The polygon should exist entirely within the thick bands around all original roads -- it just
|
||||
// carves up part of that space, doesn't reach past it.
|
||||
@ -86,7 +81,7 @@ fn generalized_trim_back(
|
||||
let mut shortest_center = if road_center.length() >= DEGENERATE_INTERSECTION_HALF_LENGTH {
|
||||
road_center
|
||||
.slice(
|
||||
0.0 * si::M,
|
||||
Distance::ZERO,
|
||||
road_center.length() - DEGENERATE_INTERSECTION_HALF_LENGTH,
|
||||
)
|
||||
.unwrap()
|
||||
@ -181,7 +176,7 @@ fn generalized_trim_back(
|
||||
}
|
||||
}
|
||||
endpoints.sort_by_key(|pt| HashablePt2D::from(*pt));
|
||||
endpoints = Pt2D::approx_dedupe(endpoints, 1.0 * si::M);
|
||||
endpoints = Pt2D::approx_dedupe(endpoints, Distance::meters(1.0));
|
||||
|
||||
let center = Pt2D::center(&endpoints);
|
||||
endpoints.sort_by_key(|pt| Line::new(center, *pt).angle().normalized_degrees() as i64);
|
||||
@ -217,7 +212,7 @@ fn deadend(
|
||||
r.trimmed_center_pts = r
|
||||
.trimmed_center_pts
|
||||
.slice(
|
||||
0.0 * si::M,
|
||||
Distance::ZERO,
|
||||
r.trimmed_center_pts.length() - DEGENERATE_INTERSECTION_HALF_LENGTH * 2.0,
|
||||
)
|
||||
.unwrap()
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::make::initial::{geometry, InitialMap};
|
||||
use crate::raw_data::StableRoadID;
|
||||
use abstutil::note;
|
||||
use dimensioned::si;
|
||||
use geom::Distance;
|
||||
|
||||
pub fn short_roads(map: &mut InitialMap) {
|
||||
if false {
|
||||
@ -29,7 +29,7 @@ pub fn short_roads(map: &mut InitialMap) {
|
||||
if let Some(r) = map
|
||||
.roads
|
||||
.values()
|
||||
.find(|r| r.trimmed_center_pts.length() < 15.0 * si::M)
|
||||
.find(|r| r.trimmed_center_pts.length() < Distance::meters(15.0))
|
||||
{
|
||||
merge(map, r.id);
|
||||
} else {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::make::sidewalk_finder::find_sidewalk_points;
|
||||
use crate::{raw_data, Lane, Parcel, ParcelID};
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, Pt2D};
|
||||
use geom::{Bounds, Distance, GPSBounds, HashablePt2D, Pt2D};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub fn make_all_parcels(
|
||||
@ -32,7 +31,7 @@ pub fn make_all_parcels(
|
||||
}
|
||||
|
||||
// Trim parcels that are too far away from the nearest sidewalk
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, 100.0 * si::M, timer);
|
||||
let sidewalk_pts = find_sidewalk_points(bounds, query, lanes, Distance::meters(100.0), timer);
|
||||
|
||||
for (idx, center) in center_per_parcel.into_iter().enumerate() {
|
||||
if sidewalk_pts.contains_key(¢er) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{FindClosest, Lane, LaneID, Position};
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D};
|
||||
use geom::{Bounds, Distance, HashablePt2D};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
// If the result doesn't contain a requested point, then there was no matching sidewalk close
|
||||
@ -10,7 +9,7 @@ pub fn find_sidewalk_points(
|
||||
bounds: &Bounds,
|
||||
pts: HashSet<HashablePt2D>,
|
||||
lanes: &Vec<Lane>,
|
||||
max_dist_away: si::Meter<f64>,
|
||||
max_dist_away: Distance,
|
||||
timer: &mut Timer,
|
||||
) -> HashMap<HashablePt2D, Position> {
|
||||
if pts.is_empty() {
|
||||
|
@ -3,8 +3,7 @@ use crate::{
|
||||
TurnType, LANE_THICKNESS,
|
||||
};
|
||||
use abstutil::wraparound_get;
|
||||
use dimensioned::si;
|
||||
use geom::{Line, PolyLine, Pt2D};
|
||||
use geom::{Distance, Line, PolyLine, Pt2D};
|
||||
use nbez::{Bez3o, BezCurve, Point2d};
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::iter;
|
||||
@ -324,8 +323,8 @@ fn make_vehicle_turn(lanes: &Vec<&Lane>, i: IntersectionID, l1: LaneID, l2: Lane
|
||||
// TODO Tune the 5.0 and pieces
|
||||
let curve = Bez3o::new(
|
||||
to_pt(src.last_pt()),
|
||||
to_pt(src_line.unbounded_dist_along(src_line.length() + 5.0 * si::M)),
|
||||
to_pt(dst_line.unbounded_dist_along(dst_line.length() + 5.0 * si::M)),
|
||||
to_pt(src_line.unbounded_dist_along(src_line.length() + Distance::meters(5.0))),
|
||||
to_pt(dst_line.unbounded_dist_along(dst_line.length() + Distance::meters(5.0))),
|
||||
to_pt(dst.first_pt()),
|
||||
);
|
||||
let pieces = 5;
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{BusRouteID, BusStopID, LaneID, LaneType, Map, Position, Traversable, TurnID};
|
||||
use dimensioned::si;
|
||||
use geom::{PolyLine, Pt2D, EPSILON_DIST};
|
||||
use geom::{Distance, PolyLine, Pt2D, EPSILON_DIST};
|
||||
use ordered_float::NotNan;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BinaryHeap, HashMap, VecDeque};
|
||||
@ -28,18 +27,18 @@ enum InternalPathStep {
|
||||
impl InternalPathStep {
|
||||
// TODO Should consider the last step too... RideBus then Lane probably won't cross the full
|
||||
// lane.
|
||||
fn cost(&self, map: &Map) -> si::Meter<f64> {
|
||||
fn cost(&self, map: &Map) -> Distance {
|
||||
match *self {
|
||||
InternalPathStep::Lane(l) | InternalPathStep::ContraflowLane(l) => {
|
||||
map.get_l(l).length()
|
||||
}
|
||||
InternalPathStep::Turn(t) => map.get_t(t).geom.length(),
|
||||
// Free! For now.
|
||||
InternalPathStep::RideBus(_, _, _) => 0.0 * si::M,
|
||||
InternalPathStep::RideBus(_, _, _) => Distance::ZERO,
|
||||
}
|
||||
}
|
||||
|
||||
fn heuristic(&self, goal_pt: Pt2D, map: &Map) -> si::Meter<f64> {
|
||||
fn heuristic(&self, goal_pt: Pt2D, map: &Map) -> Distance {
|
||||
let pt = match *self {
|
||||
InternalPathStep::Lane(l) => map.get_l(l).last_pt(),
|
||||
InternalPathStep::ContraflowLane(l) => map.get_l(l).first_pt(),
|
||||
@ -71,13 +70,13 @@ impl PathStep {
|
||||
fn slice(
|
||||
&self,
|
||||
map: &Map,
|
||||
start: si::Meter<f64>,
|
||||
dist_ahead: si::Meter<f64>,
|
||||
) -> Option<(PolyLine, si::Meter<f64>)> {
|
||||
if dist_ahead < 0.0 * si::M {
|
||||
start: Distance,
|
||||
dist_ahead: Distance,
|
||||
) -> Option<(PolyLine, Distance)> {
|
||||
if dist_ahead < Distance::ZERO {
|
||||
panic!("Negative dist_ahead?! {}", dist_ahead);
|
||||
}
|
||||
if dist_ahead == 0.0 * si::M {
|
||||
if dist_ahead == Distance::ZERO {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -99,12 +98,12 @@ impl PathStep {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Path {
|
||||
steps: VecDeque<PathStep>,
|
||||
end_dist: si::Meter<f64>,
|
||||
end_dist: Distance,
|
||||
}
|
||||
|
||||
impl Path {
|
||||
// TODO pub for DrawCarInput... bleh.
|
||||
pub fn new(map: &Map, steps: Vec<PathStep>, end_dist: si::Meter<f64>) -> Path {
|
||||
pub fn new(map: &Map, steps: Vec<PathStep>, end_dist: Distance) -> Path {
|
||||
// Can disable this after trusting it.
|
||||
validate(map, &steps);
|
||||
Path {
|
||||
@ -152,12 +151,7 @@ impl Path {
|
||||
self.steps[self.steps.len() - 1]
|
||||
}
|
||||
|
||||
pub fn trace(
|
||||
&self,
|
||||
map: &Map,
|
||||
start_dist: si::Meter<f64>,
|
||||
dist_ahead: si::Meter<f64>,
|
||||
) -> Option<Trace> {
|
||||
pub fn trace(&self, map: &Map, start_dist: Distance, dist_ahead: Distance) -> Option<Trace> {
|
||||
let mut pts_so_far: Option<PolyLine> = None;
|
||||
let mut dist_remaining = dist_ahead;
|
||||
|
||||
@ -187,7 +181,7 @@ impl Path {
|
||||
|
||||
// Crunch through the intermediate steps, as long as we can.
|
||||
for i in 1..self.steps.len() {
|
||||
if dist_remaining <= 0.0 * si::M {
|
||||
if dist_remaining <= Distance::ZERO {
|
||||
// We know there's at least some geometry if we made it here, so unwrap to verify
|
||||
// that understanding.
|
||||
return Some(pts_so_far.unwrap());
|
||||
@ -209,7 +203,7 @@ impl Path {
|
||||
// TODO Length of a PolyLine can slightly change when points are reversed! That
|
||||
// seems bad.
|
||||
PathStep::ContraflowLane(l) => map.get_l(l).lane_center_pts.reversed().length(),
|
||||
_ => 0.0 * si::M,
|
||||
_ => Distance::ZERO,
|
||||
};
|
||||
if dist_remaining - start_dist_this_step > EPSILON_DIST {
|
||||
if let Some((new_pts, dist)) =
|
||||
@ -364,7 +358,7 @@ impl Pathfinder {
|
||||
if pos.dist_along() != sidewalk.length() {
|
||||
results.push(InternalPathStep::Lane(sidewalk.id));
|
||||
}
|
||||
if pos.dist_along() != 0.0 * si::M {
|
||||
if pos.dist_along() != Distance::ZERO {
|
||||
results.push(InternalPathStep::ContraflowLane(sidewalk.id));
|
||||
}
|
||||
}
|
||||
@ -393,7 +387,7 @@ impl Pathfinder {
|
||||
let heuristic = step.heuristic(self.goal_pt, map);
|
||||
queue.push((dist_to_pri_queue(cost + heuristic), step));
|
||||
}
|
||||
if start.dist_along() != 0.0 * si::M {
|
||||
if start.dist_along() != Distance::ZERO {
|
||||
let step = InternalPathStep::ContraflowLane(start.lane());
|
||||
let cost = start.dist_along();
|
||||
let heuristic = step.heuristic(self.goal_pt, map);
|
||||
@ -459,7 +453,7 @@ fn validate(map: &Map, steps: &Vec<PathStep>) {
|
||||
PathStep::Turn(id) => map.get_t(id).geom.first_pt(),
|
||||
};
|
||||
let len = from.dist_to(to);
|
||||
if len > 0.0 * si::M {
|
||||
if len > Distance::ZERO {
|
||||
error!("All steps in invalid path:");
|
||||
for s in steps {
|
||||
match s {
|
||||
@ -487,6 +481,6 @@ fn validate(map: &Map, steps: &Vec<PathStep>) {
|
||||
}
|
||||
|
||||
// Negate since BinaryHeap is a max-heap.
|
||||
fn dist_to_pri_queue(dist: si::Meter<f64>) -> NotNan<f64> {
|
||||
NotNan::new(-1.0 * dist.value_unsafe).unwrap()
|
||||
fn dist_to_pri_queue(dist: Distance) -> NotNan<f64> {
|
||||
(dist * -1.0).as_ordered()
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::make::get_lane_types;
|
||||
use crate::{AreaType, IntersectionType, RoadSpec};
|
||||
use dimensioned::si;
|
||||
use geom::{GPSBounds, LonLat};
|
||||
use geom::{Distance, GPSBounds, LonLat};
|
||||
use gtfs::Route;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
@ -105,7 +104,7 @@ impl Road {
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct Intersection {
|
||||
pub point: LonLat,
|
||||
pub elevation: si::Meter<f64>,
|
||||
pub elevation: Distance,
|
||||
// A raw Intersection can be forced into being a Border.
|
||||
pub intersection_type: IntersectionType,
|
||||
pub label: Option<String>,
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{raw_data, IntersectionID, LaneID, LaneType};
|
||||
use abstutil::Error;
|
||||
use dimensioned::si;
|
||||
use geom::PolyLine;
|
||||
use geom::{PolyLine, Speed};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::fmt;
|
||||
@ -89,13 +88,13 @@ impl Road {
|
||||
lane == self.children_backwards[0].0
|
||||
}
|
||||
|
||||
pub fn get_speed_limit(&self) -> si::MeterPerSecond<f64> {
|
||||
pub fn get_speed_limit(&self) -> Speed {
|
||||
// TODO Should probably cache this
|
||||
if let Some(limit) = self.osm_tags.get("maxspeed") {
|
||||
// TODO handle other units
|
||||
if limit.ends_with(" mph") {
|
||||
if let Ok(mph) = limit[0..limit.len() - 4].parse::<f64>() {
|
||||
return mph * 0.44704 * si::MPS;
|
||||
return Speed::miles_per_hour(mph);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,11 +102,9 @@ impl Road {
|
||||
if self.osm_tags.get("highway") == Some(&"primary".to_string())
|
||||
|| self.osm_tags.get("highway") == Some(&"secondary".to_string())
|
||||
{
|
||||
// 40mph
|
||||
return 17.8816 * si::MPS;
|
||||
return Speed::miles_per_hour(40.0);
|
||||
}
|
||||
// 20mph
|
||||
8.9408 * si::MPS
|
||||
Speed::miles_per_hour(20.0)
|
||||
}
|
||||
|
||||
pub fn get_zorder(&self) -> isize {
|
||||
|
@ -1,14 +1,10 @@
|
||||
use crate::{IntersectionID, Map, RoadID, TurnID, TurnPriority, TurnType};
|
||||
use abstutil::Error;
|
||||
use dimensioned::si;
|
||||
use geom::Duration;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
const CYCLE_DURATION: si::Second<f64> = si::Second {
|
||||
value_unsafe: 30.0,
|
||||
_marker: std::marker::PhantomData,
|
||||
};
|
||||
const CYCLE_DURATION: Duration = Duration::const_seconds(30.0);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ControlTrafficSignal {
|
||||
@ -32,13 +28,10 @@ impl ControlTrafficSignal {
|
||||
self.changed
|
||||
}
|
||||
|
||||
pub fn current_cycle_and_remaining_time(
|
||||
&self,
|
||||
time: si::Second<f64>,
|
||||
) -> (&Cycle, si::Second<f64>) {
|
||||
pub fn current_cycle_and_remaining_time(&self, time: Duration) -> (&Cycle, Duration) {
|
||||
let cycle_idx = (time / CYCLE_DURATION).floor() as usize;
|
||||
let cycle = &self.cycles[cycle_idx % self.cycles.len()];
|
||||
let next_cycle_time = (cycle_idx + 1) as f64 * CYCLE_DURATION;
|
||||
let next_cycle_time = CYCLE_DURATION * (cycle_idx + 1) as f64;
|
||||
let remaining_cycle_time = next_cycle_time - time;
|
||||
(cycle, remaining_cycle_time)
|
||||
}
|
||||
@ -307,7 +300,7 @@ pub struct Cycle {
|
||||
pub idx: usize,
|
||||
pub priority_turns: BTreeSet<TurnID>,
|
||||
pub yield_turns: BTreeSet<TurnID>,
|
||||
pub duration: si::Second<f64>,
|
||||
pub duration: Duration,
|
||||
}
|
||||
|
||||
impl Cycle {
|
||||
@ -379,7 +372,7 @@ impl Cycle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_duration(&mut self, new_duration: si::Second<f64>) {
|
||||
pub fn edit_duration(&mut self, new_duration: Duration) {
|
||||
self.duration = new_duration;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{LaneID, Map, TurnID};
|
||||
use dimensioned::si;
|
||||
use geom::{Angle, PolyLine, Pt2D};
|
||||
use geom::{Angle, Distance, PolyLine, Pt2D, Speed};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
@ -8,7 +7,7 @@ use std::fmt;
|
||||
pub struct Position {
|
||||
// Don't let callers construct a Position directly, so it's easy to find callers of new().
|
||||
lane: LaneID,
|
||||
dist_along: si::Meter<f64>,
|
||||
dist_along: Distance,
|
||||
}
|
||||
|
||||
impl fmt::Display for Position {
|
||||
@ -18,7 +17,7 @@ impl fmt::Display for Position {
|
||||
}
|
||||
|
||||
impl Position {
|
||||
pub fn new(lane: LaneID, dist_along: si::Meter<f64>) -> Position {
|
||||
pub fn new(lane: LaneID, dist_along: Distance) -> Position {
|
||||
Position { lane, dist_along }
|
||||
}
|
||||
|
||||
@ -26,7 +25,7 @@ impl Position {
|
||||
self.lane
|
||||
}
|
||||
|
||||
pub fn dist_along(&self) -> si::Meter<f64> {
|
||||
pub fn dist_along(&self) -> Distance {
|
||||
self.dist_along
|
||||
}
|
||||
|
||||
@ -83,33 +82,28 @@ impl Traversable {
|
||||
}
|
||||
|
||||
// TODO Just expose the PolyLine instead of all these layers of helpers
|
||||
pub fn length(&self, map: &Map) -> si::Meter<f64> {
|
||||
pub fn length(&self, map: &Map) -> Distance {
|
||||
match *self {
|
||||
Traversable::Lane(id) => map.get_l(id).length(),
|
||||
Traversable::Turn(id) => map.get_t(id).geom.length(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dist_along(&self, dist: si::Meter<f64>, map: &Map) -> (Pt2D, Angle) {
|
||||
pub fn dist_along(&self, dist: Distance, map: &Map) -> (Pt2D, Angle) {
|
||||
match *self {
|
||||
Traversable::Lane(id) => map.get_l(id).dist_along(dist),
|
||||
Traversable::Turn(id) => map.get_t(id).geom.dist_along(dist),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slice(
|
||||
&self,
|
||||
start: si::Meter<f64>,
|
||||
end: si::Meter<f64>,
|
||||
map: &Map,
|
||||
) -> Option<(PolyLine, si::Meter<f64>)> {
|
||||
pub fn slice(&self, start: Distance, end: Distance, map: &Map) -> Option<(PolyLine, Distance)> {
|
||||
match *self {
|
||||
Traversable::Lane(id) => map.get_l(id).lane_center_pts.slice(start, end),
|
||||
Traversable::Turn(id) => map.get_t(id).geom.slice(start, end),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn speed_limit(&self, map: &Map) -> si::MeterPerSecond<f64> {
|
||||
pub fn speed_limit(&self, map: &Map) -> Speed {
|
||||
match *self {
|
||||
Traversable::Lane(id) => map.get_parent(id).get_speed_limit(),
|
||||
Traversable::Turn(id) => map.get_parent(id.dst).get_speed_limit(),
|
||||
|
Loading…
Reference in New Issue
Block a user