FIX: auto arrange estimates wrong wipe tower

Jira: STUDIO-4678
Change-Id: Iff2273b464db939a2b5e19f8791bd2a4d67ce8c1
(cherry picked from commit fe4b1f79faeade42300622367fb23d7bd1079785)
This commit is contained in:
Arthur 2023-10-08 19:54:21 +08:00 committed by Lane.Wei
parent 00373df52c
commit 8d74732348
7 changed files with 103 additions and 56 deletions

View File

@ -73,6 +73,7 @@ static constexpr double INSET_OVERLAP_TOLERANCE = 0.4;
//FIXME This is quite a lot.
static constexpr double EXTERNAL_INFILL_MARGIN = 3;
static constexpr double BRIDGE_INFILL_MARGIN = 1;
static constexpr double WIPE_TOWER_MARGIN = 15.;
//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)

View File

@ -1737,45 +1737,6 @@ bool GLCanvas3D::make_current_for_postinit() {
return _set_current();
}
Points GLCanvas3D::estimate_wipe_tower_points(int plate_index, bool global) 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;
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
Vec3d wipe_tower_size = ppl.get_plate(plate_index)->estimate_wipe_tower_size(print_cfg, 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;
if (global) {
auto objs = wxGetApp().obj_list()->objects();
for (ModelObject *obj : *objs) {
for (ModelVolume *volume : obj->volumes) {
std::vector<int> es = volume->get_extruders();
extruder_ids.insert(es.begin(), es.end());
}
}
} else {
PartPlate* pl = ppl.get_plate(plate_index);
std::vector<int> es = pl->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) {
@ -2639,7 +2600,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, v);
const float margin = 15.f;
const float margin = WIPE_TOWER_MARGIN;
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_id)->get_bounding_box();
coordf_t plate_bbox_x_max_local_coord = plate_bbox.max(0) - plate_origin(0);
coordf_t plate_bbox_y_max_local_coord = plate_bbox.max(1) - plate_origin(1);
@ -4913,10 +4874,10 @@ GLCanvas3D::WipeTowerInfo GLCanvas3D::get_wipe_tower_info(int plate_idx) const
wti.m_bb.offset((brim_width));
// BBS: the wipe tower pos might be outside bed
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
BoundingBoxf3 build_volume = plate->get_build_volume();
wti.m_pos.x() = std::clamp(wti.m_pos.x(), 0.0, build_volume.max.x() - wti.m_bb.size().x());
wti.m_pos.y() = std::clamp(wti.m_pos.y(), 0.0, build_volume.max.y() - wti.m_bb.size().y());
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
Vec2d plate_size = plate->get_size();
wti.m_pos.x() = std::clamp(wti.m_pos.x(), 0.0, plate_size(0) - wti.m_bb.size().x());
wti.m_pos.y() = std::clamp(wti.m_pos.y(), 0.0, plate_size(1) - wti.m_bb.size().y());
// BBS: add partplate logic
wti.m_plate_idx = plate_idx;

View File

@ -1083,9 +1083,6 @@ public:
bool make_current_for_postinit();
//BBS
Points estimate_wipe_tower_points(int plate_index, bool global = true) const;
private:
bool _is_shown_on_screen() const;

View File

@ -57,7 +57,7 @@ public:
ret.is_wipe_tower = true;
++ret.priority;
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " arrange: wipe tower info:" << m_bb << ", m_pos: " << m_pos.transpose();
BOOST_LOG_TRIVIAL(debug) << " arrange: wipe tower info:" << m_bb << ", m_pos: " << m_pos.transpose();
return ret;
}
@ -240,6 +240,21 @@ void ArrangeJob::prepare_all() {
plate_list.preprocess_exclude_areas(m_unselected, MAX_NUM_PLATES);
}
arrangement::ArrangePolygon estimate_wipe_tower_info(int plate_index, std::set<int>& extruder_ids)
{
PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
const auto& full_config = wxGetApp().preset_bundle->full_config();
int plate_count = ppl.get_plate_count();
int plate_index_valid = std::min(plate_index, plate_count - 1);
// we have to estimate the depth using the extruder number of all plates
int extruder_size = extruder_ids.size();
auto arrange_poly = ppl.get_plate(plate_index_valid)->estimate_wipe_tower_polygon(full_config, plate_index, extruder_size);
arrange_poly.bed_idx = plate_index;
return arrange_poly;
}
// 准备料塔。逻辑如下:
// 1. 以下几种情况不需要料塔:
// 1料塔被禁用
@ -299,6 +314,14 @@ 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());
std::set<int> extruder_ids;
PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
int plate_count = ppl.get_plate_count();
if (!only_on_partplate) {
extruder_ids = ppl.get_extruders(true);
}
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
if (auto wti = get_wipe_tower(*m_plater, bedid)) {
// wipe tower is already there
@ -307,8 +330,14 @@ void ArrangeJob::prepare_wipe_tower()
m_unselected.emplace_back(wipe_tower_ap);
}
else if (need_wipe_tower) {
wipe_tower_ap.translation = { 0, 0 };
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate);
if (only_on_partplate) {
int plate_index_valid = std::min(bedid, plate_count - 1);
PartPlate* pl = ppl.get_plate(plate_index_valid);
auto plate_extruders = pl->get_extruders(true);
extruder_ids.clear();
extruder_ids.insert(plate_extruders.begin(), plate_extruders.end());
}
wipe_tower_ap = estimate_wipe_tower_info(bedid, extruder_ids);
wipe_tower_ap.bed_idx = bedid;
m_unselected.emplace_back(wipe_tower_ap);
}
@ -365,7 +394,7 @@ void ArrangeJob::prepare_partplate() {
//skip this object due to be not in current plate, treated as locked
ap.itemid = m_locked.size();
m_locked.emplace_back(std::move(ap));
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
}
}
}
@ -523,7 +552,8 @@ void ArrangeJob::process()
}
BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: ";
for (auto item : m_unselected)
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose()
<<", bbox:"<<get_extents(item.poly).min.transpose()<<","<<get_extents(item.poly).max.transpose();
}
arrangement::arrange(m_selected, m_unselected, bedpts, params);

View File

@ -1701,6 +1701,46 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
return wipe_tower_size;
}
arrangement::ArrangePolygon PartPlate::estimate_wipe_tower_polygon(const DynamicPrintConfig& config, int plate_index, int plate_extruder_size) const
{
float x = dynamic_cast<const ConfigOptionFloats*>(config.option("wipe_tower_x"))->get_at(plate_index);
float y = dynamic_cast<const ConfigOptionFloats*>(config.option("wipe_tower_y"))->get_at(plate_index);
float w = dynamic_cast<const ConfigOptionFloat*>(config.option("prime_tower_width"))->value;
//float a = dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value;
float v = dynamic_cast<const ConfigOptionFloat*>(config.option("prime_volume"))->value;
Vec3d wipe_tower_size = estimate_wipe_tower_size(config, w, v, plate_extruder_size);
int plate_width=m_width, plate_depth=m_depth;
float depth = wipe_tower_size(1);
float margin = WIPE_TOWER_MARGIN, wp_brim_width = 0.f;
const ConfigOption* wipe_tower_brim_width_opt = config.option("prime_tower_brim_width");
if (wipe_tower_brim_width_opt) {
wp_brim_width = wipe_tower_brim_width_opt->getFloat();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange wipe_tower: wp_brim_width %1%") % wp_brim_width;
}
x = std::clamp(x, margin, (float)plate_width - w - margin - wp_brim_width);
y = std::clamp(y, margin, (float)plate_depth - depth - margin - wp_brim_width);
arrangement::ArrangePolygon wipe_tower_ap;
Polygon ap({
{scaled(x - wp_brim_width), scaled(y - wp_brim_width)},
{scaled(x + w + wp_brim_width), scaled(y - wp_brim_width)},
{scaled(x + w + wp_brim_width), scaled(y + depth + wp_brim_width)},
{scaled(x - wp_brim_width), scaled(y + depth + wp_brim_width)}
});
wipe_tower_ap.bed_idx = plate_index;
wipe_tower_ap.setter = NULL; // do not move wipe tower
wipe_tower_ap.poly.contour = std::move(ap);
wipe_tower_ap.translation = { scaled(0.f), scaled(0.f) };
//wipe_tower_ap.rotation = a;
wipe_tower_ap.name = "WipeTower";
wipe_tower_ap.is_virt_object = true;
wipe_tower_ap.is_wipe_tower = true;
return wipe_tower_ap;
}
bool PartPlate::operator<(PartPlate& plate) const
{
int index = plate.get_index();
@ -3702,6 +3742,20 @@ std::vector<const GCodeProcessorResult*> PartPlateList::get_nonempty_plates_slic
return nonempty_plates_slice_result;
}
std::set<int> PartPlateList::get_extruders(bool conside_custom_gcode) const
{
int plate_count = get_plate_count();
std::set<int> extruder_ids;
for (size_t i = 0; i < plate_count; i++) {
auto plate_extruders = m_plate_list[i]->get_extruders(conside_custom_gcode);
extruder_ids.insert(plate_extruders.begin(), plate_extruders.end());
}
return extruder_ids;
}
//select plate
int PartPlateList::select_plate(int index)
{
@ -3795,7 +3849,7 @@ double PartPlateList::plate_stride_y()
}
//get the plate counts, not including the invalid plate
int PartPlateList::get_plate_count()
int PartPlateList::get_plate_count() const
{
int ret = 0;
@ -4353,7 +4407,7 @@ bool PartPlateList::preprocess_arrange_polygon_other_locked(int obj_index, int i
arrange_polygon.col = i % m_plate_cols;
arrange_polygon.translation(X) -= scaled<double>(plate_stride_x() * arrange_polygon.col);
arrange_polygon.translation(Y) += scaled<double>(plate_stride_y() * arrange_polygon.row);
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj_id %1% instance_id %2% in plate %3%, locked %4%, row %5%, col %6%\n") % obj_index % instance_index % i % locked % arrange_polygon.row % arrange_polygon.col;
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj_id %1% instance_id %2% in plate %3%, locked %4%, row %5%, col %6%\n") % obj_index % instance_index % i % locked % arrange_polygon.row % arrange_polygon.col;
return locked;
}
}

View File

@ -288,11 +288,13 @@ public:
void set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move);
// BBS
Vec2d get_size() const { return Vec2d(m_width, m_depth); }
ModelObjectPtrs get_objects() { return m_model->objects; }
ModelInstance* get_instance(int obj_id, int instance_id);
Vec3d get_origin() { return m_origin; }
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int plate_extruder_size = 0) const;
arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, int plate_extruder_size = 0) const;
std::vector<int> get_extruders(bool conside_custom_gcode = false) const;
std::vector<int> get_extruders_under_cli(bool conside_custom_gcode, DynamicPrintConfig& full_config) const;
std::vector<int> get_extruders_without_support(bool conside_custom_gcode = false) const;
@ -687,11 +689,13 @@ public:
Vec2d get_current_shape_position() { return compute_shape_position(m_current_plate, m_plate_cols); }
Pointfs get_exclude_area() { return m_exclude_areas; }
std::set<int> get_extruders(bool conside_custom_gcode = false) const;
//select plate
int select_plate(int index);
//get the plate counts, not including the invalid plate
int get_plate_count();
int get_plate_count() const;
//update the plate cols due to plate count change
void update_plate_cols();

View File

@ -899,7 +899,7 @@ void Selection::translate(const Vec3d& displacement, bool local)
Vec3d tower_size = v.bounding_box().size();
Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
Vec3d actual_displacement = displacement;
const double margin = 15.f;
const double margin = WIPE_TOWER_MARGIN;
if (!local)
actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;