From 29d393ec9c9d240b39ae72c510cc34e018f5ac5d Mon Sep 17 00:00:00 2001 From: supermerill Date: Sun, 22 Nov 2020 01:56:52 +0100 Subject: [PATCH] update to arrange: a little bit more sane (but need more work) also calibration can now use arrange if needed --- src/PrusaSlicer.cpp | 12 ++- src/libslic3r/Model.cpp | 59 +++------------ src/libslic3r/Model.hpp | 2 +- src/libslic3r/ModelArrange.cpp | 8 +- src/libslic3r/ModelArrange.hpp | 19 ++--- src/libslic3r/Print.cpp | 73 +++++++++++-------- src/libslic3r/PrintConfig.cpp | 24 ++++-- src/slic3r/GUI/CalibrationAbstractDialog.hpp | 13 ++++ src/slic3r/GUI/CalibrationBridgeDialog.cpp | 17 ++++- src/slic3r/GUI/CalibrationFlowDialog.cpp | 17 ++++- .../GUI/CalibrationOverBridgeDialog.cpp | 17 ++++- .../GUI/CalibrationRetractionDialog.cpp | 24 ++++-- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 16 ++-- src/slic3r/GUI/Jobs/ArrangeJob.hpp | 11 ++- src/slic3r/GUI/Plater.cpp | 2 +- 15 files changed, 185 insertions(+), 129 deletions(-) diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index fd4438604..b786b08eb 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -232,8 +232,6 @@ int CLI::run(int argc, char **argv) // Loop through transform options. bool user_center_specified = false; Points bed = get_bed_shape(m_print_config); - ArrangeParams arrange_cfg; - arrange_cfg.min_obj_distance = scaled(PrintConfig::min_object_distance(&m_print_config)); int dups = 1; for (auto const &opt_key : m_transforms) { @@ -467,13 +465,13 @@ int CLI::run(int argc, char **argv) PrintBase *print = (printer_technology == ptFFF) ? static_cast(&fff_print) : static_cast(&sla_print); - if (! m_config.opt_bool("dont_arrange")) { - print->apply(model, m_print_config); // arrange_objects needs that the print has the config + ArrangeParams arrange_cfg; + arrange_cfg.min_obj_distance = scaled(PrintConfig::min_object_distance(&m_print_config)) * 2; if (dups > 1) { try { // if all input objects have defined position(s) apply duplication to the whole model - duplicate(print, model, size_t(dups), bed, arrange_cfg); + duplicate(model, size_t(dups), bed, arrange_cfg); } catch (std::exception & ex) { boost::nowide::cerr << "error: " << ex.what() << std::endl; return 1; @@ -481,9 +479,9 @@ int CLI::run(int argc, char **argv) } if (user_center_specified) { Vec2d c = m_config.option("center")->value; - arrange_objects(print, model, InfiniteBed{scaled(c)}, arrange_cfg); + arrange_objects(model, InfiniteBed{scaled(c)}, arrange_cfg); } else - arrange_objects(print, model, bed, arrange_cfg); + arrange_objects(model, bed, arrange_cfg); } if (printer_technology == ptFFF) { for (auto* mo : model.objects) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d0ee56082..747b3f5e2 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1855,15 +1855,16 @@ void ModelInstance::transform_polygon(Polygon* polygon) const polygon->scale(get_scaling_factor(X), get_scaling_factor(Y)); // scale around polygon origin } -arrangement::ArrangePolygon ModelInstance::get_arrange_polygon(const PrintBase *print_base) const + +arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const { static const double SIMPLIFY_TOLERANCE_MM = 0.1; - + Vec3d rotation = get_rotation(); - rotation.z() = 0.; + rotation.z() = 0.; Transform3d trafo_instance = Geometry::assemble_transform(Vec3d::Zero(), rotation, - get_scaling_factor(), get_mirror()); + get_scaling_factor(), get_mirror()); Polygon p = get_object()->convex_hull_2d(trafo_instance); @@ -1872,59 +1873,19 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon(const PrintBase * // this may happen for malformed models, see: // https://github.com/prusa3d/PrusaSlicer/issues/2209 if (!p.points.empty()) { - Polygons pp{p}; - if (const Print* print = dynamic_cast(print_base)) - { - //grow - double dist = print->config().min_object_distance(&print->full_print_config()); - pp = offset(pp, scale_(dist)); - //simplify - if (!pp.empty()) - pp = pp.front().simplify(scaled(SIMPLIFY_TOLERANCE_MM)); - }else - pp = p.simplify(scaled(SIMPLIFY_TOLERANCE_MM)); + Polygons pp{ p }; + pp = p.simplify(scaled(SIMPLIFY_TOLERANCE_MM)); if (!pp.empty()) p = pp.front(); } - + arrangement::ArrangePolygon ret; ret.poly.contour = std::move(p); - ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))}; - ret.rotation = get_rotation(Z); + ret.translation = Vec2crd{ scaled(get_offset(X)), scaled(get_offset(Y)) }; + ret.rotation = get_rotation(Z); return ret; } -// -//arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const -//{ -// static const double SIMPLIFY_TOLERANCE_MM = 0.1; -// -// Vec3d rotation = get_rotation(); -// rotation.z() = 0.; -// Transform3d trafo_instance = -// Geometry::assemble_transform(Vec3d::Zero(), rotation, -// get_scaling_factor(), get_mirror()); -// -// Polygon p = get_object()->convex_hull_2d(trafo_instance); -// -// assert(!p.points.empty()); -// -// // this may happen for malformed models, see: -// // https://github.com/prusa3d/PrusaSlicer/issues/2209 -// if (!p.points.empty()) { -// Polygons pp{ p }; -// pp = p.simplify(scaled(SIMPLIFY_TOLERANCE_MM)); -// if (!pp.empty()) p = pp.front(); -// } -// -// arrangement::ArrangePolygon ret; -// ret.poly.contour = std::move(p); -// ret.translation = Vec2crd{ scaled(get_offset(X)), scaled(get_offset(Y)) }; -// ret.rotation = get_rotation(Z); -// -// return ret; -//} - indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const { TriangleSelector selector(mv.mesh()); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 36eea8b72..28a39b454 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -874,7 +874,7 @@ public: bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); } // Getting the input polygon for arrange - arrangement::ArrangePolygon get_arrange_polygon(const PrintBase* print) const; + arrangement::ArrangePolygon get_arrange_polygon() const; // Apply the arrange result on the ModelInstance void apply_arrange_result(const Vec2d& offs, double rotation) diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index f1d1944d7..230b04de5 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -5,7 +5,7 @@ namespace Slic3r { -arrangement::ArrangePolygons get_arrange_polys(const PrintBase* print, const Model &model, ModelInstancePtrs &instances) +arrangement::ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances) { size_t count = 0; for (auto obj : model.objects) count += obj->instances.size(); @@ -15,7 +15,7 @@ arrangement::ArrangePolygons get_arrange_polys(const PrintBase* print, const Mod instances.clear(); instances.reserve(count); for (ModelObject *mo : model.objects) for (ModelInstance *minst : mo->instances) { - input.emplace_back(minst->get_arrange_polygon(print)); + input.emplace_back(minst->get_arrange_polygon()); instances.emplace_back(minst); } @@ -36,13 +36,13 @@ bool apply_arrange_polys(ArrangePolygons &input, ModelInstancePtrs &instances, V return ret; } -Slic3r::arrangement::ArrangePolygon get_arrange_poly(const PrintBase* print, const Model &model) +Slic3r::arrangement::ArrangePolygon get_arrange_poly(const Model &model) { ArrangePolygon ap; Points &apts = ap.poly.contour.points; for (const ModelObject *mo : model.objects) for (const ModelInstance *minst : mo->instances) { - ArrangePolygon obj_ap = minst->get_arrange_polygon(print); + ArrangePolygon obj_ap = minst->get_arrange_polygon(); ap.poly.contour.rotate(obj_ap.rotation); ap.poly.contour.translate(obj_ap.translation.x(), obj_ap.translation.y()); const Points &pts = obj_ap.poly.contour.points; diff --git a/src/libslic3r/ModelArrange.hpp b/src/libslic3r/ModelArrange.hpp index 36a2696c0..f052716f2 100644 --- a/src/libslic3r/ModelArrange.hpp +++ b/src/libslic3r/ModelArrange.hpp @@ -24,50 +24,47 @@ using VirtualBedFn = std::function; throw Slic3r::RuntimeError("Objects could not fit on the bed"); } -ArrangePolygons get_arrange_polys(const PrintBase* print, const Model &model, ModelInstancePtrs &instances); -ArrangePolygon get_arrange_poly(const PrintBase* print, const Model &model); +ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances); +ArrangePolygon get_arrange_poly(const Model &model); bool apply_arrange_polys(ArrangePolygons &polys, ModelInstancePtrs &instances, VirtualBedFn); void duplicate(Model &model, ArrangePolygons &copies, VirtualBedFn); void duplicate_objects(Model &model, size_t copies_num); template -bool arrange_objects(PrintBase* print, - Model & model, +bool arrange_objects(Model & model, const TBed & bed, const ArrangeParams ¶ms, VirtualBedFn vfn = throw_if_out_of_bed) { ModelInstancePtrs instances; - ArrangePolygons input = get_arrange_polys(print, model, instances); + ArrangePolygons input = get_arrange_polys(model, instances); arrangement::arrange(input, bed, params); return apply_arrange_polys(input, instances, vfn); } template -void duplicate(PrintBase* print, - Model & model, +void duplicate(Model & model, size_t copies_num, const TBed & bed, const ArrangeParams ¶ms, VirtualBedFn vfn = throw_if_out_of_bed) { - ArrangePolygons copies(copies_num, get_arrange_poly(print, model)); + ArrangePolygons copies(copies_num, get_arrange_poly(model)); arrangement::arrange(copies, bed, params); duplicate(model, copies, vfn); } template -void duplicate_objects(PrintBase* print, - Model & model, +void duplicate_objects(Model & model, size_t copies_num, const TBed & bed, const ArrangeParams ¶ms, VirtualBedFn vfn = throw_if_out_of_bed) { duplicate_objects(model, copies_num); - arrange_objects(print, model, bed, params, vfn); + arrange_objects(model, bed, params, vfn); } } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 1c8bddbe5..03dfdabf7 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1259,35 +1259,49 @@ bool Print::has_skirt() const static inline bool sequential_print_horizontal_clearance_valid(const Print &print) { Polygons convex_hulls_other; - //std::map map_model_object_to_convex_hull; + std::map map_model_object_to_convex_hull; for (const PrintObject *print_object : print.objects()) { + double dist_grow = PrintConfig::min_object_distance(&print_object->config()); assert(! print_object->model_object()->instances.empty()); assert(! print_object->instances().empty()); - //ObjectID model_object_id = print_object->model_object()->id(); - //auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id); + ObjectID model_object_id = print_object->model_object()->id(); + auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id); // Get convex hull of all printable volumes assigned to this print object. - // ModelInstance *model_instance0 = print_object->model_object()->instances.front(); - // if (it_convex_hull == map_model_object_to_convex_hull.end()) { - // // Calculate the convex hull of a printable object. - // // Grow convex hull with the clearance margin. - // // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2) - // // which causes that the warning will be showed after arrangement with the - // // appropriate object distance. Even if I set this to jtMiter the warning still shows up. - // it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id, - // offset(print_object->model_object()->convex_hull_2d( - // Geometry::assemble_transform(Vec3d::Zero(), model_instance0->get_rotation(), model_instance0->get_scaling_factor(), model_instance0->get_mirror())), - // // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects - // // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. - // float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)), - // jtRound, float(scale_(0.1))).front()); - // } - // // Make a copy, so it may be rotated for instances. - // //FIXME seems like the rotation isn't taken into account - // Polygon convex_hull0 = it_convex_hull->second; - // //this can create bugs in macos, for reasons. - //double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation()); - //if (std::abs(z_diff) > EPSILON) - // convex_hull0.rotate(z_diff); + ModelInstance *model_instance0 = print_object->model_object()->instances.front(); + if (it_convex_hull == map_model_object_to_convex_hull.end()) { + // Calculate the convex hull of a printable object. + // Grow convex hull with the clearance margin. + // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2) + // which causes that the warning will be showed after arrangement with the + // appropriate object distance. Even if I set this to jtMiter the warning still shows up. + it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id, + offset(print_object->model_object()->convex_hull_2d( + Geometry::assemble_transform(Vec3d::Zero(), model_instance0->get_rotation(), model_instance0->get_scaling_factor(), model_instance0->get_mirror())), + // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects + // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. + float(scale_(0.5 * dist_grow - EPSILON)), + jtRound, float(scale_(0.1))).front()); + } + // Make a copy, so it may be rotated for instances. + //FIXME seems like the rotation isn't taken into account + Polygon convex_hull0 = it_convex_hull->second; + //this can create bugs in macos, for reasons. + double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation()); + if (std::abs(z_diff) > EPSILON) + convex_hull0.rotate(z_diff); + // Now we check that no instance of convex_hull intersects any of the previously checked object instances. + for (const PrintInstance& instance : print_object->instances()) { + Polygon convex_hull = convex_hull0; + // instance.shift is a position of a centered object, while model object may not be centered. + // Conver the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset. + convex_hull.translate(instance.shift - print_object->center_offset()); + if (!intersection(convex_hulls_other, convex_hull).empty()) + return false; + polygons_append(convex_hulls_other, convex_hull); + } + + /* + 'old' superslicer sequential_print_horizontal_clearance_valid, that is better at skirts, but need some works, as the arrange has changed. // Now we check that no instance of convex_hull intersects any of the previously checked object instances. for (const PrintInstance &instance : print_object->instances()) { Polygons convex_hull = print_object->model_object()->convex_hull_2d( @@ -1295,8 +1309,8 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin instance.model_instance->get_rotation(), instance.model_instance->get_scaling_factor(), instance.model_instance->get_mirror())); // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. - /*float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)), - jtRound, float(scale_(0.1)));*/ + //float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)), + //jtRound, float(scale_(0.1))); if (convex_hull.empty()) continue; // instance.shift is a position of a centered object, while model object may not be centered. @@ -1305,13 +1319,14 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin poly.translate(instance.shift - print_object->center_offset()); if (! intersection( convex_hulls_other, - offset(convex_hull[0], double(scale_(print.config().min_object_distance(&instance.print_object->config(),0.)) - SCALED_EPSILON), jtRound, scale_(0.1))).empty()) + offset(convex_hull[0], double(scale_(PrintConfig::min_object_distance(&instance.print_object->config(),0.)) - SCALED_EPSILON), jtRound, scale_(0.1))).empty()) return false; - double extra_grow = print.config().min_object_distance(&instance.print_object->config(), 1.); + double extra_grow = PrintConfig::min_object_distance(&instance.print_object->config(), 1.); if (extra_grow > 0) convex_hull = offset(convex_hull, scale_(extra_grow)); polygons_append(convex_hulls_other, convex_hull); } + */ } return true; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 46a74bad6..bca4793e3 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5205,8 +5205,9 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei //test if called from usaslicer::l240 where it's called on an empty config... if (dd_opt == nullptr) return 0; - double duplicate_distance = dd_opt->value; - double base_dist = duplicate_distance / 2; + // /2 becasue we only count the grawing for the current object + const double duplicate_distance = dd_opt->value / 2; + double base_dist = duplicate_distance; //std::cout << "START min_object_distance =>" << base_dist << "\n"; const ConfigOptionBool* co_opt = config->option("complete_objects"); if (co_opt && co_opt->value) { @@ -5218,24 +5219,35 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei for (double val : vals) max_nozzle_diam = std::fmax(max_nozzle_diam, val); // min object distance is max(duplicate_distance, clearance_radius) + // /2 becasue we only count the grawing for the current object //add 1 as safety offset. - double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat(); + double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat() / 2 + 1; if (extruder_clearance_radius > base_dist) { - base_dist = extruder_clearance_radius / 2; + base_dist = extruder_clearance_radius; } //std::cout << " min_object_distance add extruder_clearance_radius ("<< extruder_clearance_radius <<") =>" << base_dist << "\n"; + //FIXME: now brim can be per-object, so you ahve to get a different min_object_distance per object //add brim width const double first_layer_height = config->get_abs_value("first_layer_height"); - if (ref_height <= first_layer_height) { + if (ref_height <= first_layer_height && ref_height != 0) { //FIXME: does not take into account object-defined brim !!! you can crash yoursefl with it if (config->option("brim_width")->getFloat() > 0) { brim_dist += config->option("brim_width")->getFloat(); //std::cout << " Set brim=" << config->option("brim_width")->getFloat() << " => " << brim_dist << "\n"; } + } else if (config->option("brim_width")->getFloat() + 1 > base_dist) { + base_dist = config->option("brim_width")->getFloat(); } //add the skirt - if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() > 0 && !config->option("complete_objects_one_skirt")->getBool()) { + if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() == 1 && ref_height == 0) { + skirt_dist = config->option("skirt_distance")->getFloat(); + const double first_layer_width = config->get_abs_value("first_layer_extrusion_width"); + Flow flow(first_layer_width, first_layer_height, max_nozzle_diam); + skirt_dist += first_layer_width + (flow.spacing() * ((double)config->option("skirts")->getInt() - 1)); + base_dist = std::max(base_dist, skirt_dist + 1); + skirt_dist = 0; + }else if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() > 0 && !config->option("complete_objects_one_skirt")->getBool()) { double skirt_height = ((double)config->option("skirt_height")->getInt() - 1) * config->get_abs_value("layer_height") + first_layer_height; if (ref_height <= skirt_height) { skirt_dist = config->option("skirt_distance")->getFloat(); diff --git a/src/slic3r/GUI/CalibrationAbstractDialog.hpp b/src/slic3r/GUI/CalibrationAbstractDialog.hpp index f5320444e..a6e87dec8 100644 --- a/src/slic3r/GUI/CalibrationAbstractDialog.hpp +++ b/src/slic3r/GUI/CalibrationAbstractDialog.hpp @@ -5,6 +5,7 @@ #include #include +#include "Jobs/ProgressIndicator.hpp" #include "GUI_App.hpp" #include "GUI_Utils.hpp" #include "MainFrame.hpp" @@ -48,6 +49,18 @@ protected: }; +class ProgressIndicatorStub : ProgressIndicator { +public: + + virtual ~ProgressIndicatorStub() override = default; + + virtual void set_range(int range) override {} + virtual void set_cancel_callback(CancelFn = CancelFn()) override {} + virtual void set_progress(int pr) override {} + virtual void set_status_text(const char*) override {} + virtual int get_range() const override { return 0; } +}; + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/CalibrationBridgeDialog.cpp b/src/slic3r/GUI/CalibrationBridgeDialog.cpp index d26e04d44..10e8d83ba 100644 --- a/src/slic3r/GUI/CalibrationBridgeDialog.cpp +++ b/src/slic3r/GUI/CalibrationBridgeDialog.cpp @@ -3,6 +3,7 @@ #include "libslic3r/Model.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/AppConfig.hpp" +#include "Jobs/ArrangeJob.hpp" #include "GUI.hpp" #include "GUI_ObjectList.hpp" #include "Plater.hpp" @@ -98,6 +99,7 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool } /// --- translate ---; + bool has_to_arrange = false; const float brim_width = std::max(print_config->option("brim_width")->value, nozzle_diameter * 5.); const ConfigOptionFloat* extruder_clearance_radius = print_config->option("extruder_clearance_radius"); const ConfigOptionPoints* bed_shape = printer_config->option("bed_shape"); @@ -108,7 +110,9 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool for (int i = 1; i < nb_items; i++) { model.objects[objs_idx[i]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2 + (i % 2 == 0 ? -1 : 1) * offsety * ((i + 1) / 2), 0 }); } - //TODO: if not enough space, forget about complete_objects + // if not enough space, forget about complete_objects + if (bed_size.y() < offsety * (nb_items + 1)) + has_to_arrange = true; /// --- main config, please modify object config when possible --- @@ -141,6 +145,17 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool ObjectList* obj = this->gui_app->obj_list(); obj->update_after_undo_redo(); + // arrange if needed, after new settings, to take them into account + if (has_to_arrange) { + //update print config (done at reslice but we need it here) + if (plat->printer_technology() == ptFFF) + plat->fff_print().apply(plat->model(), *plat->config()); + std::shared_ptr fake_statusbar = std::make_shared(); + ArrangeJob arranger(std::dynamic_pointer_cast(fake_statusbar), plat); + arranger.prepare_all(); + arranger.process(); + arranger.finalize(); + } plat->reslice(); plat->select_view_3D("Preview"); diff --git a/src/slic3r/GUI/CalibrationFlowDialog.cpp b/src/slic3r/GUI/CalibrationFlowDialog.cpp index 58d525e20..8d2920d2c 100644 --- a/src/slic3r/GUI/CalibrationFlowDialog.cpp +++ b/src/slic3r/GUI/CalibrationFlowDialog.cpp @@ -3,6 +3,7 @@ #include "libslic3r/Model.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/AppConfig.hpp" +#include "Jobs/ArrangeJob.hpp" #include "GUI.hpp" #include "GUI_ObjectList.hpp" #include "Plater.hpp" @@ -101,6 +102,7 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) { } /// --- translate ---; + bool has_to_arrange = false; const ConfigOptionFloat* extruder_clearance_radius = print_config->option("extruder_clearance_radius"); const ConfigOptionPoints* bed_shape = printerConfig->option("bed_shape"); const double brim_width = nozzle_diameter * 3.5; @@ -113,8 +115,10 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) { model.objects[objs_idx[2]]->translate({ bed_min.x() + bed_size.x() / 2 - offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 }); model.objects[objs_idx[3]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 - offsety, 0 }); model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 }); - //TODO: if not enough space, forget about complete_objects + // if not enough space, forget about complete_objects + if (bed_size.y() < offsety * 2 + 25 * xyScale + brim_width || bed_size.x() < offsetx + 25 * xyScale + brim_width) + has_to_arrange = true; /// --- main config, please modify object config when possible --- DynamicPrintConfig new_print_config = *print_config; //make a copy @@ -157,6 +161,17 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) { ObjectList* obj = this->gui_app->obj_list(); obj->update_after_undo_redo(); + // arrange if needed, after new settings, to take them into account + if (has_to_arrange) { + //update print config (done at reslice but we need it here) + if (plat->printer_technology() == ptFFF) + plat->fff_print().apply(plat->model(), *plat->config()); + std::shared_ptr fake_statusbar = std::make_shared(); + ArrangeJob arranger(std::dynamic_pointer_cast(fake_statusbar), plat); + arranger.prepare_all(); + arranger.process(); + arranger.finalize(); + } plat->reslice(); plat->select_view_3D("Preview"); diff --git a/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp b/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp index 984520c4f..42f0d3fb2 100644 --- a/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp +++ b/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp @@ -3,6 +3,7 @@ #include "libslic3r/Model.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/AppConfig.hpp" +#include "Jobs/ArrangeJob.hpp" #include "GUI.hpp" #include "GUI_ObjectList.hpp" #include "Plater.hpp" @@ -85,6 +86,7 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) { } /// --- translate ---; + bool has_to_arrange = false; const ConfigOptionFloat* extruder_clearance_radius = print_config->option("extruder_clearance_radius"); const ConfigOptionPoints* bed_shape = printer_config->option("bed_shape"); const float brim_width = print_config->option("brim_width")->getFloat(); @@ -98,8 +100,10 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) { model.objects[objs_idx[3]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 - offsety, 0 }); model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 , 0 }); model.objects[objs_idx[5]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 }); - //TODO: if not enough space, forget about complete_objects + // if not enough space, forget about complete_objects + if (bed_size.y() < offsety * 2 + 30 * xyz_scale + brim_width || bed_size.x() < offsetx + 35 * xyz_scale + brim_width) + has_to_arrange = true; /// --- main config, please modify object config when possible --- DynamicPrintConfig new_print_config = *print_config; //make a copy @@ -136,6 +140,17 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) { ObjectList* obj = this->gui_app->obj_list(); obj->update_after_undo_redo(); + // arrange if needed, after new settings, to take them into account + if (has_to_arrange) { + //update print config (done at reslice but we need it here) + if (plat->printer_technology() == ptFFF) + plat->fff_print().apply(plat->model(), *plat->config()); + std::shared_ptr fake_statusbar = std::make_shared(); + ArrangeJob arranger(std::dynamic_pointer_cast(fake_statusbar), plat); + arranger.prepare_all(); + arranger.process(); + arranger.finalize(); + } plat->reslice(); plat->select_view_3D("Preview"); diff --git a/src/slic3r/GUI/CalibrationRetractionDialog.cpp b/src/slic3r/GUI/CalibrationRetractionDialog.cpp index 4b454cd7f..902f24700 100644 --- a/src/slic3r/GUI/CalibrationRetractionDialog.cpp +++ b/src/slic3r/GUI/CalibrationRetractionDialog.cpp @@ -3,6 +3,7 @@ #include "libslic3r/Model.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/AppConfig.hpp" +#include "Jobs/ArrangeJob.hpp" #include "GUI.hpp" #include "GUI_ObjectList.hpp" #include "Plater.hpp" @@ -190,22 +191,20 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) { } /// --- translate ---; + bool has_to_arrange = false; const ConfigOptionFloat* extruder_clearance_radius = print_config->option("extruder_clearance_radius"); const ConfigOptionPoints* bed_shape = printer_config->option("bed_shape"); const float brim_width = std::max(print_config->option("brim_width")->value, nozzle_diameter * 5.); Vec2d bed_size = BoundingBoxf(bed_shape->values).size(); Vec2d bed_min = BoundingBoxf(bed_shape->values).min; - float offset = 4 + 26 * 1 + extruder_clearance_radius->value + brim_width + (brim_width > extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value : 0); + float offset = 4 + 26 * scale * 1 + extruder_clearance_radius->value + brim_width + (brim_width > extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value : 0); if (nb_items == 1) { model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2, 0 }); } else { - for (size_t i = 0; i < nb_items; i++) { - model.objects[objs_idx[i]]->translate({ bed_min.x() + bed_size.x() / 2 + (i%2 ==0 ? -offset/2: offset/2), bed_min.y() + bed_size.y() / 2 + ( (i/2) % 2 == 0 ? -1 : 1) * offset * (((i / 2) + 1) / 2), 0 }); - } + has_to_arrange = true; } - /// --- custom config --- for (size_t i = 0; i < nb_items; i++) { //speed @@ -252,16 +251,29 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) { new_print_config.set_key_value("complete_objects_one_skirt", new ConfigOptionBool(true)); } this->gui_app->get_tab(Preset::TYPE_PRINT)->load_config(new_print_config); - plat->on_config_change(new_print_config); this->gui_app->get_tab(Preset::TYPE_PRINT)->update_dirty(); + plat->on_config_change(new_print_config); } //update plater plat->changed_objects(objs_idx); + //if (plat->printer_technology() == ptFFF) + //plat->fff_print().full_print_config().apply(plat->config()); //update everything, easier to code. ObjectList* obj = this->gui_app->obj_list(); obj->update_after_undo_redo(); + // arrange if needed, after new settings, to take them into account + if (has_to_arrange) { + //update print config (done at reslice but we need it here) + if (plat->printer_technology() == ptFFF) + plat->fff_print().apply(plat->model(), *plat->config()); + std::shared_ptr fake_statusbar = std::make_shared(); + ArrangeJob arranger(std::dynamic_pointer_cast(fake_statusbar), plat); + arranger.prepare_all(); + arranger.process(); + arranger.finalize(); + } plat->reslice(); plat->select_view_3D("Preview"); diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 9b60951bf..016d3e43b 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -28,7 +28,7 @@ public: apply_wipe_tower(); } - ArrangePolygon get_arrange_polygon(const PrintBase* print_base) const + ArrangePolygon get_arrange_polygon() const { Polygon ap({ {coord_t(0), coord_t(0)}, @@ -80,11 +80,11 @@ void ArrangeJob::prepare_all() { for (ModelObject *obj: m_plater->model().objects) for (ModelInstance *mi : obj->instances) { ArrangePolygons & cont = mi->printable ? m_selected : m_unprintable; - cont.emplace_back(get_arrange_poly(m_plater->current_print(), mi)); + cont.emplace_back(get_arrange_poly(mi)); } if (auto wti = get_wipe_tower(*m_plater)) - m_selected.emplace_back(wti.get_arrange_polygon(m_plater->current_print())); + m_selected.emplace_back(wti.get_arrange_polygon()); } void ArrangeJob::prepare_selected() { @@ -112,7 +112,7 @@ void ArrangeJob::prepare_selected() { inst_sel[size_t(inst_id)] = true; for (size_t i = 0; i < inst_sel.size(); ++i) { - ArrangePolygon &&ap = get_arrange_poly(m_plater->current_print(), mo->instances[i]); + ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]); ArrangePolygons &cont = mo->instances[i]->printable ? (inst_sel[i] ? m_selected : @@ -124,7 +124,7 @@ void ArrangeJob::prepare_selected() { } if (auto wti = get_wipe_tower(*m_plater)) { - ArrangePolygon &&ap = get_arrange_poly(m_plater->current_print(), &wti); + ArrangePolygon &&ap = get_arrange_poly(&wti); m_plater->get_selection().is_wipe_tower() ? m_selected.emplace_back(std::move(ap)) : @@ -149,10 +149,10 @@ void ArrangeJob::process() { static const auto arrangestr = _(L("Arranging")); - double dist = PrintConfig::min_object_distance(m_plater->config()); + double dist = PrintConfig::min_object_distance(&m_plater->current_print()->full_print_config()); arrangement::ArrangeParams params; - params.min_obj_distance = scaled(dist); + params.min_obj_distance = scaled(dist) * 2; auto count = unsigned(m_selected.size() + m_unprintable.size()); Points bedpts = get_bed_shape(*m_plater->config()); @@ -214,7 +214,7 @@ void ArrangeJob::finalize() { arrangement::ArrangePolygon get_wipe_tower_arrangepoly(Plater &plater) { - return WipeTower{plater.canvas3D()->get_wipe_tower_info()}.get_arrange_polygon(plater.current_print()); + return WipeTower{plater.canvas3D()->get_wipe_tower_info()}.get_arrange_polygon(); } void apply_wipe_tower_arrangepoly(Plater &plater, const arrangement::ArrangePolygon &ap) diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index 99a24018f..e3810946f 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -29,9 +29,9 @@ class ArrangeJob : public Job double bed_stride() const; // Set up arrange polygon for a ModelInstance and Wipe tower - template ArrangePolygon get_arrange_poly(const PrintBase* print_base, T *obj) const + template ArrangePolygon get_arrange_poly(T *obj) const { - ArrangePolygon ap = obj->get_arrange_polygon(print_base); + ArrangePolygon ap = obj->get_arrange_polygon(); ap.priority = 0; ap.bed_idx = ap.translation.x() / bed_stride(); ap.setter = [obj, this](const ArrangePolygon &p) { @@ -44,8 +44,6 @@ class ArrangeJob : public Job return ap; } - // Prepare all objects on the bed regardless of the selection - void prepare_all(); // Prepare the selected and unselected items separately. If nothing is // selected, behaves as if everything would be selected. @@ -56,6 +54,11 @@ protected: void prepare() override; public: + // Prepare all objects on the bed regardless of the selection + //put on public to be accessed by calibrations + void prepare_all(); + + ArrangeJob(std::shared_ptr pri, Plater *plater) : Job{std::move(pri)}, m_plater{plater} {} diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c8085bb31..9c0e88006 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2775,7 +2775,7 @@ void Plater::find_new_position(const ModelInstancePtrs &instances, for (const ModelObject *mo : p->model.objects) for (const ModelInstance *inst : mo->instances) { auto it = std::find(instances.begin(), instances.end(), inst); - arrangement::ArrangePolygon arrpoly = inst->get_arrange_polygon(this->current_print()); + arrangement::ArrangePolygon arrpoly = inst->get_arrange_polygon(); if (it == instances.end()) fixed.emplace_back(std::move(arrpoly));