use hyperreal::{Real, RealSign};
use crate::{PackError, PackResult};
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ItemId(String);
#[derive(Clone, Debug, PartialEq)]
pub struct AxisBox3 {
pub x: Real,
pub y: Real,
pub z: Real,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Item3 {
pub id: ItemId,
pub size: AxisBox3,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Bin3 {
pub size: AxisBox3,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ContainerFrame3 {
pub name: String,
pub unit: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Placement3 {
pub item: ItemId,
pub x: Real,
pub y: Real,
pub z: Real,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum HeuristicFamily {
Shelf2,
Skyline2,
MaxRects2,
Guillotine2,
ExtremePoint3,
MaximalSpace3,
Dblf3,
Layer3,
Laff3,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FreeSpaceReport3 {
pub boxes: Vec<AxisBox3>,
pub exact: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct LowerBoundReport {
pub lower_bound: Real,
pub incumbent: Option<Real>,
pub method: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct PackingReport3 {
pub heuristic: HeuristicFamily,
pub seed: u64,
pub placements: Vec<Placement3>,
pub free_space: FreeSpaceReport3,
pub lower_bound: Option<LowerBoundReport>,
}
impl ItemId {
pub fn new(value: impl Into<String>) -> PackResult<Self> {
let value = value.into();
if value.is_empty() {
return Err(PackError::EmptyIdentifier);
}
Ok(Self(value))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl AxisBox3 {
pub fn new(x: Real, y: Real, z: Real) -> PackResult<Self> {
for value in [&x, &y, &z] {
match value.refine_sign_until(-64) {
Some(RealSign::Positive) => {}
Some(RealSign::Negative | RealSign::Zero) | None => {
return Err(PackError::NonPositiveDimension);
}
}
}
Ok(Self { x, y, z })
}
pub fn volume(&self) -> Real {
&self.x * &self.y * &self.z
}
}