diff --git a/resources/profiles/BBL.json b/resources/profiles/BBL.json index 452df3a66..099687819 100644 --- a/resources/profiles/BBL.json +++ b/resources/profiles/BBL.json @@ -1,7 +1,7 @@ { "name": "Bambulab", "url": "http://www.bambulab.com/Parameters/vendor/BBL.json", - "version": "01.04.00.06", + "version": "01.04.00.07", "force_update": "0", "description": "the initial version of BBL configurations", "machine_model_list": [ diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.08.json b/resources/profiles/BBL/process/fdm_process_bbl_0.08.json index d6068a71d..146295708 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.08.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.08.json @@ -5,6 +5,7 @@ "instantiation": "false", "inherits": "fdm_process_bbl_common", "layer_height": "0.08", + "elefant_foot_compensation": "0.15", "bottom_shell_layers": "7", "top_shell_layers": "9", "bridge_flow": "1", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.12.json b/resources/profiles/BBL/process/fdm_process_bbl_0.12.json index c515f8475..453f58276 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.12.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.12.json @@ -6,7 +6,9 @@ "inherits": "fdm_process_bbl_common", "layer_height": "0.12", "bottom_shell_layers": "5", - "top_shell_layers": "6", + "elefant_foot_compensation": "0.15", + "top_shell_layers": "5", + "top_shell_thickness": "0.6", "bridge_flow": "1", "initial_layer_speed": "50", "initial_layer_infill_speed": "105", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.16.json b/resources/profiles/BBL/process/fdm_process_bbl_0.16.json index 56c8afe84..08513bb82 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.16.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.16.json @@ -5,8 +5,10 @@ "instantiation": "false", "inherits": "fdm_process_bbl_common", "layer_height": "0.16", + "elefant_foot_compensation": "0.15", "bottom_shell_layers": "4", - "top_shell_layers": "5", + "top_shell_layers": "4", + "top_shell_thickness": "0.6", "bridge_flow": "1", "initial_layer_speed": "50", "initial_layer_infill_speed": "105", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.20.json b/resources/profiles/BBL/process/fdm_process_bbl_0.20.json index 7b9336c4e..66d7dc51a 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.20.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.20.json @@ -5,8 +5,10 @@ "instantiation": "false", "inherits": "fdm_process_bbl_common", "layer_height": "0.2", + "elefant_foot_compensation": "0.15", "bottom_shell_layers": "3", - "top_shell_layers": "4", + "top_shell_layers": "3", + "top_shell_thickness": "0.6", "bridge_flow": "1", "initial_layer_speed": "50", "initial_layer_infill_speed": "105", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.24.json b/resources/profiles/BBL/process/fdm_process_bbl_0.24.json index 87c7bf5a3..159410e75 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.24.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.24.json @@ -5,9 +5,11 @@ "instantiation": "false", "inherits": "fdm_process_bbl_common", "layer_height": "0.24", + "elefant_foot_compensation": "0.15", "top_surface_line_width": "0.45", "bottom_shell_layers": "3", - "top_shell_layers": "4", + "top_shell_layers": "3", + "top_shell_thickness": "0.6", "bridge_flow": "1", "initial_layer_speed": "50", "initial_layer_infill_speed": "105", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_0.28.json b/resources/profiles/BBL/process/fdm_process_bbl_0.28.json index f773eaa4c..22438e709 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_0.28.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_0.28.json @@ -5,9 +5,11 @@ "instantiation": "false", "inherits": "fdm_process_bbl_common", "layer_height": "0.28", + "elefant_foot_compensation": "0.15", "top_surface_line_width": "0.45", "bottom_shell_layers": "3", - "top_shell_layers": "4", + "top_shell_layers": "3", + "top_shell_thickness": "0.6", "bridge_flow": "1", "initial_layer_speed": "50", "initial_layer_infill_speed": "105", diff --git a/resources/profiles/BBL/process/fdm_process_bbl_common.json b/resources/profiles/BBL/process/fdm_process_bbl_common.json index c1cab4863..8e6e05fc4 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_common.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_common.json @@ -30,6 +30,7 @@ "infill_direction": "45", "sparse_infill_density": "15%", "sparse_infill_pattern": "grid", + "internal_bridge_support_thickness": "0.8", "initial_layer_acceleration": "500", "initial_layer_line_width": "0.5", "initial_layer_print_height": "0.2", diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 3cf98c547..20fd3b760 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -46,6 +46,8 @@ struct SurfaceFillParams // 1000mm is roughly the maximum length line that fits into a 32bit coord_t. float anchor_length = 1000.f; float anchor_length_max = 1000.f; + //BBS + bool with_loop = false; // width, height of extrusion, nozzle diameter, is bridge // For the output, for fill generator. @@ -77,6 +79,7 @@ struct SurfaceFillParams // RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust); RETURN_COMPARE_NON_EQUAL(anchor_length); RETURN_COMPARE_NON_EQUAL(anchor_length_max); + RETURN_COMPARE_NON_EQUAL(with_loop); RETURN_COMPARE_NON_EQUAL(flow.width()); RETURN_COMPARE_NON_EQUAL(flow.height()); RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter()); @@ -97,6 +100,7 @@ struct SurfaceFillParams // this->dont_adjust == rhs.dont_adjust && this->anchor_length == rhs.anchor_length && this->anchor_length_max == rhs.anchor_length_max && + this->with_loop == rhs.with_loop && this->flow == rhs.flow && this->extrusion_role == rhs.extrusion_role; } @@ -147,6 +151,8 @@ std::vector group_fills(const Layer &layer) params.extruder = layerm.region().extruder(extrusion_role); params.pattern = region_config.sparse_infill_pattern.value; params.density = float(region_config.sparse_infill_density); + //BBS + params.with_loop = surface.surface_type == stInternalWithLoop; if (surface.is_solid()) { params.density = 100.f; @@ -465,6 +471,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: params.extrusion_role = surface_fill.params.extrusion_role; params.using_internal_flow = using_internal_flow; params.no_extrusion_overlap = surface_fill.params.overlap; + params.with_loop = surface_fill.params.with_loop; LayerRegion* layerm = this->m_regions[surface_fill.region_id]; for (ExPolygon& expoly : surface_fill.expolygons) { diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index ae4811ca8..1ab70e652 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -29,7 +29,7 @@ namespace Slic3r { //BBS: 0% of sparse_infill_line_width, no anchor at the start of sparse infill -float Fill::infill_anchor = 0; +float Fill::infill_anchor = 400; //BBS: 20mm float Fill::infill_anchor_max = 20; @@ -122,13 +122,57 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para { Polylines polylines; ThickPolylines thick_polylines; - try { - if (params.use_arachne) - thick_polylines = this->fill_surface_arachne(surface, params); - else - polylines = this->fill_surface(surface, params); + if (!params.with_loop) { + try { + if (params.use_arachne) + thick_polylines = this->fill_surface_arachne(surface, params); + else + polylines = this->fill_surface(surface, params); + } + catch (InfillFailedException&) {} + } + //BBS: add handling for infill pattern with loop + else { + Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(scale_(this->overlap - 0.5 * this->spacing))); + Polylines loop_polylines = to_polylines(expp); + { + //BBS: clip the loop + size_t j = 0; + for (size_t i = 0; i < loop_polylines.size(); ++i) { + loop_polylines[i].clip_end(this->loop_clipping); + if (loop_polylines[i].is_valid()) { + if (j < i) + loop_polylines[j] = std::move(loop_polylines[i]); + ++j; + } + } + if (j < loop_polylines.size()) + loop_polylines.erase(loop_polylines.begin() + int(j), loop_polylines.end()); + } + + if (!loop_polylines.empty()) { + if (params.use_arachne) + append(thick_polylines, to_thick_polylines(std::move(loop_polylines), scaled(this->spacing))); + else + append(polylines, std::move(loop_polylines)); + expp = offset_ex(expp, float(scale_(0 - 0.5 * this->spacing))); + } else { + //BBS: the area is too narrow to place a loop, return to original expolygon + expp = { surface->expolygon }; + } + + Surface temp_surface = *surface; + for (ExPolygon& ex : expp) { + temp_surface.expolygon = ex; + try { + if (params.use_arachne) + append(thick_polylines, std::move(this->fill_surface_arachne(&temp_surface, params))); + else + append(polylines, std::move(this->fill_surface(&temp_surface, params))); + } + catch (InfillFailedException&) {} + } } - catch (InfillFailedException&) {} if (!polylines.empty() || !thick_polylines.empty()) { // calculate actual flow from spacing (which might have been adjusted by the infill diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 9487e463b..78a8d5b14 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -67,6 +67,8 @@ struct FillParams bool use_arachne{ false }; // Layer height for Concentric infill with Arachne. coordf_t layer_height { 0.f }; + //BBS + bool with_loop { false }; // BBS Flow flow; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 828639218..c3ac6b366 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -730,7 +730,7 @@ static std::vector s_Preset_print_options { "gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/ "support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed", "initial_layer_infill_speed", "only_one_wall_top", - "timelapse_type" + "timelapse_type", "internal_bridge_support_thickness" }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 74aebc645..3e95e36af 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -916,6 +916,19 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(true)); + def = this->add("internal_bridge_support_thickness", coFloat); + def->label = L("Internal bridge support thickness"); + def->category = L("Strength"); + def->tooltip = L("When sparse infill density is low, the internal solid infill or internal bridge may have no archor at the end of line. " + "This cause falling and bad quality when printing internal solid infill. " + "When enable this feature, loop paths will be added to the sparse fill of the lower layers for specific thickness, so that better archor can be provided for internal bridge. " + "0 means disable this feature"); + def->sidetext = L("mm"); + def->min = 0; + def->max = 2; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0)); + auto def_top_fill_pattern = def = this->add("top_surface_pattern", coEnum); def->label = L("Top surface pattern"); def->category = L("Strength"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index efab27520..a772ac686 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -655,6 +655,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, detect_narrow_internal_solid_infill)) // ((ConfigOptionBool, adaptive_layer_height)) ((ConfigOptionFloat, support_bottom_interface_spacing)) + ((ConfigOptionFloat, internal_bridge_support_thickness)) ) // This object is mapped to Perl as Slic3r::Config::PrintRegion. diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index b0c06a87b..622f5a64e 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -770,7 +770,9 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "solid_infill_filament" || opt_key == "sparse_infill_line_width" || opt_key == "ensure_vertical_shell_thickness" - || opt_key == "bridge_angle") { + || opt_key == "bridge_angle" + //BBS + || opt_key == "internal_bridge_support_thickness") { steps.emplace_back(posPrepareInfill); } else if ( opt_key == "top_surface_pattern" @@ -1611,6 +1613,7 @@ void PrintObject::bridge_over_infill() Layer *layer = *layer_it; LayerRegion *layerm = layer->m_regions[region_id]; + const PrintObjectConfig& object_config = layer->object()->config(); //BBS: enable thick bridge for internal bridge only Flow bridge_flow = layerm->bridging_flow(frSolidInfill, true); @@ -1678,8 +1681,43 @@ void PrintObject::bridge_over_infill() (layerm->fill_surfaces.surfaces.end() - 1)->bridge_angle = ibd.angle; } } + for (ExPolygon &ex : not_to_bridge) layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, ex)); + + //BBS: modify stInternal to be stInternalWithLoop to give better support to internal bridge + if (!to_bridge.empty()){ + float internal_loop_thickness = object_config.internal_bridge_support_thickness.value; + double bottom_z = layer->print_z - layer->height - internal_loop_thickness + EPSILON; + //BBS: lighting infill doesn't support this feature. Don't need to add loop when infill density is high than 50% + if (region.config().sparse_infill_pattern != InfillPattern::ipLightning && region.config().sparse_infill_density.value < 50) + for (int i = int(layer_it - m_layers.begin()) - 1; i >= 0; --i) { + const Layer* lower_layer = m_layers[i]; + + if (lower_layer->print_z < bottom_z) break; + + for (LayerRegion* lower_layerm : lower_layer->m_regions) { + Polygons lower_internal; + lower_layerm->fill_surfaces.filter_by_type(stInternal, &lower_internal); + ExPolygons internal_with_loop = intersection_ex(lower_internal, to_bridge); + ExPolygons internal = diff_ex(lower_internal, to_bridge); + if (internal_with_loop.empty()) { + //BBS: don't need to do anything + } + else if (internal.empty()) { + lower_layerm->fill_surfaces.change_to_new_type(stInternal, stInternalWithLoop); + } + else { + lower_layerm->fill_surfaces.remove_type(stInternal); + for (ExPolygon& ex : internal_with_loop) + lower_layerm->fill_surfaces.surfaces.push_back(Surface(stInternalWithLoop, ex)); + for (ExPolygon& ex : internal) + lower_layerm->fill_surfaces.surfaces.push_back(Surface(stInternal, ex)); + } + } + } + } + /* # exclude infill from the layers below if needed # see discussion at https://github.com/alexrj/Slic3r/issues/240 diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp index 4920efbbf..4591e2bcd 100644 --- a/src/libslic3r/Surface.hpp +++ b/src/libslic3r/Surface.hpp @@ -15,6 +15,8 @@ enum SurfaceType { stBottomBridge, // Normal sparse infill. stInternal, + // Normal sparse infill. + stInternalWithLoop, // Full infill, supporting the top surfaces and/or defining the verticall wall thickness. stInternalSolid, // 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow. diff --git a/src/libslic3r/SurfaceCollection.hpp b/src/libslic3r/SurfaceCollection.hpp index 7e01a68df..50be3e97d 100644 --- a/src/libslic3r/SurfaceCollection.hpp +++ b/src/libslic3r/SurfaceCollection.hpp @@ -37,6 +37,12 @@ public: for (Surface &surface : this->surfaces) surface.surface_type = type; } + //BBS + void change_to_new_type(SurfaceType old_type, SurfaceType new_type) { + for (Surface& surface : this->surfaces) + if (surface.surface_type == old_type) + surface.surface_type = new_type; + } void clear() { surfaces.clear(); } bool empty() const { return surfaces.empty(); } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 718fc7583..77b31bd1c 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1815,6 +1815,7 @@ void TabPrint::build() optgroup->append_single_option_line("infill_combination"); optgroup->append_single_option_line("detect_narrow_internal_solid_infill"); optgroup->append_single_option_line("ensure_vertical_shell_thickness"); + optgroup->append_single_option_line("internal_bridge_support_thickness"); page = add_options_page(L("Speed"), "empty"); optgroup = page->new_optgroup(L("Initial layer speed"), L"param_speed_first", 15);