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!()
    }
}