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};
bool fixed_{false};
std::function<void(_Item&)> on_packed_;
public:
@ -205,6 +206,23 @@ public:
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.
*

View file

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

View file

@ -583,8 +583,12 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
outp.emplace_back(std::move(p));
outp.back().rotation(rotation);
outp.back().translation({offs.x(), offs.y()});
outp.back().inflate(arrpoly.inflation);
outp.back().binId(arrpoly.bed_idx);
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)

View file

@ -71,7 +71,7 @@ static const constexpr int UNARRANGED = -1;
/// polygon belongs: UNARRANGED means no place for the polygon
/// (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.
struct ArrangePolygon {
struct ArrangePolygon {
ExPolygon poly; /// The 2D silhouette to be arranged
Vec2crd translation{0, 0}; /// The translation of the poly
double rotation{0.0}; /// The rotation of the poly in radians

View file

@ -2,6 +2,8 @@
#include "libslic3r/BuildVolume.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
@ -11,6 +13,7 @@
#include "slic3r/GUI/NotificationManager.hpp"
#include "slic3r/GUI/format.hpp"
#include "libnest2d/common.hpp"
#include <numeric>
@ -76,6 +79,7 @@ void ArrangeJob::clear_input()
m_selected.reserve(count + 1 /* for optional wti */);
m_unselected.reserve(count + 1 /* for optional wti */);
m_unprintable.reserve(cunprint /* for optional wti */);
m_min_inflation = 0;
}
void ArrangeJob::prepare_all() {
@ -145,6 +149,50 @@ void ArrangeJob::prepare_selected() {
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 ap = get_arrange_poly(mi, m_plater);
@ -156,12 +204,28 @@ arrangement::ArrangePolygon ArrangeJob::get_arrange_poly_(ModelInstance *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;
}
void ArrangeJob::prepare()
{
wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all();
for (auto &ap : m_selected) {
ap.inflation = m_min_inflation;
}
}
void ArrangeJob::process(Ctl &ctl)
@ -286,7 +350,9 @@ template<>
arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst,
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)

View file

@ -21,6 +21,8 @@ class ArrangeJob : public Job
ArrangePolygons m_selected, m_unselected, m_unprintable;
std::vector<ModelInstance*> m_unarranged;
coord_t m_min_inflation = 0;
Plater *m_plater;
// clear m_selected and m_unselected, reserve space for next usage