geo
geo copied to clipboard
Point boundaries
I've been using this crate recently for some robotics path planning experiments. I've done similar work using python and shapely, and the fact that this crate offers a lot of the features shapely does I felt like it was a great fit(thanks for making this crate). One thing I haven't figure out how to do is create a circle with a radius. In shapely you do this by adding a boundary to a circle(see here for example), and then if you intersect a line with this point it intersects this boundary. I don't see any way to do this in geo currently. It would be nice to be able to either have a Circle geo-type, or similar to shapely have a point that can have a defined boundary of a given radius which can be intersected and used for Contains
trait. I'm not sure if this is implemented, or a proper way of doing this exists. If not I can see if I can create a PR if anyone would offer a little guidance on getting started.
For anyone else with this same issue my current workaround is to create a polygon which represents the circle. I do this by plotting points around the circumference radius length from the center like so(code isn't tested):
use std::f64::consts::PI;
fn create_circle(center: Coordinate<f64>, radius: f64) -> Polygon<f64> {
let (cx, cy) = center.x_y();
let circum = 2.0 * PI * radius;
// this controls how many points to create by dividing circum by 10 units of measurement
let n = (circum / 10.0).ceil();
let mut points = Vec::<(f64, f64)>::new();
for _x in 0..n as usize + 1 {
let x = _x as f64;
points.push( (((2.0 * PI / n * x).cos() * radius) + cx, ((2.0 * PI / n *x).sin() * radius) + cy) )
}
Polygon::new(LineString::from(points), vec![])
}
The issue for us is that we don't yet have a way of buffering geometries (which is what creates the boundary, in the case of a circle). It's a fairly complex algorithm and implementation (do we include different end cap styles in the public API etc). I know that https://github.com/lelongg/geo-offset provides some (or all? I haven't had a chance to look at it properly) of the functionality using the Martinez-Rueda algorithm, and uses geo-types
for primitives, so it may be useful to you…
(I should also note thatgeo-offset
makes use of geo-clipper
for its boolean operations, which in turn requires the use of Clipper
, which may or may not be a deal-breaker for you)
I appreciate the quick response. I had no idea the complexity was so high on this. My work around is working. I'm just making "circles" from Polygons. I thought with a lot of circles this wouldn't scale well, but I'm happy to report that's not the case.
Let me share my implementation for creating a circle with a radius in meter:
pub fn generate_geo_circle(location: &geo::Point<f64>, radius: f64) -> geo::Polygon<f64> {
// generate a point in distance in every 10 degree bearing
let points: Vec<geo::Point<f64>> = (0..=36)
.map(|i| location.haversine_destination(i as f64 * 10_f64, radius))
.collect();
geo::Polygon::new(geo::LineString::from(points), Vec::new())
}
See also https://github.com/georust/geo/pull/935