diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 6b35acb47..d3dc61826 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -64,6 +64,10 @@ struct SurfaceFillParams float top_surface_speed = 0; float solid_infill_speed = 0; + // Params for lattice infill angles + float lattice_angle_1 = 0.f; + float lattice_angle_2 = 0.f; + bool operator<(const SurfaceFillParams &rhs) const { #define RETURN_COMPARE_NON_EQUAL(KEY) if (this->KEY < rhs.KEY) return true; if (this->KEY > rhs.KEY) return false; #define RETURN_COMPARE_NON_EQUAL_TYPED(TYPE, KEY) if (TYPE(this->KEY) < TYPE(rhs.KEY)) return true; if (TYPE(this->KEY) > TYPE(rhs.KEY)) return false; @@ -90,6 +94,8 @@ struct SurfaceFillParams RETURN_COMPARE_NON_EQUAL(sparse_infill_speed); RETURN_COMPARE_NON_EQUAL(top_surface_speed); RETURN_COMPARE_NON_EQUAL(solid_infill_speed); + RETURN_COMPARE_NON_EQUAL(lattice_angle_1); + RETURN_COMPARE_NON_EQUAL(lattice_angle_2); return false; } @@ -111,7 +117,9 @@ struct SurfaceFillParams this->extrusion_role == rhs.extrusion_role && this->sparse_infill_speed == rhs.sparse_infill_speed && this->top_surface_speed == rhs.top_surface_speed && - this->solid_infill_speed == rhs.solid_infill_speed; + this->solid_infill_speed == rhs.solid_infill_speed && + this->lattice_angle_1 == rhs.lattice_angle_1 && + this->lattice_angle_2 == rhs.lattice_angle_2; } }; @@ -611,6 +619,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); + params.lattice_angle_1 = region_config.lattice_angle_1; + params.lattice_angle_2 = region_config.lattice_angle_2; if (surface.is_solid()) { params.density = 100.f; @@ -953,6 +963,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: params.resolution = resolution; params.use_arachne = surface_fill.params.pattern == ipConcentric || surface_fill.params.pattern == ipConcentricInternal; params.layer_height = layerm->layer()->height; + params.lattice_angle_1 = surface_fill.params.lattice_angle_1; + params.lattice_angle_2 = surface_fill.params.lattice_angle_2; // BBS params.flow = surface_fill.params.flow; @@ -1022,6 +1034,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc case ipMonotonicLine: case ipAlignedRectilinear: case ipGrid: + case ip2DLattice: case ipTriangles: case ipStars: case ipCubic: @@ -1076,6 +1089,8 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc params.resolution = resolution; params.use_arachne = false; params.layer_height = layerm.layer()->height; + params.lattice_angle_1 = surface_fill.params.lattice_angle_1; + params.lattice_angle_2 = surface_fill.params.lattice_angle_2; for (ExPolygon &expoly : surface_fill.expolygons) { // Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon. diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index d5ce03d3b..b4adacbf7 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -47,6 +47,7 @@ Fill* Fill::new_from_type(const InfillPattern type) case ipMonotonic: return new FillMonotonic(); case ipLine: return new FillLine(); case ipGrid: return new FillGrid(); + case ip2DLattice: return new Fill2DLattice(); case ipTriangles: return new FillTriangles(); case ipStars: return new FillStars(); case ipCubic: return new FillCubic(); diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 4812fcd5e..de93db369 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -69,6 +69,10 @@ struct FillParams // Layer height for Concentric infill with Arachne. coordf_t layer_height { 0.f }; + // For 2D lattice + coordf_t lattice_angle_1 { 0.f }; + coordf_t lattice_angle_2 { 0.f }; + // BBS Flow flow; ExtrusionRole extrusion_role{ ExtrusionRole(0) }; diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 6b1ba2f92..c85d5e02f 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -3002,6 +3002,23 @@ Polylines FillGrid::fill_surface(const Surface *surface, const FillParams ¶m return polylines_out; } +Polylines Fill2DLattice::fill_surface(const Surface *surface, const FillParams ¶ms) +{ + Polylines polylines_out; + coordf_t dx1 = tan(Geometry::deg2rad(params.lattice_angle_1)) * z; + coordf_t dx2 = tan(Geometry::deg2rad(params.lattice_angle_2)) * z; + if (! this->fill_surface_by_multilines( + surface, params, + { { float(M_PI / 2.), float(dx1) }, { float(M_PI / 2.), float(dx2) } }, + polylines_out)) + BOOST_LOG_TRIVIAL(error) << "Fill2DLattice::fill_surface() failed to fill a region."; + + if (this->layer_id % 2 == 1) + for (int i = 0; i < polylines_out.size(); i++) + std::reverse(polylines_out[i].begin(), polylines_out[i].end()); + return polylines_out; +} + Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams ¶ms) { Polylines polylines_out; diff --git a/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp index c835607ce..58f9afb1d 100644 --- a/src/libslic3r/Fill/FillRectilinear.hpp +++ b/src/libslic3r/Fill/FillRectilinear.hpp @@ -71,6 +71,18 @@ protected: float _layer_angle(size_t idx) const override { return 0.f; } }; +class Fill2DLattice : public FillRectilinear +{ +public: + Fill* clone() const override { return new Fill2DLattice(*this); } + ~Fill2DLattice() override = default; + Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override; + +protected: + // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. + float _layer_angle(size_t idx) const override { return 0.f; } +}; + class FillTriangles : public FillRectilinear { public: diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index ad494aeac..4d717381f 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -391,6 +391,7 @@ coordf_t Layer::get_sparse_infill_max_void_area() max_void_area = std::max(max_void_area, spacing * spacing); break; case ipGrid: + case ip2DLattice: case ipHoneycomb: case ipLightning: max_void_area = std::max(max_void_area, 4.0 * spacing * spacing); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index f8f48985d..083d9921a 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -784,7 +784,7 @@ static std::vector s_Preset_print_options { "layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "slicing_mode", "top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness", "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction", - "seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", + "seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "lattice_angle_1", "lattice_angle_2", "top_surface_pattern", "bottom_surface_pattern", "infill_direction", "solid_infill_direction", "rotate_solid_infill_direction", "counterbore_hole_bridging", "minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target", "ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index aa1a1ef04..beb15b38f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -136,6 +136,7 @@ static t_config_enum_values s_keys_map_InfillPattern { { "concentric", ipConcentric }, { "zig-zag", ipRectilinear }, { "grid", ipGrid }, + { "2dlattice", ip2DLattice }, { "line", ipLine }, { "cubic", ipCubic }, { "triangles", ipTriangles }, @@ -2282,6 +2283,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("concentric"); def->enum_values.push_back("zig-zag"); def->enum_values.push_back("grid"); + def->enum_values.push_back("2dlattice"); def->enum_values.push_back("line"); def->enum_values.push_back("cubic"); def->enum_values.push_back("triangles"); @@ -2301,6 +2303,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Concentric")); def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Grid")); + def->enum_labels.push_back(L("2D Lattice")); def->enum_labels.push_back(L("Line")); def->enum_labels.push_back(L("Cubic")); def->enum_labels.push_back(L("Triangles")); @@ -2319,6 +2322,26 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Quarter Cubic")); def->set_default_value(new ConfigOptionEnum(ipCrossHatch)); + def = this->add("lattice_angle_1", coFloat); + def->label = L("Lattice angle 1"); + def->category = L("Strength"); + def->tooltip = L("The angle of the first set of 2D lattice elements in the Z direction. Zero is vertical."); + def->sidetext = L("°"); + def->min = -75; + def->max = 75; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(-45)); + + def = this->add("lattice_angle_2", coFloat); + def->label = L("Lattice angle 2"); + def->category = L("Strength"); + def->tooltip = L("The angle of the second set of 2D lattice elements in the Z direction. Zero is vertical."); + def->sidetext = L("°"); + def->min = -75; + def->max = 75; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(45)); + auto def_infill_anchor_min = def = this->add("infill_anchor", coFloatOrPercent); def->label = L("Sparse infill anchor length"); def->category = L("Strength"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b1d2defae..ff6cb2aee 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -58,7 +58,7 @@ enum AuthorizationType { }; enum InfillPattern : int { - ipConcentric, ipRectilinear, ipGrid, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb, + ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal, ipLightning, ipCrossHatch, ipQuarterCubic, ipCount, @@ -923,6 +923,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, rotate_solid_infill_direction)) ((ConfigOptionPercent, sparse_infill_density)) ((ConfigOptionEnum, sparse_infill_pattern)) + ((ConfigOptionFloat, lattice_angle_1)) + ((ConfigOptionFloat, lattice_angle_2)) ((ConfigOptionEnum, fuzzy_skin)) ((ConfigOptionFloat, fuzzy_skin_thickness)) ((ConfigOptionFloat, fuzzy_skin_point_distance)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 22bdd8306..e30f5272e 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1092,7 +1092,9 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "infill_anchor_max" || opt_key == "top_surface_line_width" || opt_key == "initial_layer_line_width" - || opt_key == "small_area_infill_flow_compensation") { + || opt_key == "small_area_infill_flow_compensation" + || opt_key == "lattice_angle_1" + || opt_key == "lattice_angle_2") { steps.emplace_back(posInfill); } else if (opt_key == "sparse_infill_pattern") { steps.emplace_back(posPrepareInfill); @@ -3504,6 +3506,7 @@ void PrintObject::combine_infill() ((infill_pattern == ipRectilinear || infill_pattern == ipMonotonic || infill_pattern == ipGrid || + infill_pattern == ip2DLattice || infill_pattern == ipLine || infill_pattern == ipHoneycomb) ? 1.5f : 0.5f) * layerms.back()->flow(frSolidInfill).scaled_width(); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index cd8417050..dd56478b6 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -782,6 +782,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co toggle_line("interlocking_beam_layer_count", use_beam_interlocking); toggle_line("interlocking_depth", use_beam_interlocking); toggle_line("interlocking_boundary_avoidance", use_beam_interlocking); + + bool lattice_options = config->opt_enum("sparse_infill_pattern") == InfillPattern::ip2DLattice; + for (auto el : { "lattice_angle_1", "lattice_angle_2"}) + toggle_line(el, lattice_options); } void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/) diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index b626f58d2..701004692 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -105,7 +105,7 @@ std::map> SettingsFactory::PART_CAT }}, { L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1}, {"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1}, - {"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1}, + {"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"lattice_angle_1", "",1},{"lattice_angle_2", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1}, {"internal_solid_infill_pattern", "",1}, {"infill_combination", "",1}, {"infill_combination_max_layer_height", "",1}, {"infill_wall_overlap", "",1},{"top_bottom_infill_wall_overlap", "",1}, {"solid_infill_direction", "",1}, {"rotate_solid_infill_direction", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"internal_bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1} }}, { L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5}, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 345482ccd..ee04f00c2 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2138,6 +2138,8 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Infill"), L"param_infill"); optgroup->append_single_option_line("sparse_infill_density"); optgroup->append_single_option_line("sparse_infill_pattern", "fill-patterns#infill types and their properties of sparse"); + optgroup->append_single_option_line("lattice_angle_1"); + optgroup->append_single_option_line("lattice_angle_2"); optgroup->append_single_option_line("infill_anchor_max"); optgroup->append_single_option_line("infill_anchor"); optgroup->append_single_option_line("internal_solid_infill_pattern");