FIX: avoid wipe tower conflict with objects

Use a more accurate way to estimate wipe tower:
1. read wipe configure from front-end (the positions may be different at
different plates).
2. when depth is unavailable, use all materials to estimate depth (the
estimated wipe tower may be larger than the actual generated one).

Change-Id: I42ffd03d9817b57f5023a6820cda0032509c6fe5
(cherry picked from commit 77ba9757023afb9160c996eeea6ead8a27b50ce4)
This commit is contained in:
manch1n 2023-04-07 21:52:59 +08:00 committed by Lane.Wei
parent 67d95d3fc8
commit dd473bdc3f
6 changed files with 71 additions and 35 deletions

View file

@ -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<int> 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<RawShape> 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<MaxNfpLevel::value>());

View file

@ -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

View file

@ -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<ConfigOptionBool>(config_global, "enable_support");
bool is_support_enabled = op && op->getBool();
if (is_support_enabled) {
auto op1 = object->get_config_value<ConfigOptionInt>(config_global, "support_filament");
auto op2 = object->get_config_value<ConfigOptionInt>(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

View file

@ -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<const ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->get_at(plate_index);
float y = dynamic_cast<const ConfigOptionFloats *>(proj_cfg.option("wipe_tower_y"))->get_at(plate_index);
if (plate_index >= plate_count) { plate_index = 0; }
float w = dynamic_cast<const ConfigOptionFloat *>(m_config->option("prime_tower_width"))->value;
float v = dynamic_cast<const ConfigOptionFloat *>(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<int> 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) {

View file

@ -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;

View file

@ -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<int> 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<int, std::set<int>> 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<const GLCanvas3D *>(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);
}