FFF arrange minding skirt and brim distances

many thanks to @individ-divided and @jschuh
This commit is contained in:
tamasmeszaros 2023-02-16 16:06:21 +01:00
parent 6b1c9119be
commit 3c5ecd4a8f
5 changed files with 89 additions and 18 deletions

View File

@ -565,6 +565,11 @@ public:
SpanOfConstPtrs<PrintObject> objects() const { return SpanOfConstPtrs<PrintObject>(const_cast<const PrintObject* const* const>(m_objects.data()), m_objects.size()); } SpanOfConstPtrs<PrintObject> objects() const { return SpanOfConstPtrs<PrintObject>(const_cast<const PrintObject* const* const>(m_objects.data()), m_objects.size()); }
PrintObject* get_object(size_t idx) { return const_cast<PrintObject*>(m_objects[idx]); } PrintObject* get_object(size_t idx) { return const_cast<PrintObject*>(m_objects[idx]); }
const PrintObject* get_object(size_t idx) const { return m_objects[idx]; } const PrintObject* get_object(size_t idx) const { return m_objects[idx]; }
const PrintObject* get_print_object_by_model_object_id(ObjectID object_id) const {
auto it = std::find_if(m_objects.begin(), m_objects.end(),
[object_id](const PrintObject* obj) { return obj->model_object()->id() == object_id; });
return (it == m_objects.end()) ? nullptr : *it;
}
// PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects // PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects
// in the notification center. // in the notification center.
const PrintObject* get_object(ObjectID object_id) const { const PrintObject* get_object(ObjectID object_id) const {

View File

@ -2,6 +2,7 @@
#include "libslic3r/BuildVolume.hpp" #include "libslic3r/BuildVolume.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Print.hpp"
#include "libslic3r/SLAPrint.hpp" #include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp" #include "libslic3r/Geometry/ConvexHull.hpp"
@ -79,7 +80,6 @@ void ArrangeJob::clear_input()
m_selected.reserve(count + 1 /* for optional wti */); m_selected.reserve(count + 1 /* for optional wti */);
m_unselected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */);
m_unprintable.reserve(cunprint /* for optional wti */); m_unprintable.reserve(cunprint /* for optional wti */);
m_min_inflation = 0;
} }
void ArrangeJob::prepare_all() { void ArrangeJob::prepare_all() {
@ -151,8 +151,7 @@ void ArrangeJob::prepare_selected() {
static void update_arrangepoly_slaprint(arrangement::ArrangePolygon &ret, static void update_arrangepoly_slaprint(arrangement::ArrangePolygon &ret,
const SLAPrintObject &po, const SLAPrintObject &po,
const ModelInstance &inst, const ModelInstance &inst)
coord_t min_infl)
{ {
auto laststep = po.last_completed_step(); auto laststep = po.last_completed_step();
@ -189,10 +188,22 @@ static void update_arrangepoly_slaprint(arrangement::ArrangePolygon &ret,
po.config().pad_around_object.getBool() * po.config().pad_around_object.getBool() *
po.config().pad_object_gap.getFloat()); po.config().pad_object_gap.getFloat());
ret.inflation = std::max(infl, min_infl); ret.inflation = infl;
} }
} }
static coord_t brim_offset(const PrintObject &po, const ModelInstance &inst)
{
const BrimType brim_type = po.config().brim_type.value;
const float brim_separation = po.config().brim_separation.getFloat();
const float brim_width = po.config().brim_width.getFloat();
const bool has_outer_brim = brim_type == BrimType::btOuterOnly ||
brim_type == BrimType::btOuterAndInner;
// How wide is the brim? (in scaled units)
return has_outer_brim ? scaled(brim_width + brim_separation) : 0;
}
arrangement::ArrangePolygon ArrangeJob::get_arrange_poly_(ModelInstance *mi) arrangement::ArrangePolygon ArrangeJob::get_arrange_poly_(ModelInstance *mi)
{ {
arrangement::ArrangePolygon ap = get_arrange_poly(mi, m_plater); arrangement::ArrangePolygon ap = get_arrange_poly(mi, m_plater);
@ -204,27 +215,40 @@ arrangement::ArrangePolygon ArrangeJob::get_arrange_poly_(ModelInstance *mi)
m_unarranged.emplace_back(mi); m_unarranged.emplace_back(mi);
}; };
if (m_plater->printer_technology() == ptSLA) { return ap;
auto obj_id = mi->get_object()->id(); }
const SLAPrintObject *po =
m_plater->sla_print().get_print_object_by_model_object_id(obj_id);
if (po) { coord_t get_skirt_offset(const Plater* plater) {
update_arrangepoly_slaprint(ap, *po, *mi, m_min_inflation); float skirt_inset = 0.f;
m_min_inflation = std::max(m_min_inflation, ap.inflation); // Try to subtract the skirt from the bed shape so we don't arrange outside of it.
} if (plater->printer_technology() == ptFFF && plater->fff_print().has_skirt()) {
} else { const auto& print = plater->fff_print();
// TODO: get fff supports outline skirt_inset = print.config().skirts.value * print.skirt_flow().width() +
print.config().skirt_distance.value;
} }
return ap; return scaled(skirt_inset);
} }
void ArrangeJob::prepare() void ArrangeJob::prepare()
{ {
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all(); wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
coord_t min_offset = 0;
for (auto &ap : m_selected) { for (auto &ap : m_selected) {
ap.inflation = m_min_inflation; min_offset = std::max(ap.inflation, min_offset);
}
if (m_plater->printer_technology() == ptSLA) {
// Apply the max offset for all the objects
for (auto &ap : m_selected) {
ap.inflation = min_offset;
}
} else { // it's fff, brims only need to be minded from bed edges
for (auto &ap : m_selected) {
ap.inflation = 0;
}
m_min_bed_inset = min_offset;
} }
} }
@ -238,6 +262,8 @@ void ArrangeJob::process(Ctl &ctl)
prepare(); prepare();
params = get_arrange_params(m_plater); params = get_arrange_params(m_plater);
get_bed_shape(*m_plater->config(), bed); get_bed_shape(*m_plater->config(), bed);
coord_t min_inset = get_skirt_offset(m_plater) + m_min_bed_inset;
params.min_bed_distance = std::max(params.min_bed_distance, min_inset);
}).wait(); }).wait();
auto count = unsigned(m_selected.size() + m_unprintable.size()); auto count = unsigned(m_selected.size() + m_unprintable.size());
@ -352,6 +378,23 @@ arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst,
{ {
auto ap = get_arrange_poly(PtrWrapper{inst}, plater); auto ap = get_arrange_poly(PtrWrapper{inst}, plater);
auto obj_id = inst->get_object()->id();
if (plater->printer_technology() == ptSLA) {
const SLAPrintObject *po =
plater->sla_print().get_print_object_by_model_object_id(obj_id);
if (po) {
update_arrangepoly_slaprint(ap, *po, *inst);
}
} else {
const PrintObject *po =
plater->fff_print().get_print_object_by_model_object_id(obj_id);
if (po) {
ap.inflation = brim_offset(*po, *inst);
}
}
return ap; return ap;
} }

View File

@ -21,7 +21,7 @@ class ArrangeJob : public Job
ArrangePolygons m_selected, m_unselected, m_unprintable; ArrangePolygons m_selected, m_unselected, m_unprintable;
std::vector<ModelInstance*> m_unarranged; std::vector<ModelInstance*> m_unarranged;
coord_t m_min_inflation = 0; coord_t m_min_bed_inset = 0.;
Plater *m_plater; Plater *m_plater;
@ -104,6 +104,8 @@ arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst,
arrangement::ArrangeParams get_arrange_params(Plater *p); arrangement::ArrangeParams get_arrange_params(Plater *p);
coord_t get_skirt_offset(const Plater* plater);
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI
#endif // ARRANGEJOB_HPP #endif // ARRANGEJOB_HPP

View File

@ -18,6 +18,7 @@ void FillBedJob::prepare()
m_selected.clear(); m_selected.clear();
m_unselected.clear(); m_unselected.clear();
m_bedpts.clear(); m_bedpts.clear();
m_min_bed_inset = 0.;
m_object_idx = m_plater->get_selected_object_idx(); m_object_idx = m_plater->get_selected_object_idx();
if (m_object_idx == -1) if (m_object_idx == -1)
@ -29,7 +30,7 @@ void FillBedJob::prepare()
m_selected.reserve(model_object->instances.size()); m_selected.reserve(model_object->instances.size());
for (ModelInstance *inst : model_object->instances) for (ModelInstance *inst : model_object->instances)
if (inst->printable) { if (inst->printable) {
ArrangePolygon ap = get_arrange_poly(PtrWrapper{inst}, m_plater); ArrangePolygon ap = get_arrange_poly(inst, m_plater);
// Existing objects need to be included in the result. Only // Existing objects need to be included in the result. Only
// the needed amount of object will be added, no more. // the needed amount of object will be added, no more.
++ap.priority; ++ap.priority;
@ -101,6 +102,23 @@ void FillBedJob::prepare()
for (auto &p : m_unselected) for (auto &p : m_unselected)
if (p.bed_idx > 0) if (p.bed_idx > 0)
p.translation(X) -= p.bed_idx * stride; p.translation(X) -= p.bed_idx * stride;
coord_t min_offset = 0;
for (auto &ap : m_selected) {
min_offset = std::max(ap.inflation, min_offset);
}
if (m_plater->printer_technology() == ptSLA) {
// Apply the max offset for all the objects
for (auto &ap : m_selected) {
ap.inflation = min_offset;
}
} else { // it's fff, brims only need to be minded from bed edges
for (auto &ap : m_selected) {
ap.inflation = 0;
}
m_min_bed_inset = min_offset;
}
} }
void FillBedJob::process(Ctl &ctl) void FillBedJob::process(Ctl &ctl)
@ -110,6 +128,8 @@ void FillBedJob::process(Ctl &ctl)
ctl.call_on_main_thread([this, &params] { ctl.call_on_main_thread([this, &params] {
prepare(); prepare();
params = get_arrange_params(m_plater); params = get_arrange_params(m_plater);
coord_t min_inset = get_skirt_offset(m_plater) + m_min_bed_inset;
params.min_bed_distance = std::max(params.min_bed_distance, min_inset);
}).wait(); }).wait();
ctl.update_status(0, statustxt); ctl.update_status(0, statustxt);

View File

@ -16,6 +16,7 @@ class FillBedJob : public Job
ArrangePolygons m_selected; ArrangePolygons m_selected;
ArrangePolygons m_unselected; ArrangePolygons m_unselected;
coord_t m_min_bed_inset = 0.;
Points m_bedpts; Points m_bedpts;