Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
libnest2d::placers::_NofitPolyPlacer< RawShape, TBin > Class Template Reference

#include <src/libnest2d/include/libnest2d/placers/nfpplacer.hpp>

+ Inheritance diagram for libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >:
+ Collaboration diagram for libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >:

Classes

class  Optimizer
 
struct  Optimum
 

Public Types

using Pile = nfp::Shapes< RawShape >
 

Public Member Functions

 _NofitPolyPlacer (const BinType &bin)
 
 _NofitPolyPlacer (const _NofitPolyPlacer &)=default
 
_NofitPolyPlaceroperator= (const _NofitPolyPlacer &)=default
 
 _NofitPolyPlacer (_NofitPolyPlacer &&)=default
 
_NofitPolyPlaceroperator= (_NofitPolyPlacer &&)=default
 
 ~_NofitPolyPlacer ()
 
void clearItems ()
 
void preload (const ItemGroup &packeditems)
 
template<class Range = ConstItemRange<typename Base::DefaultIter>>
PackResult trypack (Item &item, const Range &remaining=Range())
 

Static Public Member Functions

static double overfit (const Box &bb, const RawShape &bin)
 
static double overfit (const RawShape &chull, const RawShape &bin)
 
static double overfit (const RawShape &chull, const Box &bin)
 
static double overfit (const Box &bb, const Box &bin)
 
static double overfit (const Box &bb, const _Circle< Vertex > &bin)
 
static double overfit (const RawShape &chull, const _Circle< Vertex > &bin)
 

Private Types

using Base = PlacerBoilerplate< _NofitPolyPlacer< RawShape, TBin >, RawShape, TBin, NfpPConfig< RawShape > >
 
using Box = _Box< TPoint< RawShape > >
 
using MaxNfpLevel = nfp::MaxNfpLevel< RawShape >
 
using Shapes = TMultiShape< RawShape >
 
using Edges = EdgeCache< RawShape >
 

Private Member Functions

Shapes calcnfp (const Item &trsh, Lvl< nfp::NfpLevel::CONVEX_ONLY >)
 
template<class Level >
Shapes calcnfp (const Item &, Level)
 
void finalAlign (const RawShape &pbin)
 
void finalAlign (_Circle< TPoint< RawShape > > cbin)
 
void finalAlign (Box bbin)
 
void setInitialPosition (Item &item)
 
void placeOutsideOfBin (Item &item)
 

Private Attributes

const double norm_
 
Pile merged_pile_
 

Detailed Description

template<class RawShape, class TBin = _Box<TPoint<RawShape>>>
class libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >

Member Typedef Documentation

◆ Base

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
using libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::Base = PlacerBoilerplate<_NofitPolyPlacer<RawShape, TBin>, RawShape, TBin, NfpPConfig<RawShape> >
private

◆ Box

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
using libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::Box = _Box<TPoint<RawShape> >
private

◆ Edges

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
using libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::Edges = EdgeCache<RawShape>
private

◆ MaxNfpLevel

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
using libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::MaxNfpLevel = nfp::MaxNfpLevel<RawShape>
private

◆ Pile

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
using libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::Pile = nfp::Shapes<RawShape>

◆ Shapes

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
using libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::Shapes = TMultiShape<RawShape>
private

Constructor & Destructor Documentation

◆ _NofitPolyPlacer() [1/3]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::_NofitPolyPlacer ( const BinType &  bin)
inlineexplicit
461 :
462 Base(bin),
463 norm_(std::sqrt(sl::area(bin)))
464 {
465 // In order to not have items out of bin, it will be shrinked by an
466 // very little empiric offset value.
467 // sl::offset(bin_, 1e-5 * norm_);
468 }
const double norm_
Definition nfpplacer.hpp:456
PlacerBoilerplate< _NofitPolyPlacer< RawShape, TBin >, RawShape, TBin, NfpPConfig< RawShape > > Base
Definition nfpplacer.hpp:441
Unit area(const Cntr &poly, const PathTag &)
Definition geometry_traits.hpp:971

◆ _NofitPolyPlacer() [2/3]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::_NofitPolyPlacer ( const _NofitPolyPlacer< RawShape, TBin > &  )
default

◆ _NofitPolyPlacer() [3/3]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::_NofitPolyPlacer ( _NofitPolyPlacer< RawShape, TBin > &&  )
default

◆ ~_NofitPolyPlacer()

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::~_NofitPolyPlacer ( )
inline
527 {
528 clearItems();
529 }
void clearItems()
Definition nfpplacer.hpp:531

References libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::clearItems().

+ Here is the call graph for this function:

Member Function Documentation

◆ calcnfp() [1/2]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
template<class Level >
Shapes libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::calcnfp ( const Item ,
Level   
)
inlineprivate
592 { // Function for arbitrary level of nfp implementation
593
594 // TODO: implement
595 return {};
596 }

◆ calcnfp() [2/2]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
Shapes libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::calcnfp ( const Item trsh,
Lvl< nfp::NfpLevel::CONVEX_ONLY  
)
inlineprivate
554 {
555 using namespace nfp;
556
557 Shapes nfps(items_.size());
558
559 // /////////////////////////////////////////////////////////////////////
560 // TODO: this is a workaround and should be solved in Item with mutexes
561 // guarding the mutable members when writing them.
562 // /////////////////////////////////////////////////////////////////////
563 trsh.transformedShape();
564 trsh.referenceVertex();
565 trsh.rightmostTopVertex();
566 trsh.leftmostBottomVertex();
567
568 for(Item& itm : items_) {
569 itm.transformedShape();
570 itm.referenceVertex();
571 itm.rightmostTopVertex();
572 itm.leftmostBottomVertex();
573 }
574 // /////////////////////////////////////////////////////////////////////
575
576 __parallel::enumerate(items_.begin(), items_.end(),
577 [&nfps, &trsh](const Item& sh, size_t n)
578 {
579 auto& fixedp = sh.transformedShape();
580 auto& orbp = trsh.transformedShape();
581 auto subnfp_r = noFitPolygon<NfpLevel::CONVEX_ONLY>(fixedp, orbp);
582 correctNfpPosition(subnfp_r, sh, trsh);
583 nfps[n] = subnfp_r.first;
584 });
585
586 return nfp::merge(nfps);
587 }
TMultiShape< RawShape > Shapes
Definition nfpplacer.hpp:551
void enumerate(Iterator from, Iterator to, std::function< void(TIteratorValue< Iterator >, size_t)> fn, std::launch policy=std::launch::deferred|std::launch::async)
Definition parallel.hpp:22
TMultiShape< PolygonImpl > merge(const TMultiShape< PolygonImpl > &shapes)
Definition geometries.hpp:259
_Item< PolygonImpl > Item
Definition libnest2d.hpp:36

References libnest2d::__parallel::enumerate(), libnest2d::_Item< RawShape >::leftmostBottomVertex(), libnest2d::nfp::merge(), libnest2d::_Item< RawShape >::referenceVertex(), libnest2d::_Item< RawShape >::rightmostTopVertex(), and libnest2d::_Item< RawShape >::transformedShape().

Referenced by libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::trypack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clearItems()

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::clearItems ( )
inline
531 {
532 finalAlign(bin_);
533 merged_pile_ = {};
535 }
Pile merged_pile_
Definition nfpplacer.hpp:457
void finalAlign(const RawShape &pbin)
Definition nfpplacer.hpp:914
void clearItems()
Definition placer_boilerplate.hpp:93

References libnest2d::placers::PlacerBoilerplate< Subclass, RawShape, TBin, Cfg >::clearItems(), libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::finalAlign(), and libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::merged_pile_.

Referenced by libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::~_NofitPolyPlacer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ finalAlign() [1/3]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::finalAlign ( _Circle< TPoint< RawShape > >  cbin)
inlineprivate
919 {
920 if(items_.empty() ||
921 config_.alignment == Config::Alignment::DONT_ALIGN) return;
922
923 nfp::Shapes<RawShape> m;
924 m.reserve(items_.size());
925 for(Item& item : items_) m.emplace_back(item.transformedShape());
926
928
929 auto d = cbin.center() - c.center();
930 for(Item& item : items_) item.translate(d);
931 }
_Circle< TPoint< RawShape > > boundingCircle(const RawShape &sh)
Definition nfpplacer.hpp:432
S convexHull(const S &sh, const PathTag &)
Definition geometry_traits.hpp:1032
void translate(Slic3r::ExPolygon &sh, const Slic3r::Point &offs)
Definition geometries.hpp:241

References libnest2d::placers::boundingCircle(), libnest2d::shapelike::convexHull(), libnest2d::_Item< RawShape >::transformedShape(), and libnest2d::_Item< RawShape >::translate().

+ Here is the call graph for this function:

◆ finalAlign() [2/3]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::finalAlign ( Box  bbin)
inlineprivate
933 {
934 if(items_.empty() ||
935 config_.alignment == Config::Alignment::DONT_ALIGN) return;
936
937 Box bb = items_.front().get().boundingBox();
938 for(Item& item : items_)
939 bb = sl::boundingBox(item.boundingBox(), bb);
940
941 Vertex ci, cb;
942
943 switch(config_.alignment) {
944 case Config::Alignment::CENTER: {
945 ci = bb.center();
946 cb = bbin.center();
947 break;
948 }
949 case Config::Alignment::BOTTOM_LEFT: {
950 ci = bb.minCorner();
951 cb = bbin.minCorner();
952 break;
953 }
954 case Config::Alignment::BOTTOM_RIGHT: {
955 ci = {getX(bb.maxCorner()), getY(bb.minCorner())};
956 cb = {getX(bbin.maxCorner()), getY(bbin.minCorner())};
957 break;
958 }
959 case Config::Alignment::TOP_LEFT: {
960 ci = {getX(bb.minCorner()), getY(bb.maxCorner())};
961 cb = {getX(bbin.minCorner()), getY(bbin.maxCorner())};
962 break;
963 }
964 case Config::Alignment::TOP_RIGHT: {
965 ci = bb.maxCorner();
966 cb = bbin.maxCorner();
967 break;
968 }
969 default: ; // DONT_ALIGN
970 }
971
972 auto d = cb - ci;
973 for(Item& item : items_) item.translate(d);
974 }
_Box< TPoint< RawShape > > Box
Definition nfpplacer.hpp:445
_Box< TPoint< S > > boundingBox(const S &, const PathTag &)
Definition geometry_traits.hpp:706
TCoord< P > getX(const P &p)
Definition geometry_traits.hpp:424
TCoord< P > getY(const P &p)
Definition geometry_traits.hpp:427

References libnest2d::_Item< RawShape >::boundingBox(), libnest2d::shapelike::boundingBox(), libnest2d::_Box< P >::center(), libnest2d::getX(), libnest2d::getY(), libnest2d::_Box< P >::maxCorner(), libnest2d::_Box< P >::minCorner(), and libnest2d::_Item< RawShape >::translate().

+ Here is the call graph for this function:

◆ finalAlign() [3/3]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::finalAlign ( const RawShape &  pbin)
inlineprivate
914 {
915 auto bbin = sl::boundingBox(pbin);
916 finalAlign(bbin);
917 }

References libnest2d::shapelike::boundingBox().

Referenced by libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::clearItems().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ operator=() [1/2]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
_NofitPolyPlacer & libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::operator= ( _NofitPolyPlacer< RawShape, TBin > &&  )
default

◆ operator=() [2/2]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
_NofitPolyPlacer & libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::operator= ( const _NofitPolyPlacer< RawShape, TBin > &  )
default

◆ overfit() [1/6]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
static double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit ( const Box bb,
const _Circle< Vertex > &  bin 
)
inlinestatic
513 {
514 double boxr = 0.5*pl::distance(bb.minCorner(), bb.maxCorner());
515 double diff = boxr - bin.radius();
516 return diff;
517 }
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:672
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329

References libnest2d::pointlike::distance(), libnest2d::_Box< P >::maxCorner(), libnest2d::_Box< P >::minCorner(), and libnest2d::_Circle< P >::radius().

+ Here is the call graph for this function:

◆ overfit() [2/6]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
static double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit ( const Box bb,
const Box bin 
)
inlinestatic
502 {
503 auto wdiff = TCompute<RawShape>(bb.width()) - bin.width();
504 auto hdiff = TCompute<RawShape>(bb.height()) - bin.height();
505 double diff = .0;
506 if(wdiff > 0) diff += double(wdiff);
507 if(hdiff > 0) diff += double(hdiff);
508
509 return diff;
510 }

References libnest2d::_Box< P >::height(), and libnest2d::_Box< P >::width().

+ Here is the call graph for this function:

◆ overfit() [3/6]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
static double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit ( const Box bb,
const RawShape &  bin 
)
inlinestatic
478 {
479 auto bbin = sl::boundingBox(bin);
480 auto d = bbin.center() - bb.center();
481 _Rectangle<RawShape> rect(bb.width(), bb.height());
482 rect.translate(bb.minCorner() + d);
483 return sl::isInside(rect.transformedShape(), bin) ? -1.0 : 1;
484 }
bool isInside(const TGuest &, const THost &, const PointTag &, const PolygonTag &)
Definition geometry_traits.hpp:672

References libnest2d::shapelike::boundingBox(), libnest2d::_Box< P >::center(), libnest2d::_Box< P >::height(), libnest2d::shapelike::isInside(), libnest2d::_Box< P >::minCorner(), libnest2d::_Item< RawShape >::transformedShape(), libnest2d::_Item< RawShape >::translate(), and libnest2d::_Box< P >::width().

Referenced by libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit(), and libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::trypack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ overfit() [4/6]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
static double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit ( const RawShape &  chull,
const _Circle< Vertex > &  bin 
)
inlinestatic
521 {
522 double r = boundingCircle(chull).radius();
523 double diff = r - bin.radius();
524 return diff;
525 }

References libnest2d::placers::boundingCircle(), and libnest2d::_Circle< P >::radius().

+ Here is the call graph for this function:

◆ overfit() [5/6]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
static double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit ( const RawShape &  chull,
const Box bin 
)
inlinestatic
496 {
497 auto bbch = sl::boundingBox(chull);
498 return overfit(bbch, bin);
499 }
static double overfit(const Box &bb, const RawShape &bin)
Definition nfpplacer.hpp:478

References libnest2d::shapelike::boundingBox(), and libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit().

+ Here is the call graph for this function:

◆ overfit() [6/6]

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
static double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit ( const RawShape &  chull,
const RawShape &  bin 
)
inlinestatic
486 {
487 auto bbch = sl::boundingBox(chull);
488 auto bbin = sl::boundingBox(bin);
489 auto d = bbch.center() - bbin.center();
490 auto chullcpy = chull;
491 sl::translate(chullcpy, d);
492 return sl::isInside(chullcpy, bin) ? -1.0 : 1.0;
493 }

References libnest2d::shapelike::boundingBox(), libnest2d::shapelike::isInside(), and libnest2d::shapelike::translate().

+ Here is the call graph for this function:

◆ placeOutsideOfBin()

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::placeOutsideOfBin ( Item item)
inlineprivate
1015 {
1016 auto&& bb = item.boundingBox();
1017 Box binbb = sl::boundingBox(bin_);
1018
1019 Vertex v = { getX(bb.maxCorner()), getY(bb.minCorner()) };
1020
1021 Coord dx = getX(binbb.maxCorner()) - getX(v);
1022 Coord dy = getY(binbb.maxCorner()) - getY(v);
1023
1024 item.translate({dx, dy});
1025 }
TCoord< PointImpl > Coord
Definition libnest2d.hpp:30

References libnest2d::_Item< RawShape >::boundingBox(), libnest2d::shapelike::boundingBox(), libnest2d::getX(), libnest2d::getY(), libnest2d::_Box< P >::maxCorner(), and libnest2d::_Item< RawShape >::translate().

Referenced by libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::trypack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ preload()

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::preload ( const ItemGroup &  packeditems)
inline
537 {
538 Base::preload(packeditems);
539
540 for (const Item& itm : packeditems)
541 merged_pile_.emplace_back(itm.transformedShape());
542
544
545 if (config_.on_preload)
546 config_.on_preload(packeditems, config_);
547 }
void preload(const ItemGroup &packeditems)
Definition placer_boilerplate.hpp:72

References libnest2d::nfp::merge(), libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::merged_pile_, and libnest2d::placers::PlacerBoilerplate< Subclass, RawShape, TBin, Cfg >::preload().

+ Here is the call graph for this function:

◆ setInitialPosition()

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
void libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::setInitialPosition ( Item item)
inlineprivate
976 {
977 Box bb = item.boundingBox();
978
979 Vertex ci, cb;
980 auto bbin = sl::boundingBox(bin_);
981
982 switch(config_.starting_point) {
983 case Config::Alignment::CENTER: {
984 ci = bb.center();
985 cb = bbin.center();
986 break;
987 }
988 case Config::Alignment::BOTTOM_LEFT: {
989 ci = bb.minCorner();
990 cb = bbin.minCorner();
991 break;
992 }
993 case Config::Alignment::BOTTOM_RIGHT: {
994 ci = {getX(bb.maxCorner()), getY(bb.minCorner())};
995 cb = {getX(bbin.maxCorner()), getY(bbin.minCorner())};
996 break;
997 }
998 case Config::Alignment::TOP_LEFT: {
999 ci = {getX(bb.minCorner()), getY(bb.maxCorner())};
1000 cb = {getX(bbin.minCorner()), getY(bbin.maxCorner())};
1001 break;
1002 }
1003 case Config::Alignment::TOP_RIGHT: {
1004 ci = bb.maxCorner();
1005 cb = bbin.maxCorner();
1006 break;
1007 }
1008 default:;
1009 }
1010
1011 auto d = cb - ci;
1012 item.translate(d);
1013 }

References libnest2d::_Item< RawShape >::boundingBox(), libnest2d::shapelike::boundingBox(), libnest2d::_Box< P >::center(), libnest2d::getX(), libnest2d::getY(), libnest2d::_Box< P >::maxCorner(), libnest2d::_Box< P >::minCorner(), and libnest2d::_Item< RawShape >::translate().

Referenced by libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::trypack().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ trypack()

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
template<class Range = ConstItemRange<typename Base::DefaultIter>>
PackResult libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::trypack ( Item item,
const Range &  remaining = Range() 
)
inline
624 {
625
626 PackResult ret;
627
628 bool can_pack = false;
629 double best_overfit = std::numeric_limits<double>::max();
630
631 ItemGroup remlist;
632 if(remaining.valid) {
633 remlist.insert(remlist.end(), remaining.from, remaining.to);
634 }
635
636 double global_score = std::numeric_limits<double>::max();
637
638 auto initial_tr = item.translation();
639 auto initial_rot = item.rotation();
640 Vertex final_tr = {0, 0};
641 Radians final_rot = initial_rot;
642 Shapes nfps;
643
644 auto& bin = bin_;
645 double norm = norm_;
646 auto pbb = sl::boundingBox(merged_pile_);
647 auto binbb = sl::boundingBox(bin);
648
649 // This is the kernel part of the object function that is
650 // customizable by the library client
651 std::function<double(const Item&)> _objfunc;
652 if(config_.object_function) _objfunc = config_.object_function;
653 else {
654
655 // Inside check has to be strict if no alignment was enabled
656 std::function<double(const Box&)> ins_check;
657 if(config_.alignment == Config::Alignment::DONT_ALIGN)
658 ins_check = [&binbb, norm](const Box& fullbb) {
659 double ret = 0;
660 if(!sl::isInside(fullbb, binbb))
661 ret += norm;
662 return ret;
663 };
664 else
665 ins_check = [&bin](const Box& fullbb) {
666 double miss = overfit(fullbb, bin);
667 miss = miss > 0? miss : 0;
668 return std::pow(miss, 2);
669 };
670
671 _objfunc = [norm, binbb, pbb, ins_check](const Item& item)
672 {
673 auto ibb = item.boundingBox();
674 auto fullbb = sl::boundingBox(pbb, ibb);
675
676 double score = pl::distance(ibb.center(),
677 binbb.center());
678 score /= norm;
679
680 score += ins_check(fullbb);
681
682 return score;
683 };
684 }
685
686 if(items_.empty()) {
687 setInitialPosition(item);
688 auto best_tr = item.translation();
689 auto best_rot = item.rotation();
690 best_overfit = overfit(item.transformedShape(), bin_);
691
692 for(auto rot : config_.rotations) {
693 item.translation(initial_tr);
694 item.rotation(initial_rot + rot);
695 setInitialPosition(item);
696 double of = 0.;
697 if ((of = overfit(item.transformedShape(), bin_)) < best_overfit) {
698 best_overfit = of;
699 best_tr = item.translation();
700 best_rot = item.rotation();
701 }
702 }
703
704 can_pack = best_overfit <= 0;
705 item.rotation(best_rot);
706 item.translation(best_tr);
707 } else {
708
709 Pile merged_pile = merged_pile_;
710
711 for(auto rot : config_.rotations) {
712
713 item.translation(initial_tr);
714 item.rotation(initial_rot + rot);
715 item.boundingBox(); // fill the bb cache
716
717 // place the new item outside of the print bed to make sure
718 // it is disjunct from the current merged pile
719 placeOutsideOfBin(item);
720
721 nfps = calcnfp(item, Lvl<MaxNfpLevel::value>());
722
723 auto iv = item.referenceVertex();
724
725 auto startpos = item.translation();
726
727 std::vector<Edges> ecache;
728 ecache.reserve(nfps.size());
729
730 for(auto& nfp : nfps ) {
731 ecache.emplace_back(nfp);
732 ecache.back().accuracy(config_.accuracy);
733 }
734
735 // Our object function for placement
736 auto rawobjfunc = [_objfunc, iv, startpos]
737 (Vertex v, Item& itm)
738 {
739 auto d = (v - iv) + startpos;
740 itm.translation(d);
741 return _objfunc(itm);
742 };
743
744 auto getNfpPoint = [&ecache](const Optimum& opt)
745 {
746 return opt.hidx < 0? ecache[opt.nfpidx].coords(opt.relpos) :
747 ecache[opt.nfpidx].coords(opt.hidx, opt.relpos);
748 };
749
750 auto alignment = config_.alignment;
751
752 auto boundaryCheck = [alignment, &merged_pile, &getNfpPoint,
753 &item, &bin, &iv, &startpos] (const Optimum& o)
754 {
755 auto v = getNfpPoint(o);
756 auto d = (v - iv) + startpos;
757 item.translation(d);
758
759 merged_pile.emplace_back(item.transformedShape());
760 auto chull = sl::convexHull(merged_pile);
761 merged_pile.pop_back();
762
763 double miss = 0;
764 if(alignment == Config::Alignment::DONT_ALIGN)
765 miss = sl::isInside(chull, bin) ? -1.0 : 1.0;
766 else miss = overfit(chull, bin);
767
768 return miss;
769 };
770
771 Optimum optimum(0, 0);
772 double best_score = std::numeric_limits<double>::max();
773 std::launch policy = std::launch::deferred;
774 if(config_.parallel) policy |= std::launch::async;
775
776 if(config_.before_packing)
777 config_.before_packing(merged_pile, items_, remlist);
778
779 using OptResult = opt::Result<double>;
780 using OptResults = std::vector<OptResult>;
781
782 // Local optimization with the four polygon corners as
783 // starting points
784 for(unsigned ch = 0; ch < ecache.size(); ch++) {
785 auto& cache = ecache[ch];
786
787 OptResults results(cache.corners().size());
788
789 auto& rofn = rawobjfunc;
790 auto& nfpoint = getNfpPoint;
791 float accuracy = config_.accuracy;
792
794 cache.corners().begin(),
795 cache.corners().end(),
796 [&results, &item, &rofn, &nfpoint, ch, accuracy]
797 (double pos, size_t n)
798 {
799 Optimizer solver(accuracy);
800
801 Item itemcpy = item;
802 auto contour_ofn = [&rofn, &nfpoint, ch, &itemcpy]
803 (double relpos)
804 {
805 Optimum op(relpos, ch);
806 return rofn(nfpoint(op), itemcpy);
807 };
808
809 try {
810 results[n] = solver.optimize_min(contour_ofn,
811 opt::initvals<double>(pos),
812 opt::bound<double>(0, 1.0)
813 );
814 } catch(std::exception& e) {
815 derr() << "ERROR: " << e.what() << "\n";
816 }
817 }, policy);
818
819 auto resultcomp =
820 []( const OptResult& r1, const OptResult& r2 ) {
821 return r1.score < r2.score;
822 };
823
824 auto mr = *std::min_element(results.begin(), results.end(),
825 resultcomp);
826
827 if(mr.score < best_score) {
828 Optimum o(std::get<0>(mr.optimum), ch, -1);
829 double miss = boundaryCheck(o);
830 if(miss <= 0) {
831 best_score = mr.score;
832 optimum = o;
833 } else {
834 best_overfit = std::min(miss, best_overfit);
835 }
836 }
837
838 for(unsigned hidx = 0; hidx < cache.holeCount(); ++hidx) {
839 results.clear();
840 results.resize(cache.corners(hidx).size());
841
842 // TODO : use parallel for
843 __parallel::enumerate(cache.corners(hidx).begin(),
844 cache.corners(hidx).end(),
845 [&results, &item, &nfpoint,
846 &rofn, ch, hidx, accuracy]
847 (double pos, size_t n)
848 {
849 Optimizer solver(accuracy);
850
851 Item itmcpy = item;
852 auto hole_ofn =
853 [&rofn, &nfpoint, ch, hidx, &itmcpy]
854 (double pos)
855 {
856 Optimum opt(pos, ch, hidx);
857 return rofn(nfpoint(opt), itmcpy);
858 };
859
860 try {
861 results[n] = solver.optimize_min(hole_ofn,
862 opt::initvals<double>(pos),
863 opt::bound<double>(0, 1.0)
864 );
865
866 } catch(std::exception& e) {
867 derr() << "ERROR: " << e.what() << "\n";
868 }
869 }, policy);
870
871 auto hmr = *std::min_element(results.begin(),
872 results.end(),
873 resultcomp);
874
875 if(hmr.score < best_score) {
876 Optimum o(std::get<0>(hmr.optimum),
877 ch, hidx);
878 double miss = boundaryCheck(o);
879 if(miss <= 0.0) {
880 best_score = hmr.score;
881 optimum = o;
882 } else {
883 best_overfit = std::min(miss, best_overfit);
884 }
885 }
886 }
887 }
888
889 if( best_score < global_score ) {
890 auto d = (getNfpPoint(optimum) - iv) + startpos;
891 final_tr = d;
892 final_rot = initial_rot + rot;
893 can_pack = true;
894 global_score = best_score;
895 }
896 }
897
898 item.translation(final_tr);
899 item.rotation(final_rot);
900 }
901
902 if(can_pack) {
903 ret = PackResult(item);
904 item.onPacked();
905 merged_pile_ = nfp::merge(merged_pile_, item.transformedShape());
906 } else {
907 ret = PackResult(best_overfit);
908 }
909
910 return ret;
911 }
Shapes calcnfp(const Item &trsh, Lvl< nfp::NfpLevel::CONVEX_ONLY >)
Definition nfpplacer.hpp:553
nfp::Shapes< RawShape > Pile
Definition nfpplacer.hpp:451
void placeOutsideOfBin(Item &item)
Definition nfpplacer.hpp:1015
void setInitialPosition(Item &item)
Definition nfpplacer.hpp:976
std::vector< std::reference_wrapper< Item > > ItemGroup
Definition Arrange.cpp:77
DErr derr()
Definition common.hpp:64

References libnest2d::_Item< RawShape >::boundingBox(), libnest2d::shapelike::boundingBox(), libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::calcnfp(), libnest2d::shapelike::convexHull(), libnest2d::derr(), libnest2d::pointlike::distance(), libnest2d::__parallel::enumerate(), libnest2d::shapelike::isInside(), libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::merged_pile_, libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::norm_, libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::overfit(), libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::placeOutsideOfBin(), libnest2d::_Item< RawShape >::referenceVertex(), libnest2d::_Item< RawShape >::rotation(), libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::setInitialPosition(), libnest2d::_Item< RawShape >::transformedShape(), and libnest2d::_Item< RawShape >::translation().

+ Here is the call graph for this function:

Member Data Documentation

◆ merged_pile_

◆ norm_

template<class RawShape , class TBin = _Box<TPoint<RawShape>>>
const double libnest2d::placers::_NofitPolyPlacer< RawShape, TBin >::norm_
private

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