Skip to content

Commit

Permalink
improved docs & some minor refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
JeroenGar committed Feb 29, 2024
1 parent 3df4981 commit 6a808c7
Show file tree
Hide file tree
Showing 22 changed files with 123 additions and 104 deletions.
7 changes: 4 additions & 3 deletions jagua-rs/src/collision_detection/cd_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl CDEngine {
/// <br>
/// Call [`Self::commit_deregisters`] to commit all uncommitted deregisters in both quadtree & hazard proximity grid
/// or [`Self::flush_haz_prox_grid`] to just clear the hazard proximity grid.
pub fn deregister_hazard(&mut self, hazard_entity: &HazardEntity, commit_instantly: bool) {
pub fn deregister_hazard(&mut self, hazard_entity: &HazardEntity, commit_instant: bool) {
let haz_index = self
.dynamic_hazards
.iter()
Expand All @@ -123,15 +123,15 @@ impl CDEngine {

let hazard = self.dynamic_hazards.swap_remove(haz_index);

match commit_instantly {
match commit_instant {
true => self.quadtree.deregister_hazard(hazard_entity),
false => {
self.quadtree.deactivate_hazard(hazard_entity);
self.uncommitted_deregisters.push(hazard);
}
}
self.haz_prox_grid.as_mut().map(|hpg| {
hpg.deregister_hazard(hazard_entity, self.dynamic_hazards.iter(), commit_instantly)
hpg.deregister_hazard(hazard_entity, self.dynamic_hazards.iter(), commit_instant)
});
debug_assert!(assertions::qt_contains_no_dangling_hazards(&self));
}
Expand Down Expand Up @@ -247,6 +247,7 @@ impl CDEngine {
}
}

/// Flushes all uncommitted deregisters in the hazard proximity grid.
pub fn flush_haz_prox_grid(&mut self) {
self.haz_prox_grid
.as_mut()
Expand Down
8 changes: 4 additions & 4 deletions jagua-rs/src/collision_detection/hazard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub enum HazardEntity {
/// 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 },
InferiorQualityZone { quality: usize, id: usize },
}

impl HazardEntity {
Expand All @@ -45,7 +45,7 @@ impl HazardEntity {
HazardEntity::PlacedItem(_) => GeoPosition::Interior,
HazardEntity::BinExterior => GeoPosition::Exterior,
HazardEntity::BinHole { .. } => GeoPosition::Interior,
HazardEntity::QualityZoneInferior { .. } => GeoPosition::Interior,
HazardEntity::InferiorQualityZone { .. } => GeoPosition::Interior,
}
}

Expand All @@ -55,7 +55,7 @@ impl HazardEntity {
HazardEntity::PlacedItem(_) => true,
HazardEntity::BinExterior => false,
HazardEntity::BinHole { .. } => false,
HazardEntity::QualityZoneInferior { .. } => false,
HazardEntity::InferiorQualityZone { .. } => false,
}
}

Expand All @@ -65,7 +65,7 @@ impl HazardEntity {
HazardEntity::PlacedItem(_) => true,
HazardEntity::BinExterior => true,
HazardEntity::BinHole { .. } => true,
HazardEntity::QualityZoneInferior { .. } => false,
HazardEntity::InferiorQualityZone { .. } => false,
}
}
}
Expand Down
16 changes: 6 additions & 10 deletions jagua-rs/src/collision_detection/hazard_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,12 @@ 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 cutoff quality as irrelevant.
#[derive(Clone, Debug)]
pub struct QZHazardFilter {
pub cutoff_quality: usize,
}
pub struct QZHazardFilter(pub usize);

/// Deems hazards induced by specific entities as irrelevant.
pub struct EntityHazardFilter {
pub entities: Vec<HazardEntity>,
}
pub struct EntityHazardFilter(pub Vec<HazardEntity>);

/// Combines multiple `HazardFilter`s into a single filter.
pub struct CombinedHazardFilter<'a> {
Expand All @@ -48,7 +44,7 @@ impl HazardFilter for BinHazardFilter {
HazardEntity::PlacedItem(_) => false,
HazardEntity::BinExterior => true,
HazardEntity::BinHole { .. } => true,
HazardEntity::QualityZoneInferior { .. } => true,
HazardEntity::InferiorQualityZone { .. } => true,
}
}
}
Expand All @@ -61,14 +57,14 @@ impl<'a> HazardFilter for CombinedHazardFilter<'a> {

impl HazardFilter for EntityHazardFilter {
fn is_irrelevant(&self, entity: &HazardEntity) -> bool {
self.entities.contains(entity)
self.0.contains(entity)
}
}

impl HazardFilter for QZHazardFilter {
fn is_irrelevant(&self, entity: &HazardEntity) -> bool {
match entity {
HazardEntity::QualityZoneInferior { quality, .. } => *quality >= self.cutoff_quality,
HazardEntity::InferiorQualityZone { quality, .. } => *quality >= self.0,
_ => false,
}
}
Expand Down
2 changes: 1 addition & 1 deletion jagua-rs/src/collision_detection/hpg/hpg_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl HPGCell {
static_uni_prox = (prox, hazard.entity.clone());
}
}
HazardEntity::QualityZoneInferior { quality, .. } => {
HazardEntity::InferiorQualityZone { quality, .. } => {
qz_prox[*quality] = qz_prox[*quality].min(prox);
}
_ => panic!("Unexpected hazard entity type"),
Expand Down
69 changes: 33 additions & 36 deletions jagua-rs/src/entities/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ 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::QualityZone;
use crate::entities::quality_zone::InferiorQualityZone;
use crate::entities::quality_zone::N_QUALITIES;
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;

/// A `Bin` is a container in which items can be placed.
/// A container in which items can be placed.
#[derive(Clone, Debug)]
pub struct Bin {
pub id: usize,
Expand All @@ -26,7 +26,7 @@ pub struct Bin {
/// Shapes of holes/defects in the bins, if any
pub holes: Vec<Arc<SimplePolygon>>,
/// Zones of different qualities in the bin, stored per quality.
pub quality_zones: [Option<QualityZone>; N_QUALITIES],
pub quality_zones: [Option<InferiorQualityZone>; N_QUALITIES],
/// The starting state of the `CDEngine` for this bin.
pub base_cde: Arc<CDEngine>,
pub area: f64,
Expand All @@ -39,7 +39,7 @@ impl Bin {
value: u64,
centering_transform: Transformation,
holes: Vec<SimplePolygon>,
quality_zones: Vec<QualityZone>,
quality_zones: Vec<InferiorQualityZone>,
cde_config: CDEConfig,
) -> Self {
let outer = Arc::new(outer);
Expand All @@ -65,11 +65,9 @@ impl Bin {
qz
};

let base_cde = CDEngine::new(
outer.bbox().inflate_to_square(),
Bin::generate_hazards(&outer, &holes, &quality_zones),
cde_config,
);
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::<f64>();

Expand Down Expand Up @@ -100,35 +98,34 @@ impl Bin {
cde_config,
)
}
fn generate_hazards(
outer: &Arc<SimplePolygon>,
holes: &[Arc<SimplePolygon>],
quality_zones: &[Option<QualityZone>],
) -> Vec<Hazard> {
//Hazard induced by the outside of the bin
let mut hazards = vec![Hazard::new(HazardEntity::BinExterior, outer.clone())];

//Hazard induced by any holes in the bin
hazards.extend(holes.iter().enumerate().map(|(i, shape)| {
let haz_entity = HazardEntity::BinHole { id: i };
Hazard::new(haz_entity, shape.clone())
}));

//Hazards induced by quality zones
for q_zone in quality_zones.iter().flatten() {
for (id, shape) in q_zone.zones.iter().enumerate() {
let haz_entity = HazardEntity::QualityZoneInferior {
quality: q_zone.quality,
id,
};
hazards.push(Hazard::new(haz_entity, shape.clone()));
}
}

hazards
}

pub fn bbox(&self) -> AARectangle {
self.outer.bbox()
}
}
fn generate_bin_hazards(
outer: &Arc<SimplePolygon>,
holes: &[Arc<SimplePolygon>],
quality_zones: &[Option<InferiorQualityZone>],
) -> Vec<Hazard> {
//Hazard induced by the outside of the bin
let mut hazards = vec![Hazard::new(HazardEntity::BinExterior, outer.clone())];

//Hazard induced by any holes in the bin
hazards.extend(holes.iter().enumerate().map(|(i, shape)| {
let haz_entity = HazardEntity::BinHole { id: i };
Hazard::new(haz_entity, shape.clone())
}));

//Hazards induced by quality zones
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
}
9 changes: 7 additions & 2 deletions jagua-rs/src/entities/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ use crate::geometry::primitives::simple_polygon::SimplePolygon;
use crate::geometry::transformation::Transformation;
use crate::util::config::SPSurrogateConfig;

/// An `Item` to be placed in a `Bin`.
/// Item to be placed in a Layout
#[derive(Clone, Debug)]
pub struct Item {
pub id: usize,
/// Contour of the item
pub shape: Arc<SimplePolygon>,
/// Possible rotations in which to place the item
pub allowed_rotation: AllowedRotation,
/// The quality of the item, if `None` the item requires full quality
pub base_quality: Option<usize>,
pub value: u64,
/// The transformation to center the item around its centroid
pub centering_transform: Transformation,
/// Filter for hazards that the item is unaffected by
pub hazard_filter: Option<QZHazardFilter>,
}

Expand All @@ -30,7 +35,7 @@ impl Item {
) -> Item {
shape.generate_surrogate(surrogate_config);
let shape = Arc::new(shape);
let hazard_filter = base_quality.map(|q| QZHazardFilter { cutoff_quality: q });
let hazard_filter = base_quality.map(|q| QZHazardFilter(q));
Item {
id,
shape,
Expand Down
36 changes: 26 additions & 10 deletions jagua-rs/src/entities/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ use crate::util::assertions;
///It is a mutable representation, and can be modified by placing or removing items.
#[derive(Clone)]
pub struct Layout {
/// The unique identifier of the layout, only used for restoring from a snapshot.
/// The unique identifier of the layout, used only to match with a [LayoutSnapshot].
id: usize,
/// The bin used for this layout
bin: Bin,
/// How the items are placed in the bin
placed_items: Vec<PlacedItem>,
/// The collision detection engine for this layout
cde: CDEngine,
}

Expand All @@ -29,13 +32,13 @@ impl Layout {
}
}

pub fn new_from_stored(id: usize, layout_snapshot: &LayoutSnapshot) -> Self {
pub fn from_snapshot(id: usize, layout_snapshot: &LayoutSnapshot) -> Self {
let mut layout = Layout::new(id, layout_snapshot.bin.clone());
layout.restore(&layout_snapshot);
layout
}

pub fn create_layout_snapshot(&mut self) -> LayoutSnapshot {
pub fn create_snapshot(&mut self) -> LayoutSnapshot {
debug_assert!(assertions::layout_is_collision_free(self));

LayoutSnapshot {
Expand Down Expand Up @@ -70,19 +73,23 @@ impl Layout {
debug_assert!(assertions::layout_is_collision_free(self));
}

pub fn remove_item(&mut self, pi_uid: &PlacedItemUID, commit_instantly: bool) {
pub fn remove_item(&mut self, pi_uid: &PlacedItemUID, commit_instant: bool) {
// Find the placed item and remove it
let pos = self
.placed_items
.iter()
.position(|pi| &pi.uid == pi_uid)
.expect("item not found");
let placed_item = self.placed_items.swap_remove(pos);
self.cde
.deregister_hazard(&placed_item.uid.clone().into(), commit_instantly);
.expect("placed item does not exist");
let p_item = self.placed_items.swap_remove(pos);
// update the collision detection engine

let hazard_entity = p_item.uid.clone().into();
self.cde.deregister_hazard(&hazard_entity, commit_instant);

debug_assert!(assertions::layout_qt_matches_fresh_qt(self));
}

/// True if no items are placed
pub fn is_empty(&self) -> bool {
self.placed_items.is_empty()
}
Expand All @@ -95,6 +102,8 @@ impl Layout {
&self.placed_items
}

/// Returns the usage of the bin with the items placed.
/// It is the ratio of the area of the items placed to the area of the bin.
pub fn usage(&self) -> f64 {
let bin_area = self.bin().area;
let item_area = self
Expand All @@ -110,22 +119,29 @@ impl Layout {
self.id
}

/// Returns the collision detection engine for this layout
pub fn cde(&self) -> &CDEngine {
&self.cde
}

/// Makes sure that the collision detection engine is completely updated with the changes made to the layout.
pub fn flush_changes(&mut self) {
self.cde.flush_haz_prox_grid();
}
}

/// A `LayoutSnapshot` is an immutable representation of a `Layout` at a certain point in time.
/// `Layout`s can create `LayoutSnapshot`s, and restore themselves to a previous state using them.
/// Immutable and compact representation of a [Layout].
/// `Layout`s can create `LayoutSnapshot`s, and revert back themselves to a previous state using them.
#[derive(Clone, Debug)]
pub struct LayoutSnapshot {
/// The unique identifier of the layout, used only to match with a [Layout].
pub id: usize,
/// The bin used for this layout
pub bin: Bin,
/// How the items are placed in the bin
pub placed_items: Vec<PlacedItem>,
/// The collision detection engine snapshot for this layout
pub cde_snapshot: CDESnapshot,
/// The usage of the bin with the items placed
pub usage: f64,
}
5 changes: 3 additions & 2 deletions jagua-rs/src/entities/placed_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use crate::geometry::primitives::simple_polygon::SimplePolygon;
pub struct PlacedItem {
/// Unique identifier for the placed item
pub uid: PlacedItemUID,
pub qz_haz_filter: Option<QZHazardFilter>,
/// The filter for hazards that the `Item` is unaffected by
pub hazard_filter: Option<QZHazardFilter>,
/// The shape of the `Item` after it has been transformed and placed in a `Layout`
pub shape: Arc<SimplePolygon>,
}
Expand All @@ -37,7 +38,7 @@ impl PlacedItem {
PlacedItem {
uid: pi_uid,
shape,
qz_haz_filter,
hazard_filter: qz_haz_filter,
}
}

Expand Down
Loading

0 comments on commit 6a808c7

Please sign in to comment.