mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +03:00
random fixes in the map importer to try to import a bunch of new cities.
not too successful, but made progress.
This commit is contained in:
parent
128e649236
commit
62ed91925a
@ -266,7 +266,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
|
||||
},
|
||||
);
|
||||
}
|
||||
Err(err) => println!("Skipping building: {}", err),
|
||||
Err(err) => println!("Skipping building {}: {}", id, err),
|
||||
}
|
||||
} else if rel.tags.is("type", "route") {
|
||||
map.bus_routes
|
||||
@ -423,7 +423,7 @@ fn is_road(tags: &mut Tags, opts: &Options) -> bool {
|
||||
|
||||
// Service roads can represent lots of things, most of which we don't want to keep yet. What's
|
||||
// allowed here is just based on what's been encountered so far in Seattle and Kraków.
|
||||
if highway == "service" && !tags.is("psv", "yes") && !tags.is("bus", "yes") {
|
||||
if highway == "service" && !tags.is_any("psv", vec!["yes", "bus"]) && !tags.is("bus", "yes") {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -602,6 +602,9 @@ fn glue_multipolygon(
|
||||
polygons.push(ring.to_polygon());
|
||||
return polygons;
|
||||
}
|
||||
if result.len() < 2 {
|
||||
return Vec::new();
|
||||
}
|
||||
if let Some(poly) = glue_to_boundary(PolyLine::must_new(result.clone()), boundary) {
|
||||
polygons.push(poly);
|
||||
} else {
|
||||
@ -802,9 +805,13 @@ fn multipoly_geometry(
|
||||
Ok(Polygon::buggy_new(outer.remove(0)))
|
||||
}
|
||||
} else {
|
||||
let mut inner_rings = Vec::new();
|
||||
for pts in inner {
|
||||
inner_rings.push(Ring::new(pts)?);
|
||||
}
|
||||
Ok(Polygon::with_holes(
|
||||
Ring::must_new(outer.pop().unwrap()),
|
||||
inner.into_iter().map(Ring::must_new).collect(),
|
||||
Ring::new(outer.pop().unwrap())?,
|
||||
inner_rings,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::make::initial::{Intersection, Road};
|
||||
use crate::osm;
|
||||
use crate::raw::{DrivingSide, OriginalIntersection, OriginalRoad};
|
||||
use abstutil::{wraparound_get, Timer};
|
||||
use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
|
||||
use geom::{Distance, Line, PolyLine, Polygon, Pt2D, Ring, EPSILON_DIST};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
const DEGENERATE_INTERSECTION_HALF_LENGTH: Distance = Distance::const_meters(2.5);
|
||||
@ -15,7 +15,7 @@ pub fn intersection_polygon(
|
||||
i: &Intersection,
|
||||
roads: &mut BTreeMap<OriginalRoad, Road>,
|
||||
timer: &mut Timer,
|
||||
) -> (Vec<Pt2D>, Vec<(String, Polygon)>) {
|
||||
) -> (Polygon, Vec<(String, Polygon)>) {
|
||||
if i.roads.is_empty() {
|
||||
panic!("{} has no roads", i.id);
|
||||
}
|
||||
@ -72,7 +72,7 @@ fn generalized_trim_back(
|
||||
i: OriginalIntersection,
|
||||
lines: &Vec<(OriginalRoad, Line, PolyLine, PolyLine)>,
|
||||
timer: &mut Timer,
|
||||
) -> (Vec<Pt2D>, Vec<(String, Polygon)>) {
|
||||
) -> (Polygon, Vec<(String, Polygon)>) {
|
||||
let mut debug = Vec::new();
|
||||
|
||||
let mut road_lines: Vec<(OriginalRoad, PolyLine)> = Vec::new();
|
||||
@ -104,16 +104,15 @@ fn generalized_trim_back(
|
||||
};
|
||||
|
||||
// Always trim back a minimum amount, if possible.
|
||||
let mut shortest_center = if road_center.length()
|
||||
>= DEGENERATE_INTERSECTION_HALF_LENGTH + 3.0 * geom::EPSILON_DIST
|
||||
{
|
||||
road_center.exact_slice(
|
||||
Distance::ZERO,
|
||||
road_center.length() - DEGENERATE_INTERSECTION_HALF_LENGTH,
|
||||
)
|
||||
} else {
|
||||
road_center.clone()
|
||||
};
|
||||
let mut shortest_center =
|
||||
if road_center.length() >= DEGENERATE_INTERSECTION_HALF_LENGTH + 3.0 * EPSILON_DIST {
|
||||
road_center.exact_slice(
|
||||
Distance::ZERO,
|
||||
road_center.length() - DEGENERATE_INTERSECTION_HALF_LENGTH,
|
||||
)
|
||||
} else {
|
||||
road_center.clone()
|
||||
};
|
||||
|
||||
for (r2, pl2) in &road_lines {
|
||||
if r1 == r2 {
|
||||
@ -204,9 +203,7 @@ fn generalized_trim_back(
|
||||
// Include collisions between polylines of adjacent roads, so the polygon doesn't cover area
|
||||
// not originally covered by the thick road bands.
|
||||
// It's apparently safe to always take the second_half here.
|
||||
if fwd_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||
&& adj_fwd_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||
{
|
||||
if fwd_pl.length() >= EPSILON_DIST * 3.0 && adj_fwd_pl.length() >= EPSILON_DIST * 3.0 {
|
||||
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half()) {
|
||||
endpoints.push(hit);
|
||||
}
|
||||
@ -243,9 +240,7 @@ fn generalized_trim_back(
|
||||
);
|
||||
}
|
||||
|
||||
if back_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||
&& adj_back_pl.length() >= geom::EPSILON_DIST * 3.0
|
||||
{
|
||||
if back_pl.length() >= EPSILON_DIST * 3.0 && adj_back_pl.length() >= EPSILON_DIST * 3.0 {
|
||||
if let Some((hit, _)) = back_pl
|
||||
.second_half()
|
||||
.intersection(&adj_back_pl.second_half())
|
||||
@ -274,13 +269,13 @@ fn generalized_trim_back(
|
||||
deduped = Pt2D::approx_dedupe(deduped, Distance::meters(0.1));
|
||||
deduped = close_off_polygon(deduped);
|
||||
if main_result.len() == deduped.len() {
|
||||
(main_result, debug)
|
||||
(Ring::must_new(main_result).to_polygon(), debug)
|
||||
} else {
|
||||
timer.warn(format!(
|
||||
"{}'s polygon has weird repeats, forcibly removing points",
|
||||
i
|
||||
));
|
||||
(deduped, debug)
|
||||
(Ring::must_new(deduped).to_polygon(), debug)
|
||||
}
|
||||
|
||||
// TODO Or always sort points? Helps some cases, hurts other for downtown Seattle.
|
||||
@ -296,7 +291,7 @@ fn deadend(
|
||||
roads: &mut BTreeMap<OriginalRoad, Road>,
|
||||
i: OriginalIntersection,
|
||||
lines: &Vec<(OriginalRoad, Line, PolyLine, PolyLine)>,
|
||||
) -> (Vec<Pt2D>, Vec<(String, Polygon)>) {
|
||||
) -> (Polygon, Vec<(String, Polygon)>) {
|
||||
let len = DEGENERATE_INTERSECTION_HALF_LENGTH * 4.0;
|
||||
|
||||
let (id, _, mut pl_a, mut pl_b) = lines[0].clone();
|
||||
@ -308,7 +303,7 @@ fn deadend(
|
||||
pl_b = pl_b.extend_to_length(len + 1.5 * DEGENERATE_INTERSECTION_HALF_LENGTH);
|
||||
|
||||
let r = roads.get_mut(&id).unwrap();
|
||||
let len_with_buffer = len + 3.0 * geom::EPSILON_DIST;
|
||||
let len_with_buffer = len + 3.0 * EPSILON_DIST;
|
||||
let trimmed = if r.trimmed_center_pts.length() >= len_with_buffer {
|
||||
if r.src_i == i {
|
||||
r.trimmed_center_pts = r
|
||||
@ -356,7 +351,10 @@ fn deadend(
|
||||
}
|
||||
|
||||
endpts.dedup();
|
||||
(close_off_polygon(endpts), Vec::new())
|
||||
(
|
||||
Ring::must_new(close_off_polygon(endpts)).to_polygon(),
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
fn close_off_polygon(mut pts: Vec<Pt2D>) -> Vec<Pt2D> {
|
||||
@ -381,7 +379,7 @@ fn on_off_ramp(
|
||||
roads: &mut BTreeMap<OriginalRoad, Road>,
|
||||
i: OriginalIntersection,
|
||||
lines: Vec<(OriginalRoad, Line, PolyLine, PolyLine)>,
|
||||
) -> Option<(Vec<Pt2D>, Vec<(String, Polygon)>)> {
|
||||
) -> Option<(Polygon, Vec<(String, Polygon)>)> {
|
||||
if lines.len() != 3 {
|
||||
return None;
|
||||
}
|
||||
@ -520,7 +518,7 @@ fn on_off_ramp(
|
||||
};
|
||||
roads.get_mut(&thick_id).unwrap().trimmed_center_pts = trimmed_thick;
|
||||
// Give the merge point some length
|
||||
if extra.length() <= 2.0 * DEGENERATE_INTERSECTION_HALF_LENGTH {
|
||||
if extra.length() <= 2.0 * DEGENERATE_INTERSECTION_HALF_LENGTH + 3.0 * EPSILON_DIST {
|
||||
return None;
|
||||
}
|
||||
let extra = extra.exact_slice(2.0 * DEGENERATE_INTERSECTION_HALF_LENGTH, extra.length());
|
||||
@ -577,7 +575,11 @@ fn on_off_ramp(
|
||||
endpoints.dedup();
|
||||
let center = Pt2D::center(&endpoints);
|
||||
endpoints.sort_by_key(|pt| pt.angle_to(center).normalized_degrees() as i64);
|
||||
Some((close_off_polygon(endpoints), debug))
|
||||
endpoints.dedup();
|
||||
Some((
|
||||
Ring::must_new(close_off_polygon(endpoints)).to_polygon(),
|
||||
debug,
|
||||
))
|
||||
|
||||
//let dummy = geom::Circle::new(orig_lines[0].3.last_pt(), Distance::meters(3.0)).to_polygon();
|
||||
//Some((close_off_polygon(dummy.into_points()), debug))
|
||||
|
@ -5,7 +5,7 @@ pub use self::geometry::intersection_polygon;
|
||||
use crate::raw::{DrivingSide, OriginalIntersection, OriginalRoad, RawMap, RawRoad};
|
||||
use crate::IntersectionType;
|
||||
use abstutil::{Tags, Timer};
|
||||
use geom::{Bounds, Circle, Distance, PolyLine, Pt2D};
|
||||
use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};
|
||||
use lane_specs::LaneSpec;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
@ -48,7 +48,7 @@ impl Road {
|
||||
pub struct Intersection {
|
||||
// Redundant but useful to embed
|
||||
pub id: OriginalIntersection,
|
||||
pub polygon: Vec<Pt2D>,
|
||||
pub polygon: Polygon,
|
||||
pub roads: BTreeSet<OriginalRoad>,
|
||||
pub intersection_type: IntersectionType,
|
||||
pub elevation: Distance,
|
||||
@ -67,7 +67,8 @@ impl InitialMap {
|
||||
*id,
|
||||
Intersection {
|
||||
id: *id,
|
||||
polygon: Vec::new(),
|
||||
// Dummy thing to start with
|
||||
polygon: Circle::new(Pt2D::new(0.0, 0.0), Distance::meters(1.0)).to_polygon(),
|
||||
roads: BTreeSet::new(),
|
||||
intersection_type: i.intersection_type,
|
||||
elevation: i.elevation,
|
||||
@ -142,11 +143,7 @@ impl InitialMap {
|
||||
} else {
|
||||
r.trimmed_center_pts.last_pt()
|
||||
};
|
||||
let mut pts = Circle::new(pt, Distance::meters(3.0))
|
||||
.to_polygon()
|
||||
.into_points();
|
||||
pts.push(pts[0]);
|
||||
i.polygon = pts;
|
||||
i.polygon = Circle::new(pt, Distance::meters(3.0)).to_polygon();
|
||||
|
||||
// Also don't attempt to make TurnGroups later!
|
||||
i.intersection_type = IntersectionType::StopSign;
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
||||
};
|
||||
use abstutil::{Parallelism, Timer};
|
||||
use enumset::EnumSet;
|
||||
use geom::{Bounds, Distance, FindClosest, HashablePt2D, Ring, Speed, EPSILON_DIST};
|
||||
use geom::{Bounds, Distance, FindClosest, HashablePt2D, Speed, EPSILON_DIST};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
|
||||
impl Map {
|
||||
@ -67,7 +67,7 @@ impl Map {
|
||||
let id = IntersectionID(idx);
|
||||
map.intersections.push(Intersection {
|
||||
id,
|
||||
polygon: Ring::must_new(i.polygon.clone()).to_polygon(),
|
||||
polygon: i.polygon.clone(),
|
||||
turns: BTreeSet::new(),
|
||||
elevation: i.elevation,
|
||||
// Might change later
|
||||
|
@ -117,25 +117,27 @@ pub fn make_all_parking_lots(
|
||||
.map(|(id, _, _)| id)
|
||||
.collect();
|
||||
|
||||
let (polylines, rings) = Ring::split_points(pts).unwrap();
|
||||
'PL: for pl in polylines {
|
||||
for id in &candidates {
|
||||
let lot = &mut results[id.0];
|
||||
for segment in lot.polygon.clip_polyline(&pl) {
|
||||
lot.aisles.push(segment);
|
||||
continue 'PL;
|
||||
}
|
||||
}
|
||||
}
|
||||
'RING: for ring in rings {
|
||||
for id in &candidates {
|
||||
let lot = &mut results[id.0];
|
||||
for segment in lot.polygon.clip_ring(&ring) {
|
||||
lot.aisles.push(segment);
|
||||
continue 'RING;
|
||||
if let Ok((polylines, rings)) = Ring::split_points(pts) {
|
||||
'PL: for pl in polylines {
|
||||
for id in &candidates {
|
||||
let lot = &mut results[id.0];
|
||||
for segment in lot.polygon.clip_polyline(&pl) {
|
||||
lot.aisles.push(segment);
|
||||
continue 'PL;
|
||||
}
|
||||
}
|
||||
}
|
||||
'RING: for ring in rings {
|
||||
for id in &candidates {
|
||||
let lot = &mut results[id.0];
|
||||
for segment in lot.polygon.clip_ring(&ring) {
|
||||
lot.aisles.push(segment);
|
||||
continue 'RING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO Should plumb along the OSM ID too and warn here
|
||||
}
|
||||
|
||||
timer.start_iter("generate parking lot spots", results.len());
|
||||
@ -192,18 +194,19 @@ fn infer_spots(lot_polygon: &Polygon, aisles: &Vec<Vec<Pt2D>>) -> Vec<(Pt2D, Ang
|
||||
for pair in lines.windows(2) {
|
||||
let l1 = &pair[0];
|
||||
let l2 = &pair[1];
|
||||
let back = Line::must_new(l1.pt2(), l2.pt2());
|
||||
if l1.intersection(&l2).is_none()
|
||||
&& l1.angle().approx_eq(l2.angle(), 5.0)
|
||||
&& line_valid(lot_polygon, aisles, l1, &finalized_lines)
|
||||
&& line_valid(lot_polygon, aisles, l2, &finalized_lines)
|
||||
&& line_valid(lot_polygon, aisles, &back, &finalized_lines)
|
||||
{
|
||||
let avg_angle = (l1.angle() + l2.angle()) / 2.0;
|
||||
spots.push((back.middle().unwrap(), avg_angle.opposite()));
|
||||
finalized_lines.push(l1.clone());
|
||||
finalized_lines.push(l2.clone());
|
||||
finalized_lines.push(back);
|
||||
if let Some(back) = Line::new(l1.pt2(), l2.pt2()) {
|
||||
if l1.intersection(&l2).is_none()
|
||||
&& l1.angle().approx_eq(l2.angle(), 5.0)
|
||||
&& line_valid(lot_polygon, aisles, l1, &finalized_lines)
|
||||
&& line_valid(lot_polygon, aisles, l2, &finalized_lines)
|
||||
&& line_valid(lot_polygon, aisles, &back, &finalized_lines)
|
||||
{
|
||||
let avg_angle = (l1.angle() + l2.angle()) / 2.0;
|
||||
spots.push((back.middle().unwrap(), avg_angle.opposite()));
|
||||
finalized_lines.push(l1.clone());
|
||||
finalized_lines.push(l2.clone());
|
||||
finalized_lines.push(back);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,10 +68,13 @@ impl IntersectionCluster {
|
||||
continue;
|
||||
}
|
||||
|
||||
panic!(
|
||||
// TODO Saw this is New Orleans
|
||||
println!(
|
||||
"Need a cluster containing {:?} for turn restrictions, but there's more than one \
|
||||
existing cluster that partly covers it. Union them?"
|
||||
existing cluster that partly covers it. Union them?",
|
||||
members
|
||||
);
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
clusters
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::make::initial::lane_specs::get_lane_specs;
|
||||
use crate::{osm, AreaType, IntersectionType, LaneType, MapConfig};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Tags, Timer};
|
||||
use geom::{Angle, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Ring};
|
||||
use geom::{Angle, Circle, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D};
|
||||
use petgraph::graphmap::DiGraphMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
@ -189,7 +189,7 @@ impl RawMap {
|
||||
|
||||
let i = initial::Intersection {
|
||||
id,
|
||||
polygon: Vec::new(),
|
||||
polygon: Circle::new(Pt2D::new(0.0, 0.0), Distance::meters(1.0)).to_polygon(),
|
||||
roads: self.roads_per_intersection(id).into_iter().collect(),
|
||||
intersection_type: self.intersections[&id].intersection_type,
|
||||
elevation: self.intersections[&id].elevation,
|
||||
@ -202,10 +202,10 @@ impl RawMap {
|
||||
);
|
||||
}
|
||||
|
||||
let (i_pts, debug) =
|
||||
let (poly, debug) =
|
||||
initial::intersection_polygon(self.config.driving_side, &i, &mut roads, timer);
|
||||
(
|
||||
Ring::must_new(i_pts).to_polygon(),
|
||||
poly,
|
||||
roads
|
||||
.values()
|
||||
.map(|r| r.trimmed_center_pts.make_polygons(2.0 * r.half_width))
|
||||
|
Loading…
Reference in New Issue
Block a user