diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 56aa3fdd80..863dcb43cd 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -1064,27 +1064,9 @@ private: if (!item.is_virt_object) bb = sl::boundingBox(item.boundingBox(), bb); - // 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(alignment) { + switch(config_.alignment) { case Config::Alignment::CENTER: { ci = bb.center(); cb = bbin.center(); @@ -1118,6 +1100,13 @@ private: // BBS make sure the item won't clash with excluded regions if(1) { + // do we have wipe tower after arranging? + std::set extruders; + for (const Item& item : items_) { + if (!item.is_virt_object) { extruders.insert(item.extrude_ids.begin(), item.extrude_ids.end()); } + } + bool need_wipe_tower = extruders.size() > 1; + std::vector objs,excludes; for (const Item &item : items_) { if (item.isFixed()) continue; @@ -1127,7 +1116,10 @@ private: if (objs.size() != 0) { for (const Item &item : config_.m_excluded_regions) { excludes.push_back(item.transformedShape()); } for (const Item &item : items_) { - if (item.isFixed()) { excludes.push_back(item.transformedShape()); } + if (item.isFixed()) { + if (!(item.is_wipe_tower && !need_wipe_tower)) + excludes.push_back(item.transformedShape()); + } } Box binbb = sl::boundingBox(bin_); auto allowShifts = calcnfp(objs_convex_hull, excludes, binbb, Lvl()); diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index ca462269b4..eeb385676a 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -545,11 +545,11 @@ public: 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; + //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 ? binbb.minCorner() : binbb.center(); // if we have wipe tower, items should be arranged around wipe tower diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index f1031ee126..0af344e876 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -3360,18 +3360,20 @@ void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConf return; } ret.extrude_ids = volume->get_extruders(); - if (ret.extrude_ids.empty()) //the default extruder - ret.extrude_ids.push_back(1); - // get per-object support extruders auto op = object->get_config_value(config_global, "enable_support"); bool is_support_enabled = op && op->getBool(); if (is_support_enabled) { auto op1 = object->get_config_value(config_global, "support_filament"); auto op2 = object->get_config_value(config_global, "support_interface_filament"); - if (op1) ret.extrude_ids.push_back(op1->getInt()); - if (op2) ret.extrude_ids.push_back(op2->getInt()); + int extruder_id; + // id==0 means follow previous material, so need not be recorded + if (op1 && (extruder_id = op1->getInt()) > 0) ret.extrude_ids.push_back(extruder_id); + if (op2 && (extruder_id = op2->getInt()) > 0) ret.extrude_ids.push_back(extruder_id); } + + if (ret.extrude_ids.empty()) //the default extruder + ret.extrude_ids.push_back(1); } indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4aa80e0181..50224cdb96 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1718,6 +1718,36 @@ bool GLCanvas3D::make_current_for_postinit() { return _set_current(); } +Points GLCanvas3D::estimate_wipe_tower_points(int plate_index) const +{ + PartPlateList & ppl = wxGetApp().plater()->get_partplate_list(); + DynamicPrintConfig &proj_cfg = wxGetApp().preset_bundle->project_config; + auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); + int plate_count = ppl.get_plate_count(); + float x = dynamic_cast(proj_cfg.option("wipe_tower_x"))->get_at(plate_index); + float y = dynamic_cast(proj_cfg.option("wipe_tower_y"))->get_at(plate_index); + if (plate_index >= plate_count) { plate_index = 0; } + float w = dynamic_cast(m_config->option("prime_tower_width"))->value; + float v = dynamic_cast(m_config->option("prime_volume"))->value; + Vec3d wipe_tower_size = ppl.get_plate(plate_index)->estimate_wipe_tower_size(w, v); + + if (wipe_tower_size(1) == 0) { + // when depth is unavailable (no items on this plate), we have to estimate the depth using the extruder number of all plates + std::set extruder_ids; + auto pl = ppl.get_plate_list(); + for (const auto& p : pl) { + auto es = p->get_extruders(); + extruder_ids.insert(es.begin(), es.end()); + } + int extruder_size = extruder_ids.size(); + wipe_tower_size(1) = extruder_size * print.wipe_tower_data(extruder_size).depth + 2 * print.wipe_tower_data().brim_width; + } + Vec3d plate_origin = ppl.get_plate(plate_index)->get_origin(); + Point wt_min_corner{scale_(x), scale_(y)}; + Point wt_max_corner(scale_(x + wipe_tower_size(0)), scale_(y + wipe_tower_size(1))); + return {wt_min_corner, {wt_max_corner.x(), wt_min_corner.y()}, wt_max_corner, {wt_min_corner.x(),wt_max_corner.y()}}; +} + void GLCanvas3D::render(bool only_init) { if (m_in_render) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 0325cf6e28..37f61d0713 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -1058,6 +1058,9 @@ public: bool make_current_for_postinit(); + //BBS + Points estimate_wipe_tower_points(int plate_index) const; + private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index dc2a5016ca..b81b015168 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -241,9 +241,15 @@ void ArrangeJob::prepare_all() { } // 准备料塔。逻辑如下: -// 1. 如果料塔被禁用,或是逐件打印,则不需要料塔 -// 2. 以下两种情况需要料塔:1)某对象是多色对象;2)打开了支撑,且支撑体与接触面使用的是不同材料 -// 3. 如果允许不同材料落在相同盘,则以下情况也需要料塔:1)所有选定对象中使用了多种热床温度相同的材料(比如颜色不同的PLA) +// 1. 以下几种情况不需要料塔: +// 1)料塔被禁用, +// 2)逐件打印, +// 3)不允许不同材料落在相同盘,且没有多色对象 +// 2. 以下情况需要料塔: +// 1)某对象是多色对象; +// 2)打开了支撑,且支撑体与接触面使用的是不同材料 +// 3)允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料 +// (所有对象都是单色的,但不同对象的材料不同,例如:对象A使用红色PLA,对象B使用白色PLA) void ArrangeJob::prepare_wipe_tower() { bool need_wipe_tower = false; @@ -257,7 +263,7 @@ void ArrangeJob::prepare_wipe_tower() // need wipe tower if some object has multiple extruders (has paint-on colors or support material) for (const auto &item : m_selected) { std::set obj_extruders; - for (int id : item.extrude_ids) obj_extruders.insert(id); + obj_extruders.insert(item.extrude_ids.begin(), item.extrude_ids.end()); if (obj_extruders.size() > 1) { need_wipe_tower = true; BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because object " << item.name << " has multiple extruders (has paint-on colors)"; @@ -266,6 +272,7 @@ void ArrangeJob::prepare_wipe_tower() } // if multile extruders have same bed temp, we need wipe tower + // 允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料 if (params.allow_multi_materials_on_same_plate) { std::map> bedTemp2extruderIds; for (const auto &item : m_selected) @@ -301,9 +308,11 @@ void ArrangeJob::prepare_wipe_tower() wipe_tower_ap.is_virt_object = true; wipe_tower_ap.is_wipe_tower = true; } - + const GLCanvas3D* canvas3D=static_cast(m_plater->canvas3D()); for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) { if (!plates_have_wipe_tower[bedid]) { + wipe_tower_ap.translation = {0, 0}; + wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid); wipe_tower_ap.bed_idx = bedid; m_unselected.emplace_back(wipe_tower_ap); }