OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::arrangement::AutoArranger< TBin > Class Template Reference
Collaboration diagram for Slic3r::arrangement::AutoArranger< TBin >:

Public Types

using Placer = typename placers::_NofitPolyPlacer<ExPolygon, TBin>
using Selector = selections::_FirstFitSelection<ExPolygon>
using Packer = _Nester<Placer, Selector>
using PConfig = typename Packer::PlacementConfig
using Distance = TCoord<PointImpl>

Public Member Functions

 AutoArranger (const TBin &bin, const ArrangeParams &params, std::function< void(unsigned, std::string)> progressind, std::function< bool(void)> stopcond)
template<class It>
void operator() (It from, It to)
PConfig & config ()
const PConfig & config () const
void preload (std::vector< Item > &fixeditems)

Public Attributes

std::vector< Item > m_excluded_items_in_each_plate

Protected Member Functions

template<class T>
ArithmeticOnly< T, double > norm (T val)
double dist_for_BOTTOM_LEFT (Box ibb, const Slic3r::Point &origin_pack)
bool corner_packing () const
double belt_pos (const Box::PointType &pt) const
double belt_start (const Box &bb) const
double belt_end (const Box &bb) const
Box::PointType belt_origin () const
double dist_along_belt (const Box &ibb)
double corner_bindist (const Box &ibb, const Slic3r::Point &origin_pack)
double dist_to_bin (const Box &ibb, const Slic3r::Point &origin_pack, typename Packer::PlacementConfig::Alignment starting_point_alignment)
std::tuple< double, Box > objfunc (const Item &item, const Slic3r::Point &origin_pack)
std::function< double(const Item &, const ItemGroup &)> get_objfn ()
std::function< double(const Item &, const ItemGroup &)> get_objfn ()
std::function< double(const Item &, const ItemGroup &)> get_objfn ()
std::function< double(const Item &, const ItemGroup &)> get_objfn ()

Static Protected Member Functions

static double at (const Box::PointType &pt, int i)

Protected Attributes

Packer m_pck
PConfig m_pconf
TBin m_bin
double m_bin_area
SpatIndex m_rtree
SpatIndex m_smallsrtree
double m_norm
MultiPolygon m_merged_pile
Box m_pilebb
ItemGroup m_remaining
ItemGroup m_items
std::vector< Box > m_excluded_and_extruCali_regions
size_t m_item_count = 0
ArrangeParams params

Detailed Description

template<class TBin>
class Slic3r::arrangement::AutoArranger< TBin >

Member Typedef Documentation

◆ Distance

template<class TBin>
using Slic3r::arrangement::AutoArranger< TBin >::Distance = TCoord<PointImpl>

◆ Packer

template<class TBin>
using Slic3r::arrangement::AutoArranger< TBin >::Packer = _Nester<Placer, Selector>

◆ PConfig

template<class TBin>
using Slic3r::arrangement::AutoArranger< TBin >::PConfig = typename Packer::PlacementConfig

◆ Placer

template<class TBin>
using Slic3r::arrangement::AutoArranger< TBin >::Placer = typename placers::_NofitPolyPlacer<ExPolygon, TBin>

◆ Selector

template<class TBin>
using Slic3r::arrangement::AutoArranger< TBin >::Selector = selections::_FirstFitSelection<ExPolygon>

Constructor & Destructor Documentation

◆ AutoArranger()

template<class TBin>
Slic3r::arrangement::AutoArranger< TBin >::AutoArranger ( const TBin & bin,
const ArrangeParams & params,
std::function< void(unsigned, std::string)> progressind,
std::function< bool(void)> stopcond )
inline
858 : m_pck(bin, params.min_obj_distance)
859 , m_bin(bin)
860 {
861 m_bin_area = abs(sl::area(bin)); // due to clockwise or anti-clockwise, the result of sl::area may be negative
864 this->params = params;
865
866 // if best object center is not bed center, specify starting point here
867 if (std::abs(this->params.align_center.x() - 0.5) > 0.001 || std::abs(this->params.align_center.y() - 0.5) > 0.001) {
869 m_pconf.best_object_pos = binbb.minCorner() + Point{ binbb.width() * this->params.align_center.x(), binbb.height() * this->params.align_center.y() };
871 }
872
873 for (auto& region : m_pconf.m_excluded_regions) {
874 Box bb = region.boundingBox();
876 }
877 for (auto& region : m_pconf.m_nonprefered_regions) {
878 Box bb = region.boundingBox();
880 }
881
882 // Set up a callback that is called just before arranging starts
883 // This functionality is provided by the Nester class (m_pack).
884 m_pconf.before_packing =
885 [this](const MultiPolygon& merged_pile, // merged pile
886 const ItemGroup& items, // packed items
887 const ItemGroup& remaining) // future items to be packed
888 {
889 m_items = items;
892
893 m_pilebb.defined = false;
894 if (!merged_pile.empty())
895 {
897 m_pilebb.defined = true;
898 }
899
900 m_rtree.clear();
901 m_smallsrtree.clear();
902
903 // We will treat big items (compared to the print bed) differently
904 auto isBig = [this](double a) {
905 return a / m_bin_area > BIG_ITEM_TRESHOLD ;
906 };
907
908 for(unsigned idx = 0; idx < items.size(); ++idx) {
909 Item& itm = items[idx];
910 if (itm.is_virt_object) continue;
911 if(isBig(itm.area())) m_rtree.insert({itm.boundingBox(), idx});
912 m_smallsrtree.insert({itm.boundingBox(), idx});
913 }
914 };
915
916 m_pconf.object_function = get_objfn();
917
918 // preload fixed items (and excluded regions) on plate
919 m_pconf.on_preload = [this](const ItemGroup &items, PConfig &cfg) {
920 if (items.empty()) return;
921
923
924 auto starting_point = this->params.is_belt ? belt_origin() :
926 // if we have wipe tower, items should be arranged around wipe tower
927 for (Item itm : items) {
928 if (itm.is_wipe_tower) {
929 starting_point = itm.boundingBox().center();
930 BOOST_LOG_TRIVIAL(debug) << "arrange we have wipe tower, change starting point to: " << starting_point;
931 break;
932 }
933 }
934
935 cfg.object_function = [this, binbb, starting_point](const Item &item, const ItemGroup &packed_items) {
937 };
938 };
939
940 auto on_packed = params.on_packed;
941
942 if (progressind || on_packed)
943 m_pck.progressIndicator(
944 [this, progressind, on_packed](unsigned num_finished) {
945 int last_bed = m_pck.lastPackedBinId();
946 if (last_bed >= 0) {
947 Item& last_packed = m_pck.lastResult()[last_bed].back();
949 ap.bed_idx = last_packed.binId();
950 ap.priority = last_packed.priority();
952 if (on_packed)
953 on_packed(ap);
954 BOOST_LOG_TRIVIAL(debug) << "arrange " + last_packed.name + " succeed!"
955 << ", plate id=" << ap.bed_idx << ", pos=" << last_packed.translation()
956 << ", temp_type=" << last_packed.filament_temp_type;
957 }
958 });
959
960 m_pck.unfitIndicator([](std::string name) {
961 BOOST_LOG_TRIVIAL(debug) << "arrange progress: " + name;
962 });
963
964 if (stopcond) m_pck.stopCondition(stopcond);
965
966 m_pconf.sortfunc= [&params](Item& i1, Item& i2) {
967 int p1 = i1.priority(), p2 = i2.priority();
968 if (p1 != p2)
969 return p1 > p2;
970 if (params.is_seq_print) {
971 return i1.bed_temp != i2.bed_temp ? (i1.bed_temp > i2.bed_temp) :
972 i1.height != i2.height ? (i1.height < i2.height) :
973 std::abs(i1.area() / i2.area() - 1) > 0.2 ? (i1.area() > i2.area()) :
975 }
976 else {
977 return i1.bed_temp != i2.bed_temp ? (i1.bed_temp > i2.bed_temp) :
979 }
980 };
981
982 m_pck.configure(m_pconf);
983 }
Definition Arrange.cpp:455
PConfig m_pconf
Definition Arrange.cpp:467
TBin m_bin
Definition Arrange.cpp:468
ArrangeParams params
Definition Arrange.cpp:489
double m_norm
Definition Arrange.cpp:482
double m_bin_area
Definition Arrange.cpp:469
ItemGroup m_items
Definition Arrange.cpp:486
Packer m_pck
Definition Arrange.cpp:466
std::tuple< double, Box > objfunc(const Item &item, const Slic3r::Point &origin_pack)
Definition Arrange.cpp:579
ItemGroup m_remaining
Definition Arrange.cpp:485
Box m_pilebb
Definition Arrange.cpp:484
Box::PointType belt_origin() const
Definition Arrange.cpp:529
SpatIndex m_rtree
Definition Arrange.cpp:476
typename Packer::PlacementConfig PConfig
Definition Arrange.cpp:461
SpatIndex m_smallsrtree
Definition Arrange.cpp:477
std::vector< Box > m_excluded_and_extruCali_regions
Definition Arrange.cpp:487
std::function< double(const Item &, const ItemGroup &)> get_objfn()
MultiPolygon m_merged_pile
Definition Arrange.cpp:483
void fill_config(PConf &pcfg, const ArrangeParams &params)
Definition Arrange.cpp:356
static double fixed_overfit(const std::tuple< double, Box > &result, const Box &binbb)
Definition Arrange.cpp:416
Vec2d align_center
Definition Arrange.hpp:159

References Slic3r::arrangement::ArrangeParams::align_center, Slic3r::arrangement::ArrangePolygon::bed_idx, belt_origin(), Slic3r::arrangement::BIG_ITEM_TRESHOLD, Slic3r::arrangement::fill_config(), Slic3r::arrangement::fixed_overfit(), get_objfn(), Slic3r::arrangement::ArrangeParams::is_belt, m_bin, m_bin_area, m_excluded_and_extruCali_regions, m_items, m_merged_pile, m_norm, m_pck, m_pconf, m_pilebb, m_remaining, m_rtree, m_smallsrtree, objfunc(), params, and Slic3r::arrangement::ArrangePolygon::priority.

Here is the call graph for this function:

Member Function Documentation

◆ at()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::at ( const Box::PointType & pt,
int i )
inlinestaticprotected
521{ return double(i == 0 ? getX(pt) : getY(pt)); }

Referenced by belt_pos(), and dist_along_belt().

Here is the caller graph for this function:

◆ belt_end()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::belt_end ( const Box & bb) const
inlineprotected
526{ return belt_pos(params.belt_reversed ? bb.minCorner() : bb.maxCorner()); }
double belt_pos(const Box::PointType &pt) const
Definition Arrange.cpp:524

References belt_pos(), and params.

Referenced by dist_along_belt(), and objfunc().

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

◆ belt_origin()

template<class TBin>
Box::PointType Slic3r::arrangement::AutoArranger< TBin >::belt_origin ( ) const
inlineprotected
530 {
531 const Box bb = sl::boundingBox(m_bin);
532 auto o = bb.minCorner();
533 if (params.belt_reversed) {
534 if (params.belt_axis == 0) setX(o, getX(bb.maxCorner()));
535 else setY(o, getY(bb.maxCorner()));
536 }
537 return o;
538 }

References m_bin, and params.

Referenced by AutoArranger().

Here is the caller graph for this function:

◆ belt_pos()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::belt_pos ( const Box::PointType & pt) const
inlineprotected
524{ return params.belt_reversed ? -at(pt, params.belt_axis) : at(pt, params.belt_axis); }
static double at(const Box::PointType &pt, int i)
Definition Arrange.cpp:521

References at(), and params.

Referenced by belt_end(), and belt_start().

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

◆ belt_start()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::belt_start ( const Box & bb) const
inlineprotected
525{ return belt_pos(params.belt_reversed ? bb.maxCorner() : bb.minCorner()); }

References belt_pos(), and params.

Referenced by dist_along_belt(), and objfunc().

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

◆ config() [1/2]

template<class TBin>
PConfig & Slic3r::arrangement::AutoArranger< TBin >::config ( )
inline
992{ return m_pconf; }

References m_pconf.

◆ config() [2/2]

template<class TBin>
const PConfig & Slic3r::arrangement::AutoArranger< TBin >::config ( ) const
inline
993{ return m_pconf; }

References m_pconf.

◆ corner_bindist()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::corner_bindist ( const Box & ibb,
const Slic3r::Point & origin_pack )
inlineprotected
557 {
559 }
double dist_along_belt(const Box &ibb)
Definition Arrange.cpp:544
double dist_for_BOTTOM_LEFT(Box ibb, const Slic3r::Point &origin_pack)
Definition Arrange.cpp:501

References dist_along_belt(), dist_for_BOTTOM_LEFT(), and params.

Referenced by objfunc().

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

◆ corner_packing()

template<class TBin>
bool Slic3r::arrangement::AutoArranger< TBin >::corner_packing ( ) const
inlineprotected
519{ return params.is_belt || m_pconf.starting_point == PConfig::Alignment::BOTTOM_LEFT; }

References m_pconf, and params.

Referenced by get_objfn(), and objfunc().

Here is the caller graph for this function:

◆ dist_along_belt()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::dist_along_belt ( const Box & ibb)
inlineprotected
545 {
546 const Box bin = sl::boundingBox(m_bin);
547 const int l = 1 - params.belt_axis;
548 const double lat = at(ibb.minCorner(), l) - at(bin.minCorner(), l);
549 double d = belt_end(ibb) - belt_start(bin);
550 d += lat < 0 ? 10 * -lat : 0.1 * lat;
551 if (double behind = belt_start(ibb) - belt_start(bin); behind < 0)
552 d += 10 * -behind;
553 return norm(d);
554 }
double belt_end(const Box &bb) const
Definition Arrange.cpp:526
double belt_start(const Box &bb) const
Definition Arrange.cpp:525
ArithmeticOnly< T, double > norm(T val)
Definition Arrange.cpp:491

References at(), belt_end(), belt_start(), m_bin, norm(), and params.

Referenced by corner_bindist().

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

◆ dist_for_BOTTOM_LEFT()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::dist_for_BOTTOM_LEFT ( Box ibb,
const Slic3r::Point & origin_pack )
inlineprotected
502 {
503 double dist_corner_y = ibb.minCorner().y() - origin_pack.y();
504 double dist_corner_x = ibb.minCorner().x() - origin_pack.x();
505 // occupy as few rows as possible if we have rotations
506 double bindist = double(ibb.maxCorner().y() - ibb.minCorner().y());
507 if (dist_corner_x >= 0 && dist_corner_y >= 0)
509 else {
510 if (dist_corner_x < 0) bindist += 10 * (-dist_corner_x);
511 if (dist_corner_y < 0) bindist += 10 * (-dist_corner_y);
512 }
514 return bindist;
515 }

References norm().

Referenced by corner_bindist().

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

◆ dist_to_bin()

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::dist_to_bin ( const Box & ibb,
const Slic3r::Point & origin_pack,
typename Packer::PlacementConfig::Alignment starting_point_alignment )
inlineprotected
562 {
563 double bindist = 0;
565 bindist = norm(pl::distance(ibb.minCorner(), origin_pack));
567 bindist = norm(pl::distance(ibb.maxCorner(), origin_pack));
568 else
570 return bindist;
571 }

References norm().

Referenced by objfunc().

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

◆ get_objfn() [1/4]

std::function< double(const Item &, const ItemGroup &)> Slic3r::arrangement::AutoArranger< ExPolygon >::get_objfn ( )
protected
1065{
1066 auto bb = sl::boundingBox(m_bin);
1067 auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? bb.center() : bb.minCorner();
1068 return [this, origin_pack](const Item &itm, const ItemGroup&) {
1069 auto result = objfunc(itm, origin_pack);
1070
1071 double score = std::get<0>(result);
1072
1073 auto mp = m_merged_pile;
1074 mp.emplace_back(itm.transformedShape());
1075 auto chull = sl::convexHull(mp);
1076 if (corner_packing())
1077 {
1078 if (!sl::isInside(chull, m_bin))
1080 }
1081 else
1082 {
1083 double miss = Placer::overfit(chull, m_bin);
1084 miss = miss > 0 ? miss : 0;
1085 score += miss * miss;
1086 }
1087
1088 return score;
1089 };
1090}
bool corner_packing() const
Definition Arrange.cpp:519

References corner_packing(), get_objfn(), m_bin, m_merged_pile, m_pconf, and objfunc().

Here is the call graph for this function:

◆ get_objfn() [2/4]

std::function< double(const Item &, const ItemGroup &)> Slic3r::arrangement::AutoArranger< Circle >::get_objfn ( )
protected
1035{
1036 auto bb = sl::boundingBox(m_bin);
1037 auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? bb.center() : bb.minCorner();
1038 return [this, origin_pack](const Item &item, const ItemGroup&) {
1039
1040 auto result = objfunc(item, origin_pack);
1041
1042 double score = std::get<0>(result);
1043
1044 auto isBig = [this](const Item& itm) {
1045 return itm.area() / m_bin_area > BIG_ITEM_TRESHOLD ;
1046 };
1047
1048 if(isBig(item)) {
1049 auto mp = m_merged_pile;
1050 mp.push_back(item.transformedShape());
1051 auto chull = sl::convexHull(mp);
1052 double miss = Placer::overfit(chull, m_bin);
1053 if(miss < 0) miss = 0;
1054 score += miss*miss;
1055 }
1056
1057 return score;
1058 };
1059}

References Slic3r::arrangement::BIG_ITEM_TRESHOLD, get_objfn(), m_bin, m_bin_area, m_merged_pile, m_pconf, and objfunc().

Here is the call graph for this function:

◆ get_objfn() [3/4]

std::function< double(const Item &, const ItemGroup &)> Slic3r::arrangement::AutoArranger< Box >::get_objfn ( )
protected
1006{
1007 auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? m_bin.center() :
1008 m_pconf.starting_point == PConfig::Alignment::TOP_RIGHT ? m_bin.maxCorner() : m_bin.minCorner();
1009
1010 return [this, origin_pack](const Item &itm, const ItemGroup&) {
1011 auto result = objfunc(itm, origin_pack);
1012
1013 double score = std::get<0>(result);
1014 auto& fullbb = std::get<1>(result);
1015
1016 //if (m_pconf.starting_point == PConfig::Alignment::BOTTOM_LEFT)
1017 //{
1018 // if (!sl::isInside(fullbb, m_bin))
1019 // score += LARGE_COST_TO_REJECT;
1020 //}
1021 //else
1022 {
1023 double miss = Placer::overfit(fullbb, m_bin);
1024 miss = miss > 0 ? miss : 0;
1025 score += miss * miss;
1028 }
1029
1030 return score;
1031 };
1032}

References get_objfn(), m_bin, m_pconf, and objfunc().

Here is the call graph for this function:

◆ get_objfn() [4/4]

template<class TBin>
std::function< double(const Item &, const ItemGroup &)> Slic3r::arrangement::AutoArranger< TBin >::get_objfn ( )
protected

Referenced by AutoArranger(), and get_objfn().

Here is the caller graph for this function:

◆ norm()

template<class TBin>
template<class T>
ArithmeticOnly< T, double > Slic3r::arrangement::AutoArranger< TBin >::norm ( T val)
inlineprotected
492 {
493 return double(val) / m_norm;
494 }

References m_norm.

Referenced by dist_along_belt(), dist_for_BOTTOM_LEFT(), dist_to_bin(), and objfunc().

Here is the caller graph for this function:

◆ objfunc()

template<class TBin>
std::tuple< double, Box > Slic3r::arrangement::AutoArranger< TBin >::objfunc ( const Item & item,
const Slic3r::Point & origin_pack )
inlineprotected
580 {
581 const double bin_area = m_bin_area;
582 const SpatIndex& spatindex = m_rtree;
584
585 // We will treat big items (compared to the print bed) differently
586 auto isBig = [bin_area](double a) {
587 return a/bin_area > BIG_ITEM_TRESHOLD ;
588 };
589
590 // Candidate item bounding box
591 auto ibb = item.boundingBox();
592
593 // Calculate the full bounding box of the pile with the candidate item
595
596 // The bounding box of the big items (they will accumulate in the center
597 // of the pile
598 Box bigbb;
599 if(spatindex.empty()) bigbb = fullbb;
600 else {
601 auto boostbb = spatindex.bounds();
603 }
604
605 // Will hold the resulting score
606 double score = 0;
607
608 // Density is the pack density: how big is the arranged pile
609 double density = 0;
610
611 // Distinction of cases for the arrangement scene
612 enum e_cases {
613 // This branch is for big items in a mixed (big and small) scene
614 // OR for all items in a small-only scene.
615 BIG_ITEM,
616
617 // This branch is for the last big item in a mixed scene
619
620 // For small items in a mixed scene.
622 } compute_case;
623
624 bool bigitems = isBig(item.area()) || spatindex.empty();
625 if(!params.is_seq_print && bigitems && !m_remaining.empty()) compute_case = BIG_ITEM; // do not use so complicated logic for sequential printing
626 else if (bigitems && m_remaining.empty()) compute_case = LAST_BIG_ITEM;
628
629 switch (compute_case) {
630 case BIG_ITEM: {
631 const Point& minc = ibb.minCorner(); // bottom left corner
632 const Point& maxc = ibb.maxCorner(); // top right corner
633
634 // top left and bottom right corners
637
638 // Now the distance of the gravity center will be calculated to the
639 // five anchor points and the smallest will be chosen.
641 auto cc = fullbb.center(); // The gravity center
642 dists[0] = pl::distance(minc, cc);
643 dists[1] = pl::distance(maxc, cc);
644 dists[2] = pl::distance(ibb.center(), cc);
647
648 // The smalles distance from the arranged pile center:
649 double dist = norm(*(std::min_element(dists.begin(), dists.end())));
650 if (corner_packing()) {
652 score = 0.2 * dist + 0.8 * bindist;
653 }
654 else {
655 double bindist = dist_to_bin(ibb, origin_pack, m_pconf.starting_point);
656 dist = 0.8 * dist + 0.2 * bindist;
657
658
659 // Prepare a variable for the alignment score.
660 // This will indicate: how well is the candidate item
661 // aligned with its neighbors. We will check the alignment
662 // with all neighbors and return the score for the best
663 // alignment. So it is enough for the candidate to be
664 // aligned with only one item.
665 auto alignment_score = 1.0;
666
667 auto query = bgi::intersects(ibb);
668 auto& index = isBig(item.area()) ? spatindex : smalls_spatindex;
669
670 // Query the spatial index for the neighbors
672 result.reserve(index.size());
673
675
676 // now get the score for the best alignment
677 for (auto& e : result) {
678 auto idx = e.second;
679 Item& p = m_items[idx];
680 auto parea = p.area();
681 if (std::abs(1.0 - parea / item.area()) < 1e-6) {
682 auto bb = sl::boundingBox(p.boundingBox(), ibb);
683 auto bbarea = bb.area();
684 auto ascore = 1.0 - (item.area() + parea) / bbarea;
685
687 }
688 }
689
690 density = std::sqrt(norm(fullbb.width()) * norm(fullbb.height()));
691 double R = double(m_remaining.size()) / m_item_count;
692 // alighment score is more important for rectangle items
693 double alignment_weight = std::max(0.3, 0.6 * item.area() / ibb.area());
694
695 // The final mix of the score is the balance between the
696 // distance from the full pile center, the pack density and
697 // the alignment with the neighbors
698 if (result.empty())
699 score = 0.50 * dist + 0.50 * density;
700 else
701 // Let the density matter more when fewer objects remain
702 score = (1 - 0.2 - alignment_weight) * dist + (1.0 - R) * 0.20 * density +
704 }
705 break;
706 }
707 case LAST_BIG_ITEM: {
708 if (corner_packing()) {
710 }
711 else {
712 if (m_pilebb.defined)
713 score = 0.5 * norm(pl::distance(ibb.center(), m_pilebb.center()));
714 else
715 score = 0.5 * norm(pl::distance(ibb.center(), origin_pack));
716 }
717 break;
718 }
719 case SMALL_ITEM: {
720 // Here there are the small items that should be placed around the
721 // already processed bigger items.
722 // No need to play around with the anchor points, the center will be
723 // just fine for small items
724 if (corner_packing())
726 else {
727 // Align mainly around existing items
728 score = 0.8 * norm(pl::distance(ibb.center(), bigbb.center()))+ 0.2*norm(pl::distance(ibb.center(), origin_pack));
729 // Align to 135 degree line {calc distance to the line x+y-(xc+yc)=0}
730 //auto ic = ibb.center(), bigbbc = origin_pack;// bigbb.center();
731 //score = norm(std::abs(ic.x() + ic.y() - bigbbc.x() - bigbbc.y()));
732 }
733
734 break;
735 }
736 }
737
738
739 if (params.is_seq_print) {
740 double clearance_height_to_lid = params.clearance_height_to_lid;
741 double clearance_height_to_rod = params.clearance_height_to_rod;
742 bool hasRowHeightConflict = false;
743 bool hasLidHeightConflict = false;
744 auto iy1 = item.boundingBox().minCorner().y();
745 auto iy2 = item.boundingBox().maxCorner().y();
746 auto ix1 = item.boundingBox().minCorner().x();
747
748 for (int i = 0; i < m_items.size(); i++) {
749 Item& p = m_items[i];
750 if (p.is_virt_object) continue;
751 auto px1 = p.boundingBox().minCorner().x();
752 auto py1 = p.boundingBox().minCorner().y();
753 auto py2 = p.boundingBox().maxCorner().y();
754 auto inter_min = std::max(iy1, py1); // min y of intersection
755 auto inter_max = std::min(iy2, py2); // max y of intersection. length=max_y-min_y>0 means intersection exists
756 // if this item is lower than existing ones, this item will be printed first, so should not exceed height_to_rod
758 else if (inter_max - inter_min > 0) {
759 // if they inter, the one on the left will be printed first
760 double h = ix1 < px1 ? item.height : p.height;
762 }
763 // only last item can be heigher than clearance_height_to_lid, so if the existing items are higher than clearance_height_to_lid, there is height conflict
765 }
766
767 double lambda3 = LARGE_COST_TO_REJECT*1.1;
768 double lambda4 = LARGE_COST_TO_REJECT*1.2;
769 for (int i = 0; i < m_items.size(); i++) {
770 Item& p = m_items[i];
771 if (p.is_virt_object) continue;
772 //score += lambda3 * (item.bed_temp - p.vitrify_temp > VITRIFY_TEMP_DIFF_THRSH);
773 if (!Print::is_filaments_compatible({item.filament_temp_type,p.filament_temp_type}))
774 score += lambda3;
775 }
776 //score += lambda3 * (item.bed_temp - item.vitrify_temp > VITRIFY_TEMP_DIFF_THRSH);
778 }
779 else {
780 int valid_items_cnt = 0;
781 double height_score = 0;
782 for (int i = 0; i < m_items.size(); i++) {
783 Item& p = m_items[i];
784 if (!p.is_virt_object) {
786 // 高度接近的件尽量摆到一起
787 height_score += (1- std::abs(item.height - p.height) / params.printable_height)
788 * norm(pl::distance(ibb.center(), p.boundingBox().center()));
789 //score += LARGE_COST_TO_REJECT * (item.bed_temp - p.bed_temp != 0);
790 if (!Print::is_filaments_compatible({ item.filament_temp_type,p.filament_temp_type })) {
792 break;
793 }
794 }
795 }
796 if (valid_items_cnt > 0)
798 }
799
801 for (int i = 0; i < m_items.size(); i++) {
802 Item& p = m_items[i];
803 if (p.is_virt_object) continue;
804 extruder_ids.insert(p.extrude_ids.begin(),p.extrude_ids.end());
805 }
806
807 // add a large cost if not multi materials on same plate is not allowed
808 if (!params.allow_multi_materials_on_same_plate) {
809 // it's the first object, which can be multi-color
810 bool first_object = extruder_ids.empty();
811 // the two objects (previously packed items and the current item) are considered having same color if either one's colors are a subset of the other
812 std::set<int> item_extruder_ids(item.extrude_ids.begin(), item.extrude_ids.end());
816 }
817 // for layered printing, we want extruder change as few as possible
818 // this has very weak effect, CAN NOT use a large weight
819 int last_extruder_cnt = extruder_ids.size();
820 extruder_ids.insert(item.extrude_ids.begin(), item.extrude_ids.end());
821 int new_extruder_cnt= extruder_ids.size();
822 if (!params.is_seq_print) {
824 }
825
826 // On a belt the parts print in belt order, so every colour change between
827 // parts is a filament change. Items arrive sorted by extruder and the pile
828 // grows from the leading end; keep each colour's run contiguous by charging
829 // an item for every packed item of another colour it does not fully follow,
830 // counting the tilted layers that reach belt_tilt_slope * height past that
831 // item's far edge.
832 if (params.is_belt && !params.is_seq_print) {
833 const std::set<int> item_colours(item.extrude_ids.begin(), item.extrude_ids.end());
834 const double item_start = belt_start(ibb);
835 for (Item &p : m_items) {
836 if (p.is_virt_object)
837 continue;
838 const std::set<int> p_colours(p.extrude_ids.begin(), p.extrude_ids.end());
839 const bool same_colour = std::includes(item_colours.begin(), item_colours.end(), p_colours.begin(), p_colours.end())
840 || std::includes(p_colours.begin(), p_colours.end(), item_colours.begin(), item_colours.end());
841 if (same_colour)
842 continue;
843 if (item_start < belt_end(p.boundingBox()) + scaled(p.height * params.belt_tilt_slope))
844 score += 10.;
845 }
846 }
847
849 }
double corner_bindist(const Box &ibb, const Slic3r::Point &origin_pack)
Definition Arrange.cpp:556
size_t m_item_count
Definition Arrange.cpp:488
double dist_to_bin(const Box &ibb, const Slic3r::Point &origin_pack, typename Packer::PlacementConfig::Alignment starting_point_alignment)
Definition Arrange.cpp:561

References belt_end(), belt_start(), Slic3r::arrangement::BIG_ITEM_TRESHOLD, corner_bindist(), corner_packing(), Slic3r::Geometry::dist(), dist_to_bin(), Slic3r::Print::is_filaments_compatible(), m_bin_area, m_item_count, m_items, m_pconf, m_pilebb, m_remaining, m_rtree, m_smallsrtree, norm(), params, and Slic3r::scaled().

Referenced by AutoArranger(), and get_objfn().

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

◆ operator()()

template<class TBin>
template<class It>
void Slic3r::arrangement::AutoArranger< TBin >::operator() ( It from,
It to )
inline
985 {
986 m_rtree.clear();
988 m_pck.execute(from, to);
989 m_item_count = 0;
990 }

References m_item_count, m_pck, and m_rtree.

◆ preload()

template<class TBin>
void Slic3r::arrangement::AutoArranger< TBin >::preload ( std::vector< Item > & fixeditems)
inline
995 {
996 for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
998 itm.markAsFixedInBin(itm.binId());
999 }
1000
1001 m_item_count += fixeditems.size();
1002 }

References m_item_count.

Referenced by Slic3r::arrangement::_arrange().

Here is the caller graph for this function:

Member Data Documentation

◆ m_bin

template<class TBin>
TBin Slic3r::arrangement::AutoArranger< TBin >::m_bin
protected

◆ m_bin_area

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::m_bin_area
protected

Referenced by AutoArranger(), get_objfn(), and objfunc().

◆ m_excluded_and_extruCali_regions

template<class TBin>
std::vector<Box> Slic3r::arrangement::AutoArranger< TBin >::m_excluded_and_extruCali_regions
protected

Referenced by AutoArranger().

◆ m_excluded_items_in_each_plate

template<class TBin>
std::vector<Item> Slic3r::arrangement::AutoArranger< TBin >::m_excluded_items_in_each_plate

◆ m_item_count

template<class TBin>
size_t Slic3r::arrangement::AutoArranger< TBin >::m_item_count = 0
protected

Referenced by objfunc(), operator()(), and preload().

◆ m_items

template<class TBin>
ItemGroup Slic3r::arrangement::AutoArranger< TBin >::m_items
protected

Referenced by AutoArranger(), and objfunc().

◆ m_merged_pile

template<class TBin>
MultiPolygon Slic3r::arrangement::AutoArranger< TBin >::m_merged_pile
protected

Referenced by AutoArranger(), and get_objfn().

◆ m_norm

template<class TBin>
double Slic3r::arrangement::AutoArranger< TBin >::m_norm
protected

Referenced by AutoArranger(), and norm().

◆ m_pck

template<class TBin>
Packer Slic3r::arrangement::AutoArranger< TBin >::m_pck
protected

Referenced by AutoArranger(), and operator()().

◆ m_pconf

template<class TBin>
PConfig Slic3r::arrangement::AutoArranger< TBin >::m_pconf
protected

◆ m_pilebb

template<class TBin>
Box Slic3r::arrangement::AutoArranger< TBin >::m_pilebb
protected

Referenced by AutoArranger(), and objfunc().

◆ m_remaining

template<class TBin>
ItemGroup Slic3r::arrangement::AutoArranger< TBin >::m_remaining
protected

Referenced by AutoArranger(), and objfunc().

◆ m_rtree

template<class TBin>
SpatIndex Slic3r::arrangement::AutoArranger< TBin >::m_rtree
protected

Referenced by AutoArranger(), objfunc(), and operator()().

◆ m_smallsrtree

template<class TBin>
SpatIndex Slic3r::arrangement::AutoArranger< TBin >::m_smallsrtree
protected

Referenced by AutoArranger(), and objfunc().

◆ params


The documentation for this class was generated from the following file:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Arrange.cpp