FIX: several auto arranging bugs

1. fill bed crash (jira: STUDIO-10350)
2. reset arranging settings gives wrong sequential printing order (jira: STUDIO-10346)
3. do not show "arranging done" message when there is no model

Change-Id: Ic1c7eac75e3917b9f1d87ab6acc403f78e0c9f7c
This commit is contained in:
Arthur 2025-02-13 08:57:58 +08:00 committed by lane.wei
parent 65267b9866
commit c414e51999
8 changed files with 87 additions and 69 deletions

View File

@ -2,7 +2,6 @@
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_ #define SRC_LIBSLIC3R_AABBTREELINES_HPP_
#include "Point.hpp" #include "Point.hpp"
#include "Utils.hpp"
#include "libslic3r.h" #include "libslic3r.h"
#include "libslic3r/AABBTreeIndirect.hpp" #include "libslic3r/AABBTreeIndirect.hpp"
#include "libslic3r/Line.hpp" #include "libslic3r/Line.hpp"

View File

@ -3949,30 +3949,30 @@ double ModelInstance::get_auto_brim_width() const
void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConfig &config_global) const void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConfig &config_global) const
{ {
// static const double SIMPLIFY_TOLERANCE_MM = 0.1; // static const double SIMPLIFY_TOLERANCE_MM = 0.1;
Geometry::Transformation trafo_instance = get_transformation(); Geometry::Transformation trafo_instance = get_transformation();
//BOOST_LOG_TRIVIAL(debug) << "get_arrange_polygon: " << object->name << " instance trans:\n" // BOOST_LOG_TRIVIAL(debug) << "get_arrange_polygon: " << object->name << " instance trans:\n"
// << trafo_instance.get_matrix().matrix() << "\n object trans:\n" // << trafo_instance.get_matrix().matrix() << "\n object trans:\n"
// << object->volumes.front()->get_transformation().get_matrix().matrix(); // << object->volumes.front()->get_transformation().get_matrix().matrix();
trafo_instance.set_offset(Vec3d(0, 0, get_offset(Z))); trafo_instance.set_offset(Vec3d(0, 0, get_offset(Z)));
Polygon p = get_object()->convex_hull_2d(trafo_instance.get_matrix()); Polygon p = get_object()->convex_hull_2d(trafo_instance.get_matrix());
// if (!p.points.empty()) { // if (!p.points.empty()) {
// Polygons pp{p}; // Polygons pp{p};
// pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM)); // pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
// if (!pp.empty()) p = pp.front(); // if (!pp.empty()) p = pp.front();
// } // }
arrangement::ArrangePolygon& ret = *(arrangement::ArrangePolygon*)ap; arrangement::ArrangePolygon &ret = *(arrangement::ArrangePolygon *) ap;
ret.poly.contour = std::move(p); ret.poly.contour = std::move(p);
ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))}; ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))};
ret.rotation = 0; ret.rotation = 0;
//BBS: add materials related information // BBS: add materials related information
ModelVolume *volume = NULL; ModelVolume *volume = NULL;
for (size_t i = 0; i < object->volumes.size(); ++i) { for (size_t i = 0; i < object->volumes.size(); ++i) {
if (object->volumes[i]->is_model_part()) { if (object->volumes[i]->is_model_part()) {
@ -3987,19 +3987,22 @@ void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConf
} }
// get per-object support extruders // get per-object support extruders
auto op = object->get_config_value<ConfigOptionBool>(config_global, "enable_support"); auto op = object->get_config_value<ConfigOptionBool>(config_global, "enable_support");
bool is_support_enabled = op && op->getBool(); bool is_support_enabled = op && op->getBool();
if (is_support_enabled) { if (is_support_enabled) {
auto op1 = object->get_config_value<ConfigOptionInt>(config_global, "support_filament"); auto op1 = object->get_config_value<ConfigOptionInt>(config_global, "support_filament");
auto op2 = object->get_config_value<ConfigOptionInt>(config_global, "support_interface_filament"); auto op2 = object->get_config_value<ConfigOptionInt>(config_global, "support_interface_filament");
int extruder_id; int extruder_id;
// id==0 means follow previous material, so need not be recorded // 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 (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 (op2 && (extruder_id = op2->getInt()) > 0) ret.extrude_ids.push_back(extruder_id);
} }
if (ret.extrude_ids.empty()) //the default extruder if (ret.extrude_ids.empty()) // the default extruder
ret.extrude_ids.push_back(1); ret.extrude_ids.push_back(1);
// filament types must be same size as extrude_ids
ret.filament_types.resize(ret.extrude_ids.size(), "PLA");
} }
void ModelInstance::apply_arrange_result(const Vec2d &offs, double rotation) void ModelInstance::apply_arrange_result(const Vec2d &offs, double rotation)

View File

@ -2070,7 +2070,8 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor
gcode.do_export(this, path.c_str(), result, thumbnail_cb); gcode.do_export(this, path.c_str(), result, thumbnail_cb);
gcode.export_layer_filaments(result); gcode.export_layer_filaments(result);
//BBS //BBS
result->conflict_result = m_conflict_result; if (result != nullptr)
result->conflict_result = m_conflict_result;
return path.c_str(); return path.c_str();
} }

View File

@ -668,25 +668,6 @@ inline std::string filter_characters(const std::string& str, const std::string&
return filteredStr; return filteredStr;
} }
// custom vector wrapper for outputting to log
template<typename T> struct VectorFormatter
{
const std::vector<T> &vec;
explicit VectorFormatter(const std::vector<T> &v) : vec(v) {}
friend std::ostream &operator<<(std::ostream &os, const VectorFormatter<T> &vf)
{
os << "[";
for (size_t i = 0; i < vf.vec.size(); ++i) {
os << vf.vec[i];
if (i != vf.vec.size() - 1) { os << ", "; }
}
os << "]";
return os;
}
};
} // namespace Slic3r } // namespace Slic3r
#if WIN32 #if WIN32

View File

@ -0,0 +1,33 @@
#pragma once
#include <Eigen/Core>
#include <vector>
#include <iostream>
// custom vector wrapper for outputting to log
template<typename T> struct VectorFormatter
{
const std::vector<T>* vec = nullptr;
const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>* mat = nullptr;
explicit VectorFormatter(const std::vector<T>& v) : vec(&v) {}
explicit VectorFormatter(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& m) : mat(&m) {}
friend std::ostream& operator<<(std::ostream& os, const VectorFormatter<T>& vf)
{
os << "[";
if (vf.vec) {
for (size_t i = 0; i < vf.vec->size(); ++i) {
os << (*vf.vec)[i];
if (i != vf.vec->size() - 1) { os << ", "; }
}
}
else {
for (int i = 0; i < vf.mat->size(); ++i) {
os << (*vf.mat)(i);
if (i != vf.mat->size() - 1) { os << ", "; }
}
}
os << "]";
return os;
}
};

View File

@ -1122,12 +1122,16 @@ GLCanvas3D::ArrangeSettings& GLCanvas3D::get_arrange_settings()
if (ptech == ptSLA) { if (ptech == ptSLA) {
ptr = &m_arrange_settings_sla; ptr = &m_arrange_settings_sla;
ptr->postfix = "_sla";
} }
else if (ptech == ptFFF) { else if (ptech == ptFFF) {
if (wxGetApp().global_print_sequence() == PrintSequence::ByObject) if (wxGetApp().global_print_sequence() == PrintSequence::ByObject) {
ptr = &m_arrange_settings_fff_seq_print; ptr = &m_arrange_settings_fff_seq_print;
else ptr->postfix = "_fff_seq_print";
ptr = &m_arrange_settings_fff; } else {
ptr = &m_arrange_settings_fff;
ptr->postfix = "_fff";
}
} }
return *ptr; return *ptr;
@ -5909,20 +5913,9 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
std::string multi_material_key = "allow_multi_materials_on_same_plate"; std::string multi_material_key = "allow_multi_materials_on_same_plate";
std::string avoid_extrusion_key = "avoid_extrusion_cali_region"; std::string avoid_extrusion_key = "avoid_extrusion_cali_region";
std::string align_to_y_axis_key = "align_to_y_axis"; std::string align_to_y_axis_key = "align_to_y_axis";
std::string postfix; std::string postfix = settings.postfix;
//BBS: //BBS:
bool seq_print = false; bool seq_print = settings.is_seq_print;
if (ptech == ptSLA) {
postfix = "_sla";
} else if (ptech == ptFFF) {
seq_print = &settings == &m_arrange_settings_fff_seq_print;
if (seq_print) {
postfix = "_fff_seq_print";
} else {
postfix = "_fff";
}
}
dist_key += postfix; dist_key += postfix;
rot_key += postfix; rot_key += postfix;
@ -5998,8 +5991,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
ImGui::SameLine(); ImGui::SameLine();
if (imgui->button(_L("Reset"))) { if (imgui->button(_L("Reset"))) {
settings_out = ArrangeSettings{}; settings_out.reset();
settings_out.distance = std::max(dist_min, settings_out.distance);
//BBS: add specific arrange settings //BBS: add specific arrange settings
if (seq_print) settings_out.is_seq_print = true; if (seq_print) settings_out.is_seq_print = true;

View File

@ -514,6 +514,17 @@ public:
//BBS: add more arrangeSettings //BBS: add more arrangeSettings
bool is_seq_print = false; bool is_seq_print = false;
bool align_to_y_axis = false; bool align_to_y_axis = false;
std::string postfix;
void reset()
{
distance = 0.f;
accuracy = 0.65f;
enable_rotation = false;
allow_multi_materials_on_same_plate = true;
avoid_extrusion_cali_region = true;
is_seq_print = false;
align_to_y_axis = false;
}
}; };
struct OrientSettings struct OrientSettings

View File

@ -2,6 +2,7 @@
#include "libslic3r/SVG.hpp" #include "libslic3r/SVG.hpp"
#include "libslic3r/ModelArrange.hpp" #include "libslic3r/ModelArrange.hpp"
#include "libslic3r/VectorFormatter.hpp"
#include "slic3r/GUI/PartPlate.hpp" #include "slic3r/GUI/PartPlate.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
@ -519,10 +520,6 @@ void ArrangeJob::prepare_outside_plate() {
//BBS: add partplate logic //BBS: add partplate logic
void ArrangeJob::prepare() void ArrangeJob::prepare()
{ {
m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing,
NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging..."));
m_plater->get_notification_manager()->bbl_close_plateinfo_notification();
params = init_arrange_params(m_plater); params = init_arrange_params(m_plater);
//BBS update extruder params and speed table before arranging //BBS update extruder params and speed table before arranging
@ -620,8 +617,8 @@ void ArrangeJob::on_exception(const std::exception_ptr &eptr)
if (eptr) if (eptr)
std::rethrow_exception(eptr); std::rethrow_exception(eptr);
} catch (libnest2d::GeometryException &) { } catch (libnest2d::GeometryException &) {
show_error(m_plater, _(L("Arrange failed. " show_error(m_plater, _L("Arrange failed. "
"Found some exceptions when processing object geometries."))); "Found some exceptions when processing object geometries."));
} catch (std::exception &) { } catch (std::exception &) {
PlaterJob::on_exception(eptr); PlaterJob::on_exception(eptr);
} }
@ -655,10 +652,10 @@ void ArrangeJob::process()
BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json(); BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size(); BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
for (auto selected : m_selected) { for (auto selected : m_selected) {
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << VectorFormatter( selected.extrude_ids) BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << VectorFormatter(selected.extrude_ids)
<< ", filament types: " << VectorFormatter(selected.filament_types) << ", bed: " << selected.bed_idx << ", filament types: " << VectorFormatter(selected.filament_types) << ", bed: " << selected.bed_idx
<< ", filemant_type:" << selected.filament_temp_type << ", trans: " << selected.translation.transpose() << ", filemant_type:" << selected.filament_temp_type << ", trans: " << unscale<double>(selected.translation(X)) << ","
<< ", rotation: " << selected.rotation; << unscale<double>(selected.translation(Y)) << ", rotation: " << selected.rotation;
} }
BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected before arrange: " << m_unselected.size(); BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected before arrange: " << m_unselected.size();
for (auto item : m_unselected) for (auto item : m_unselected)
@ -673,7 +670,7 @@ void ArrangeJob::process()
{ {
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected after arranging: %1%") % m_selected.size(); BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected after arranging: %1%") % m_selected.size();
for (auto selected : m_selected) for (auto selected : m_selected)
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << VectorFormatter(selected.extrude_ids) << ", bed: " << selected.bed_idx
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp << ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp
<< ", trans: " << unscale<double>(selected.translation(X)) << "," << unscale<double>(selected.translation(Y)) << ", trans: " << unscale<double>(selected.translation(X)) << "," << unscale<double>(selected.translation(Y))
<< ", rotation: " << selected.rotation; << ", rotation: " << selected.rotation;
@ -822,8 +819,9 @@ void ArrangeJob::finalize()
wxGetApp().obj_list()->reload_all_plates(); wxGetApp().obj_list()->reload_all_plates();
m_plater->update(); m_plater->update();
m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing, if (!m_selected.empty())
NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging done.")); m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing, NotificationManager::NotificationLevel::RegularNotificationLevel,
_u8L("Arranging done."));
} }
else { else {
m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing, m_plater->get_notification_manager()->push_notification(NotificationType::ArrangeOngoing,