Skip to content

Commit

Permalink
Debug how roads are being ordered around an intersection, and restore…
Browse files Browse the repository at this point in the history
… map_editor's ability to preview one intersection with the debugging geometry. #654
  • Loading branch information
dabreegster committed Jul 20, 2021
1 parent ab83fd0 commit 6f549e5
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 15 deletions.
10 changes: 9 additions & 1 deletion map_editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl MainState {
let model = if let Some(path) = load {
Model::import(ctx, path, include_bldgs)
} else {
Model::blank()
Model::blank(ctx)
};
if !model.map.name.map.is_empty() {
CameraState::load(ctx, &model.map.name);
Expand Down Expand Up @@ -187,6 +187,8 @@ impl State<App> for MainState {
app.model.world.handle_mouseover(ctx);
} else if ctx.input.pressed(Key::T) {
app.model.toggle_i(ctx, i);
} else if ctx.input.pressed(Key::P) {
app.model.debug_intersection_geometry(ctx, i);
}

let mut txt = Text::new();
Expand All @@ -210,6 +212,11 @@ impl State<App> for MainState {
Key::T.txt(ctx),
Line(" to toggle stop sign / traffic signal"),
]);
txt.add_appended(vec![
Line("- Press "),
Key::P.txt(ctx),
Line(" to debug intersection geometry"),
]);
let instructions = txt.into_widget(ctx);
self.panel.replace(ctx, "instructions", instructions);
}
Expand Down Expand Up @@ -464,6 +471,7 @@ impl State<App> for MainState {
app.model.map.boundary_polygon.clone(),
);
app.model.world.draw(g, |_| true);
g.redraw(&app.model.draw_extra);

match self.mode {
Mode::CreatingRoad(i1) => {
Expand Down
25 changes: 22 additions & 3 deletions map_editor/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use abstutil::{Tags, Timer};
use geom::{Bounds, Circle, Distance, FindClosest, GPSBounds, HashablePt2D, LonLat, Polygon, Pt2D};
use map_model::raw::{OriginalRoad, RawBuilding, RawIntersection, RawMap, RawRoad};
use map_model::{osm, IntersectionType};
use widgetry::{Color, EventCtx};
use widgetry::{Color, Drawable, EventCtx, GeomBatch, Line, Text};

use crate::world::{Object, ObjectID, World};

Expand All @@ -19,14 +19,15 @@ pub struct Model {
pub map: RawMap,
showing_pts: Option<OriginalRoad>,
pub world: World<ID>,
pub draw_extra: Drawable,

include_bldgs: bool,
intersection_geom: bool,
}

// Construction
impl Model {
pub fn blank() -> Model {
pub fn blank(ctx: &EventCtx) -> Model {
Model {
map: RawMap::blank(MapName {
city: CityName {
Expand All @@ -36,6 +37,7 @@ impl Model {
map: String::new(),
}),
showing_pts: None,
draw_extra: Drawable::empty(ctx),

include_bldgs: false,
world: World::new(),
Expand All @@ -45,7 +47,7 @@ impl Model {

pub fn import(ctx: &EventCtx, path: String, include_bldgs: bool) -> Model {
let mut timer = Timer::new("import map");
let mut model = Model::blank();
let mut model = Model::blank(ctx);
model.include_bldgs = include_bldgs;

model.map = if path.ends_with(".osm") {
Expand Down Expand Up @@ -237,6 +239,23 @@ impl Model {
self.world.delete(ID::Intersection(id));
self.intersection_added(ctx, id);
}

// Also clear out any debugged intersections
self.draw_extra = Drawable::empty(ctx);
}

pub fn debug_intersection_geometry(&mut self, ctx: &EventCtx, id: osm::NodeID) {
let mut batch = GeomBatch::new();
let (_, _, labels) = self.map.preview_intersection(id);
for (label, polygon) in labels {
let txt_batch = Text::from(Line(label).fg(Color::CYAN))
.render_autocropped(ctx)
.scale(0.1)
.centered_on(polygon.polylabel());
batch.push(Color::BLUE, polygon);
batch.append(txt_batch);
}
self.draw_extra = batch.upload(ctx);
}
}

Expand Down
35 changes: 25 additions & 10 deletions map_model/src/make/initial/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,34 +86,48 @@ pub fn intersection_polygon(
// intersection become less meaningful.
lines.sort_by_key(|(_, pt, _, _)| pt.angle_to(intersection_center).normalized_degrees() as i64);

let mut debug = Vec::new();
// Debug the sorted order.
if true {
debug.push((
"center".to_string(),
Circle::new(intersection_center, Distance::meters(1.0)).to_polygon(),
));
for (idx, (_, pt, _, _)) in lines.iter().enumerate() {
debug.push((
idx.to_string(),
Circle::new(*pt, Distance::meters(1.0)).to_polygon(),
));
}
}

if lines.len() == 1 {
return deadend(roads, intersection_id, &lines);
return deadend(roads, intersection_id, &lines, debug);
}
let rollback = lines
.iter()
.map(|(r, _, _, _)| (*r, roads[r].trimmed_center_pts.clone()))
.collect::<Vec<_>>();

if !trim_roads_for_merging.is_empty() {
pretrimmed_geometry(roads, intersection_id, &lines)
} else if let Some(result) = on_off_ramp(roads, intersection_id, lines.clone()) {
pretrimmed_geometry(roads, intersection_id, &lines, debug)
} else if let Some(result) = on_off_ramp(roads, intersection_id, lines.clone(), debug.clone()) {
Ok(result)
} else {
// on_off_ramp failed, so first restore lines
for (r, trimmed_center_pts) in rollback {
roads.get_mut(&r).unwrap().trimmed_center_pts = trimmed_center_pts;
}
generalized_trim_back(roads, intersection_id, &lines)
generalized_trim_back(roads, intersection_id, &lines, debug)
}
}

fn generalized_trim_back(
roads: &mut BTreeMap<OriginalRoad, Road>,
i: osm::NodeID,
lines: &[(OriginalRoad, Pt2D, PolyLine, PolyLine)],
mut debug: Vec<(String, Polygon)>,
) -> Result<(Polygon, Vec<(String, Polygon)>)> {
let mut debug = Vec::new();

let mut road_lines: Vec<(OriginalRoad, PolyLine)> = Vec::new();
for (r, _, pl1, pl2) in lines {
road_lines.push((*r, pl1.clone()));
Expand Down Expand Up @@ -321,6 +335,7 @@ fn pretrimmed_geometry(
roads: &mut BTreeMap<OriginalRoad, Road>,
i: osm::NodeID,
lines: &[(OriginalRoad, Pt2D, PolyLine, PolyLine)],
debug: Vec<(String, Polygon)>,
) -> Result<(Polygon, Vec<(String, Polygon)>)> {
let mut endpoints: Vec<Pt2D> = Vec::new();
for (r, _, _, _) in lines {
Expand All @@ -340,13 +355,14 @@ fn pretrimmed_geometry(
endpoints,
Distance::meters(0.1),
)))?;
Ok((result.into_polygon(), Vec::new()))
Ok((result.into_polygon(), debug))
}

fn deadend(
roads: &mut BTreeMap<OriginalRoad, Road>,
i: osm::NodeID,
lines: &[(OriginalRoad, Pt2D, PolyLine, PolyLine)],
debug: Vec<(String, Polygon)>,
) -> Result<(Polygon, Vec<(String, Polygon)>)> {
let len = DEGENERATE_INTERSECTION_HALF_LENGTH * 4.0;

Expand Down Expand Up @@ -395,7 +411,7 @@ fn deadend(
endpts.dedup();
Ok((
Ring::must_new(close_off_polygon(endpts)).into_polygon(),
Vec::new(),
debug,
))
}

Expand All @@ -422,6 +438,7 @@ fn on_off_ramp(
roads: &mut BTreeMap<OriginalRoad, Road>,
i: osm::NodeID,
lines: Vec<(OriginalRoad, Pt2D, PolyLine, PolyLine)>,
mut debug: Vec<(String, Polygon)>,
) -> Option<(Polygon, Vec<(String, Polygon)>)> {
if lines.len() != 3 {
return None;
Expand Down Expand Up @@ -451,8 +468,6 @@ fn on_off_ramp(
return None;
}

let mut debug = Vec::new();

let mut pieces = Vec::new();
// TODO Use this abstraction for all the code here?
for (id, _, right, left) in lines {
Expand Down
2 changes: 1 addition & 1 deletion map_model/src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl RawMap {
}
}

/// (Intersection polygon, polygons for roads, list of labeled polylines to debug)
/// (Intersection polygon, polygons for roads, list of labeled polygons to debug)
pub fn preview_intersection(
&self,
id: osm::NodeID,
Expand Down

0 comments on commit 6f549e5

Please sign in to comment.