Skip to content

Commit

Permalink
Add example
Browse files Browse the repository at this point in the history
  • Loading branch information
chinedufn committed Mar 9, 2020
1 parent 40f55dd commit c50b366
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ version = "0.1.0"
authors = ["Chinedu Francis Nwafili <[email protected]>"]
edition = "2018"
keywords = ["texture", "atlas", "bin", "rect", "box", "packer"]

description = "A minimal rectangle packer designed to conform to any two or three dimensional use case."
81 changes: 69 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# rectangle-pack [![Actions Status](https://github.com/chinedufn/rectangle-pack/workflows/test/badge.svg)](https://github.com/chinedufn/rectangle-pack/actions) [![docs](https://docs.rs/rectangle-pack/badge.svg)](https://docs.rs/rectangle-pack)

> A minimal, zero dependency rectangle packer designed to conform to any use two or three dimensional case.
> A minimal rectangle packer designed to conform to any two or three dimensional use case.
`rectangle-pack` is a library focused on laying out any number of smaller rectangles (both 2d rectangles and 3d rectangular prisms) inside any number of larger rectangles.

Expand All @@ -18,11 +18,72 @@ rectangle-pack = "0.1"
```

```rust
//! A basic use case

use rectangle_pack;

// Trivial example here
//! A basic example of packing rectangles into target bins

use rectangle_pack::{
GroupedRectsToPlace,
RectToInsert,
pack_rects,
TargetBin,
volume_heuristic,
contains_smallest_box
};
use std::collections::HashMap;

// A rectangle ID just needs to meet these trait bounds (ideally also Copy)
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum MyCustomRectId {
RectOne,
RectTwo,
RectThree,
}

// A target bin ID just needs to meet these trait bounds (ideally also Copy)
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum MyCustomBinId {
DestinationBinOne,
DestinationBinTwo,
}

// A placement group just needs to meet these trait bounds (ideally also Copy).
//
// Groups allow you to ensure that a set of rectangles will be placed
// into the same bin. If this isn't possible an error is returned.
//
// Groups are optional.
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
enum MyCustomGroupId {
GroupIdOne
}

let mut rects_to_place = GroupedRectsToPlace::new();
rects_to_place.push_rect(
MyCustomRectId::RectOne,
Some(vec![MyCustomGroupId::GroupIdOne]),
RectToInsert::new(10, 20, 255)
);
rects_to_place.push_rect(
MyCustomRectId::RectTwo,
Some(vec![MyCustomGroupId::GroupIdOne]),
RectToInsert::new(5, 50, 255)
);
rects_to_place.push_rect(
MyCustomRectId::RectThree,
None,
RectToInsert::new(30, 30, 255)
);

let mut target_bins = HashMap::new();
target_bins.insert(MyCustomBinId::DestinationBinOne, TargetBin::new(2048, 2048, 255));
target_bins.insert(MyCustomBinId::DestinationBinTwo, TargetBin::new(4096, 4096, 1020));

// Information about where each `MyCustomRectId` was placed
let rectangle_placements = pack_rects(
&rects_to_place,
target_bins,
&volume_heuristic,
&contains_smallest_box
).unwrap();
```

[Full API Documentation](https://docs.rs/rectangle-pack)
Expand Down Expand Up @@ -79,15 +140,11 @@ The API shouldn't know about the specifics of any of these requirements - it sho

- Supports three dimensional rectangles through a width + height + depth based API.

- Supports two dimensional rectangles (depth = 1)
- Supports two dimensional rectangles (depth = 1).

- User provided heuristics to grant full control over the packing algorithm.

## Example Usage

```rust

```
- Zero dependencies, making it easier to embed it inside of a more use case specific library without introducing bloat.

## Future Work

Expand Down
2 changes: 1 addition & 1 deletion src/box_size_heuristics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ 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 _
whd.width as u128 * whd.height as u128 * whd.depth as u128
}
70 changes: 69 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use std::hash::Hash;

pub use crate::bin_section::contains_smallest_box;
use crate::bin_section::{BinSection, MoreSuitableContainersFn};
use crate::grouped_rects_to_place::{Group, GroupedRectsToPlace};
use crate::grouped_rects_to_place::Group;
pub use crate::grouped_rects_to_place::GroupedRectsToPlace;
pub use crate::target_bin::TargetBin;
use crate::width_height_depth::WidthHeightDepth;

Expand Down Expand Up @@ -61,6 +62,73 @@ impl Display for RectanglePackError {

/// Determine how to fit a set of incoming rectangles (2d or 3d) into a set of target bins.
///
/// ## Example
///
/// ```
/// use rectangle_pack::{
/// GroupedRectsToPlace,
/// RectToInsert,
/// pack_rects,
/// TargetBin,
/// volume_heuristic,
/// contains_smallest_box
/// };
/// use std::collections::HashMap;
///
/// // A rectangle ID just needs to meet these trait bounds (ideally also Copy)
/// #[derive(Debug, Hash, PartialEq, Eq, Clone)]
/// enum MyCustomRectId {
/// RectOne,
/// RectTwo,
/// RectThree,
/// }
///
/// // A target bin ID just needs to meet these trait bounds (ideally also Copy)
/// #[derive(Debug, Hash, PartialEq, Eq, Clone)]
/// enum MyCustomBinId {
/// DestinationBinOne,
/// DestinationBinTwo,
/// }
///
/// // A placement group just needs to meet these trait bounds (ideally also Copy).
/// //
/// // Groups are optional - they allow you to ensure that a set of rectangles will be placed
/// // into the same bin. If this isn't possible an error is returned.
/// #[derive(Debug, Hash, PartialEq, Eq, Clone)]
/// enum MyCustomGroupId {
/// GroupIdOne
/// }
///
/// let mut rects_to_place = GroupedRectsToPlace::new();
/// rects_to_place.push_rect(
/// MyCustomRectId::RectOne,
/// Some(vec![MyCustomGroupId::GroupIdOne]),
/// RectToInsert::new(10, 20, 255)
/// );
/// rects_to_place.push_rect(
/// MyCustomRectId::RectTwo,
/// Some(vec![MyCustomGroupId::GroupIdOne]),
/// RectToInsert::new(5, 50, 255)
/// );
/// rects_to_place.push_rect(
/// MyCustomRectId::RectThree,
/// None,
/// RectToInsert::new(30, 30, 255)
/// );
///
/// let mut target_bins = HashMap::new();
/// target_bins.insert(MyCustomBinId::DestinationBinOne, TargetBin::new(2048, 2048, 255));
/// target_bins.insert(MyCustomBinId::DestinationBinTwo, TargetBin::new(4096, 4096, 1020));
///
/// // Information about where each `MyCustomRectId` was placed
/// let rectangle_placements = pack_rects(
/// &rects_to_place,
/// target_bins,
/// &volume_heuristic,
/// &contains_smallest_box
/// ).unwrap();
/// ```
///
/// ## Algorithm
///
/// The algorithm was originally inspired by [rectpack2D] and then modified to work in 3D.
Expand Down

0 comments on commit c50b366

Please sign in to comment.