mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 17:45:58 +08:00
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:
parent
e46891fa8c
commit
6b1c9119be
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user