diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index dc75fb8a3..83d25aefb 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -427,9 +427,10 @@ void PrintObject::generate_support_spots() BOOST_LOG_TRIVIAL(debug) << "Searching support spots - start"; m_print->set_status(75, L("Searching support spots")); if (!this->shared_regions()->generated_support_points.has_value()) { - PrintTryCancel cancel_func = m_print->make_try_cancel(); - SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values}; - SupportSpotsGenerator::SupportPoints supp_points = SupportSpotsGenerator::full_search(this, cancel_func, params); + PrintTryCancel cancel_func = m_print->make_try_cancel(); + SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values, + float(this->print()->m_config.perimeter_acceleration.getFloat())}; + auto [supp_points, partial_objects] = SupportSpotsGenerator::full_search(this, cancel_func, params); this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points}; m_print->throw_if_canceled(); } @@ -468,7 +469,8 @@ void PrintObject::estimate_curled_extrusions() // Estimate curling of support material and add it to the malformaition lines of each layer float support_flow_width = support_material_flow(this, this->config().layer_height).width(); - SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values}; + SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values, + float(this->print()->config().perimeter_acceleration.getFloat())}; SupportSpotsGenerator::estimate_supports_malformations(this->support_layers(), support_flow_width, params); SupportSpotsGenerator::estimate_malformations(this->layers(), params); m_print->throw_if_canceled(); diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 73eae069f..0b0c1b457 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -579,12 +579,13 @@ public: }; // return new object part and actual area covered by extrusions -std::tuple build_object_part_from_slice(const LayerSlice &slice, const Layer *layer) +std::tuple build_object_part_from_slice(const LayerSlice &slice, const Layer *layer, const Params& params) { ObjectPart new_object_part; float area_covered_by_extrusions = 0; - auto add_extrusions_to_object = [&new_object_part, &area_covered_by_extrusions](const ExtrusionEntity *e, const LayerRegion *region) { + auto add_extrusions_to_object = [&new_object_part, &area_covered_by_extrusions, ¶ms](const ExtrusionEntity *e, + const LayerRegion *region) { float flow_width = get_flow_width(region, e->role()); const Layer *l = region->layer(); float slice_z = l->slice_z; @@ -596,9 +597,9 @@ std::tuple build_object_part_from_slice(const LayerSlice &sli new_object_part.volume += volume; new_object_part.volume_centroid_accumulator += to_3d(Vec2f((line.a + line.b) / 2.0f), slice_z) * volume; - if (l->bottom_z() < EPSILON) { // layer attached on bed + if (l->id() == params.raft_layers_count) { // layer attached on bed/raft new_object_part.connected_to_bed = true; - float sticking_area = line.len * flow_width; + float sticking_area = line.len * flow_width; new_object_part.sticking_area += sticking_area; Vec2f middle = Vec2f((line.a + line.b) / 2.0f); new_object_part.sticking_centroid_accumulator += sticking_area * to_3d(middle, slice_z); @@ -681,11 +682,12 @@ public: } }; -SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms) +std::tuple check_stability(const PrintObject *po, const PrintTryCancel &cancel_func, const Params ¶ms) { - SupportPoints supp_points{}; + SupportPoints supp_points{}; SupportGridFilter supports_presence_grid(po, params.min_distance_between_support_points); ActiveObjectParts active_object_parts{}; + PartialObjects partial_objects{}; LD prev_layer_ext_perim_lines; std::unordered_map prev_slice_idx_to_object_part_mapping; @@ -693,6 +695,14 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance std::unordered_map prev_slice_idx_to_weakest_connection; std::unordered_map next_slice_idx_to_weakest_connection; + auto remember_partial_object = [&active_object_parts, &partial_objects](size_t object_part_id) { + auto object_part = active_object_parts.access(object_part_id); + if (object_part.volume > EPSILON) { + partial_objects.emplace_back(object_part.volume_centroid_accumulator / object_part.volume, object_part.volume, + object_part.connected_to_bed); + } + }; + for (size_t layer_idx = 0; layer_idx < po->layer_count(); ++layer_idx) { cancel_func(); const Layer *layer = po->get_layer(layer_idx); @@ -701,7 +711,7 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance for (size_t slice_idx = 0; slice_idx < layer->lslices_ex.size(); ++slice_idx) { const LayerSlice &slice = layer->lslices_ex.at(slice_idx); - auto [new_part, covered_area] = build_object_part_from_slice(slice, layer); + auto [new_part, covered_area] = build_object_part_from_slice(slice, layer, params); SliceConnection connection_to_below = estimate_slice_connection(slice_idx, layer); #ifdef DETAILED_DEBUG_LOGS @@ -730,7 +740,10 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance final_part_id = *parts_ids.begin(); for (size_t part_id : parts_ids) { - if (final_part_id != part_id) { active_object_parts.merge(part_id, final_part_id); } + if (final_part_id != part_id) { + remember_partial_object(part_id); + active_object_parts.merge(part_id, final_part_id); + } } } auto estimate_conn_strength = [bottom_z](const SliceConnection &conn) { @@ -881,11 +894,16 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance } // slice iterations prev_layer_ext_perim_lines = LD(current_layer_ext_perims_lines); } // layer iterations - return supp_points; + + for (const auto& active_obj_pair : prev_slice_idx_to_object_part_mapping) { + remember_partial_object(active_obj_pair.second); + } + + return {supp_points, partial_objects}; } #ifdef DEBUG_FILES -void debug_export(SupportPoints support_points, std::string file_name) +void debug_export(const SupportPoints& support_points,const PartialObjects& objects, std::string file_name) { Slic3r::CNumericLocalesSetter locales_setter; { @@ -910,19 +928,29 @@ void debug_export(SupportPoints support_points, std::string file_name) support_points[i].position(2), color[0], color[1], color[2]); } + for (size_t i = 0; i < objects.size(); ++i) { + Vec3f color{1.0f, 0.0f, 1.0f}; + if (objects[i].connected_to_bed) { + color = {1.0f, 0.0f, 0.0f}; + } + fprintf(fp, "v %f %f %f %f %f %f\n", objects[i].centroid(0), objects[i].centroid(1), objects[i].centroid(2), color[0], + color[1], color[2]); + } + fclose(fp); } } #endif -SupportPoints full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms) +std::tuple full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms) { - SupportPoints supp_points = check_stability(po, cancel_func, params); + auto results = check_stability(po, cancel_func, params); #ifdef DEBUG_FILES - debug_export(supp_points, "issues"); + auto [supp_points, objects] = results; + debug_export(supp_points, objects, "issues"); #endif - return supp_points; + return results; } void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width, const Params ¶ms) diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index 9ef3b8637..498795993 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -5,31 +5,38 @@ #include "Line.hpp" #include "PrintBase.hpp" #include +#include #include namespace Slic3r { namespace SupportSpotsGenerator { -struct Params { - Params(const std::vector &filament_types) { +struct Params +{ + Params(const std::vector &filament_types, float max_acceleration, size_t raft_layers_count) + : max_acceleration(max_acceleration), raft_layers_count(raft_layers_count) + { if (filament_types.size() > 1) { BOOST_LOG_TRIVIAL(warning) - << "SupportSpotsGenerator does not currently handle different materials properly, only first will be used"; + << "SupportSpotsGenerator does not currently handle different materials properly, only first will be used"; } if (filament_types.empty() || filament_types[0].empty()) { - BOOST_LOG_TRIVIAL(error) - << "SupportSpotsGenerator error: empty filament_type"; + BOOST_LOG_TRIVIAL(error) << "SupportSpotsGenerator error: empty filament_type"; filament_type = std::string("PLA"); } else { filament_type = filament_types[0]; - BOOST_LOG_TRIVIAL(debug) - << "SupportSpotsGenerator: applying filament type: " << filament_type; + BOOST_LOG_TRIVIAL(debug) << "SupportSpotsGenerator: applying filament type: " << filament_type; } } // the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2] - const float bridge_distance = 12.0f; //mm + const float bridge_distance = 12.0f; // mm + const float max_acceleration; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the + // jerk phase, so the usual machine limits are too low) + const size_t raft_layers_count; + std::string filament_type; + const std::pair malformation_distance_factors = std::pair { 0.4, 1.2 }; const float max_curled_height_factor = 10.0f; @@ -37,9 +44,7 @@ struct Params { const float support_points_interface_radius = 1.5f; // mm const float min_distance_to_allow_local_supports = 1.0f; //mm - std::string filament_type; const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position. - const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low) const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials. const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... ); @@ -47,6 +52,10 @@ struct Params { // MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface double get_bed_adhesion_yield_strength() const { + if (raft_layers_count > 0) { + return get_support_spots_adhesion_strength(); + } + if (filament_type == "PLA") { return 0.018 * 1e6; } else if (filament_type == "PET" || filament_type == "PETG") { @@ -67,7 +76,7 @@ struct Params { enum class SupportPointCause { LongBridge, // point generated on bridge extrusion longer than the allowed length FloatingBridgeAnchor, // point generated on unsupported bridge endpoint - FloatingExtrusion, // point generated on extrusion that does not hold on its own - huge overhangs + FloatingExtrusion, // point generated on extrusion that does not hold on its own SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too small and there is a risk of separation (brim may help) UnstableFloatingPart, // point generated for object parts not connected to the bed, holded only by the other support points (brim will not help here) WeakObjectPart // point generated when some part of the object is too weak to hold the upper part and may break (imagine hourglass) @@ -118,8 +127,20 @@ struct Malformations { std::vector layers; //for each layer }; -// std::vector quick_search(const PrintObject *po, const Params ¶ms); -SupportPoints full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms); +struct PartialObject +{ + PartialObject(Vec3f centroid, float volume, bool connected_to_bed) + : centroid(centroid), volume(volume), connected_to_bed(connected_to_bed) + {} + + Vec3f centroid; + float volume; + bool connected_to_bed; +}; + +using PartialObjects = std::vector; + +std::tuple full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms); void estimate_supports_malformations(std::vector &layers, float supports_flow_width, const Params ¶ms); void estimate_malformations(std::vector &layers, const Params ¶ms);