Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
libnest2d::selections::_DJDHeuristic< RawShape > Class Template Reference

#include <src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp>

+ Inheritance diagram for libnest2d::selections::_DJDHeuristic< RawShape >:
+ Collaboration diagram for libnest2d::selections::_DJDHeuristic< RawShape >:

Classes

struct  Config
 The Config for DJD heuristic. More...
 
class  SpinLock
 

Public Types

using ItemRef = std::reference_wrapper< Item >
 
using Item = _Item< RawShape >
 
using ShapeType = RawShape
 
using PackGroup = _PackGroup< RawShape >
 

Public Member Functions

void configure (const Config &config)
 
template<class TPlacer , class TIterator , class TBin = typename PlacementStrategyLike<TPlacer>::BinType, class PConfig = typename PlacementStrategyLike<TPlacer>::Config>
void packItems (TIterator first, TIterator last, const TBin &bin, PConfig &&pconfig=PConfig())
 
const PackGroupgetResult () const
 
int lastPackedBinId () const
 
void progressIndicator (ProgressFunction fn)
 
void stopCondition (StopCondition cond)
 
void clear ()
 

Protected Member Functions

template<class Placer , class Container , class Bin , class PCfg >
void remove_unpackable_items (Container &c, const Bin &bin, const PCfg &pcfg)
 

Protected Attributes

ProgressFunction progress_ = [](unsigned){}
 
StopCondition stopcond_ = [](){ return false; }
 
int last_packed_bin_id_ = -1
 

Private Types

using Base = SelectionBoilerplate< RawShape >
 
using ItemGroup = typename Base::ItemGroup
 
using Container = ItemGroup
 

Private Attributes

Container store_
 
Config config_
 
PackGroup packed_bins_
 

Static Private Attributes

static const unsigned MAX_ITEMS_SEQUENTIALLY = 30
 
static const unsigned MAX_VERTICES_SEQUENTIALLY = MAX_ITEMS_SEQUENTIALLY*20
 

Detailed Description

template<class RawShape>
class libnest2d::selections::_DJDHeuristic< RawShape >

Selection heuristic based on [López-Camacho]\ (http://www.cs.stir.ac.uk/~goc/papers/EffectiveHueristic2DAOR2013.pdf)


Class Documentation

◆ libnest2d::selections::_DJDHeuristic::Config

struct libnest2d::selections::_DJDHeuristic::Config
template<class RawShape>
struct libnest2d::selections::_DJDHeuristic< RawShape >::Config

The Config for DJD heuristic.

Class Members
bool allow_parallel = true Allow parallel jobs for filling multiple bins.

This will decrease the soution quality but can greatly boost up performance for large number of items.

bool force_parallel = false Always use parallel processing if the items don't fit into one bin.
double initial_fill_proportion = 1.0/3.0

The initial fill proportion of the bin area that will be filled before trying items one by one, or pairs or triplets.

The initial fill proportion suggested by [López-Camacho]\ (http://www.cs.stir.ac.uk/~goc/papers/EffectiveHueristic2DAOR2013.pdf) is one third of the area of bin.

bool try_pairs = true try_pairs Whether to try pairs of items to pack. It will add a quadratic component to the complexity.
bool try_reverse_order = true

If true, the algorithm will try to place pair and triplets in all possible order. It will have a hugely negative impact on performance.

bool try_triplets = false Whether to try groups of 3 items to pack. This could be very slow for large number of items (>100) as it adds a cubic component to the complexity.
double waste_increment = 0.1 How much is the acceptable waste incremented at each iteration.

Member Typedef Documentation

◆ Base

template<class RawShape >
using libnest2d::selections::_DJDHeuristic< RawShape >::Base = SelectionBoilerplate<RawShape>
private

◆ Container

template<class RawShape >
using libnest2d::selections::_DJDHeuristic< RawShape >::Container = ItemGroup
private

◆ Item

template<class RawShape >
using libnest2d::selections::SelectionBoilerplate< RawShape >::Item = _Item<RawShape>

◆ ItemGroup

template<class RawShape >
using libnest2d::selections::_DJDHeuristic< RawShape >::ItemGroup = typename Base::ItemGroup
private

◆ ItemRef

template<class RawShape >
using libnest2d::selections::_DJDHeuristic< RawShape >::ItemRef = std::reference_wrapper<Item>

◆ PackGroup

template<class RawShape >
using libnest2d::selections::SelectionBoilerplate< RawShape >::PackGroup = _PackGroup<RawShape>
inherited

◆ ShapeType

template<class RawShape >
using libnest2d::selections::SelectionBoilerplate< RawShape >::ShapeType = RawShape
inherited

Member Function Documentation

◆ clear()

template<class RawShape >
void libnest2d::selections::SelectionBoilerplate< RawShape >::clear ( )
inlineinherited
27{ packed_bins_.clear(); }
PackGroup packed_bins_
Definition selection_boilerplate.hpp:56

References libnest2d::selections::SelectionBoilerplate< RawShape >::packed_bins_.

◆ configure()

template<class RawShape >
void libnest2d::selections::_DJDHeuristic< RawShape >::configure ( const Config config)
inline
106 {
107 config_ = config;
108 }
Config config_
Definition djd_heuristic.hpp:99

References libnest2d::selections::_DJDHeuristic< RawShape >::config_.

◆ getResult()

template<class RawShape >
const PackGroup & libnest2d::selections::SelectionBoilerplate< RawShape >::getResult ( ) const
inlineinherited

◆ lastPackedBinId()

template<class RawShape >
int libnest2d::selections::SelectionBoilerplate< RawShape >::lastPackedBinId ( ) const
inlineinherited

◆ packItems()

template<class RawShape >
template<class TPlacer , class TIterator , class TBin = typename PlacementStrategyLike<TPlacer>::BinType, class PConfig = typename PlacementStrategyLike<TPlacer>::Config>
void libnest2d::selections::_DJDHeuristic< RawShape >::packItems ( TIterator  first,
TIterator  last,
const TBin &  bin,
PConfig &&  pconfig = PConfig() 
)
inline
117 {
118 using Placer = PlacementStrategyLike<TPlacer>;
119 using ItemList = std::list<ItemRef>;
120
121 const double bin_area = sl::area(bin);
122 const double w = bin_area * config_.waste_increment;
123
124 const double INITIAL_FILL_PROPORTION = config_.initial_fill_proportion;
125 const double INITIAL_FILL_AREA = bin_area*INITIAL_FILL_PROPORTION;
126
127 store_.clear();
128 store_.reserve(last-first);
129
130 // TODO: support preloading
131 packed_bins_.clear();
132
133 std::copy(first, last, std::back_inserter(store_));
134
135 std::sort(store_.begin(), store_.end(), [](Item& i1, Item& i2) {
136 return i1.area() > i2.area();
137 });
138
139 size_t glob_vertex_count = 0;
140 std::for_each(store_.begin(), store_.end(),
141 [&glob_vertex_count](const Item& item) {
142 glob_vertex_count += item.vertexCount();
143 });
144
145 std::vector<Placer> placers;
146
147 bool try_reverse = config_.try_reverse_order;
148
149 // Will use a subroutine to add a new bin
150 auto addBin = [this, &placers, &bin, &pconfig]()
151 {
152 placers.emplace_back(bin);
153 packed_bins_.emplace_back();
154 placers.back().configure(pconfig);
155 };
156
157 // Types for pairs and triplets
158 using TPair = std::tuple<ItemRef, ItemRef>;
159 using TTriplet = std::tuple<ItemRef, ItemRef, ItemRef>;
160
161
162 // Method for checking a pair whether it was a pack failure.
163 auto check_pair = [](const std::vector<TPair>& wrong_pairs,
164 ItemRef i1, ItemRef i2)
165 {
166 return std::any_of(wrong_pairs.begin(), wrong_pairs.end(),
167 [&i1, &i2](const TPair& pair)
168 {
169 Item& pi1 = std::get<0>(pair), &pi2 = std::get<1>(pair);
170 Item& ri1 = i1, &ri2 = i2;
171 return (&pi1 == &ri1 && &pi2 == &ri2) ||
172 (&pi1 == &ri2 && &pi2 == &ri1);
173 });
174 };
175
176 // Method for checking if a triplet was a pack failure
177 auto check_triplet = [](
178 const std::vector<TTriplet>& wrong_triplets,
179 ItemRef i1,
180 ItemRef i2,
181 ItemRef i3)
182 {
183 return std::any_of(wrong_triplets.begin(),
184 wrong_triplets.end(),
185 [&i1, &i2, &i3](const TTriplet& tripl)
186 {
187 Item& pi1 = std::get<0>(tripl);
188 Item& pi2 = std::get<1>(tripl);
189 Item& pi3 = std::get<2>(tripl);
190 Item& ri1 = i1, &ri2 = i2, &ri3 = i3;
191 return (&pi1 == &ri1 && &pi2 == &ri2 && &pi3 == &ri3) ||
192 (&pi1 == &ri1 && &pi2 == &ri3 && &pi3 == &ri2) ||
193 (&pi1 == &ri2 && &pi2 == &ri1 && &pi3 == &ri3) ||
194 (&pi1 == &ri3 && &pi2 == &ri2 && &pi3 == &ri1);
195 });
196 };
197
198 using ItemListIt = typename ItemList::iterator;
199
200 auto largestPiece = [](ItemListIt it, ItemList& not_packed) {
201 return it == not_packed.begin()? std::next(it) : not_packed.begin();
202 };
203
204 auto secondLargestPiece = [&largestPiece](ItemListIt it,
205 ItemList& not_packed) {
206 auto ret = std::next(largestPiece(it, not_packed));
207 return ret == it? std::next(ret) : ret;
208 };
209
210 auto smallestPiece = [](ItemListIt it, ItemList& not_packed) {
211 auto last = std::prev(not_packed.end());
212 return it == last? std::prev(it) : last;
213 };
214
215 auto secondSmallestPiece = [&smallestPiece](ItemListIt it,
216 ItemList& not_packed) {
217 auto ret = std::prev(smallestPiece(it, not_packed));
218 return ret == it? std::prev(ret) : ret;
219 };
220
221 auto tryOneByOne = // Subroutine to try adding items one by one.
222 [&bin_area]
223 (Placer& placer, ItemList& not_packed,
224 double waste,
225 double& free_area,
226 double& filled_area)
227 {
228 double item_area = 0;
229 bool ret = false;
230 auto it = not_packed.begin();
231
232 auto pack = [&placer, &not_packed](ItemListIt it) {
233 return placer.pack(*it, rem(it, not_packed));
234 };
235
236 while(it != not_packed.end() && !ret &&
237 free_area - (item_area = it->get().area()) <= waste)
238 {
239 if(item_area <= free_area && pack(it) ) {
240 free_area -= item_area;
241 filled_area = bin_area - free_area;
242 ret = true;
243 } else
244 it++;
245 }
246
247 if(ret) not_packed.erase(it);
248
249 return ret;
250 };
251
252 auto tryGroupsOfTwo = // Try adding groups of two items into the bin.
253 [&bin_area, &check_pair, &largestPiece, &smallestPiece,
254 try_reverse]
255 (Placer& placer, ItemList& not_packed,
256 double waste,
257 double& free_area,
258 double& filled_area)
259 {
260 double item_area = 0;
261 const auto endit = not_packed.end();
262
263 if(not_packed.size() < 2)
264 return false; // No group of two items
265
266 double largest_area = not_packed.front().get().area();
267 auto itmp = not_packed.begin(); itmp++;
268 double second_largest = itmp->get().area();
269 if( free_area - second_largest - largest_area > waste)
270 return false; // If even the largest two items do not fill
271 // the bin to the desired waste than we can end here.
272
273
274 bool ret = false;
275 auto it = not_packed.begin();
276 auto it2 = it;
277
278 std::vector<TPair> wrong_pairs;
279 using std::placeholders::_1;
280
281 auto trypack = [&placer, &not_packed](ItemListIt it) {
282 return placer.trypack(*it, rem(it, not_packed));
283 };
284
285 while(it != endit && !ret &&
286 free_area - (item_area = it->get().area()) -
287 largestPiece(it, not_packed)->get().area() <= waste)
288 {
289 if(item_area + smallestPiece(it, not_packed)->get().area() >
290 free_area ) { it++; continue; }
291
292 auto pr = trypack(it);
293
294 // First would fit
295 it2 = not_packed.begin();
296 double item2_area = 0;
297 while(it2 != endit && pr && !ret && free_area -
298 (item2_area = it2->get().area()) - item_area <= waste)
299 {
300 double area_sum = item_area + item2_area;
301
302 if(it == it2 || area_sum > free_area ||
303 check_pair(wrong_pairs, *it, *it2)) {
304 it2++; continue;
305 }
306
307 placer.accept(pr);
308 auto pr2 = trypack(it2);
309 if(!pr2) {
310 placer.unpackLast(); // remove first
311 if(try_reverse) {
312 pr2 = trypack(it2);
313 if(pr2) {
314 placer.accept(pr2);
315 auto pr12 = trypack(it);
316 if(pr12) {
317 placer.accept(pr12);
318 ret = true;
319 } else {
320 placer.unpackLast();
321 }
322 }
323 }
324 } else {
325 placer.accept(pr2); ret = true;
326 }
327
328 if(ret)
329 { // Second fits as well
330 free_area -= area_sum;
331 filled_area = bin_area - free_area;
332 } else {
333 wrong_pairs.emplace_back(*it, *it2);
334 it2++;
335 }
336 }
337
338 if(!ret) it++;
339 }
340
341 if(ret) { not_packed.erase(it); not_packed.erase(it2); }
342
343 return ret;
344 };
345
346 auto tryGroupsOfThree = // Try adding groups of three items.
347 [&bin_area,
348 &smallestPiece, &largestPiece,
349 &secondSmallestPiece, &secondLargestPiece,
350 &check_pair, &check_triplet, try_reverse]
351 (Placer& placer, ItemList& not_packed,
352 double waste,
353 double& free_area,
354 double& filled_area)
355 {
356 auto np_size = not_packed.size();
357 if(np_size < 3) return false;
358
359 auto it = not_packed.begin(); // from
360 const auto endit = not_packed.end(); // to
361 auto it2 = it, it3 = it;
362
363 // Containers for pairs and triplets that were tried before and
364 // do not work.
365 std::vector<TPair> wrong_pairs;
366 std::vector<TTriplet> wrong_triplets;
367
368 auto cap = np_size*np_size / 2 ;
369 wrong_pairs.reserve(cap);
370 wrong_triplets.reserve(cap);
371
372 // Will be true if a succesfull pack can be made.
373 bool ret = false;
374
375 auto area = [](const ItemListIt& it) {
376 return it->get().area();
377 };
378
379 auto trypack = [&placer, &not_packed](ItemListIt it) {
380 return placer.trypack(*it, rem(it, not_packed));
381 };
382
383 auto pack = [&placer, &not_packed](ItemListIt it) {
384 return placer.pack(*it, rem(it, not_packed));
385 };
386
387 while (it != endit && !ret) { // drill down 1st level
388
389 // We need to determine in each iteration the largest, second
390 // largest, smallest and second smallest item in terms of area.
391
392 Item& largest = *largestPiece(it, not_packed);
393 Item& second_largest = *secondLargestPiece(it, not_packed);
394
395 double area_of_two_largest =
396 largest.area() + second_largest.area();
397
398 // Check if there is enough free area for the item and the two
399 // largest item
400 if(free_area - area(it) - area_of_two_largest > waste)
401 break;
402
403 // Determine the area of the two smallest item.
404 Item& smallest = *smallestPiece(it, not_packed);
405 Item& second_smallest = *secondSmallestPiece(it, not_packed);
406
407 // Check if there is enough free area for the item and the two
408 // smallest item.
409 double area_of_two_smallest =
410 smallest.area() + second_smallest.area();
411
412 if(area(it) + area_of_two_smallest > free_area) {
413 it++; continue;
414 }
415
416 auto pr = trypack(it);
417
418 // Check for free area and try to pack the 1st item...
419 if(!pr) { it++; continue; }
420
421 it2 = not_packed.begin();
422 double rem2_area = free_area - largest.area();
423 double a2_sum = 0;
424
425 while(it2 != endit && !ret &&
426 rem2_area - (a2_sum = area(it) + area(it2)) <= waste) {
427 // Drill down level 2
428
429 if(a2_sum != area(it) + area(it2)) throw -1;
430
431 if(it == it2 || check_pair(wrong_pairs, *it, *it2)) {
432 it2++; continue;
433 }
434
435 if(a2_sum + smallest.area() > free_area) {
436 it2++; continue;
437 }
438
439 bool can_pack2 = false;
440
441 placer.accept(pr);
442 auto pr2 = trypack(it2);
443 auto pr12 = pr;
444 if(!pr2) {
445 placer.unpackLast(); // remove first
446 if(try_reverse) {
447 pr2 = trypack(it2);
448 if(pr2) {
449 placer.accept(pr2);
450 pr12 = trypack(it);
451 if(pr12) can_pack2 = true;
452 placer.unpackLast();
453 }
454 }
455 } else {
456 placer.unpackLast();
457 can_pack2 = true;
458 }
459
460 if(!can_pack2) {
461 wrong_pairs.emplace_back(*it, *it2);
462 it2++;
463 continue;
464 }
465
466 // Now we have packed a group of 2 items.
467 // The 'smallest' variable now could be identical with
468 // it2 but we don't bother with that
469
470 it3 = not_packed.begin();
471
472 double a3_sum = 0;
473
474 while(it3 != endit && !ret &&
475 free_area - (a3_sum = a2_sum + area(it3)) <= waste) {
476 // 3rd level
477
478 if(it3 == it || it3 == it2 ||
479 check_triplet(wrong_triplets, *it, *it2, *it3))
480 { it3++; continue; }
481
482 if(a3_sum > free_area) { it3++; continue; }
483
484 placer.accept(pr12); placer.accept(pr2);
485 bool can_pack3 = pack(it3);
486
487 if(!can_pack3) {
488 placer.unpackLast();
489 placer.unpackLast();
490 }
491
492 if(!can_pack3 && try_reverse) {
493
494 std::array<size_t, 3> indices = {0, 1, 2};
495 std::array<typename ItemList::iterator, 3>
496 candidates = {it, it2, it3};
497
498 auto tryPack = [&placer, &candidates, &pack](
499 const decltype(indices)& idx)
500 {
501 std::array<bool, 3> packed = {false};
502
503 for(auto id : idx) packed.at(id) =
504 pack(candidates[id]);
505
506 bool check =
507 std::all_of(packed.begin(),
508 packed.end(),
509 [](bool b) { return b; });
510
511 if(!check) for(bool b : packed) if(b)
512 placer.unpackLast();
513
514 return check;
515 };
516
517 while (!can_pack3 && std::next_permutation(
518 indices.begin(),
519 indices.end())){
520 can_pack3 = tryPack(indices);
521 };
522 }
523
524 if(can_pack3) {
525 // finishit
526 free_area -= a3_sum;
527 filled_area = bin_area - free_area;
528 ret = true;
529 } else {
530 wrong_triplets.emplace_back(*it, *it2, *it3);
531 it3++;
532 }
533
534 } // 3rd while
535
536 if(!ret) it2++;
537
538 } // Second while
539
540 if(!ret) it++;
541
542 } // First while
543
544 if(ret) { // If we eventually succeeded, remove all the packed ones.
545 not_packed.erase(it);
546 not_packed.erase(it2);
547 not_packed.erase(it3);
548 }
549
550 return ret;
551 };
552
553 this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
554
555 int acounter = int(store_.size());
556 std::atomic_flag flg = ATOMIC_FLAG_INIT;
557 SpinLock slock(flg);
558
559 auto makeProgress = [this, &acounter, &slock]
560 (Placer& placer, size_t idx, int packednum)
561 {
562
563 packed_bins_[idx] = placer.getItems();
564
565 // TODO here should be a spinlock
566 slock.lock();
567 acounter -= packednum;
568 this->progress_(acounter);
569 slock.unlock();
570 };
571
572 double items_area = 0;
573 for(Item& item : store_) items_area += item.area();
574
575 // Number of bins that will definitely be needed
576 auto bincount_guess = unsigned(std::ceil(items_area / bin_area));
577
578 // Do parallel if feasible
579 bool do_parallel = config_.allow_parallel && bincount_guess > 1 &&
580 ((glob_vertex_count > MAX_VERTICES_SEQUENTIALLY ||
581 store_.size() > MAX_ITEMS_SEQUENTIALLY) ||
583
584 if(do_parallel) dout() << "Parallel execution..." << "\n";
585
586 bool do_pairs = config_.try_pairs;
587 bool do_triplets = config_.try_triplets;
588 StopCondition stopcond = this->stopcond_;
589
590 // The DJD heuristic algorithm itself:
591 auto packjob = [INITIAL_FILL_AREA, bin_area, w, do_triplets, do_pairs,
592 stopcond,
593 &tryOneByOne,
594 &tryGroupsOfTwo,
595 &tryGroupsOfThree,
596 &makeProgress]
597 (Placer& placer, ItemList& not_packed, size_t idx)
598 {
599 double filled_area = placer.filledArea();
600 double free_area = bin_area - filled_area;
601 double waste = .0;
602 bool lasttry = false;
603
604 while(!not_packed.empty() && !stopcond()) {
605
606 {// Fill the bin up to INITIAL_FILL_PROPORTION of its capacity
607 auto it = not_packed.begin();
608
609 while(it != not_packed.end() && !stopcond() &&
610 filled_area < INITIAL_FILL_AREA)
611 {
612 if(placer.pack(*it, rem(it, not_packed))) {
613 filled_area += it->get().area();
614 free_area = bin_area - filled_area;
615 it = not_packed.erase(it);
616 makeProgress(placer, idx, 1);
617 } else it++;
618 }
619 }
620
621 // try pieces one by one
622 while(tryOneByOne(placer, not_packed, waste, free_area,
623 filled_area)) {
624 waste = 0; lasttry = false;
625 makeProgress(placer, idx, 1);
626 }
627
628 // try groups of 2 pieces
629 while(do_pairs &&
630 tryGroupsOfTwo(placer, not_packed, waste, free_area,
631 filled_area)) {
632 waste = 0; lasttry = false;
633 makeProgress(placer, idx, 2);
634 }
635
636 // try groups of 3 pieces
637 while(do_triplets &&
638 tryGroupsOfThree(placer, not_packed, waste, free_area,
639 filled_area)) {
640 waste = 0; lasttry = false;
641 makeProgress(placer, idx, 3);
642 }
643
644 waste += w;
645 if(!lasttry && waste > free_area) lasttry = true;
646 else if(lasttry) break;
647 }
648 };
649
650 size_t idx = 0;
651 ItemList remaining;
652
653 if(do_parallel) {
654 std::vector<ItemList> not_packeds(bincount_guess);
655
656 // Preallocating the bins
657 for(unsigned b = 0; b < bincount_guess; b++) {
658 addBin();
659 ItemList& not_packed = not_packeds[b];
660 for(unsigned idx = b; idx < store_.size(); idx+=bincount_guess) {
661 not_packed.emplace_back(store_[idx]);
662 }
663 }
664
665 // The parallel job
666 auto job = [&placers, &not_packeds, &packjob](unsigned idx) {
667 Placer& placer = placers[idx];
668 ItemList& not_packed = not_packeds[idx];
669 return packjob(placer, not_packed, idx);
670 };
671
672 // We will create jobs for each bin
673 std::vector<std::future<void>> rets(bincount_guess);
674
675 for(unsigned b = 0; b < bincount_guess; b++) { // launch the jobs
676 rets[b] = std::async(std::launch::async, job, b);
677 }
678
679 for(unsigned fi = 0; fi < rets.size(); ++fi) {
680 rets[fi].wait();
681
682 // Collect remaining items while waiting for the running jobs
683 remaining.merge( not_packeds[fi], [](Item& i1, Item& i2) {
684 return i1.area() > i2.area();
685 });
686
687 }
688
689 idx = placers.size();
690
691 // Try to put the remaining items into one of the packed bins
692 if(remaining.size() <= placers.size())
693 for(size_t j = 0; j < idx && !remaining.empty(); j++) {
694 packjob(placers[j], remaining, j);
695 }
696
697 } else {
698 remaining = ItemList(store_.begin(), store_.end());
699 }
700
701 while(!remaining.empty()) {
702 addBin();
703 packjob(placers[idx], remaining, idx); idx++;
704 }
705
706 int binid = 0;
707 for(auto &bin : packed_bins_) {
708 for(Item& itm : bin) itm.binId(binid);
709 binid++;
710 }
711 }
double initial_fill_proportion
Definition djd_heuristic.hpp:71
bool try_pairs
try_pairs Whether to try pairs of items to pack. It will add a quadratic component to the complexity.
Definition djd_heuristic.hpp:53
double waste_increment
How much is the acceptable waste incremented at each iteration.
Definition djd_heuristic.hpp:76
bool try_reverse_order
Definition djd_heuristic.hpp:47
_Item< RawShape > Item
Definition selection_boilerplate.hpp:13
static const unsigned MAX_ITEMS_SEQUENTIALLY
Definition djd_heuristic.hpp:101
PackGroup packed_bins_
Definition selection_boilerplate.hpp:56
bool try_triplets
Whether to try groups of 3 items to pack. This could be very slow for large number of items (>100) as...
Definition djd_heuristic.hpp:60
static const unsigned MAX_VERTICES_SEQUENTIALLY
Definition djd_heuristic.hpp:102
std::reference_wrapper< Item > ItemRef
Definition djd_heuristic.hpp:36
bool force_parallel
Always use parallel processing if the items don't fit into one bin.
Definition djd_heuristic.hpp:90
bool allow_parallel
Allow parallel jobs for filling multiple bins.
Definition djd_heuristic.hpp:84
Container store_
Definition djd_heuristic.hpp:98
StopCondition stopcond_
Definition selection_boilerplate.hpp:58
ProgressFunction progress_
Definition selection_boilerplate.hpp:57
if(!(yy_init))
Definition lexer.c:1190
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
Unit area(const Cntr &poly, const PathTag &)
Definition geometry_traits.hpp:971
std::function< bool(void)> StopCondition
Definition nester.hpp:678
DOut dout()
Definition common.hpp:63
ConstItemRange< typename Container::const_iterator > rem(typename Container::const_iterator it, const Container &cont)
Definition nester.hpp:534
bool check(const DataBase &input, bool check_fontfile=true, bool use_surface=false)
Assert check of inputs data.
Definition EmbossJob.cpp:348

References libnest2d::selections::_DJDHeuristic< RawShape >::Config::allow_parallel, libnest2d::_Item< RawShape >::area(), libnest2d::shapelike::area(), libnest2d::selections::_DJDHeuristic< RawShape >::config_, libnest2d::dout(), libnest2d::selections::_DJDHeuristic< RawShape >::Config::force_parallel, libnest2d::selections::_DJDHeuristic< RawShape >::Config::initial_fill_proportion, libnest2d::selections::_DJDHeuristic< RawShape >::SpinLock::lock(), libnest2d::selections::_DJDHeuristic< RawShape >::MAX_ITEMS_SEQUENTIALLY, libnest2d::selections::_DJDHeuristic< RawShape >::MAX_VERTICES_SEQUENTIALLY, libnest2d::selections::_DJDHeuristic< RawShape >::packed_bins_, libnest2d::selections::SelectionBoilerplate< RawShape >::progress_, libnest2d::rem(), libnest2d::selections::SelectionBoilerplate< RawShape >::stopcond_, libnest2d::selections::_DJDHeuristic< RawShape >::store_, libnest2d::selections::_DJDHeuristic< RawShape >::Config::try_pairs, libnest2d::selections::_DJDHeuristic< RawShape >::Config::try_reverse_order, libnest2d::selections::_DJDHeuristic< RawShape >::Config::try_triplets, libnest2d::selections::_DJDHeuristic< RawShape >::SpinLock::unlock(), and libnest2d::selections::_DJDHeuristic< RawShape >::Config::waste_increment.

+ Here is the call graph for this function:

◆ progressIndicator()

template<class RawShape >
void libnest2d::selections::SelectionBoilerplate< RawShape >::progressIndicator ( ProgressFunction  fn)
inlineinherited

◆ remove_unpackable_items()

template<class RawShape >
template<class Placer , class Container , class Bin , class PCfg >
void libnest2d::selections::SelectionBoilerplate< RawShape >::remove_unpackable_items ( Container &  c,
const Bin &  bin,
const PCfg &  pcfg 
)
inlineprotectedinherited
33 {
34 // Safety test: try to pack each item into an empty bin. If it fails
35 // then it should be removed from the list
36 auto it = c.begin();
37 while (it != c.end() && !stopcond_()) {
38
39 // WARNING: The copy of itm needs to be created before Placer.
40 // Placer is working with references and its destructor still
41 // manipulates the item this is why the order of stack creation
42 // matters here.
43 const Item& itm = *it;
44 Item cpy{itm};
45
46 Placer p{bin};
47 p.configure(pcfg);
48 if (itm.area() <= 0 || !p.pack(cpy)) {
49 static_cast<Item&>(*it).binId(BIN_ID_UNSET);
50 it = c.erase(it);
51 }
52 else it++;
53 }
54 }
_Item< RawShape > Item
Definition selection_boilerplate.hpp:13
static const constexpr int BIN_ID_UNSET
Definition nester.hpp:15

References libnest2d::_Item< RawShape >::area(), libnest2d::BIN_ID_UNSET, libnest2d::_Item< RawShape >::binId(), and libnest2d::selections::SelectionBoilerplate< RawShape >::stopcond_.

+ Here is the call graph for this function:

◆ stopCondition()

template<class RawShape >
void libnest2d::selections::SelectionBoilerplate< RawShape >::stopCondition ( StopCondition  cond)
inlineinherited

Member Data Documentation

◆ config_

◆ last_packed_bin_id_

◆ MAX_ITEMS_SEQUENTIALLY

template<class RawShape >
const unsigned libnest2d::selections::_DJDHeuristic< RawShape >::MAX_ITEMS_SEQUENTIALLY = 30
staticprivate

◆ MAX_VERTICES_SEQUENTIALLY

template<class RawShape >
const unsigned libnest2d::selections::_DJDHeuristic< RawShape >::MAX_VERTICES_SEQUENTIALLY = MAX_ITEMS_SEQUENTIALLY*20
staticprivate

◆ packed_bins_

template<class RawShape >
PackGroup libnest2d::selections::SelectionBoilerplate< RawShape >::packed_bins_
private

◆ progress_

◆ stopcond_

◆ store_

template<class RawShape >
Container libnest2d::selections::_DJDHeuristic< RawShape >::store_
private

The documentation for this class was generated from the following file: