use std::sync::Arc;
use itertools::Itertools;
use crate::collision_detection::cd_engine::CDEngine;
use crate::collision_detection::hazard::Hazard;
use crate::collision_detection::hazard::HazardEntity;
use crate::entities::quality_zone::InferiorQualityZone;
use crate::entities::quality_zone::N_QUALITIES;
use crate::fsize;
use crate::geometry::geo_traits::Shape;
use crate::geometry::primitives::aa_rectangle::AARectangle;
use crate::geometry::primitives::simple_polygon::SimplePolygon;
use crate::geometry::transformation::Transformation;
use crate::util::config::CDEConfig;
#[derive(Clone, Debug)]
pub struct Bin {
pub id: usize,
pub outer: Arc<SimplePolygon>,
pub value: u64,
pub pretransform: Transformation,
pub holes: Vec<Arc<SimplePolygon>>,
pub quality_zones: [Option<InferiorQualityZone>; N_QUALITIES],
pub base_cde: Arc<CDEngine>,
pub area: fsize,
}
impl Bin {
pub fn new(
id: usize,
outer: SimplePolygon,
value: u64,
pretransform: Transformation,
holes: Vec<SimplePolygon>,
quality_zones: Vec<InferiorQualityZone>,
cde_config: CDEConfig,
) -> Self {
let outer = Arc::new(outer);
let holes = holes.into_iter().map(Arc::new).collect_vec();
assert_eq!(
quality_zones.len(),
quality_zones.iter().map(|qz| qz.quality).unique().count(),
"Quality zones must have unique qualities"
);
assert!(
quality_zones
.iter()
.map(|qz| qz.quality)
.all(|q| q < N_QUALITIES),
"All quality zones must be below N_QUALITIES"
);
let quality_zones = {
let mut qz = <[_; N_QUALITIES]>::default();
for q in quality_zones {
let quality = q.quality;
qz[quality] = Some(q);
}
qz
};
let bin_hazards = generate_bin_hazards(&outer, &holes, &quality_zones);
let base_cde = CDEngine::new(outer.bbox().inflate_to_square(), bin_hazards, cde_config);
let base_cde = Arc::new(base_cde);
let area = outer.area() - holes.iter().map(|h| h.area()).sum::<fsize>();
Self {
id,
outer,
value,
pretransform,
holes,
quality_zones,
base_cde,
area,
}
}
pub fn from_strip(rect: AARectangle, cde_config: CDEConfig) -> Self {
let id = 0;
let pretransform = Transformation::from_translation((rect.x_min, rect.y_min));
let poly = SimplePolygon::from(rect);
let value = poly.area() as u64;
Bin::new(id, poly, value, pretransform, vec![], vec![], cde_config)
}
pub fn bbox(&self) -> AARectangle {
self.outer.bbox()
}
}
fn generate_bin_hazards(
outer: &Arc<SimplePolygon>,
holes: &[Arc<SimplePolygon>],
quality_zones: &[Option<InferiorQualityZone>],
) -> Vec<Hazard> {
let mut hazards = vec![Hazard::new(HazardEntity::BinExterior, outer.clone())];
hazards.extend(holes.iter().enumerate().map(|(i, shape)| {
let haz_entity = HazardEntity::BinHole { id: i };
Hazard::new(haz_entity, shape.clone())
}));
for q_zone in quality_zones.iter().flatten() {
for (id, shape) in q_zone.zones.iter().enumerate() {
let haz_entity = HazardEntity::InferiorQualityZone {
quality: q_zone.quality,
id,
};
hazards.push(Hazard::new(haz_entity, shape.clone()));
}
}
hazards
}