diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 29de288b9..96f1ff1c4 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -481,7 +481,7 @@ public: auto d = bbin.center() - bb.center(); _Rectangle rect(bb.width(), bb.height()); rect.translate(bb.minCorner() + d); - return sl::isInside(rect.transformedShape(), bin) ? -1.0 : 1; + return sl::isInside(rect.transformedShape(), bin) ? -1.5 : 1; } static inline double overfit(const RawShape& chull, const RawShape& bin) { @@ -907,7 +907,7 @@ private: } } - if( best_score < global_score && best_score< LARGE_COST_TO_REJECT) { + if( best_score < global_score) { auto d = (getNfpPoint(optimum) - iv) + startpos; final_tr = d; final_rot = initial_rot + rot; @@ -922,7 +922,10 @@ private: #ifdef SVGTOOLS_HPP svg::SVGWriter svgwriter; - svgwriter.setSize(binbb); + Box binbb2(binbb.width() * 2, binbb.height() * 2, binbb.center()); // expand bbox to allow object be drawed outside + svgwriter.setSize(binbb2); + svgwriter.conf_.x0 = binbb.width(); + svgwriter.conf_.y0 = -binbb.height()/2; // origin is top left corner svgwriter.writeShape(box2RawShape(binbb), "none", "black"); for (int i = 0; i < nfps.size(); i++) svgwriter.writeShape(nfps[i], "none", "blue"); diff --git a/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp index 18c70468e..4b2af5f7b 100644 --- a/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp @@ -43,7 +43,7 @@ public: public: operator bool() { return item_ptr_ != nullptr; } double overfit() const { return overfit_; } - double score_ = -1; + double score_ = -1.11; double score() { return score_; } int plate_id = 0; // BBS }; diff --git a/src/libnest2d/tools/svgtools.hpp b/src/libnest2d/tools/svgtools.hpp index d00a74227..2bf090b32 100644 --- a/src/libnest2d/tools/svgtools.hpp +++ b/src/libnest2d/tools/svgtools.hpp @@ -35,8 +35,9 @@ public: }; -private: Config conf_; + +private: std::vector svg_layers_; bool finished_ = false; public: diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 82dcf0c9a..11e6b026b 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -202,14 +202,20 @@ protected: // 1) Y distance of item corner to bed corner. Must be put above bed corner. (high weight) // 2) X distance of item corner to bed corner (low weight) // 3) item row occupancy (useful when rotation is enabled) + // 4)需要允许往屏蔽区域的左边或下边去一点,不然很多物体可能认为摆不进去,实际上我们最后是可以做平移的 double dist_for_BOTTOM_LEFT(Box ibb, const ClipperLib::IntPoint& origin_pack) { double dist_corner_y = ibb.minCorner().y() - origin_pack.y(); double dist_corner_x = ibb.minCorner().x() - origin_pack.x(); - if (dist_corner_y < 0 || dist_corner_x<0) - return LARGE_COST_TO_REJECT; - double bindist = norm(dist_corner_y + 1 * dist_corner_x - + 1 * double(ibb.maxCorner().y() - ibb.minCorner().y())); // occupy as few rows as possible + // occupy as few rows as possible if we have rotations + double bindist = double(ibb.maxCorner().y() - ibb.minCorner().y()); + if (dist_corner_x >= 0 && dist_corner_y >= 0) + bindist += dist_corner_y + 1 * dist_corner_x; + else { + if (dist_corner_x < 0) bindist += 10 * (-dist_corner_x); + if (dist_corner_y < 0) bindist += 10 * (-dist_corner_y); + } + bindist = norm(bindist); return bindist; } @@ -513,13 +519,15 @@ public: m_pconf.on_preload = [this](const ItemGroup &items, PConfig &cfg) { if (items.empty()) return; - auto bb = sl::boundingBox(m_bin); + auto binbb = sl::boundingBox(m_bin); // BBS: excluded region (virtual object but not wipe tower) should not affect final alignment bool all_is_excluded_region = std::all_of(items.begin(), items.end(), [](Item &itm) { return itm.is_virt_object && !itm.is_wipe_tower; }); if (!all_is_excluded_region) cfg.alignment = PConfig::Alignment::DONT_ALIGN; + else + cfg.alignment = PConfig::Alignment::CENTER; - auto starting_point = cfg.starting_point == PConfig::Alignment::BOTTOM_LEFT ? bb.minCorner() : bb.center(); + auto starting_point = cfg.starting_point == PConfig::Alignment::BOTTOM_LEFT ? binbb.minCorner() : binbb.center(); // if we have wipe tower, items should be arranged around wipe tower for (Item itm : items) { if (itm.is_wipe_tower) { @@ -528,12 +536,16 @@ public: } } - cfg.object_function = [this, bb, starting_point](const Item& item, const ItemGroup& packed_items) { - bool packed_are_excluded_region = std::all_of(packed_items.begin(), packed_items.end(), [](Item& itm) { return itm.is_virt_object && !itm.is_wipe_tower; }); - if(packed_are_excluded_region) - return fixed_overfit_topright_sliding(objfunc(item, starting_point), bb); - else - return fixed_overfit(objfunc(item, starting_point), bb); + cfg.object_function = [this, binbb, starting_point](const Item& item, const ItemGroup& packed_items) { + // 在我们的摆盘中,没有天然的固定对象。固定对象只有:屏蔽区域、挤出补偿区域、料塔。 + // 对于屏蔽区域,摆入的对象仍然是可以向右上滑动的; + // 对挤出料塔,摆入的对象不能滑动(必须围绕料塔) + bool pack_around_wipe_tower = std::any_of(packed_items.begin(), packed_items.end(), [](Item& itm) { return itm.is_wipe_tower; }); + if(pack_around_wipe_tower) + return fixed_overfit(objfunc(item, starting_point), binbb); + else { + return fixed_overfit_topright_sliding(objfunc(item, starting_point), binbb); + } }; }; @@ -611,16 +623,18 @@ template<> std::function AutoArranger(result); auto& fullbb = std::get<1>(result); - if (m_pconf.starting_point == PConfig::Alignment::BOTTOM_LEFT) - { - if (!sl::isInside(fullbb, m_bin)) - score += LARGE_COST_TO_REJECT; - } - else + //if (m_pconf.starting_point == PConfig::Alignment::BOTTOM_LEFT) + //{ + // if (!sl::isInside(fullbb, m_bin)) + // score += LARGE_COST_TO_REJECT; + //} + //else { double miss = Placer::overfit(fullbb, m_bin); miss = miss > 0 ? miss : 0; score += miss * miss; + if (score > LARGE_COST_TO_REJECT) + score = 1.5 * LARGE_COST_TO_REJECT; } return score; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 79e0b91cf..51685031c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -529,12 +529,9 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print auto inter_min = std::max(ly1, ry1); auto inter_max = std::min(ly2, ry2); auto inter_y = inter_max - inter_min; - inter_min = std::max(lx1, rx1); - inter_max = std::min(lx2, rx2); - auto inter_x = inter_max - inter_min; // 如果y方向的重合超过轮廓的膨胀量,说明两个物体在一行,应该先打左边的物体,即先比较二者的x坐标。 - if (inter_y > scale_(1)) { + if (inter_y > scale_(0.5 * print.config().extruder_clearance_radius.value)) { if (std::max(rx1 - lx2, lx1 - rx2) < unsafe_dist) { if (lx1 > rx1) { left_right_pair.insert({j, i}); @@ -555,7 +552,8 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print } else if (l.height > hc2 && l.height > r.height && l.arrange_scorehc2, print_instance " << inst.print_instance->model_instance->get_object()->name << ", right=" << r.print_instance->model_instance->get_object()->name << ", l.score: " << l.arrange_score << ", r.score: " << r.arrange_score; @@ -563,7 +561,6 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print } } } - BOOST_LOG_TRIVIAL(debug) << "bed width: " << bed_width << ", unsafe_dist:" << unsafe_dist; // 多做几次代价传播,因为前一次有些值没有更新。 // TODO 更好的办法是建立一颗树,一步到位。不过我暂时没精力搞,先就这样吧 for (int k=0;k<5;k++) @@ -571,14 +568,15 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print auto &l = print_instance_with_bounding_box[p(0)]; auto &r = print_instance_with_bounding_box[p(1)]; if(r.arrange_scoremodel_instance->get_object()->name << "(" << l.arrange_score << ")" - << " -> " << r.print_instance->model_instance->get_object()->name << "(" << r.arrange_score << ")"; + BOOST_LOG_TRIVIAL(debug) << "print_instance " << I18N::translate(l.print_instance->model_instance->get_object()->name) << "(" << l.arrange_score << ")" + << " -> " << I18N::translate(r.print_instance->model_instance->get_object()->name) << "(" << r.arrange_score << ")"; } // sort the print instance std::sort(print_instance_with_bounding_box.begin(), print_instance_with_bounding_box.end(), diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 3a5e539bc..8589d705f 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -75,6 +75,7 @@ static constexpr double BRIDGE_INFILL_MARGIN = 1; //FIXME Better to use an inline function with an explicit return type. //inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); } #define scale_(val) ((val) / SCALING_FACTOR) +#define unscale_(val) ((val) * SCALING_FACTOR) //BBS: BBS only support relative E and can't been changed by user at the moment. because //BBS need to support skip object when printing. diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index f8a3874ec..ffe7f179f 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -241,6 +241,10 @@ void ArrangeJob::prepare_wipe_tower() { bool need_wipe_tower = false; + // if wipe tower is explicitly disabled, no need to estimate + auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); + if (!print.config().enable_prime_tower) return; + // estimate if we need wipe tower for all plates: // if multile extruders have same bed temp, we need wipe tower if (!params.is_seq_print) { @@ -531,10 +535,13 @@ void ArrangeJob::process() std::for_each(m_selected.begin(), m_selected.end(), [&](auto& ap) {ap.inflation = params.min_obj_distance / 2; }); // For occulusion regions, inflation should be larger to prevent genrating brim on them. // However, extrusion cali regions are exceptional, since we can allow brim overlaps them. + // 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。 + // 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体, + // 其他物体的膨胀轮廓是可以跟它们重叠的。 std::for_each(m_unselected.begin(), m_unselected.end(), [&](auto &ap) { ap.inflation = !ap.is_virt_object ? params.min_obj_distance / 2 : - (ap.is_extrusion_cali_object ? scaled(params.cleareance_radius / 2) : scaled(params.brim_skirt_distance + params.cleareance_radius / 2)); + (ap.is_extrusion_cali_object ? 0 : scaled(params.brim_skirt_distance)); }); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 15d00a8db..8b613ee26 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -3473,8 +3473,8 @@ bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& r bool added = false; std::vector nonprefered_regions; - nonprefered_regions.emplace_back(Vec2d{ 45,15 }, Vec2d{ 225,25 }); // extrusion calibration region - nonprefered_regions.emplace_back(Vec2d{ 25,10 }, Vec2d{ 50,60 }); // hand-eye calibration region + nonprefered_regions.emplace_back(Vec2d{ 45,0 }, Vec2d{ 225,25 }); // extrusion calibration region + nonprefered_regions.emplace_back(Vec2d{ 25,0 }, Vec2d{ 50,60 }); // hand-eye calibration region //has exclude areas PartPlate* plate = m_plate_list[0];