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