Add code to extract sla supports outline for arrangement

Add functionality to libnest to support on_packed handler for all items.

Use it to swap arrange polygon from envelope to core poly after packing was succesful.
Solving brim issue by offset adjustments of arrange polygons

Only in sla yet
This commit is contained in:
tamasmeszaros 2023-02-15 16:27:03 +01:00
parent e46891fa8c
commit 6b1c9119be
6 changed files with 93 additions and 2 deletions

View File

@ -70,6 +70,7 @@ class _Item {
int binid_{BIN_ID_UNSET}, priority_{0}; int binid_{BIN_ID_UNSET}, priority_{0};
bool fixed_{false}; bool fixed_{false};
std::function<void(_Item&)> on_packed_;
public: public:
@ -205,6 +206,23 @@ public:
sl::vertex(sh_, idx) = v; sl::vertex(sh_, idx) = v;
} }
void setShape(RawShape rsh)
{
sh_ = std::move(rsh);
invalidateCache();
}
void setOnPackedFn(std::function<void(_Item&)> onpackedfn)
{
on_packed_ = onpackedfn;
}
void onPacked()
{
if (on_packed_)
on_packed_(*this);
}
/** /**
* @brief Calculate the shape area. * @brief Calculate the shape area.
* *

View File

@ -901,6 +901,7 @@ public:
if(can_pack) { if(can_pack) {
ret = PackResult(item); ret = PackResult(item);
item.onPacked();
merged_pile_ = nfp::merge(merged_pile_, item.transformedShape()); merged_pile_ = nfp::merge(merged_pile_, item.transformedShape());
} else { } else {
ret = PackResult(best_overfit); ret = PackResult(best_overfit);

View File

@ -583,8 +583,12 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
outp.emplace_back(std::move(p)); outp.emplace_back(std::move(p));
outp.back().rotation(rotation); outp.back().rotation(rotation);
outp.back().translation({offs.x(), offs.y()}); outp.back().translation({offs.x(), offs.y()});
outp.back().inflate(arrpoly.inflation);
outp.back().binId(arrpoly.bed_idx); outp.back().binId(arrpoly.bed_idx);
outp.back().priority(arrpoly.priority); outp.back().priority(arrpoly.priority);
outp.back().setOnPackedFn([&arrpoly](Item &itm){
itm.inflate(-arrpoly.inflation);
});
} }
template<class Fn> auto call_with_bed(const Points &bed, Fn &&fn) template<class Fn> auto call_with_bed(const Points &bed, Fn &&fn)

View File

@ -71,7 +71,7 @@ static const constexpr int UNARRANGED = -1;
/// polygon belongs: UNARRANGED means no place for the polygon /// polygon belongs: UNARRANGED means no place for the polygon
/// (also the initial state before arrange), 0..N means the index of the bed. /// (also the initial state before arrange), 0..N means the index of the bed.
/// Zero is the physical bed, larger than zero means a virtual bed. /// Zero is the physical bed, larger than zero means a virtual bed.
struct ArrangePolygon { struct ArrangePolygon {
ExPolygon poly; /// The 2D silhouette to be arranged ExPolygon poly; /// The 2D silhouette to be arranged
Vec2crd translation{0, 0}; /// The translation of the poly Vec2crd translation{0, 0}; /// The translation of the poly
double rotation{0.0}; /// The rotation of the poly in radians double rotation{0.0}; /// The rotation of the poly in radians

View File

@ -2,6 +2,8 @@
#include "libslic3r/BuildVolume.hpp" #include "libslic3r/BuildVolume.hpp"
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
@ -11,6 +13,7 @@
#include "slic3r/GUI/NotificationManager.hpp" #include "slic3r/GUI/NotificationManager.hpp"
#include "slic3r/GUI/format.hpp" #include "slic3r/GUI/format.hpp"
#include "libnest2d/common.hpp" #include "libnest2d/common.hpp"
#include <numeric> #include <numeric>
@ -76,6 +79,7 @@ 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() {
@ -145,6 +149,50 @@ void ArrangeJob::prepare_selected() {
for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride; for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride;
} }
static void update_arrangepoly_slaprint(arrangement::ArrangePolygon &ret,
const SLAPrintObject &po,
const ModelInstance &inst,
coord_t min_infl)
{
auto laststep = po.last_completed_step();
if (laststep < slaposCount && laststep > slaposSupportTree) {
auto omesh = po.get_mesh_to_print();
auto &smesh = po.support_mesh();
Vec3d rotation = inst.get_rotation();
rotation.z() = 0.;
Transform3f trafo_instance =
Geometry::assemble_transform(inst.get_offset().z() * Vec3d::UnitZ(),
rotation,
inst.get_scaling_factor(),
inst.get_mirror()).cast<float>();
trafo_instance = trafo_instance * po.trafo().cast<float>().inverse();
auto polys = reserve_vector<Polygon>(3);
auto zlvl = -po.get_elevation();
if (omesh) {
polys.emplace_back(its_convex_hull_2d_above(*omesh, trafo_instance, zlvl));
ret.poly.contour = polys.back();
ret.poly.holes = {};
}
polys.emplace_back(its_convex_hull_2d_above(smesh.its, trafo_instance, zlvl));
ret.poly.contour = Geometry::convex_hull(polys);
ret.poly.holes = {};
// The 1.1 multiplier is a safety gap, as the offset might be bigger
// in sharp edges of a polygon, depending on clipper's offset algorithm
coord_t infl = 1.1 * scaled(po.config().pad_brim_size.getFloat() +
po.config().pad_around_object.getBool() *
po.config().pad_object_gap.getFloat());
ret.inflation = std::max(infl, min_infl);
}
}
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);
@ -156,12 +204,28 @@ arrangement::ArrangePolygon ArrangeJob::get_arrange_poly_(ModelInstance *mi)
m_unarranged.emplace_back(mi); m_unarranged.emplace_back(mi);
}; };
if (m_plater->printer_technology() == ptSLA) {
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) {
update_arrangepoly_slaprint(ap, *po, *mi, m_min_inflation);
m_min_inflation = std::max(m_min_inflation, ap.inflation);
}
} else {
// TODO: get fff supports outline
}
return ap; return ap;
} }
void ArrangeJob::prepare() void ArrangeJob::prepare()
{ {
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all(); wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
for (auto &ap : m_selected) {
ap.inflation = m_min_inflation;
}
} }
void ArrangeJob::process(Ctl &ctl) void ArrangeJob::process(Ctl &ctl)
@ -286,7 +350,9 @@ template<>
arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst, arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst,
const Plater * plater) const Plater * plater)
{ {
return get_arrange_poly(PtrWrapper{inst}, plater); auto ap = get_arrange_poly(PtrWrapper{inst}, plater);
return ap;
} }
arrangement::ArrangeParams get_arrange_params(Plater *p) arrangement::ArrangeParams get_arrange_params(Plater *p)

View File

@ -21,6 +21,8 @@ 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;
Plater *m_plater; Plater *m_plater;
// clear m_selected and m_unselected, reserve space for next usage // clear m_selected and m_unselected, reserve space for next usage