use geo_types::{Coord, Geometry};
use crate::algorithm::centroid::get_centroid;
use crate::geometry_adapter::{distance, is_geometry_empty};
pub(crate) struct InteriorPointPoint {
centroid: Option<Coord<f64>>,
min_distance: f64,
interior_point: Option<Coord<f64>>,
}
impl InteriorPointPoint {
pub(crate) fn new(g: &Geometry<f64>) -> Self {
let mut int_pt = Self {
centroid: get_centroid(g),
min_distance: f64::MAX,
interior_point: None,
};
int_pt.add_geometry(g);
int_pt
}
fn add_geometry(&mut self, geom: &Geometry<f64>) {
if is_geometry_empty(geom) {
return;
}
match geom {
Geometry::Point(p) => self.add_coordinate(p.0),
Geometry::MultiPoint(mp) => {
for p in &mp.0 {
self.add_coordinate(p.0);
}
}
Geometry::GeometryCollection(gc) => {
for g in &gc.0 {
self.add_geometry(g);
}
}
_ => {}
}
}
fn add_coordinate(&mut self, point: Coord<f64>) {
let dist = distance(
point,
self.centroid
.expect("centroid is set for a non-empty input"),
);
if dist < self.min_distance {
self.interior_point = Some(point);
self.min_distance = dist;
}
}
pub(crate) fn get_interior_point(&self) -> Option<Coord<f64>> {
self.interior_point
}
}
pub(crate) fn interior_point_point(geom: &Geometry<f64>) -> Option<Coord<f64>> {
let int_pt = InteriorPointPoint::new(geom);
int_pt.get_interior_point()
}