33#include < vector>
44#include < array>
55#include < variant>
6+ #include < memory>
67#include < algorithm>
78
89#include " insert_and_split.h"
@@ -51,10 +52,12 @@ namespace rectpack2D {
5152 Subjects& subjects,
5253 const finder_input<F, G>& input
5354 ) {
54- using order_type = std::remove_reference_t <decltype (subjects)>;
55+ // Works with C arrays as well.
56+ using iterator_type = decltype (std::begin (subjects));
57+ using order_type = rectpack2D::span<iterator_type>;
5558
5659 return find_best_packing_impl<empty_spaces_type, order_type>(
57- [&subjects](auto callback) { callback (subjects); },
60+ [&subjects](auto callback) { callback (order_type ( std::begin ( subjects), std::end (subjects)) ); },
5861 input
5962 );
6063 }
@@ -77,43 +80,66 @@ namespace rectpack2D {
7780 Comparators... comparators
7881 ) {
7982 using rect_type = output_rect_t <empty_spaces_type>;
80- using order_type = std::vector <rect_type*>;
83+ using order_type = rectpack2D::span <rect_type* *>;
8184
8285 constexpr auto count_orders = 1 + sizeof ...(Comparators);
83- thread_local std::array<order_type, count_orders> orders ;
86+ std::size_t count_valid_subjects = 0 ;
8487
85- {
86- /* order[0] will always exist since this overload requires at least one comparator */
87- auto & initial_pointers = orders[0 ];
88- initial_pointers.clear ();
88+ // Allocate space assuming no rectangle has an area of zero.
89+ // We fill orders with valid rectangles only.
90+ auto orders = std::make_unique<rect_type*[]>(count_orders * std::size (subjects));
8991
90- for (auto & s : subjects) {
91- auto & r = s.get_rect ();
92+ for (auto & s : subjects) {
93+ auto & r = s.get_rect ();
9294
93- if (r.area () > 0 ) {
94- initial_pointers.emplace_back (std::addressof (r));
95- }
95+ if (r.area () == 0 ) {
96+ continue ;
9697 }
9798
99+ orders[count_valid_subjects++] = std::addressof (r);
100+ }
101+
102+ auto ith_order = [&orders, n = count_valid_subjects](const std::size_t i) {
103+ return order_type (
104+ orders.get () + i * n,
105+ orders.get () + (i + 1 ) * n
106+ );
107+ };
108+
109+ {
110+ /*
111+ Zero-th order is already filled.
112+ We duplicate it to all other orders.
113+ */
114+ const auto first_order = ith_order (0 );
115+
98116 for (std::size_t i = 1 ; i < count_orders; ++i) {
99- orders[i] = initial_pointers;
117+ std::copy (
118+ first_order.begin (),
119+ first_order.end (),
120+ ith_order (i).begin ()
121+ );
100122 }
101123 }
102124
103- std::size_t f = 0 ;
104-
105- auto & orders_ref = orders;
125+ {
126+ std::size_t i = 0 ;
106127
107- auto make_order = [&f, &orders_ref ](auto & predicate) {
108- std::sort (orders_ref[f]. begin (), orders_ref[f]. end (), predicate );
109- ++f ;
110- };
128+ auto make_order = [&i, ith_order ](auto & predicate) {
129+ const auto o = ith_order (i++ );
130+ std::sort (o. begin (), o. end (), predicate) ;
131+ };
111132
112- make_order (comparator);
113- (make_order (comparators), ...);
133+ make_order (comparator);
134+ (make_order (comparators), ...);
135+ }
114136
115137 return find_best_packing_impl<empty_spaces_type, order_type>(
116- [&orders_ref](auto callback){ for (auto & o : orders_ref) { callback (o); } },
138+ [ith_order](auto callback) {
139+ for (std::size_t i = 0 ; i < count_orders; ++i) {
140+ callback (ith_order (i));
141+ }
142+ },
117143 input
118144 );
119145 }
0 commit comments