FIX: auto arrange estimates wrong wipe tower
Jira: STUDIO-4678 Change-Id: Iff2273b464db939a2b5e19f8791bd2a4d67ce8c1 (cherry picked from commit fe4b1f79faeade42300622367fb23d7bd1079785)
This commit is contained in:
parent
00373df52c
commit
8d74732348
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue