mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 23:43:25 +03:00
making small_seattle fully convert, with some less messy hacks. added it
as a test!
This commit is contained in:
parent
a3b03952cf
commit
6da48c28c1
@ -43,6 +43,10 @@ pub fn make_all_buildings(
|
|||||||
let sidewalk_pt = lanes[sidewalk_pos.lane().0]
|
let sidewalk_pt = lanes[sidewalk_pos.lane().0]
|
||||||
.dist_along(sidewalk_pos.dist_along())
|
.dist_along(sidewalk_pos.dist_along())
|
||||||
.0;
|
.0;
|
||||||
|
if sidewalk_pt.epsilon_eq(bldg_center.into()) {
|
||||||
|
warn!("Skipping a building because front path has 0 length");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let line = trim_front_path(&points, Line::new(bldg_center.into(), sidewalk_pt));
|
let line = trim_front_path(&points, Line::new(bldg_center.into(), sidewalk_pt));
|
||||||
|
|
||||||
let id = BuildingID(results.len());
|
let id = BuildingID(results.len());
|
||||||
|
@ -4,6 +4,11 @@ use abstutil::Timer;
|
|||||||
use std::collections::{BTreeSet, HashSet};
|
use std::collections::{BTreeSet, HashSet};
|
||||||
|
|
||||||
pub fn fix_ramps(m: &mut InitialMap, timer: &mut Timer) {
|
pub fn fix_ramps(m: &mut InitialMap, timer: &mut Timer) {
|
||||||
|
if m.roads.len() > 15_000 {
|
||||||
|
error!("Skipping fix_ramps because map is too big! TODO: Optimize me!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Look for road center lines that hit an intersection polygon that isn't one of their
|
// Look for road center lines that hit an intersection polygon that isn't one of their
|
||||||
// endpoints.
|
// endpoints.
|
||||||
timer.start_iter(
|
timer.start_iter(
|
||||||
|
@ -139,10 +139,16 @@ fn generalized_trim_back(
|
|||||||
// 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? Also, find the hit closest to the intersection -- this matters for
|
// polyline? Also, find the hit closest to the intersection -- this matters for
|
||||||
// very curvy roads, like highway ramps.
|
// very curvy roads, like highway ramps.
|
||||||
let trim_to = road_center.reversed().intersection_infinite(&perp).unwrap();
|
if let Some(trimmed) = road_center
|
||||||
let trimmed = road_center.get_slice_ending_at(trim_to).unwrap();
|
.reversed()
|
||||||
if trimmed.length() < shortest_center.length() {
|
.intersection_infinite(&perp)
|
||||||
shortest_center = trimmed;
|
.and_then(|trim_to| road_center.get_slice_ending_at(trim_to))
|
||||||
|
{
|
||||||
|
if trimmed.length() < shortest_center.length() {
|
||||||
|
shortest_center = trimmed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("{} and {} hit, but the perpendicular never hit the original center line, or the trimmed thing is empty", r1, r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We could also do the update for r2, but we'll just get to it later.
|
// We could also do the update for r2, but we'll just get to it later.
|
||||||
@ -199,18 +205,25 @@ fn generalized_trim_back(
|
|||||||
// Include collisions between polylines of adjacent roads, so the polygon doesn't cover area
|
// Include collisions between polylines of adjacent roads, so the polygon doesn't cover area
|
||||||
// not originally covered by the thick road bands.
|
// not originally covered by the thick road bands.
|
||||||
// It's apparently safe to always take the second_half here.
|
// It's apparently safe to always take the second_half here.
|
||||||
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half()) {
|
if fwd_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||||
endpoints.push(hit);
|
&& adj_fwd_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||||
} else if r.original_endpoint(i) != roads[&adj_fwd_id].original_endpoint(i) {
|
{
|
||||||
if false {
|
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half()) {
|
||||||
// TODO This cuts some corners nicely, but also causes lots of problems.
|
endpoints.push(hit);
|
||||||
// If the original roads didn't end at the same intersection (due to intersection
|
} else if r.original_endpoint(i) != roads[&adj_fwd_id].original_endpoint(i) {
|
||||||
// merging), then use infinite lines.
|
if false {
|
||||||
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half())
|
// TODO This cuts some corners nicely, but also causes lots of problems.
|
||||||
{
|
// If the original roads didn't end at the same intersection (due to intersection
|
||||||
endpoints.push(hit);
|
// merging), then use infinite lines.
|
||||||
|
if let Some((hit, _)) =
|
||||||
|
fwd_pl.second_half().intersection(&adj_fwd_pl.second_half())
|
||||||
|
{
|
||||||
|
endpoints.push(hit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Excluding collision between original polylines of {} and something, because stuff's too short", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift those final centers out again to find the main endpoints for the polygon.
|
// Shift those final centers out again to find the main endpoints for the polygon.
|
||||||
@ -222,21 +235,27 @@ fn generalized_trim_back(
|
|||||||
endpoints.push(r.trimmed_center_pts.shift_right(r.fwd_width).first_pt());
|
endpoints.push(r.trimmed_center_pts.shift_right(r.fwd_width).first_pt());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((hit, _)) = back_pl
|
if back_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||||
.second_half()
|
&& adj_back_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||||
.intersection(&adj_back_pl.second_half())
|
|
||||||
{
|
{
|
||||||
endpoints.push(hit);
|
if let Some((hit, _)) = back_pl
|
||||||
} else if r.original_endpoint(i) != roads[&adj_back_id].original_endpoint(i) {
|
.second_half()
|
||||||
if false {
|
.intersection(&adj_back_pl.second_half())
|
||||||
if let Some(hit) = back_pl
|
{
|
||||||
.last_line()
|
endpoints.push(hit);
|
||||||
.infinite()
|
} else if r.original_endpoint(i) != roads[&adj_back_id].original_endpoint(i) {
|
||||||
.intersection(&adj_back_pl.last_line().infinite())
|
if false {
|
||||||
{
|
if let Some(hit) = back_pl
|
||||||
endpoints.push(hit);
|
.last_line()
|
||||||
|
.infinite()
|
||||||
|
.intersection(&adj_back_pl.last_line().infinite())
|
||||||
|
{
|
||||||
|
endpoints.push(hit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Excluding collision between original polylines of {} and something, because stuff's too short", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO Caller will close off the polygon. Does that affect our dedupe?
|
// TODO Caller will close off the polygon. Does that affect our dedupe?
|
||||||
|
@ -8,6 +8,8 @@ use nbez::{Bez3o, BezCurve, Point2d};
|
|||||||
use std::collections::{BTreeSet, HashSet};
|
use std::collections::{BTreeSet, HashSet};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
// TODO Add proper warnings when the geometry is too small to handle.
|
||||||
|
|
||||||
pub fn make_all_turns(i: &Intersection, roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
pub fn make_all_turns(i: &Intersection, roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
|
||||||
if i.intersection_type == IntersectionType::Border {
|
if i.intersection_type == IntersectionType::Border {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
@ -73,7 +75,7 @@ fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
|
|||||||
lane_types.remove(&LaneType::Parking);
|
lane_types.remove(&LaneType::Parking);
|
||||||
lane_types.remove(&LaneType::Sidewalk);
|
lane_types.remove(&LaneType::Sidewalk);
|
||||||
|
|
||||||
let mut result = Vec::new();
|
let mut result: Vec<Option<Turn>> = Vec::new();
|
||||||
|
|
||||||
for lane_type in lane_types.into_iter() {
|
for lane_type in lane_types.into_iter() {
|
||||||
if i.is_dead_end() {
|
if i.is_dead_end() {
|
||||||
@ -139,7 +141,7 @@ fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result.into_iter().filter_map(|x| x).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_up_lanes(
|
fn match_up_lanes(
|
||||||
@ -147,7 +149,7 @@ fn match_up_lanes(
|
|||||||
i: IntersectionID,
|
i: IntersectionID,
|
||||||
incoming: &Vec<LaneID>,
|
incoming: &Vec<LaneID>,
|
||||||
outgoing: &Vec<LaneID>,
|
outgoing: &Vec<LaneID>,
|
||||||
) -> Vec<Turn> {
|
) -> Vec<Option<Turn>> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
if incoming.len() < outgoing.len() {
|
if incoming.len() < outgoing.len() {
|
||||||
// Arbitrarily use the leftmost incoming lane to handle the excess.
|
// Arbitrarily use the leftmost incoming lane to handle the excess.
|
||||||
@ -185,7 +187,7 @@ fn make_vehicle_turns_for_dead_end(
|
|||||||
roads: &Vec<Road>,
|
roads: &Vec<Road>,
|
||||||
lanes: &Vec<Lane>,
|
lanes: &Vec<Lane>,
|
||||||
lane_type: LaneType,
|
lane_type: LaneType,
|
||||||
) -> Vec<Turn> {
|
) -> Vec<Option<Turn>> {
|
||||||
let road = &roads[i.roads.iter().next().unwrap().0];
|
let road = &roads[i.roads.iter().next().unwrap().0];
|
||||||
let incoming = filter_vehicle_lanes(road.incoming_lanes(i.id), lane_type);
|
let incoming = filter_vehicle_lanes(road.incoming_lanes(i.id), lane_type);
|
||||||
let outgoing = filter_vehicle_lanes(road.outgoing_lanes(i.id), lane_type);
|
let outgoing = filter_vehicle_lanes(road.outgoing_lanes(i.id), lane_type);
|
||||||
@ -219,18 +221,22 @@ fn make_walking_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
|
|||||||
lanes,
|
lanes,
|
||||||
wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id),
|
wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id),
|
||||||
) {
|
) {
|
||||||
result.push(Turn {
|
if !l1.last_pt().epsilon_eq(l2.first_pt()) {
|
||||||
id: turn_id(i.id, l1.id, l2.id),
|
result.push(Turn {
|
||||||
turn_type: TurnType::SharedSidewalkCorner,
|
id: turn_id(i.id, l1.id, l2.id),
|
||||||
geom: PolyLine::new(vec![l1.last_pt(), l2.first_pt()]),
|
turn_type: TurnType::SharedSidewalkCorner,
|
||||||
lookup_idx: 0,
|
geom: PolyLine::new(vec![l1.last_pt(), l2.first_pt()]),
|
||||||
});
|
lookup_idx: 0,
|
||||||
result.push(Turn {
|
});
|
||||||
id: turn_id(i.id, l2.id, l1.id),
|
}
|
||||||
turn_type: TurnType::SharedSidewalkCorner,
|
if !l2.first_pt().epsilon_eq(l1.last_pt()) {
|
||||||
geom: PolyLine::new(vec![l2.first_pt(), l1.last_pt()]),
|
result.push(Turn {
|
||||||
lookup_idx: 0,
|
id: turn_id(i.id, l2.id, l1.id),
|
||||||
});
|
turn_type: TurnType::SharedSidewalkCorner,
|
||||||
|
geom: PolyLine::new(vec![l2.first_pt(), l1.last_pt()]),
|
||||||
|
lookup_idx: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if roads.len() > 2 {
|
} else if roads.len() > 2 {
|
||||||
// See if we need to add a crosswalk over this adjacent road.
|
// See if we need to add a crosswalk over this adjacent road.
|
||||||
// TODO This is brittle; I could imagine having to cross two adjacent highway
|
// TODO This is brittle; I could imagine having to cross two adjacent highway
|
||||||
@ -249,6 +255,10 @@ fn make_walking_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
|
fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
|
||||||
|
if l1.last_pt().epsilon_eq(l2.first_pt()) {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
// Jut out a bit into the intersection, cross over, then jut back in.
|
// Jut out a bit into the intersection, cross over, then jut back in.
|
||||||
let line = Line::new(l1.last_pt(), l2.first_pt()).shift_right(LANE_THICKNESS / 2.0);
|
let line = Line::new(l1.last_pt(), l2.first_pt()).shift_right(LANE_THICKNESS / 2.0);
|
||||||
let geom_fwds = PolyLine::new(vec![l1.last_pt(), line.pt1(), line.pt2(), l2.first_pt()]);
|
let geom_fwds = PolyLine::new(vec![l1.last_pt(), line.pt1(), line.pt2(), l2.first_pt()]);
|
||||||
@ -297,11 +307,15 @@ fn filter_lanes(lanes: &Vec<(LaneID, LaneType)>, filter: LaneType) -> Vec<LaneID
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneID) -> Turn {
|
fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneID) -> Option<Turn> {
|
||||||
let src = &lanes[l1.0];
|
let src = &lanes[l1.0];
|
||||||
let dst = &lanes[l2.0];
|
let dst = &lanes[l2.0];
|
||||||
let turn_type = TurnType::from_angles(src.last_line().angle(), dst.first_line().angle());
|
let turn_type = TurnType::from_angles(src.last_line().angle(), dst.first_line().angle());
|
||||||
|
|
||||||
|
if src.last_pt().epsilon_eq(dst.first_pt()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let geom = if turn_type == TurnType::Straight {
|
let geom = if turn_type == TurnType::Straight {
|
||||||
PolyLine::new(vec![src.last_pt(), dst.first_pt()])
|
PolyLine::new(vec![src.last_pt(), dst.first_pt()])
|
||||||
} else {
|
} else {
|
||||||
@ -332,12 +346,12 @@ fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneI
|
|||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
Turn {
|
Some(Turn {
|
||||||
id: turn_id(i, l1, l2),
|
id: turn_id(i, l1, l2),
|
||||||
turn_type,
|
turn_type,
|
||||||
geom,
|
geom,
|
||||||
lookup_idx: 0,
|
lookup_idx: 0,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_pt(pt: Pt2D) -> Point2d<f64> {
|
fn to_pt(pt: Pt2D) -> Point2d<f64> {
|
||||||
|
@ -85,7 +85,12 @@ impl ControlTrafficSignal {
|
|||||||
intersection: IntersectionID,
|
intersection: IntersectionID,
|
||||||
) -> Option<ControlTrafficSignal> {
|
) -> Option<ControlTrafficSignal> {
|
||||||
if map.get_turns_in_intersection(intersection).is_empty() {
|
if map.get_turns_in_intersection(intersection).is_empty() {
|
||||||
panic!("{} has no turns", intersection);
|
error!("{} has no turns", intersection);
|
||||||
|
return Some(ControlTrafficSignal {
|
||||||
|
id: intersection,
|
||||||
|
cycles: Vec::new(),
|
||||||
|
changed: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cycles = Vec::new();
|
let mut cycles = Vec::new();
|
||||||
|
@ -51,21 +51,21 @@ pub fn run(t: &mut TestRunner) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
t.run_slow("bigger_maps", |_| {
|
t.run_slow("bigger_map_loads", |_| {
|
||||||
map_model::Map::new(
|
map_model::Map::new(
|
||||||
"../data/raw_maps/23rd.abst",
|
"../data/raw_maps/23rd.abst",
|
||||||
map_model::MapEdits::new("23rd"),
|
map_model::MapEdits::new("23rd"),
|
||||||
&mut abstutil::Timer::new("raw to map"),
|
&mut abstutil::Timer::new("raw to map"),
|
||||||
)
|
)
|
||||||
.expect("23rd broke");
|
.expect("23rd broke");
|
||||||
|
});
|
||||||
|
|
||||||
// TODO This one has lots more problems (turns with no geometry) and even when the map is
|
t.run_slow("biggest_map_loads", |_| {
|
||||||
// made successfully, can't load it in the UI without OOMing.
|
map_model::Map::new(
|
||||||
/*map_model::Map::new(
|
|
||||||
"../data/raw_maps/small_seattle.abst",
|
"../data/raw_maps/small_seattle.abst",
|
||||||
map_model::MapEdits::new("small_seattle"),
|
map_model::MapEdits::new("small_seattle"),
|
||||||
&mut abstutil::Timer::new("raw to map"),
|
&mut abstutil::Timer::new("raw to map"),
|
||||||
)
|
)
|
||||||
.expect("small_seattle broke");*/
|
.expect("small_seattle broke");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user