Merge branch 'tm_arrange_alignment_SPE-1416'
This commit is contained in:
commit
4663ec0e58
@ -85,7 +85,13 @@ template<class PConf>
|
||||
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||
|
||||
// Align the arranged pile into the center of the bin
|
||||
pcfg.alignment = PConf::Alignment::CENTER;
|
||||
switch (params.alignment) {
|
||||
case Pivots::Center: pcfg.alignment = PConf::Alignment::CENTER; break;
|
||||
case Pivots::BottomLeft: pcfg.alignment = PConf::Alignment::BOTTOM_LEFT; break;
|
||||
case Pivots::BottomRight: pcfg.alignment = PConf::Alignment::BOTTOM_RIGHT; break;
|
||||
case Pivots::TopLeft: pcfg.alignment = PConf::Alignment::TOP_LEFT; break;
|
||||
case Pivots::TopRight: pcfg.alignment = PConf::Alignment::TOP_RIGHT; break;
|
||||
}
|
||||
|
||||
// Start placing the items from the center of the print bed
|
||||
pcfg.starting_point = PConf::Alignment::CENTER;
|
||||
@ -593,23 +599,27 @@ template<class Fn> auto call_with_bed(const Points &bed, Fn &&fn)
|
||||
auto parea = poly_area(bed);
|
||||
|
||||
if ((1.0 - parea / area(bb)) < 1e-3)
|
||||
return fn(bb);
|
||||
return fn(RectangleBed{bb});
|
||||
else if (!std::isnan(circ.radius()))
|
||||
return fn(circ);
|
||||
else
|
||||
return fn(Polygon(bed));
|
||||
return fn(IrregularBed{ExPolygon(bed)});
|
||||
}
|
||||
}
|
||||
|
||||
bool is_box(const Points &bed)
|
||||
{
|
||||
return !bed.empty() &&
|
||||
((1.0 - poly_area(bed) / area(BoundingBox(bed))) < 1e-3);
|
||||
}
|
||||
|
||||
template<>
|
||||
void arrange(ArrangePolygons & items,
|
||||
const ArrangePolygons &excludes,
|
||||
const Points & bed,
|
||||
const ArrangeParams & params)
|
||||
{
|
||||
call_with_bed(bed, [&](const auto &bin) {
|
||||
arrange(items, excludes, bin, params);
|
||||
});
|
||||
arrange(items, excludes, to_arrange_bed(bed), params);
|
||||
}
|
||||
|
||||
template<class BedT>
|
||||
@ -649,5 +659,85 @@ template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, c
|
||||
template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const Polygon &bed, const ArrangeParams ¶ms);
|
||||
template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const InfiniteBed &bed, const ArrangeParams ¶ms);
|
||||
|
||||
ArrangeBed to_arrange_bed(const Points &bedpts)
|
||||
{
|
||||
ArrangeBed ret;
|
||||
|
||||
call_with_bed(bedpts, [&](const auto &bed) {
|
||||
ret = bed;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void arrange(ArrangePolygons &items,
|
||||
const ArrangePolygons &excludes,
|
||||
const SegmentedRectangleBed &bed,
|
||||
const ArrangeParams ¶ms)
|
||||
{
|
||||
arrange(items, excludes, bed.bb, params);
|
||||
|
||||
if (! excludes.empty())
|
||||
return;
|
||||
|
||||
auto it = std::max_element(items.begin(), items.end(),
|
||||
[](auto &i1, auto &i2) {
|
||||
return i1.bed_idx < i2.bed_idx;
|
||||
});
|
||||
|
||||
size_t beds = 0;
|
||||
if (it != items.end())
|
||||
beds = it->bed_idx + 1;
|
||||
|
||||
std::vector<BoundingBox> pilebb(beds);
|
||||
|
||||
for (auto &itm : items) {
|
||||
if (itm.bed_idx >= 0)
|
||||
pilebb[itm.bed_idx].merge(get_extents(itm.transformed_poly()));
|
||||
}
|
||||
|
||||
auto piecesz = unscaled(bed.bb).size();
|
||||
piecesz.x() /= bed.segments.x();
|
||||
piecesz.y() /= bed.segments.y();
|
||||
|
||||
for (size_t bedidx = 0; bedidx < beds; ++bedidx) {
|
||||
BoundingBox bb;
|
||||
auto pilesz = unscaled(pilebb[bedidx]).size();
|
||||
bb.max.x() = scaled(std::ceil(pilesz.x() / piecesz.x()) * piecesz.x());
|
||||
bb.max.y() = scaled(std::ceil(pilesz.y() / piecesz.y()) * piecesz.y());
|
||||
coord_t offs = params.min_bed_distance;
|
||||
switch (params.alignment) {
|
||||
case Pivots::BottomLeft:
|
||||
bb.translate((bed.bb.min - bb.min) + Point{offs, offs});
|
||||
break;
|
||||
case Pivots::TopRight:
|
||||
bb.translate((bed.bb.max - bb.max) - Point{offs, offs});
|
||||
break;
|
||||
case Pivots::BottomRight: {
|
||||
Point bedref{bed.bb.max.x(), bed.bb.min.y()};
|
||||
Point bbref {bb.max.x(), bb.min.y()};
|
||||
bb.translate((bedref - bbref) + Point{-offs, offs});
|
||||
break;
|
||||
}
|
||||
case Pivots::TopLeft: {
|
||||
Point bedref{bed.bb.min.x(), bed.bb.max.y()};
|
||||
Point bbref {bb.min.x(), bb.max.y()};
|
||||
bb.translate((bedref - bbref) + Point{offs, -offs});
|
||||
break;
|
||||
}
|
||||
case Pivots::Center: {
|
||||
bb.translate(bed.bb.center() - bb.center());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Vec2crd d = bb.center() - pilebb[bedidx].center();
|
||||
|
||||
for (auto &itm : items)
|
||||
if (itm.bed_idx == bedidx)
|
||||
itm.translation += d;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace arr
|
||||
} // namespace Slic3r
|
||||
|
@ -3,12 +3,25 @@
|
||||
|
||||
#include "ExPolygon.hpp"
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <libslic3r/BoundingBox.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class BoundingBox;
|
||||
|
||||
namespace arrangement {
|
||||
|
||||
/// Representing an unbounded bed.
|
||||
struct InfiniteBed {
|
||||
Point center;
|
||||
explicit InfiniteBed(const Point &p = {0, 0}): center{p} {}
|
||||
};
|
||||
|
||||
struct RectangleBed {
|
||||
BoundingBox bb;
|
||||
};
|
||||
|
||||
/// A geometry abstraction for a circular print bed. Similarly to BoundingBox.
|
||||
class CircleBed {
|
||||
Point center_;
|
||||
@ -22,12 +35,28 @@ public:
|
||||
inline const Point& center() const { return center_; }
|
||||
};
|
||||
|
||||
/// Representing an unbounded bed.
|
||||
struct InfiniteBed {
|
||||
Point center;
|
||||
explicit InfiniteBed(const Point &p = {0, 0}): center{p} {}
|
||||
struct SegmentedRectangleBed {
|
||||
Vec<2, size_t> segments;
|
||||
BoundingBox bb;
|
||||
|
||||
SegmentedRectangleBed (const BoundingBox &bb,
|
||||
size_t segments_x,
|
||||
size_t segments_y)
|
||||
: segments{segments_x, segments_y}
|
||||
, bb{bb}
|
||||
{}
|
||||
};
|
||||
|
||||
struct IrregularBed {
|
||||
ExPolygon poly;
|
||||
};
|
||||
|
||||
//enum BedType { Infinite, Rectangle, Circle, SegmentedRectangle, Irregular };
|
||||
|
||||
using ArrangeBed = boost::variant<InfiniteBed, RectangleBed, CircleBed, SegmentedRectangleBed, IrregularBed>;
|
||||
|
||||
ArrangeBed to_arrange_bed(const Points &bedpts);
|
||||
|
||||
/// A logical bed representing an object not being arranged. Either the arrange
|
||||
/// has not yet successfully run on this ArrangePolygon or it could not fit the
|
||||
/// object due to overly large size or invalid geometry.
|
||||
@ -75,6 +104,10 @@ struct ArrangePolygon {
|
||||
|
||||
using ArrangePolygons = std::vector<ArrangePolygon>;
|
||||
|
||||
enum class Pivots {
|
||||
Center, TopLeft, BottomLeft, BottomRight, TopRight
|
||||
};
|
||||
|
||||
struct ArrangeParams {
|
||||
|
||||
/// The minimum distance which is allowed for any
|
||||
@ -93,6 +126,12 @@ struct ArrangeParams {
|
||||
|
||||
bool allow_rotations = false;
|
||||
|
||||
/// Final alignment of the merged pile after arrangement
|
||||
Pivots alignment = Pivots::Center;
|
||||
|
||||
/// Starting position hint for the arrangement
|
||||
Pivots starting_point = Pivots::Center;
|
||||
|
||||
/// Progress indicator callback called when an object gets packed.
|
||||
/// The unsigned argument is the number of items remaining to pack.
|
||||
std::function<void(unsigned)> progressind;
|
||||
@ -127,12 +166,32 @@ extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excl
|
||||
extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const Polygon &bed, const ArrangeParams ¶ms);
|
||||
extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const InfiniteBed &bed, const ArrangeParams ¶ms);
|
||||
|
||||
inline void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const RectangleBed &bed, const ArrangeParams ¶ms)
|
||||
{
|
||||
arrange(items, excludes, bed.bb, params);
|
||||
}
|
||||
|
||||
inline void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const IrregularBed &bed, const ArrangeParams ¶ms)
|
||||
{
|
||||
arrange(items, excludes, bed.poly.contour, params);
|
||||
}
|
||||
|
||||
void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const SegmentedRectangleBed &bed, const ArrangeParams ¶ms);
|
||||
|
||||
inline void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const ArrangeBed &bed, const ArrangeParams ¶ms)
|
||||
{
|
||||
auto call_arrange = [&](const auto &realbed) { arrange(items, excludes, realbed, params); };
|
||||
boost::apply_visitor(call_arrange, bed);
|
||||
}
|
||||
|
||||
inline void arrange(ArrangePolygons &items, const Points &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); }
|
||||
inline void arrange(ArrangePolygons &items, const BoundingBox &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); }
|
||||
inline void arrange(ArrangePolygons &items, const CircleBed &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); }
|
||||
inline void arrange(ArrangePolygons &items, const Polygon &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); }
|
||||
inline void arrange(ArrangePolygons &items, const InfiniteBed &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); }
|
||||
|
||||
bool is_box(const Points &bed);
|
||||
|
||||
}} // namespace Slic3r::arrangement
|
||||
|
||||
#endif // MODELARRANGE_HPP
|
||||
|
@ -235,9 +235,18 @@ inline bool empty(const BoundingBox3Base<VT> &bb)
|
||||
}
|
||||
|
||||
inline BoundingBox scaled(const BoundingBoxf &bb) { return {scaled(bb.min), scaled(bb.max)}; }
|
||||
inline BoundingBox3 scaled(const BoundingBoxf3 &bb) { return {scaled(bb.min), scaled(bb.max)}; }
|
||||
inline BoundingBoxf unscaled(const BoundingBox &bb) { return {unscaled(bb.min), unscaled(bb.max)}; }
|
||||
inline BoundingBoxf3 unscaled(const BoundingBox3 &bb) { return {unscaled(bb.min), unscaled(bb.max)}; }
|
||||
|
||||
template<class T = coord_t>
|
||||
BoundingBoxBase<Vec<2, T>> scaled(const BoundingBoxf &bb) { return {scaled<T>(bb.min), scaled<T>(bb.max)}; }
|
||||
|
||||
template<class T = coord_t>
|
||||
BoundingBox3Base<Vec<3, T>> scaled(const BoundingBoxf3 &bb) { return {scaled<T>(bb.min), scaled<T>(bb.max)}; }
|
||||
|
||||
template<class T = double>
|
||||
BoundingBoxBase<Vec<2, T>> unscaled(const BoundingBox &bb) { return {unscaled<T>(bb.min), unscaled<T>(bb.max)}; }
|
||||
|
||||
template<class T = double>
|
||||
BoundingBox3Base<Vec<3, T>> unscaled(const BoundingBox3 &bb) { return {unscaled<T>(bb.min), unscaled<T>(bb.max)}; }
|
||||
|
||||
template<class Tout, class Tin>
|
||||
auto cast(const BoundingBoxBase<Tin> &b)
|
||||
|
@ -4822,6 +4822,15 @@ Points get_bed_shape(const DynamicPrintConfig &config)
|
||||
return to_points(bed_shape_opt->values);
|
||||
}
|
||||
|
||||
void get_bed_shape(const DynamicPrintConfig &cfg, arrangement::ArrangeBed &out)
|
||||
{
|
||||
if (is_XL_printer(cfg)) {
|
||||
out = arrangement::SegmentedRectangleBed{get_extents(get_bed_shape(cfg)), 4, 4};
|
||||
} else {
|
||||
out = arrangement::to_arrange_bed(get_bed_shape(cfg));
|
||||
}
|
||||
}
|
||||
|
||||
Points get_bed_shape(const PrintConfig &cfg)
|
||||
{
|
||||
return to_points(cfg.bed_shape.values);
|
||||
@ -4846,6 +4855,20 @@ std::string get_sla_suptree_prefix(const DynamicPrintConfig &config)
|
||||
return slatree;
|
||||
}
|
||||
|
||||
bool is_XL_printer(const DynamicPrintConfig &cfg)
|
||||
{
|
||||
static constexpr const char *ALIGN_ONLY_FOR = "XL";
|
||||
|
||||
bool ret = false;
|
||||
|
||||
auto *printer_model = cfg.opt<ConfigOptionString>("printer_model");
|
||||
|
||||
if (printer_model)
|
||||
ret = boost::algorithm::contains(printer_model->value, ALIGN_ONLY_FOR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#include <cereal/types/polymorphic.hpp>
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "libslic3r.h"
|
||||
#include "Config.hpp"
|
||||
#include "SLA/SupportTreeStrategies.hpp"
|
||||
#include "libslic3r/Arrange.hpp"
|
||||
|
||||
#include <boost/preprocessor/facilities/empty.hpp>
|
||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||
@ -1185,10 +1186,14 @@ private:
|
||||
static PrintAndCLIConfigDef s_def;
|
||||
};
|
||||
|
||||
bool is_XL_printer(const DynamicPrintConfig &cfg);
|
||||
|
||||
Points get_bed_shape(const DynamicPrintConfig &cfg);
|
||||
Points get_bed_shape(const PrintConfig &cfg);
|
||||
Points get_bed_shape(const SLAPrinterConfig &cfg);
|
||||
|
||||
void get_bed_shape(const DynamicPrintConfig &cfg, arrangement::ArrangeBed &out);
|
||||
|
||||
std::string get_sla_suptree_prefix(const DynamicPrintConfig &config);
|
||||
|
||||
// ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp.
|
||||
|
@ -999,6 +999,19 @@ void GLCanvas3D::load_arrange_settings()
|
||||
std::string en_rot_sla_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_sla");
|
||||
|
||||
// std::string alignment_fff_str =
|
||||
// wxGetApp().app_config->get("arrange", "alignment_fff");
|
||||
|
||||
// std::string alignment_fff_seqp_str =
|
||||
// wxGetApp().app_config->get("arrange", "alignment_fff_seq_pring");
|
||||
|
||||
// std::string alignment_sla_str =
|
||||
// wxGetApp().app_config->get("arrange", "alignment_sla");
|
||||
|
||||
// Override default alignment and save save/load it to a temporary slot "alignment_xl"
|
||||
std::string alignment_xl_str =
|
||||
wxGetApp().app_config->get("arrange", "alignment_xl");
|
||||
|
||||
if (!dist_fff_str.empty())
|
||||
m_arrange_settings_fff.distance = string_to_float_decimal_point(dist_fff_str);
|
||||
|
||||
@ -1025,6 +1038,24 @@ void GLCanvas3D::load_arrange_settings()
|
||||
|
||||
if (!en_rot_sla_str.empty())
|
||||
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "yes");
|
||||
|
||||
// if (!alignment_sla_str.empty())
|
||||
// m_arrange_settings_sla.alignment = std::stoi(alignment_sla_str);
|
||||
|
||||
// if (!alignment_fff_str.empty())
|
||||
// m_arrange_settings_fff.alignment = std::stoi(alignment_fff_str);
|
||||
|
||||
// if (!alignment_fff_seqp_str.empty())
|
||||
// m_arrange_settings_fff_seq_print.alignment = std::stoi(alignment_fff_seqp_str);
|
||||
|
||||
// Override default alignment and save save/load it to a temporary slot "alignment_xl"
|
||||
int arr_alignment = static_cast<int>(arrangement::Pivots::BottomLeft);
|
||||
if (!alignment_xl_str.empty())
|
||||
arr_alignment = std::stoi(alignment_xl_str);
|
||||
|
||||
m_arrange_settings_sla.alignment = arr_alignment ;
|
||||
m_arrange_settings_fff.alignment = arr_alignment ;
|
||||
m_arrange_settings_fff_seq_print.alignment = arr_alignment ;
|
||||
}
|
||||
|
||||
PrinterTechnology GLCanvas3D::current_printer_technology() const
|
||||
@ -1032,6 +1063,11 @@ PrinterTechnology GLCanvas3D::current_printer_technology() const
|
||||
return m_process->current_printer_technology();
|
||||
}
|
||||
|
||||
bool GLCanvas3D::is_arrange_alignment_enabled() const
|
||||
{
|
||||
return m_config ? is_XL_printer(*m_config) : false;
|
||||
}
|
||||
|
||||
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||
: m_canvas(canvas)
|
||||
, m_context(nullptr)
|
||||
@ -4160,7 +4196,7 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
||||
imgui->begin(_L("Arrange options"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
ArrangeSettings settings = get_arrange_settings();
|
||||
ArrangeSettings &settings_out = get_arrange_settings();
|
||||
ArrangeSettings &settings_out = get_arrange_settings_ref(this);
|
||||
|
||||
auto &appcfg = wxGetApp().app_config;
|
||||
PrinterTechnology ptech = current_printer_technology();
|
||||
@ -4171,6 +4207,7 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
||||
std::string dist_key = "min_object_distance";
|
||||
std::string dist_bed_key = "min_bed_distance";
|
||||
std::string rot_key = "enable_rotation";
|
||||
std::string align_key = "alignment";
|
||||
std::string postfix;
|
||||
|
||||
if (ptech == ptSLA) {
|
||||
@ -4189,6 +4226,7 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
||||
dist_key += postfix;
|
||||
dist_bed_key += postfix;
|
||||
rot_key += postfix;
|
||||
align_key += postfix;
|
||||
|
||||
imgui->text(GUI::format_wxstr(_L("Press %1%left mouse button to enter the exact value"), shortkey_ctrl_prefix()));
|
||||
|
||||
@ -4212,11 +4250,28 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
Points bed = m_config ? get_bed_shape(*m_config) : Points{};
|
||||
|
||||
if (arrangement::is_box(bed) && settings.alignment >= 0 &&
|
||||
imgui->combo(_L("Alignment"), {_u8L("Center"), _u8L("Rear left"), _u8L("Front left"), _u8L("Front right"), _u8L("Rear right"), _u8L("Random") }, settings.alignment)) {
|
||||
settings_out.alignment = settings.alignment;
|
||||
appcfg->set("arrange", align_key.c_str(), std::to_string(settings_out.alignment));
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (imgui->button(_L("Reset"))) {
|
||||
auto alignment = settings_out.alignment;
|
||||
settings_out = ArrangeSettings{};
|
||||
settings_out.distance = std::max(dist_min, settings_out.distance);
|
||||
|
||||
// Default alignment for XL printers set explicitly:
|
||||
if (is_arrange_alignment_enabled())
|
||||
settings_out.alignment = static_cast<int>(arrangement::Pivots::BottomLeft);
|
||||
else
|
||||
settings_out.alignment = alignment;
|
||||
|
||||
appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance));
|
||||
appcfg->set("arrange", dist_bed_key.c_str(), float_to_string_decimal_point(settings_out.distance_from_bed));
|
||||
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0");
|
||||
|
@ -463,6 +463,7 @@ public:
|
||||
// float distance_sla = 6.;
|
||||
float accuracy = 0.65f; // Unused currently
|
||||
bool enable_rotation = false;
|
||||
int alignment = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
@ -549,8 +550,10 @@ private:
|
||||
|
||||
PrinterTechnology current_printer_technology() const;
|
||||
|
||||
bool is_arrange_alignment_enabled() const;
|
||||
|
||||
template<class Self>
|
||||
static auto & get_arrange_settings(Self *self) {
|
||||
static auto & get_arrange_settings_ref(Self *self) {
|
||||
PrinterTechnology ptech = self->current_printer_technology();
|
||||
|
||||
auto *ptr = &self->m_arrange_settings_fff;
|
||||
@ -568,8 +571,22 @@ private:
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
ArrangeSettings &get_arrange_settings() { return get_arrange_settings(this); }
|
||||
public:
|
||||
ArrangeSettings get_arrange_settings() const {
|
||||
const ArrangeSettings &settings = get_arrange_settings_ref(this);
|
||||
ArrangeSettings ret = settings;
|
||||
if (&settings == &m_arrange_settings_fff_seq_print) {
|
||||
ret.distance = std::max(ret.distance,
|
||||
float(min_object_distance(*m_config)));
|
||||
}
|
||||
|
||||
if (!is_arrange_alignment_enabled())
|
||||
ret.alignment = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
void load_arrange_settings();
|
||||
|
||||
class SequentialPrintClearance
|
||||
@ -901,17 +918,6 @@ public:
|
||||
void highlight_toolbar_item(const std::string& item_name);
|
||||
void highlight_gizmo(const std::string& gizmo_name);
|
||||
|
||||
ArrangeSettings get_arrange_settings() const {
|
||||
const ArrangeSettings &settings = get_arrange_settings(this);
|
||||
ArrangeSettings ret = settings;
|
||||
if (&settings == &m_arrange_settings_fff_seq_print) {
|
||||
ret.distance = std::max(ret.distance,
|
||||
float(min_object_distance(*m_config)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Timestamp for FPS calculation and notification fade-outs.
|
||||
static int64_t timestamp_now() {
|
||||
#ifdef _WIN32
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "libnest2d/common.hpp"
|
||||
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@ -168,11 +169,11 @@ void ArrangeJob::process(Ctl &ctl)
|
||||
static const auto arrangestr = _u8L("Arranging");
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
Points bedpts;
|
||||
ctl.call_on_main_thread([this, ¶ms, &bedpts]{
|
||||
arrangement::ArrangeBed bed;
|
||||
ctl.call_on_main_thread([this, ¶ms, &bed]{
|
||||
prepare();
|
||||
params = get_arrange_params(m_plater);
|
||||
bedpts = get_bed_shape(*m_plater->config());
|
||||
get_bed_shape(*m_plater->config(), bed);
|
||||
}).wait();
|
||||
|
||||
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
||||
@ -191,13 +192,13 @@ void ArrangeJob::process(Ctl &ctl)
|
||||
|
||||
ctl.update_status(0, arrangestr);
|
||||
|
||||
arrangement::arrange(m_selected, m_unselected, bedpts, params);
|
||||
arrangement::arrange(m_selected, m_unselected, bed, params);
|
||||
|
||||
params.progressind = [this, count, &ctl](unsigned st) {
|
||||
if (st > 0) ctl.update_status(int(count - st) * 100 / status_range(), arrangestr);
|
||||
};
|
||||
|
||||
arrangement::arrange(m_unprintable, {}, bedpts, params);
|
||||
arrangement::arrange(m_unprintable, {}, bed, params);
|
||||
|
||||
// finalize just here.
|
||||
ctl.update_status(int(count) * 100 / status_range(), ctl.was_canceled() ?
|
||||
@ -291,13 +292,30 @@ arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst,
|
||||
arrangement::ArrangeParams get_arrange_params(Plater *p)
|
||||
{
|
||||
const GLCanvas3D::ArrangeSettings &settings =
|
||||
static_cast<const GLCanvas3D*>(p->canvas3D())->get_arrange_settings();
|
||||
p->canvas3D()->get_arrange_settings();
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
params.allow_rotations = settings.enable_rotation;
|
||||
params.min_obj_distance = scaled(settings.distance);
|
||||
params.min_bed_distance = scaled(settings.distance_from_bed);
|
||||
|
||||
arrangement::Pivots pivot = arrangement::Pivots::Center;
|
||||
|
||||
int pivot_max = static_cast<int>(arrangement::Pivots::TopRight);
|
||||
if (settings.alignment < 0) {
|
||||
pivot = arrangement::Pivots::Center;
|
||||
} else if (settings.alignment > pivot_max) {
|
||||
// means it should be random
|
||||
std::random_device rd{};
|
||||
std::mt19937 rng(rd());
|
||||
std::uniform_int_distribution<std::mt19937::result_type> dist(0, pivot_max);
|
||||
pivot = static_cast<arrangement::Pivots>(dist(rng));
|
||||
} else {
|
||||
pivot = static_cast<arrangement::Pivots>(settings.alignment);
|
||||
}
|
||||
|
||||
params.alignment = pivot;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -106,18 +106,15 @@ void FillBedJob::prepare()
|
||||
void FillBedJob::process(Ctl &ctl)
|
||||
{
|
||||
auto statustxt = _u8L("Filling bed");
|
||||
ctl.call_on_main_thread([this] { prepare(); }).wait();
|
||||
arrangement::ArrangeParams params;
|
||||
ctl.call_on_main_thread([this, ¶ms] {
|
||||
prepare();
|
||||
params = get_arrange_params(m_plater);
|
||||
}).wait();
|
||||
ctl.update_status(0, statustxt);
|
||||
|
||||
if (m_object_idx == -1 || m_selected.empty()) return;
|
||||
|
||||
const GLCanvas3D::ArrangeSettings &settings =
|
||||
static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
params.allow_rotations = settings.enable_rotation;
|
||||
params.min_obj_distance = scaled(settings.distance);
|
||||
params.min_bed_distance = scaled(settings.distance_from_bed);
|
||||
if (m_object_idx == -1 || m_selected.empty())
|
||||
return;
|
||||
|
||||
bool do_stop = false;
|
||||
params.stopcondition = [&ctl, &do_stop]() {
|
||||
|
Loading…
Reference in New Issue
Block a user