use crate::geometry::Transformation;
use crate::geometry::convex_hull;
use crate::geometry::fail_fast::{piers, pole};
use crate::geometry::geo_traits::{Transformable, TransformableFrom};
use crate::geometry::primitives::Circle;
use crate::geometry::primitives::Edge;
use crate::geometry::primitives::SPolygon;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use anyhow::Result;
#[derive(Clone, Debug)]
pub struct SPSurrogate {
pub poles: Vec<Circle>,
pub piers: Vec<Edge>,
pub convex_hull_indices: Vec<usize>,
pub convex_hull_area: f32,
pub config: SPSurrogateConfig,
}
impl SPSurrogate {
pub fn new(simple_poly: &SPolygon, config: SPSurrogateConfig) -> Result<Self> {
let convex_hull_indices = convex_hull::convex_hull_indices(simple_poly);
let convex_hull_points = convex_hull_indices
.iter()
.map(|&i| simple_poly.vertices[i])
.collect_vec();
let convex_hull_area = SPolygon::calculate_area(&convex_hull_points);
let poles = pole::generate_surrogate_poles(simple_poly, &config.n_pole_limits)?;
let n_ff_poles = usize::min(config.n_ff_poles, poles.len());
let relevant_poles_for_piers = &poles[0..n_ff_poles]; let piers =
piers::generate_piers(simple_poly, config.n_ff_piers, relevant_poles_for_piers)?;
Ok(Self {
convex_hull_indices,
poles,
piers,
convex_hull_area,
config,
})
}
pub fn ff_poles(&self) -> &[Circle] {
&self.poles[0..self.config.n_ff_poles]
}
pub fn ff_piers(&self) -> &[Edge] {
&self.piers
}
}
impl Transformable for SPSurrogate {
fn transform(&mut self, t: &Transformation) -> &mut Self {
let Self {
convex_hull_indices: _,
poles,
piers,
convex_hull_area: _,
config: _,
} = self;
poles.iter_mut().for_each(|c| {
c.transform(t);
});
piers.iter_mut().for_each(|p| {
p.transform(t);
});
self
}
}
impl TransformableFrom for SPSurrogate {
fn transform_from(&mut self, reference: &Self, t: &Transformation) -> &mut Self {
debug_assert!(self.poles.len() == reference.poles.len());
debug_assert!(self.piers.len() == reference.piers.len());
let Self {
convex_hull_indices: _,
poles,
piers,
convex_hull_area: _,
config: _,
} = self;
for (pole, ref_pole) in poles.iter_mut().zip(reference.poles.iter()) {
pole.transform_from(ref_pole, t);
}
for (pier, ref_pier) in piers.iter_mut().zip(reference.piers.iter()) {
pier.transform_from(ref_pier, t);
}
self
}
}
const N_POLE_LIMITS: usize = 3;
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct SPSurrogateConfig {
pub n_pole_limits: [(usize, f32); N_POLE_LIMITS],
pub n_ff_poles: usize,
pub n_ff_piers: usize,
}
impl SPSurrogateConfig {
pub fn none() -> Self {
Self {
n_pole_limits: [(0, 0.0); N_POLE_LIMITS],
n_ff_poles: 0,
n_ff_piers: 0,
}
}
}