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:
parent
67d95d3fc8
commit
dd473bdc3f
6 changed files with 71 additions and 35 deletions
|
@ -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>());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue