rectangle_pack/target_bin/coalesce.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use crate::TargetBin;
use core::ops::Range;
impl TargetBin {
/// Over time as you use [`TargetBin.push_available_bin_section`] to return remove packed
/// rectangles from the [`TargetBin`], you may end up with neighboring bin sections that can
/// be combined into a larger bin section.
///
/// Combining bin sections in this was is desirable because a larger bin section allows you to
/// place larger rectangles that might not fit into the smaller bin sections.
///
/// In order to coalesce, or combine a bin section with other bin sections, we need to check
/// every other available bin section to see if they are neighbors.
///
/// This means that fully coalescing the entire list of available bin sections is O(n^2) time
/// complexity, where n is the number of available empty sections.
///
/// # Basic Usage
///
/// ```ignore
/// # use rectangle_pack::TargetBin;
/// let target_bin = my_target_bin();
///
/// for idx in 0..target_bin.available_bin_sections().len() {
/// let len = target_bin.available_bin_sections().len();
/// target_bin.coalesce_available_sections(idx, 0..len);
/// }
///
/// # fn my_target_bin () -> TargetBin {
/// # TargetBin::new(1, 2, 3)
/// # }
/// ```
///
/// # Distributing the Workload
///
/// It is possible that you are developing an application that can in some cases have a lot of
/// heavily fragmented bins that need to be coalesced. If your application has a tight
/// performance budget, such as a real time simulation, you may not want to do all of your
/// coalescing at once.
///
/// This method allows you to split the work over many frames by giving you fine grained control
/// over which bin sections is getting coalesced and which other bin sections it gets tested
/// against.
///
/// So, for example, say you have an application where you want to fully coalesce the entire
/// bin every ten seconds, and you are running at 60 frames per second. You would then
/// distribute the coalescing work such that it would take 600 calls to compare every bin
/// section.
///
/// Here's a basic eample of splitting the work.
///
/// ```ignore
/// # use rectangle_pack::TargetBin;
/// let target_bin = my_target_bin();
///
/// let current_frame: usize = get_current_frame() % 600;
///
/// for idx in 0..target_bin.available_bin_sections().len() {
/// let len = target_bin.available_bin_sections().len();
///
/// let start = len / 600 * current_frame;
/// let end = start + len / 600;
///
/// target_bin.coalesce_available_sections(idx, start..end);
/// }
///
/// # fn my_target_bin () -> TargetBin {
/// # TargetBin::new(1, 2, 3)
/// # }
/// #
/// # fn get_current_frame () -> usize {
/// # 0
/// # }
/// ```
///
/// [`TargetBin.push_available_bin_section`]: #method.push_available_bin_section
// TODO: Write tests, implement then remove the "ignore" from the examples above.
// Tests cases should have a rectangle and then a neighbor (above, below, left, right) and
// verify that they get combined, but only if the comparison indices are correct and only if
// the neighbor has the same width (uf above/below) or height (if left/right).
pub fn coalesce_available_sections(
_bin_section_index: usize,
_compare_to_indices: Range<usize>,
) {
unimplemented!()
}
}