use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeoPolygon {
#[serde(rename = "type")]
pub type_name: String,
pub coordinates: Vec<Vec<Vec<f64>>>, }
impl GeoPolygon {
pub fn new(coordinates: Vec<Vec<Vec<f64>>>) -> Self {
Self { type_name: "Polygon".to_string(), coordinates }
}
pub fn contains(&self, lat: f64, lon: f64) -> bool {
if self.coordinates.is_empty() {
return false;
}
let exterior = &self.coordinates[0];
if !point_in_ring(lon, lat, exterior) {
return false;
}
for hole in self.coordinates.iter().skip(1) {
if point_in_ring(lon, lat, hole) {
return false;
}
}
true
}
}
fn point_in_ring(x: f64, y: f64, ring: &[Vec<f64>]) -> bool {
let mut inside = false;
let n = ring.len();
if n < 3 { return false; }
let mut j = n - 1;
for i in 0..n {
let xi = ring[i][0];
let yi = ring[i][1];
let xj = ring[j][0];
let yj = ring[j][1];
let intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if intersect { inside = !inside; }
j = i;
}
inside
}