diff --git a/jagua-rs/src/collision_detection/hazard.rs b/jagua-rs/src/collision_detection/hazard.rs index 248a97d..74561ba 100644 --- a/jagua-rs/src/collision_detection/hazard.rs +++ b/jagua-rs/src/collision_detection/hazard.rs @@ -4,15 +4,14 @@ use crate::entities::placed_item::PlacedItemUID; use crate::geometry::geo_enums::GeoPosition; use crate::geometry::primitives::simple_polygon::SimplePolygon; -/// Defines a certain spatial constraint that affects the feasibility of placed items -/// Hazards are defined by a certain entity, have a shape and can be active or inactive +/// Defines a certain spatial constraint that affects the feasibility of an item placement. #[derive(Clone, Debug)] pub struct Hazard { /// The entity inducing the hazard pub entity: HazardEntity, /// The shape of the hazard pub shape: Arc, - /// Whether the hazard is currently active or not + /// Hazards can be either active or inactive, inactive hazards are not considered during collision detection pub active: bool, } @@ -27,16 +26,20 @@ impl Hazard { } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -/// Entity inducing a hazard, every hazard entity must be unique +/// Entity inducing the `Hazard`. All entities are uniquely identified. pub enum HazardEntity { + /// An item placed in the layout. PlacedItem(PlacedItemUID), + /// Represents all regions outside the bin BinExterior, + /// Represents a hole in the bin. BinHole { id: usize }, + /// Represents a zone in the bin with a specific quality level that is inferior to the base quality. QualityZoneInferior { quality: usize, id: usize }, } impl HazardEntity { - /// Whether the entity induces an Interior or Exterior hazard + /// Whether the entity induces an `Interior` or `Exterior` hazard pub fn position(&self) -> GeoPosition { match self { HazardEntity::PlacedItem(_) => GeoPosition::Interior, @@ -46,7 +49,7 @@ impl HazardEntity { } } - /// True if the hazard is dynamic in nature, i.e. it can be modified by the optimizer + /// Whether the entity is dynamic in nature, i.e. it can be modified in the layout pub fn dynamic(&self) -> bool { match self { HazardEntity::PlacedItem(_) => true, @@ -56,7 +59,7 @@ impl HazardEntity { } } - /// Returns true if the hazard is universally applicable, i.e. all items are affected by it + /// Whether the entity universally applicable, i.e. all items need to be checked against it pub fn universal(&self) -> bool { match self { HazardEntity::PlacedItem(_) => true, diff --git a/jagua-rs/src/collision_detection/hazard_filter.rs b/jagua-rs/src/collision_detection/hazard_filter.rs index 706ccad..a37a014 100644 --- a/jagua-rs/src/collision_detection/hazard_filter.rs +++ b/jagua-rs/src/collision_detection/hazard_filter.rs @@ -3,13 +3,13 @@ use itertools::Itertools; use crate::collision_detection::hazard::Hazard; use crate::collision_detection::hazard::HazardEntity; -/// Trait that allows for filtering out irrelevant hazards depending on the context. -/// Enables ignoring certain hazards when querying the CDE. +/// Trait that allows for ignoring out specific hazards. +/// Enables querying the `CDEngine` only for relevant hazards. pub trait HazardFilter { fn is_irrelevant(&self, entity: &HazardEntity) -> bool; } -/// Returns the entities that are deemed irrelevant by the given filter from a set of `Hazard`s +/// Returns the entities that are deemed irrelevant by the specified `HazardFilter`. pub fn generate_irrelevant_hazards<'a>( filter: &impl HazardFilter, hazards: impl Iterator, @@ -26,22 +26,22 @@ pub fn generate_irrelevant_hazards<'a>( #[derive(Clone)] pub struct BinHazardFilter; -/// Deems hazards induced by `QualityZone`s above a certain quality as irrelevant +/// Deems hazards induced by `QualityZone`s above a certain quality as irrelevant. #[derive(Clone, Debug)] pub struct QZHazardFilter { pub cutoff_quality: usize, } -/// Combines multiple `HazardFilter`s into a single filter -pub struct CombinedHazardFilter<'a> { - pub filters: Vec>, -} - -/// Deems hazards induced by specific entities as irrelevant +/// Deems hazards induced by specific entities as irrelevant. pub struct EntityHazardFilter { pub entities: Vec, } +/// Combines multiple `HazardFilter`s into a single filter. +pub struct CombinedHazardFilter<'a> { + pub filters: Vec>, +} + impl HazardFilter for BinHazardFilter { fn is_irrelevant(&self, entity: &HazardEntity) -> bool { match entity { diff --git a/jagua-rs/src/geometry/primitives/mod.rs b/jagua-rs/src/geometry/primitives/mod.rs index 4a5d0df..0954b10 100644 --- a/jagua-rs/src/geometry/primitives/mod.rs +++ b/jagua-rs/src/geometry/primitives/mod.rs @@ -1,6 +1,5 @@ pub mod aa_rectangle; +pub mod circle; pub mod edge; pub mod point; pub mod simple_polygon; - -pub mod circle; diff --git a/jagua-rs/src/geometry/primitives/simple_polygon.rs b/jagua-rs/src/geometry/primitives/simple_polygon.rs index fb816f3..511cd35 100644 --- a/jagua-rs/src/geometry/primitives/simple_polygon.rs +++ b/jagua-rs/src/geometry/primitives/simple_polygon.rs @@ -24,11 +24,16 @@ use crate::util::f64a::F64A; /// Geometric primitive representing a simple polygon: #[derive(Clone, Debug)] pub struct SimplePolygon { + /// Set of bounds describing the polygon pub points: Vec, + /// Bounding box pub bbox: AARectangle, pub area: f64, + /// Maximum distance between any two points in the polygon pub diameter: f64, + /// Pole of inaccessibility pub poi: Circle, + /// Surrogate representation (subset of the simple polygon) pub surrogate: Option, } @@ -129,7 +134,7 @@ impl SimplePolygon { } //https://en.wikipedia.org/wiki/Shoelace_formula - //counter clockwise = positive area, clockwise = negative area + //counterclockwise = positive area, clockwise = negative area pub fn calculate_area(points: &[Point]) -> f64 { let mut sigma: f64 = 0.0; for i in 0..points.len() { diff --git a/jagua-rs/src/io/json_instance.rs b/jagua-rs/src/io/json_instance.rs index 924cf54..bbbd6ca 100644 --- a/jagua-rs/src/io/json_instance.rs +++ b/jagua-rs/src/io/json_instance.rs @@ -9,11 +9,11 @@ pub struct JsonInstance { /// Set of items to be produced #[serde(rename = "Items")] pub items: Vec, - /// Set of bins where the items are to be placed (for Bin Packing problems) + /// Containers for a Bin Packing Problem #[serde(rename = "Objects")] #[serde(skip_serializing_if = "Option::is_none")] pub bins: Option>, - /// A strip where the items are to be placed (for Strip Packing problems) + /// Container for a Strip Packing Problem #[serde(rename = "Strip")] #[serde(skip_serializing_if = "Option::is_none")] pub strip: Option, @@ -34,7 +34,7 @@ pub struct JsonBin { pub zones: Vec, } -/// The JSON representation of a strip +/// The JSON representation of a strip with fixed height and variable width #[derive(Serialize, Deserialize, Clone)] #[serde(rename_all = "PascalCase")] pub struct JsonStrip { @@ -47,7 +47,7 @@ pub struct JsonStrip { pub struct JsonItem { /// Number of times this item should be produced pub demand: u64, - /// List of allowed orientations angles (in degrees), if not present, any orientation is allowed + /// List of allowed orientations angles (in degrees). If none any orientation is allowed #[serde(skip_serializing_if = "Option::is_none")] pub allowed_orientations: Option>, /// Polygon shape of the item @@ -58,13 +58,18 @@ pub struct JsonItem { pub base_quality: Option, } -/// An enum containing all the possible possibilities to define a shape +/// All possible ways to represent a shape #[derive(Serialize, Deserialize, Clone)] #[serde(tag = "Type", content = "Data")] #[serde(rename_all = "PascalCase")] pub enum JsonShape { + /// Axis-aligned rectangle + Rectangle { width: f64, height: f64 }, + /// Polygon with a single outer boundary SimplePolygon(JsonSimplePoly), + /// Polygon with a single outer boundary and a list of holes Polygon(JsonPoly), + /// Multiple disjoint polygons MultiPolygon(Vec), } @@ -75,7 +80,7 @@ pub struct JsonPoly { /// The outer boundary of the polygon pub outer: JsonSimplePoly, /// A list of holes in the polygon - #[serde(skip_serializing_if = "Vec::is_empty", default)] + #[serde(default)] pub inner: Vec, } diff --git a/jagua-rs/src/io/json_solution.rs b/jagua-rs/src/io/json_solution.rs index a337fec..0560802 100644 --- a/jagua-rs/src/io/json_solution.rs +++ b/jagua-rs/src/io/json_solution.rs @@ -63,8 +63,8 @@ pub enum JsonContainer { index: usize, }, Strip { - /// The length of the strip (variable) - #[serde(rename = "Length")] + /// The width of the strip (variable) + #[serde(rename = "Width")] width: f64, /// The height of the strip (fixed) #[serde(rename = "Height")] diff --git a/jagua-rs/src/io/parser.rs b/jagua-rs/src/io/parser.rs index d5a81a7..95114ee 100644 --- a/jagua-rs/src/io/parser.rs +++ b/jagua-rs/src/io/parser.rs @@ -21,6 +21,7 @@ use crate::entities::solution::Solution; use crate::geometry::d_transformation::DTransformation; use crate::geometry::geo_enums::AllowedRotation; use crate::geometry::geo_traits::{Shape, Transformable}; +use crate::geometry::primitives::aa_rectangle::AARectangle; use crate::geometry::primitives::point::Point; use crate::geometry::primitives::simple_polygon::SimplePolygon; use crate::geometry::transformation::Transformation; @@ -62,6 +63,10 @@ impl Parser { for (item_id, json_item) in json_instance.items.iter().enumerate() { let handle = s.spawn(move |_| { let (shape, centering_transf) = match &json_item.shape { + JsonShape::Rectangle{ width, height } => { + let shape = SimplePolygon::from(AARectangle::new(0.0, 0.0, *width, *height)); + (shape, Transformation::empty()) + } JsonShape::SimplePolygon(sp) => convert_json_simple_poly( sp, self.center_polygons, @@ -118,6 +123,10 @@ impl Parser { for (bin_id, json_bin) in json_bins.iter().enumerate() { let handle = s.spawn(move |_| { let (bin_outer, centering_transf) = match &json_bin.shape { + JsonShape::Rectangle {width, height} => { + let shape = SimplePolygon::from(AARectangle::new(0.0, 0.0, *width, *height)); + (shape, Transformation::empty()) + } JsonShape::SimplePolygon(jsp) => convert_json_simple_poly( jsp, self.center_polygons, @@ -136,7 +145,7 @@ impl Parser { }; let bin_holes = match &json_bin.shape { - JsonShape::SimplePolygon(_) => vec![], + JsonShape::SimplePolygon(_) | JsonShape::Rectangle {..} => vec![], JsonShape::Polygon(jp) => jp .inner .iter() @@ -172,6 +181,10 @@ impl Parser { .filter(|zone| zone.quality == quality) .map(|zone| { let (zone_shape, _) = match &zone.shape { + JsonShape::Rectangle { width, height } => { + let shape = SimplePolygon::from(AARectangle::new(0.0, 0.0, *width, *height)); + (shape, Transformation::empty()) + } JsonShape::SimplePolygon(jsp) => convert_json_simple_poly( jsp, false, diff --git a/lbf/src/samplers/ls_sampler.rs b/lbf/src/samplers/ls_sampler.rs index cc2d813..299f16c 100644 --- a/lbf/src/samplers/ls_sampler.rs +++ b/lbf/src/samplers/ls_sampler.rs @@ -37,19 +37,19 @@ impl LSSampler { sd_transl_range: (f64, f64), sd_rot_range: (f64, f64), ) -> Self { - let stddev_transl = sd_transl_range.0; - let stddev_rot = sd_rot_range.0; + let sd_transl = sd_transl_range.0; + let sd_rot = sd_rot_range.0; - let normal_x = Normal::new(ref_transform.translation().0, stddev_transl).unwrap(); - let normal_y = Normal::new(ref_transform.translation().1, stddev_transl).unwrap(); - let normal_r = NormalRotDistr::from_item(item, ref_transform.rotation(), stddev_rot); + let normal_x = Normal::new(ref_transform.translation().0, sd_transl).unwrap(); + let normal_y = Normal::new(ref_transform.translation().1, sd_transl).unwrap(); + let normal_r = NormalRotDistr::from_item(item, ref_transform.rotation(), sd_rot); Self { normal_x, normal_y, normal_r, - sd_transl: stddev_transl, - sd_rot: stddev_rot, + sd_transl, + sd_rot, sd_transl_range, sd_rot_range, } @@ -58,8 +58,8 @@ impl LSSampler { /// Creates a new sampler with default standard deviation ranges: [SD_TRANSL] and [SD_ROT]. pub fn from_defaults(item: &Item, ref_transform: &DTransformation, bbox: &AARectangle) -> Self { let max_dim = f64::max(bbox.width(), bbox.height()); - let stddev_transl_range = (SD_TRANSL.0 * max_dim, SD_TRANSL.1 * max_dim); - Self::new(item, ref_transform, stddev_transl_range, SD_ROT) + let sd_transl_range = (SD_TRANSL.0 * max_dim, SD_TRANSL.1 * max_dim); + Self::new(item, ref_transform, sd_transl_range, SD_ROT) } /// Shifts the mean of the normal distributions to the given reference transformation.