Skip to content

Commit

Permalink
Add failing test for not-skipping unused splits
Browse files Browse the repository at this point in the history
  • Loading branch information
chinedufn committed Mar 9, 2020
1 parent d72db93 commit c6cbc24
Show file tree
Hide file tree
Showing 7 changed files with 408 additions and 266 deletions.
58 changes: 29 additions & 29 deletions src/bin_section.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{HeuristicFn, LayeredRect, PackedLocation, RotatedBy, WidthHeightDepth};
use crate::{BoxSizeHeuristicFn, PackedLocation, RectToInsert, RotatedBy, WidthHeightDepth};
use std::cmp::Ordering;
use std::fmt::{Display, Error, Formatter};

Expand All @@ -7,15 +7,15 @@ use std::fmt::{Display, Error, Formatter};
/// Ordering::Greater means the first set of containers is better.
/// Ordering::Less means the second set of containers is better.
pub type MoreSuitableContainersFn =
dyn Fn([WidthHeightDepth; 3], [WidthHeightDepth; 3], &HeuristicFn) -> Ordering;
dyn Fn([WidthHeightDepth; 3], [WidthHeightDepth; 3], &BoxSizeHeuristicFn) -> Ordering;

/// Select the container that has the smallest box.
///
/// If there is a tie on the smallest boxes, select whichever also has the second smallest box.
pub fn contains_smallest_box(
mut container1: [WidthHeightDepth; 3],
mut container2: [WidthHeightDepth; 3],
heuristic: &HeuristicFn,
heuristic: &BoxSizeHeuristicFn,
) -> Ordering {
container1.sort_unstable();
container2.sort_unstable();
Expand Down Expand Up @@ -144,9 +144,9 @@ impl BinSection {
/// calls and conditionals.
pub fn try_place(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
container_comparison_fn: &MoreSuitableContainersFn,
heuristic_fn: &HeuristicFn,
heuristic_fn: &BoxSizeHeuristicFn,
) -> Result<(PackedLocation, [BinSection; 3]), BinSectionError> {
self.incoming_can_fit(incoming)?;

Expand Down Expand Up @@ -184,7 +184,7 @@ impl BinSection {
Ok((packed_location, all_combinations[5]))
}

fn incoming_can_fit(&self, incoming: &LayeredRect) -> Result<(), BinSectionError> {
fn incoming_can_fit(&self, incoming: &RectToInsert) -> Result<(), BinSectionError> {
if incoming.width() > self.whd.width {
return Err(BinSectionError::PlacementWiderThanBinSection);
}
Expand All @@ -201,7 +201,7 @@ impl BinSection {

fn width_largest_height_second_largest_depth_smallest(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
) -> [BinSection; 3] {
[
self.empty_space_directly_right(incoming),
Expand All @@ -212,7 +212,7 @@ impl BinSection {

fn width_largest_depth_second_largest_height_smallest(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
) -> [BinSection; 3] {
[
self.empty_space_directly_right(incoming),
Expand All @@ -223,7 +223,7 @@ impl BinSection {

fn height_largest_width_second_largest_depth_smallest(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
) -> [BinSection; 3] {
[
self.all_empty_space_right_excluding_behind(incoming),
Expand All @@ -234,7 +234,7 @@ impl BinSection {

fn height_largest_depth_second_largest_width_smallest(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
) -> [BinSection; 3] {
[
self.all_empty_space_right(incoming),
Expand All @@ -245,7 +245,7 @@ impl BinSection {

fn depth_largest_width_second_largest_height_smallest(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
) -> [BinSection; 3] {
[
self.all_empty_space_right_excluding_above(incoming),
Expand All @@ -256,7 +256,7 @@ impl BinSection {

fn depth_largest_height_second_largest_width_smallest(
&self,
incoming: &LayeredRect,
incoming: &RectToInsert,
) -> [BinSection; 3] {
[
self.all_empty_space_right(incoming),
Expand All @@ -265,7 +265,7 @@ impl BinSection {
]
}

fn all_empty_space_above(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_above(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new_spread(
self.x,
self.y + incoming.height(),
Expand All @@ -276,7 +276,7 @@ impl BinSection {
)
}

fn all_empty_space_right(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_right(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new_spread(
self.x + incoming.width(),
self.y,
Expand All @@ -287,7 +287,7 @@ impl BinSection {
)
}

fn all_empty_space_behind(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_behind(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new_spread(
self.x,
self.y,
Expand All @@ -298,7 +298,7 @@ impl BinSection {
)
}

fn empty_space_directly_above(&self, incoming: &LayeredRect) -> BinSection {
fn empty_space_directly_above(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new_spread(
self.x,
self.y + incoming.height(),
Expand All @@ -309,7 +309,7 @@ impl BinSection {
)
}

fn empty_space_directly_right(&self, incoming: &LayeredRect) -> BinSection {
fn empty_space_directly_right(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new_spread(
self.x + incoming.width(),
self.y,
Expand All @@ -320,7 +320,7 @@ impl BinSection {
)
}

fn empty_space_directly_behind(&self, incoming: &LayeredRect) -> BinSection {
fn empty_space_directly_behind(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x,
self.y,
Expand All @@ -333,7 +333,7 @@ impl BinSection {
)
}

fn all_empty_space_above_excluding_right(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_above_excluding_right(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x,
self.y + incoming.height(),
Expand All @@ -346,7 +346,7 @@ impl BinSection {
)
}

fn all_empty_space_above_excluding_behind(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_above_excluding_behind(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x,
self.y + incoming.height(),
Expand All @@ -359,7 +359,7 @@ impl BinSection {
)
}

fn all_empty_space_right_excluding_above(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_right_excluding_above(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x + incoming.width(),
self.y,
Expand All @@ -372,7 +372,7 @@ impl BinSection {
)
}

fn all_empty_space_right_excluding_behind(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_right_excluding_behind(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x + incoming.width(),
self.y,
Expand All @@ -385,7 +385,7 @@ impl BinSection {
)
}

fn all_empty_space_behind_excluding_above(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_behind_excluding_above(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x,
self.y,
Expand All @@ -398,7 +398,7 @@ impl BinSection {
)
}

fn all_empty_space_behind_excluding_right(&self, incoming: &LayeredRect) -> BinSection {
fn all_empty_space_behind_excluding_right(&self, incoming: &RectToInsert) -> BinSection {
BinSection::new(
self.x,
self.y,
Expand All @@ -415,7 +415,7 @@ impl BinSection {
#[cfg(test)]
mod tests {
use super::*;
use crate::{volume_heuristic, LayeredRect};
use crate::{volume_heuristic, RectToInsert};

const BIGGEST: u32 = 50;
const MIDDLE: u32 = 25;
Expand All @@ -427,7 +427,7 @@ mod tests {
#[test]
fn error_if_placement_is_wider_than_bin_section() {
let bin_section = bin_section_width_height_depth(5, 20, 1);
let placement = LayeredRect::new(6, 20, 1);
let placement = RectToInsert::new(6, 20, 1);

assert_eq!(
bin_section
Expand All @@ -441,7 +441,7 @@ mod tests {
#[test]
fn error_if_placement_is_taller_than_bin_section() {
let bin_section = bin_section_width_height_depth(5, 20, 1);
let placement = LayeredRect::new(5, 21, 1);
let placement = RectToInsert::new(5, 21, 1);

assert_eq!(
bin_section
Expand All @@ -455,7 +455,7 @@ mod tests {
#[test]
fn error_if_placement_is_deeper_than_bin_section() {
let bin_section = bin_section_width_height_depth(5, 20, 1);
let placement = LayeredRect::new(5, 20, 2);
let placement = RectToInsert::new(5, 20, 2);

assert_eq!(
bin_section
Expand All @@ -475,7 +475,7 @@ mod tests {

let whd = rect_to_place;

let placement = LayeredRect::new(whd.width, whd.height, whd.depth);
let placement = RectToInsert::new(whd.width, whd.height, whd.depth);

let mut packed = bin_section
.try_place(&placement, &contains_smallest_box, &volume_heuristic)
Expand Down
13 changes: 13 additions & 0 deletions src/box_size_heuristics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::WidthHeightDepth;

/// Incoming boxes are places into the smallest hole that will fit them.
///
/// "small" vs. "large" is based on the heuristic function.
///
/// A larger heuristic means that the box is larger.
pub type BoxSizeHeuristicFn = dyn Fn(WidthHeightDepth) -> u128;

/// The volume of the box
pub fn volume_heuristic(whd: WidthHeightDepth) -> u128 {
(whd.width * whd.height * whd.depth) as _
}
34 changes: 17 additions & 17 deletions src/layered_rect_groups.rs → src/grouped_rects_to_place.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::LayeredRect;
use crate::RectToInsert;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::fmt::Debug;
Expand All @@ -12,14 +12,14 @@ use std::hash::Hash;
/// A group's heuristic is computed by calculating the heuristic of all of the rectangles inside
/// the group and then summing them.
#[derive(Debug)]
pub struct LayeredRectGroups<InboundId, GroupId = ()>
pub struct GroupedRectsToPlace<InboundId, GroupId = ()>
where
InboundId: Debug + Hash + Eq,
GroupId: Debug + Hash + Eq,
{
pub(crate) inbound_id_to_group_ids: HashMap<InboundId, Vec<Group<GroupId, InboundId>>>,
pub(crate) group_id_to_inbound_ids: HashMap<Group<GroupId, InboundId>, Vec<InboundId>>,
pub(crate) rects: HashMap<InboundId, LayeredRect>,
pub(crate) rects: HashMap<InboundId, RectToInsert>,
}

/// A group of rectangles that need to be placed together
Expand All @@ -41,7 +41,7 @@ where
Grouped(GroupId),
}

impl<InboundId, GroupId> LayeredRectGroups<InboundId, GroupId>
impl<InboundId, GroupId> GroupedRectsToPlace<InboundId, GroupId>
where
InboundId: Debug + Hash + Clone + Eq,
GroupId: Debug + Hash + Clone + Eq,
Expand All @@ -65,7 +65,7 @@ where
&mut self,
inbound_id: InboundId,
group_ids: Option<Vec<GroupId>>,
inbound: LayeredRect,
inbound: RectToInsert,
) {
self.rects.insert(inbound_id.clone(), inbound);

Expand Down Expand Up @@ -107,15 +107,15 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::LayeredRect;
use crate::RectToInsert;

/// Verify that if we insert a rectangle that doesn't have a group it is given a group ID based
/// on its inboundID.
#[test]
fn ungrouped_rectangles_use_their_inbound_id_as_their_group_id() {
let mut lrg: LayeredRectGroups<_, ()> = LayeredRectGroups::new();
let mut lrg: GroupedRectsToPlace<_, ()> = GroupedRectsToPlace::new();

lrg.push_rect(InboundId::One, None, LayeredRect::new(10, 10, 1));
lrg.push_rect(InboundId::One, None, RectToInsert::new(10, 10, 1));

assert_eq!(
lrg.group_id_to_inbound_ids[&Group::Ungrouped(InboundId::One)],
Expand All @@ -127,10 +127,10 @@ mod tests {
/// map of group id -> inbound rect id
#[test]
fn group_id_to_inbound_ids() {
let mut lrg = LayeredRectGroups::new();
let mut lrg = GroupedRectsToPlace::new();

lrg.push_rect(InboundId::One, Some(vec![0]), LayeredRect::new(10, 10, 1));
lrg.push_rect(InboundId::Two, Some(vec![0]), LayeredRect::new(10, 10, 1));
lrg.push_rect(InboundId::One, Some(vec![0]), RectToInsert::new(10, 10, 1));
lrg.push_rect(InboundId::Two, Some(vec![0]), RectToInsert::new(10, 10, 1));

assert_eq!(
lrg.group_id_to_inbound_ids[&Group::Grouped(0)],
Expand All @@ -141,15 +141,15 @@ mod tests {
/// Verify that we store the map of inbound id -> group ids
#[test]
fn inbound_id_to_group_ids() {
let mut lrg = LayeredRectGroups::new();
let mut lrg = GroupedRectsToPlace::new();

lrg.push_rect(
InboundId::One,
Some(vec![0, 1]),
LayeredRect::new(10, 10, 1),
RectToInsert::new(10, 10, 1),
);

lrg.push_rect(InboundId::Two, None, LayeredRect::new(10, 10, 1));
lrg.push_rect(InboundId::Two, None, RectToInsert::new(10, 10, 1));

assert_eq!(
lrg.inbound_id_to_group_ids[&InboundId::One],
Expand All @@ -165,15 +165,15 @@ mod tests {
/// Verify that we store in rectangle associated with its inbound ID
#[test]
fn store_the_inbound_rectangle() {
let mut lrg = LayeredRectGroups::new();
let mut lrg = GroupedRectsToPlace::new();

lrg.push_rect(
InboundId::One,
Some(vec![0, 1]),
LayeredRect::new(10, 10, 1),
RectToInsert::new(10, 10, 1),
);

assert_eq!(lrg.rects[&InboundId::One], LayeredRect::new(10, 10, 1));
assert_eq!(lrg.rects[&InboundId::One], RectToInsert::new(10, 10, 1));
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
Expand Down
Loading

0 comments on commit c6cbc24

Please sign in to comment.