Skip to content

Commit

Permalink
Start labeling zone polygons. #46
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Jul 28, 2021
1 parent ce53294 commit 2c20f9c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 25 deletions.
69 changes: 46 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use geo::{map_coords::MapCoordsInplace, LineString, Point, Polygon};
use geographiclib_rs::{DirectGeodesic, Geodesic};
use geojson::GeoJson;
use std::convert::TryInto;
use std::default::Default;
use std::f64::consts::PI;
use std::{default::Default, iter::FromIterator};

use std::iter::FromIterator;
use structopt::StructOpt;

/// Generates a clockboard centered around a point. Returns a GeoJSON object with one feature per
Expand All @@ -15,7 +15,8 @@ pub fn clockboard(
// TODO Clip to a boundary
//boundary: Option<Polygon<f64>>,
) -> GeoJson {
let mut polygons: Vec<Polygon<f64>> = Vec::new();
// Each zone has a name and a polygon
let mut zones: Vec<(String, Polygon<f64>)> = Vec::new();

let crs = if params.projected {
None
Expand All @@ -24,16 +25,20 @@ pub fn clockboard(
};

// The innermost zone is just a circle
polygons.push(Polygon::new(
make_circle(
center,
params.distances[0],
params.num_vertices_arc * params.num_segments,
crs,
zones.push((
"A".to_string(),
Polygon::new(
make_circle(
center,
params.distances[0],
params.num_vertices_arc * params.num_segments,
crs,
),
Vec::new(),
),
Vec::new(),
));

let mut ring_name = 'B';
for pair in params.distances.windows(2) {
let (inner_radius, outer_radius) = (pair[0], pair[1]);

Expand All @@ -51,30 +56,48 @@ pub fn clockboard(
params.num_vertices_arc * params.num_segments,
crs,
);
polygons.push(Polygon::new(outer_ring, vec![inner_ring]));
zones.push((
ring_name.to_string(),
Polygon::new(outer_ring, vec![inner_ring]),
));
} else {
// Each ring is chopped into num_segments
for idx in 0..params.num_segments {
polygons.push(clock_polygon(
center,
outer_radius,
inner_radius,
params.num_vertices_arc,
params.num_segments,
idx,
crs,
zones.push((
format!("{}{:02}", ring_name, idx),
clock_polygon(
center,
outer_radius,
inner_radius,
params.num_vertices_arc,
params.num_segments,
idx,
crs,
),
));
}
}

// B -> C, C -> D, etc in ASCII
ring_name = std::char::from_u32(ring_name as u32 + 1).expect("too may rings");
}

for poly in &mut polygons {
for (_, poly) in &mut zones {
round(poly, params.precision);
}

let gc = geo::GeometryCollection::from_iter(polygons);
let fc = geojson::FeatureCollection::from(&gc);
GeoJson::from(fc)
// Transform the labelled polygons from the geo crate into the geojson crate. Ideally we could
// directly map each (name, polygon) into a geojson::Feature, but the conversion APIs are
// confusing...
let geom_collection =
geo::GeometryCollection::from_iter(zones.iter().map(|(_, poly)| poly.clone()));
let mut feature_collection = geojson::FeatureCollection::from(&geom_collection);
for (feature, (name, _)) in feature_collection.features.iter_mut().zip(zones) {
let mut properties = serde_json::Map::new();
properties.insert("name".to_string(), name.into());
feature.properties = Some(properties);
}
GeoJson::from(feature_collection)
}

/// Configures a clockboard diagram
Expand Down
15 changes: 13 additions & 2 deletions web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ <h1><a href="https://zonebuilders.github.io/zonebuilder/articles/paper.html" tar
// Create an empty GeoJSON layer
var clockboard = L.geoJSON().addTo(map);

function labelZones(feature, layer) {
var center = L.polygon(feature.geometry.coordinates).getBounds().getCenter();

layer.bindTooltip(feature.properties.name);

// TODO This doesn't seem to work...
var marker = L.marker(center, { opacity: 0.1 });
marker.bindTooltip(feature.properties.name, { permanent: true });
marker.addTo(map);
}

// When you click the generate button, recalculate and display the clockboard layer.
// TODO Make everything event-based -- no regenerate button. As soon as
// you move a slider or the marker, redraw the clockboard.
Expand All @@ -80,7 +91,7 @@ <h1><a href="https://zonebuilders.github.io/zonebuilder/articles/paper.html" tar
var num_circles = parseInt(document.getElementById('num_circles').value);
var distances = generate_triangular_sequence(num_circles);
var rawJson = JSON.parse(make_clockboard(marker.getLatLng().lat, marker.getLatLng().lng, distances, num_segments));
clockboard = L.geoJSON(rawJson).addTo(map);
clockboard = L.geoJSON(rawJson, { onEachFeature: labelZones }).addTo(map);

// Also update sliders
document.getElementById('num_circles_value').innerHTML = num_circles;
Expand Down Expand Up @@ -111,4 +122,4 @@ <h1><a href="https://zonebuilders.github.io/zonebuilder/articles/paper.html" tar
</script>
</body>

</html>
</html>

0 comments on commit 2c20f9c

Please sign in to comment.