diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 96f1ff1c4..7272d4b01 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -1034,51 +1034,50 @@ private: if (!item.is_virt_object) bb = sl::boundingBox(item.boundingBox(), bb); - // BBS TODO assume the nonprefered regions are at the bottom left corner - Box bin_reduced = bbin; - for (const auto& region : config_.m_nonprefered_regions) - { - Box bb1 = region.boundingBox(); - if (bb1.maxCorner().y() bb.height() && bb.height()>bbin.height()-2*bb1.maxCorner().y()) { - // could use a tighter bound by moving bed center higher - bin_reduced.minCorner().y() = bb1.maxCorner().y(); - continue; - } - if (bb1.maxCorner().x() bb.width() && bb.width()>bbin.width()-2*bb1.maxCorner().x()) { - // could use a tighter bound - bin_reduced.minCorner().x() = bb1.maxCorner().x(); - continue; + // if move to center is infeasible, move to topright corner instead + auto alignment = config_.alignment; + if (!config_.m_excluded_regions.empty() && alignment== Config::Alignment::CENTER) { + Box bb2 = bb; + auto d = bbin.center() - bb2.center(); + d.x() = std::max(d.x(), 0); + d.y() = std::max(d.y(), 0); + bb2.minCorner() += d; + bb2.maxCorner() += d; + for (auto& region : config_.m_excluded_regions) { + auto region_bb = region.boundingBox(); + if (bb2.intersection(region_bb).area()>0) { + alignment = Config::Alignment::TOP_RIGHT; + break; + } } } Vertex ci, cb; - switch(config_.alignment) { + switch(alignment) { case Config::Alignment::CENTER: { ci = bb.center(); - cb = bin_reduced.center(); + cb = bbin.center(); break; } case Config::Alignment::BOTTOM_LEFT: { ci = bb.minCorner(); - cb = bin_reduced.minCorner(); + cb = bbin.minCorner(); break; } case Config::Alignment::BOTTOM_RIGHT: { ci = {getX(bb.maxCorner()), getY(bb.minCorner())}; - cb = {getX(bin_reduced.maxCorner()), getY(bin_reduced.minCorner())}; + cb = {getX(bbin.maxCorner()), getY(bbin.minCorner())}; break; } case Config::Alignment::TOP_LEFT: { ci = {getX(bb.minCorner()), getY(bb.maxCorner())}; - cb = {getX(bin_reduced.minCorner()), getY(bin_reduced.maxCorner())}; + cb = {getX(bbin.minCorner()), getY(bbin.maxCorner())}; break; } case Config::Alignment::TOP_RIGHT: { ci = bb.maxCorner(); - cb = bin_reduced.maxCorner(); + cb = bbin.maxCorner(); break; } default: ; // DONT_ALIGN diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 5d4812022..568d1a4d1 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -137,8 +137,7 @@ static double fixed_overfit(const std::tuple& result, const Box &bi } // useful for arranging big circle objects -template -static double fixed_overfit_topright_sliding(const std::tuple &result, const Box &binbb, const PConf &config) +static double fixed_overfit_topright_sliding(const std::tuple &result, const Box &binbb, const std::vector &excluded_boxes) { double score = std::get<0>(result); Box pilebb = std::get<1>(result); @@ -154,14 +153,8 @@ static double fixed_overfit_topright_sliding(const std::tuple &resu if (diff > 0) score += diff; // excluded regions and nonprefered regions should not intersect the translated pilebb - for (auto ®ion : config.m_excluded_regions) { - Box bb = region.boundingBox(); - auto area_ = bb.intersection(pilebb).area(); - if (area_ > 0) score += area_; - } - for (auto ®ion : config.m_nonprefered_regions) { - Box bb = region.boundingBox(); - auto area_ = bb.intersection(pilebb).area(); + for (auto &bb : excluded_boxes) { + auto area_ = pilebb.intersection(bb).area(); if (area_ > 0) score += area_; } @@ -203,6 +196,7 @@ protected: Box m_pilebb; // The bounding box of the merged pile. ItemGroup m_remaining; // Remaining items ItemGroup m_items; // allready packed items + std::vector m_excluded_and_extruCali_regions; // excluded and extrusion calib regions size_t m_item_count = 0; // Number of all items to be packed ArrangeParams params; @@ -227,7 +221,7 @@ protected: 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; } @@ -489,6 +483,14 @@ public: m_norm = std::sqrt(m_bin_area); fill_config(m_pconf, params); this->params = params; + for (auto& region : m_pconf.m_excluded_regions) { + Box bb = region.boundingBox(); + m_excluded_and_extruCali_regions.emplace_back(bb); + } + for (auto& region : m_pconf.m_nonprefered_regions) { + Box bb = region.boundingBox(); + m_excluded_and_extruCali_regions.emplace_back(bb); + } // Set up a callback that is called just before arranging starts // This functionality is provided by the Nester class (m_pack). @@ -526,17 +528,6 @@ public: m_pconf.object_function = get_objfn(); - auto bbox2expoly = [](Box bb) { - ExPolygon bin_poly; - auto c0 = bb.minCorner(); - auto c1 = bb.maxCorner(); - bin_poly.contour.points.emplace_back(c0); - bin_poly.contour.points.emplace_back(c1.x(), c0.y()); - bin_poly.contour.points.emplace_back(c1); - bin_poly.contour.points.emplace_back(c0.x(), c1.y()); - return bin_poly; - }; - // preload fixed items (and excluded regions) on plate m_pconf.on_preload = [this](const ItemGroup &items, PConfig &cfg) { if (items.empty()) return; @@ -558,7 +549,7 @@ public: } } - cfg.object_function = [this, binbb, starting_point, &cfg](const Item &item, const ItemGroup &packed_items) { + cfg.object_function = [this, binbb, starting_point](const Item &item, const ItemGroup &packed_items) { // 在我们的摆盘中,没有天然的固定对象。固定对象只有:屏蔽区域、挤出补偿区域、料塔。 // 对于屏蔽区域,摆入的对象仍然是可以向右上滑动的; // 对挤出料塔,摆入的对象不能滑动(必须围绕料塔) @@ -566,7 +557,7 @@ public: if(pack_around_wipe_tower) return fixed_overfit(objfunc(item, starting_point), binbb); else { - return fixed_overfit_topright_sliding(objfunc(item, starting_point), binbb, cfg); + return fixed_overfit_topright_sliding(objfunc(item, starting_point), binbb, m_excluded_and_extruCali_regions); } }; }; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 67fe3411b..f06ba37b5 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2588,9 +2588,9 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloat(2.5)); def = this->add("support_expansion", coFloat); - def->label = L("Support xy expansion distance"); + def->label = L("Normal Support expansion"); def->category = L("Support"); - def->tooltip = L("Expanding (+) or shrinking (-) support volume"); + def->tooltip = L("Expand (+) or shrink (-) the horizontal span of normal support"); def->sidetext = L("mm"); def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0)); diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 04ac925c5..9025fe390 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -540,15 +540,15 @@ void ArrangeJob::process() // 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。 // 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体, // 其他物体的膨胀轮廓是可以跟它们重叠的。 + double scaled_exclusion_gap = scale_(1); 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 ? 0 : scaled(params.brim_skirt_distance)); + (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); }); - partplate_list.preprocess_exclude_areas(params.excluded_regions, 1); - partplate_list.preprocess_exclude_areas(params.nonprefered_regions, 1); + partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap); // shrink bed by moving to center by dist Points bedpts = get_bed_shape(*m_plater->config()); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index bc328c029..d363d9062 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -3557,7 +3557,7 @@ bool PartPlateList::preprocess_arrange_polygon_other_locked(int obj_index, int i return locked; } -bool PartPlateList::preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, int num_plates) +bool PartPlateList::preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, int num_plates, float inflation) { bool added = false; @@ -3585,6 +3585,7 @@ bool PartPlateList::preprocess_exclude_areas(arrangement::ArrangePolygons& unsel ret.bed_idx = j; ret.height = 1; ret.name = "ExcludedRegion" + std::to_string(index); + ret.inflation = inflation; unselected.emplace_back(std::move(ret)); } @@ -3595,7 +3596,7 @@ bool PartPlateList::preprocess_exclude_areas(arrangement::ArrangePolygons& unsel return added; } -bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& regions, int num_plates) +bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& regions, int num_plates, float inflation) { bool added = false; @@ -3619,6 +3620,7 @@ bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& r ret.bed_idx = j; ret.height = 1; ret.name = "NonpreferedRegion" + std::to_string(index); + ret.inflation = inflation; regions.emplace_back(std::move(ret)); } diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 9bbffd8ce..e03732902 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -625,8 +625,8 @@ public: //preprocess an arrangement::ArrangePolygon, return true if it is in a locked plate bool preprocess_arrange_polygon(int obj_index, int instance_index, arrangement::ArrangePolygon& arrange_polygon, bool selected); bool preprocess_arrange_polygon_other_locked(int obj_index, int instance_index, arrangement::ArrangePolygon& arrange_polygon, bool selected); - bool preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, int num_plates = 16); - bool preprocess_nonprefered_areas(arrangement::ArrangePolygons& regions, int num_plates = 1); + bool preprocess_exclude_areas(arrangement::ArrangePolygons& unselected, int num_plates = 16, float inflation = 0); + bool preprocess_nonprefered_areas(arrangement::ArrangePolygons& regions, int num_plates = 1, float inflation=0); void postprocess_bed_index_for_selected(arrangement::ArrangePolygon& arrange_polygon); void postprocess_bed_index_for_unselected(arrangement::ArrangePolygon& arrange_polygon);