use crate::geometry::primitives::Point;
use crate::geometry::shapes::Rectangle;
pub trait Distance<Rhs = Self> {
fn distance(&self, other: &Rhs) -> f64;
}
pub trait Area {
fn area(&self) -> f64;
}
pub trait Centroid {
fn centroid(&self) -> Point;
}
pub trait Perimeter {
fn perimeter(&self) -> f64;
}
pub trait BoundingBox {
fn bounding_box(&self) -> Rectangle;
}
pub trait Closed: Sized + Area + BoundingBox + Perimeter + Centroid {
fn contains(&self, other: &Self) -> bool;
fn contains_point(&self, point: &Point) -> bool;
fn intersects(&self, other: &Self) -> bool;
fn intersection_area(&self, other: &Self) -> f64;
fn intersection_points(&self, other: &Self) -> Vec<Point>;
}
pub trait DiagramShape: Closed {
fn compute_exclusive_regions(
shapes: &[Self],
) -> std::collections::HashMap<crate::geometry::diagram::RegionMask, f64>
where
Self: Sized;
fn params_from_circle(x: f64, y: f64, radius: f64) -> Vec<f64>
where
Self: Sized;
fn n_params() -> usize
where
Self: Sized;
fn from_params(params: &[f64]) -> Self
where
Self: Sized;
fn to_params(&self) -> Vec<f64>;
fn compute_exclusive_regions_with_gradient(
_shapes: &[Self],
) -> Option<ExclusiveRegionsAndGradient>
where
Self: Sized,
{
None
}
}
pub type ExclusiveRegionsAndGradient = (
std::collections::HashMap<crate::geometry::diagram::RegionMask, f64>,
std::collections::HashMap<crate::geometry::diagram::RegionMask, Vec<f64>>,
);
pub trait Polygonize {
fn polygonize(&self, n_vertices: usize) -> crate::geometry::shapes::Polygon;
}
pub fn bounding_box<S: BoundingBox>(shapes: &[S]) -> Rectangle {
let mut min_x = f64::INFINITY;
let mut min_y = f64::INFINITY;
let mut max_x = f64::NEG_INFINITY;
let mut max_y = f64::NEG_INFINITY;
for shape in shapes {
let points = shape.bounding_box().to_points();
min_x = min_x.min(points.0.x());
min_y = min_y.min(points.0.y());
max_x = max_x.max(points.1.x());
max_y = max_y.max(points.1.y());
}
Rectangle::from_corners(Point::new(min_x, min_y), Point::new(max_x, max_y))
}