Add an API call to export intersection geometry to geojson, for experimental streetmix3d integration.

To get an example:
> cargo run --bin headless -- --port=1234
> curl http://localhost:1234/map/get-intersection-geometry?id=291
This commit is contained in:
Dustin Carlino 2020-10-29 12:00:34 -07:00
parent 3ed7e73aa8
commit f187cf4bd8
5 changed files with 77 additions and 0 deletions

2
Cargo.lock generated
View File

@ -1278,6 +1278,7 @@ name = "headless"
version = "0.1.0"
dependencies = [
"abstutil",
"geojson",
"geom",
"hyper",
"lazy_static",
@ -1286,6 +1287,7 @@ dependencies = [
"rand",
"rand_xorshift",
"serde",
"serde_json",
"sim",
"tokio",
"url",

View File

@ -90,6 +90,10 @@ are missing, etc. A summary of the commands available so far:
`--edits=name_of_edits`.
- **GET /map/get-edit-road-command?id=123**: Returns an object that can be
modified and then added to map edits.
- **GET /map/get-intersection-geometry?id=123**: Returns a GeoJSON object with
one feature for the intersection and a feature for all connecting roads. The
polygon coordinates are measured in meters, with the origin centered at the
intersection's center.
## Working with the map model

View File

@ -75,6 +75,17 @@ impl PolyLine {
PolyLine::new(pts)
}
/// Like make_polygons, but make sure the points actually form a ring.
pub fn to_thick_ring(&self, width: Distance) -> Ring {
let mut side1 = self.shift_with_sharp_angles(width / 2.0, MITER_THRESHOLD);
let mut side2 = self.shift_with_sharp_angles(-width / 2.0, MITER_THRESHOLD);
side2.reverse();
side1.extend(side2);
side1.push(side1[0]);
side1.dedup();
Ring::must_new(side1)
}
pub fn to_thick_boundary(
&self,
self_width: Distance,

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
abstutil = { path = "../abstutil" }
geojson = "0.19.0"
geom = { path = "../geom" }
hyper = "0.13.8"
lazy_static = "1.4.0"
@ -14,6 +15,7 @@ map_model = { path = "../map_model" }
rand = "0.7.0"
rand_xorshift = "0.2.0"
serde = "1.0.116"
serde_json = "1.0.57"
sim = { path = "../sim" }
tokio = { version = "0.2.22", features = ["full"] }
url = "2.1.1"

View File

@ -325,6 +325,10 @@ fn handle_command(
&map.edit_road_cmd(r, |_| {}).to_perma(map),
))
}
"/map/get-intersection-geometry" => {
let i = IntersectionID(params["id"].parse::<usize>()?);
Ok(abstutil::to_json(&export_geometry(map, i)))
}
_ => Err("Unknown command".into()),
}
}
@ -415,3 +419,57 @@ impl LoadSim {
(map, sim)
}
}
fn export_geometry(map: &Map, i: IntersectionID) -> geojson::GeoJson {
use geojson::{Feature, FeatureCollection, GeoJson, Geometry, Value};
let i = map.get_i(i);
// Translate all geometry to center around the intersection, with distances in meters.
let center = i.polygon.center();
// The intersection itself
let mut props = serde_json::Map::new();
props.insert("type".to_string(), "intersection".into());
props.insert("id".to_string(), i.orig_id.to_string().into());
let mut features = vec![Feature {
bbox: None,
geometry: Some(Geometry::new(Value::Polygon(vec![i
.polygon
.translate(-center.x(), -center.y())
.points()
.iter()
.map(|pt| vec![pt.x(), pt.y()])
.collect()]))),
id: None,
properties: Some(props),
foreign_members: None,
}];
// Each connected road
for r in &i.roads {
let r = map.get_r(*r);
let mut props = serde_json::Map::new();
props.insert("type".to_string(), "road".into());
props.insert("id".to_string(), r.orig_id.osm_way_id.to_string().into());
features.push(Feature {
bbox: None,
geometry: Some(Geometry::new(Value::Polygon(vec![r
.center_pts
.to_thick_ring(2.0 * r.get_half_width(map))
.into_points()
.into_iter()
.map(|pt| pt.offset(-center.x(), -center.y()))
.map(|pt| vec![pt.x(), pt.y()])
.collect()]))),
id: None,
properties: Some(props),
foreign_members: None,
});
}
GeoJson::from(FeatureCollection {
bbox: None,
features,
foreign_members: None,
})
}