624 {
625
626 PackResult ret;
627
628 bool can_pack = false;
629 double best_overfit = std::numeric_limits<double>::max();
630
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;
643
644 auto& bin = bin_;
648
649
650
651 std::function<double(
const Item&)> _objfunc;
652 if(config_.object_function) _objfunc = config_.object_function;
653 else {
654
655
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;
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();
675
677 binbb.center());
678 score /= norm;
679
680 score += ins_check(fullbb);
681
682 return score;
683 };
684 }
685
686 if(items_.empty()) {
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);
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
710
711 for(auto rot : config_.rotations) {
712
713 item.translation(initial_tr);
714 item.rotation(initial_rot + rot);
715 item.boundingBox();
716
717
718
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
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());
761 merged_pile.pop_back();
762
763 double miss = 0;
764 if(alignment == Config::Alignment::DONT_ALIGN)
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
783
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
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;
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();
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