From eaffb1492154edb31b99de591098f91e03628344 Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Wed, 22 Jun 2022 11:37:52 +0200 Subject: [PATCH] Improved stability supports - now accounts for base convex hull, decreases area of points if too close. --- src/libslic3r/CMakeLists.txt | 4 +- src/libslic3r/Print.cpp | 2 +- src/libslic3r/Print.hpp | 4 +- src/libslic3r/PrintObject.cpp | 20 ++--- ...esSearch.cpp => SupportSpotsGenerator.cpp} | 89 +++++++++++-------- ...esSearch.hpp => SupportSpotsGenerator.hpp} | 13 ++- 6 files changed, 73 insertions(+), 59 deletions(-) rename src/libslic3r/{SupportableIssuesSearch.cpp => SupportSpotsGenerator.cpp} (90%) rename src/libslic3r/{SupportableIssuesSearch.hpp => SupportSpotsGenerator.hpp} (80%) diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 0a0062a754..e478188356 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -245,8 +245,8 @@ set(SLIC3R_SOURCES SlicingAdaptive.hpp Subdivide.cpp Subdivide.hpp - SupportableIssuesSearch.cpp - SupportableIssuesSearch.hpp + SupportSpotsGenerator.cpp + SupportSpotsGenerator.hpp SupportMaterial.cpp SupportMaterial.hpp Surface.cpp diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index a50974cafd..2979b3557b 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -826,7 +826,7 @@ void Print::process() for (PrintObject *obj : m_objects) obj->ironing(); for (PrintObject *obj : m_objects) - obj->find_supportable_issues(); + obj->generate_support_spots(); for (PrintObject *obj : m_objects) obj->generate_support_material(); if (this->set_started(psWipeTower)) { diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index c89b463a8f..c2777083d8 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -61,7 +61,7 @@ enum PrintStep : unsigned int { enum PrintObjectStep : unsigned int { posSlice, posPerimeters, posPrepareInfill, - posInfill, posIroning, posSupportableIssuesSearch, posSupportMaterial, posCount, + posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posCount, }; // A PrintRegion object represents a group of volumes to print @@ -381,7 +381,7 @@ private: void prepare_infill(); void infill(); void ironing(); - void find_supportable_issues(); + void generate_support_spots(); void generate_support_material(); void slice_volumes(); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 40f740b91c..322b6844ad 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -16,7 +16,7 @@ #include "Fill/FillAdaptive.hpp" #include "Fill/FillLightning.hpp" #include "Format/STL.hpp" -#include "SupportableIssuesSearch.hpp" +#include "SupportSpotsGenerator.hpp" #include "TriangleSelectorWrapper.hpp" #include "format.hpp" @@ -399,15 +399,15 @@ void PrintObject::ironing() } -void PrintObject::find_supportable_issues() +void PrintObject::generate_support_spots() { - if (this->set_started(posSupportableIssuesSearch)) { + if (this->set_started(posSupportSpotsSearch)) { BOOST_LOG_TRIVIAL(debug) - << "Searching supportable issues - start"; - m_print->set_status(75, L("Searching supportable issues")); + << "Searching support spots - start"; + m_print->set_status(75, L("Searching support spots")); if (!this->m_config.support_material) { - std::vector problematic_layers = SupportableIssues::quick_search(this); + std::vector problematic_layers = SupportSpotsGenerator::quick_search(this); if (!problematic_layers.empty()) { std::cout << "Object needs supports" << std::endl; this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, @@ -420,7 +420,7 @@ void PrintObject::find_supportable_issues() } } } else { - SupportableIssues::Issues issues = SupportableIssues::full_search(this); + SupportSpotsGenerator::Issues issues = SupportSpotsGenerator::full_search(this); //TODO fix // if (!issues.supports_nedded.empty()) { auto obj_transform = this->trafo_centered(); @@ -430,7 +430,7 @@ void PrintObject::find_supportable_issues() Transform3f inv_transform = (obj_transform * model_transformation).inverse().cast(); TriangleSelectorWrapper selector { model_volume->mesh() }; - for (const SupportableIssues::SupportPoint &support_point : issues.supports_nedded) { + for (const SupportSpotsGenerator::SupportPoint &support_point : issues.supports_nedded) { Vec3f point = Vec3f(inv_transform * support_point.position); Vec3f origin = Vec3f( inv_transform * Vec3f(support_point.position.x(), support_point.position.y(), 0.0f)); @@ -451,8 +451,8 @@ void PrintObject::find_supportable_issues() m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) - << "Searching supportable issues - end"; - this->set_done(posSupportableIssuesSearch); + << "Searching support spots - end"; + this->set_done(posSupportSpotsSearch); } } diff --git a/src/libslic3r/SupportableIssuesSearch.cpp b/src/libslic3r/SupportSpotsGenerator.cpp similarity index 90% rename from src/libslic3r/SupportableIssuesSearch.cpp rename to src/libslic3r/SupportSpotsGenerator.cpp index ce17020ed7..1726b4cacb 100644 --- a/src/libslic3r/SupportableIssuesSearch.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -1,4 +1,4 @@ -#include "SupportableIssuesSearch.hpp" +#include "SupportSpotsGenerator.hpp" #include "tbb/parallel_for.h" #include "tbb/blocked_range.h" @@ -55,7 +55,7 @@ auto get_b(ExtrusionLine &&l) { return l.b; } -namespace SupportableIssues { +namespace SupportSpotsGenerator { void Issues::add(const Issues &layer_issues) { supports_nedded.insert(supports_nedded.end(), layer_issues.supports_nedded.begin(), @@ -237,7 +237,8 @@ public: #ifdef DEBUG_FILES Vec3f get_accumulator_color(size_t id) { if (mapping.find(id) == mapping.end()) { - std::cerr << " ERROR: uknown accumulator ID: " << id << std::endl; + BOOST_LOG_TRIVIAL(debug) + << "SSG: ERROR: uknown accumulator ID: " << id; return Vec3f(1.0f, 1.0f, 1.0f); } @@ -332,7 +333,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity, size_t current_stability_acc = NULL_ACC_ID; ExtrusionPropertiesAccumulator bridging_acc { }; bridging_acc.add_distance(params.bridge_distance + 1.0f); // Initialise unsupported distance with larger than tolerable distance -> - // -> it prevents extruding perimeter start and short loops into air. + // -> it prevents extruding perimeter starts and short loops into air. const float flow_width = get_flow_width(layer_region, entity->role()); const float max_allowed_dist_from_prev_layer = flow_width; float distance_from_last_support_point = params.min_distance_between_support_points * 2.0f; @@ -376,9 +377,9 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity, if (distance_from_last_support_point > params.min_distance_between_support_points && bridging_acc.distance // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports. > params.bridge_distance - / (1.0f + (bridging_acc.max_curvature - * params.bridge_distance_decrease_by_curvature_factor / PI))) { - current_segment.add_support_point(current, params.extrusion_support_points_area); + / (bridging_acc.max_curvature + * params.bridge_distance_decrease_by_curvature_factor / PI)) { + current_segment.add_support_point(current, 0.0f); // Do not count extrusion supports into the support area. They can be very densely placed, causing algorithm to overestimate stickiness. issues.supports_nedded.emplace_back(to_vec3f(current), 1.0); bridging_acc.reset(); distance_from_last_support_point = 0.0f; @@ -394,13 +395,13 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, const std::vector &checked_lines, float print_z, const Params ¶ms) { - std::unordered_map> layer_accs_lines; + std::unordered_map> layer_accs_w_lines; for (size_t i = 0; i < checked_lines.size(); ++i) { - layer_accs_lines[&stability_accs.access(checked_lines[i].stability_accumulator_id)].push_back(i); + layer_accs_w_lines[&stability_accs.access(checked_lines[i].stability_accumulator_id)].push_back(i); } - for (auto &acc_lines : layer_accs_lines) { - StabilityAccumulator *acc = acc_lines.first; + for (auto &accumulator : layer_accs_w_lines) { + StabilityAccumulator *acc = accumulator.first; Vec3f centroid = acc->get_centroid(); Vec2f hull_centroid = unscaled(acc->segment_base_hull().centroid()).cast(); std::vector hull_lines; @@ -411,9 +412,9 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, } if (hull_lines.empty()) { if (acc->get_support_points().empty()) { - acc->add_support_point(Point::new_scale(checked_lines[acc_lines.second[0]].a), - params.support_points_interface_area); - issues.supports_nedded.emplace_back(to_3d(checked_lines[acc_lines.second[0]].a, print_z), 1.0); + acc->add_support_point(Point::new_scale(checked_lines[accumulator.second[0]].a), + params.support_points_interface_radius*params.support_points_interface_radius* float(PI) ); + issues.supports_nedded.emplace_back(to_3d(checked_lines[accumulator.second[0]].a, print_z), 1.0); } hull_lines.push_back( { unscaled(acc->get_support_points()[0]).cast(), unscaled(acc->get_support_points()[0]).cast() }); @@ -428,7 +429,7 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, float weight = mass * params.gravity_constant; float distance_from_last_support_point = params.min_distance_between_support_points * 2.0f; - for (size_t line_idx : acc_lines.second) { + for (size_t line_idx : accumulator.second) { const ExtrusionLine &line = checked_lines[line_idx]; distance_from_last_support_point += line.len; @@ -444,39 +445,51 @@ void check_layer_global_stability(StabilityAccumulators &stability_accs, float sticking_arm = (pivot - hull_centroid).norm(); float sticking_torque = sticking_arm * sticking_force; - std::cout << "sticking_arm: " << sticking_arm << std::endl; - std::cout << "sticking_torque: " << sticking_torque << std::endl; - float weight_arm = (pivot - centroid.head<2>()).norm(); float weight_torque = weight_arm * weight; - std::cout << "weight_arm: " << sticking_arm << std::endl; - std::cout << "weight_torque: " << weight_torque << std::endl; - float bed_movement_arm = centroid.z() - acc->get_base_height(); float bed_movement_force = params.max_acceleration * mass; float bed_movement_torque = bed_movement_force * bed_movement_arm; - std::cout << "bed_movement_arm: " << bed_movement_arm << std::endl; - std::cout << "bed_movement_torque: " << bed_movement_torque << std::endl; - float conflict_torque_arm = (to_3d(Vec2f(pivot - line.b), print_z).cross( extruder_pressure_direction)).norm(); float extruder_conflict_torque = params.tolerable_extruder_conflict_force * conflict_torque_arm; - - std::cout << "conflict_torque_arm: " << conflict_torque_arm << std::endl; - std::cout << "extruder_conflict_torque: " << extruder_conflict_torque << std::endl; - float total_torque = bed_movement_torque + extruder_conflict_torque - weight_torque - sticking_torque; - std::cout << "total_torque: " << total_torque << " printz: " << print_z << std::endl; - if (total_torque > 0) { - acc->add_support_point(Point::new_scale(line.b), std::min(params.support_points_interface_area, (pivot - line.b).squaredNorm())); + size_t _nearest_idx; + Vec2f _nearest_pt; + float area = params.support_points_interface_radius* params.support_points_interface_radius * float(PI); + float dist_from_hull = hull_distancer.signed_distance_from_lines(line.b, _nearest_idx, _nearest_pt); + if (dist_from_hull < params.support_points_interface_radius) { + area = std::max(0.0f, dist_from_hull*params.support_points_interface_radius * float(PI)); + } + + acc->add_support_point(Point::new_scale(line.b), area); issues.supports_nedded.emplace_back(to_3d(line.b, print_z), extruder_conflict_torque - sticking_torque); distance_from_last_support_point = 0.0f; } - +#if 0 + BOOST_LOG_TRIVIAL(debug) + << "SSG: sticking_arm: " << sticking_arm; + BOOST_LOG_TRIVIAL(debug) + << "SSG: sticking_torque: " << sticking_torque; + BOOST_LOG_TRIVIAL(debug) + << "SSG: weight_arm: " << sticking_arm; + BOOST_LOG_TRIVIAL(debug) + << "SSG: weight_torque: " << weight_torque; + BOOST_LOG_TRIVIAL(debug) + << "SSG: bed_movement_arm: " << bed_movement_arm; + BOOST_LOG_TRIVIAL(debug) + << "SSG: bed_movement_torque: " << bed_movement_torque; + BOOST_LOG_TRIVIAL(debug) + << "SSG: conflict_torque_arm: " << conflict_torque_arm; + BOOST_LOG_TRIVIAL(debug) + << "SSG: extruder_conflict_torque: " << extruder_conflict_torque; + BOOST_LOG_TRIVIAL(debug) + << "SSG: total_torque: " << total_torque << " printz: " << print_z; +#endif } } } @@ -557,7 +570,7 @@ Issues check_object_stability(const PrintObject *po, const Params ¶ms) { size_t nearest_line_idx; Vec2f nearest_pt; float dist = prev_layer_lines.signed_distance_from_lines(l.a, nearest_line_idx, nearest_pt); - if (std::abs(dist) < max_flow_width*1.1f) { + if (std::abs(dist) < max_flow_width) { size_t other_line_acc_id = prev_layer_lines.get_line(nearest_line_idx).stability_accumulator_id; size_t from_id = std::max(other_line_acc_id, l.stability_accumulator_id); size_t to_id = std::min(other_line_acc_id, l.stability_accumulator_id); @@ -610,8 +623,8 @@ Issues check_object_stability(const PrintObject *po, const Params ¶ms) { } fill_points.emplace_back(start, acc_id); } else { - std::cout << " SUPPORTS POINT GEN, start infill in the air? on printz: " << print_z - << std::endl; + BOOST_LOG_TRIVIAL(debug) + << "SSG: ERROR: seem that infill starts in the air? on printz: " << print_z; } } } // fill @@ -630,8 +643,8 @@ Issues check_object_stability(const PrintObject *po, const Params ¶ms) { size_t to_id = std::min(other_line_acc_id, fill_point.second); stability_accs.merge_accumulators(from_id, to_id); } else { - std::cout << " SUPPORTS POINT GEN, no connection on current layer for infill? on printz: " << print_z - << std::endl; + BOOST_LOG_TRIVIAL(debug) + << "SSG: ERROR: seem that infill starts in the air? on printz: " << print_z; } } @@ -698,7 +711,9 @@ std::vector quick_search(const PrintObject *po, const Params ¶ms) { Issues full_search(const PrintObject *po, const Params ¶ms) { auto issues = check_object_stability(po, params); +#ifdef DEBUG_FILES debug_export(issues, "issues"); +#endif return issues; } diff --git a/src/libslic3r/SupportableIssuesSearch.hpp b/src/libslic3r/SupportSpotsGenerator.hpp similarity index 80% rename from src/libslic3r/SupportableIssuesSearch.hpp rename to src/libslic3r/SupportSpotsGenerator.hpp index ccda2d77af..b7c987c928 100644 --- a/src/libslic3r/SupportableIssuesSearch.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -5,22 +5,21 @@ namespace Slic3r { -namespace SupportableIssues { +namespace SupportSpotsGenerator { struct Params { const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position. - float bridge_distance = 10.0f; //mm - float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / ( 1 + this factor * (curvature / PI) ) + float bridge_distance = 15.0f; //mm + float bridge_distance_decrease_by_curvature_factor = 5.0f; // >0 REQUIRED; allowed bridge distance = bridge_distance / (this factor * (curvature / PI) ) float min_distance_between_support_points = 0.5f; // Adhesion computation : from experiment, PLA holds about 3g per mm^2 of base area (with reserve); So it can withstand about 3*gravity_constant force per mm^2 float base_adhesion = 3.0f * gravity_constant; // adhesion per mm^2 of first layer - float support_adhesion = 3.0f * gravity_constant; // adhesion per mm^2 of support interface layer - float support_points_interface_area = 5.0f; // mm^2 - float extrusion_support_points_area = 0.5f; // much lower value, because these support points appear due to unsupported extrusion, - // not stability - they can be very densely placed, making the sticking estimation incorrect + float support_adhesion = 1.0f * gravity_constant; // adhesion per mm^2 of support interface layer + + float support_points_interface_radius = 0.5f; // mm float max_acceleration = 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY float filament_density = 1.25f * 0.001f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important