diff --git a/resources/images/param_2dhoneycomb.svg b/resources/images/param_2dhoneycomb.svg
new file mode 100644
index 0000000000..5c9112b38a
--- /dev/null
+++ b/resources/images/param_2dhoneycomb.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp
index ec4afe9e9d..a3d8b45323 100644
--- a/src/libslic3r/Fill/Fill.cpp
+++ b/src/libslic3r/Fill/Fill.cpp
@@ -69,6 +69,9 @@ struct SurfaceFillParams
float lattice_angle_1 = 0.f;
float lattice_angle_2 = 0.f;
+ // Params for 2D honeycomb
+ float infill_overhang_angle = 60.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;
@@ -97,31 +100,33 @@ struct SurfaceFillParams
RETURN_COMPARE_NON_EQUAL(solid_infill_speed);
RETURN_COMPARE_NON_EQUAL(lattice_angle_1);
RETURN_COMPARE_NON_EQUAL(lattice_angle_2);
+ RETURN_COMPARE_NON_EQUAL(infill_overhang_angle);
return false;
}
- bool operator==(const SurfaceFillParams &rhs) const {
- return this->extruder == rhs.extruder &&
- this->pattern == rhs.pattern &&
- this->spacing == rhs.spacing &&
- this->overlap == rhs.overlap &&
- this->angle == rhs.angle &&
- this->rotate_angle == rhs.rotate_angle &&
- this->bridge == rhs.bridge &&
- this->bridge_angle == rhs.bridge_angle &&
- this->density == rhs.density &&
-// this->dont_adjust == rhs.dont_adjust &&
- this->anchor_length == rhs.anchor_length &&
- this->anchor_length_max == rhs.anchor_length_max &&
- this->flow == rhs.flow &&
- 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->lattice_angle_1 == rhs.lattice_angle_1 &&
- this->lattice_angle_2 == rhs.lattice_angle_2;
- }
+ bool operator==(const SurfaceFillParams &rhs) const {
+ return this->extruder == rhs.extruder &&
+ this->pattern == rhs.pattern &&
+ this->spacing == rhs.spacing &&
+ this->overlap == rhs.overlap &&
+ this->angle == rhs.angle &&
+ this->rotate_angle == rhs.rotate_angle &&
+ this->bridge == rhs.bridge &&
+ this->bridge_angle == rhs.bridge_angle &&
+ this->density == rhs.density &&
+// this->dont_adjust == rhs.dont_adjust &&
+ this->anchor_length == rhs.anchor_length &&
+ this->anchor_length_max == rhs.anchor_length_max &&
+ this->flow == rhs.flow &&
+ 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->lattice_angle_1 == rhs.lattice_angle_1 &&
+ this->lattice_angle_2 == rhs.lattice_angle_2 &&
+ this->infill_overhang_angle == rhs.infill_overhang_angle;
+ }
};
struct SurfaceFill {
@@ -622,6 +627,7 @@ std::vector group_fills(const Layer &layer)
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;
+ params.infill_overhang_angle = region_config.infill_overhang_angle;
if (surface.is_solid()) {
params.density = 100.f;
@@ -966,6 +972,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
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;
+ params.infill_overhang_angle = surface_fill.params.infill_overhang_angle;
// BBS
params.flow = surface_fill.params.flow;
@@ -1046,6 +1053,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
case ipLine:
case ipConcentric:
case ipHoneycomb:
+ case ip2DHoneycomb:
case ip3DHoneycomb:
case ipGyroid:
case ipTpmsD:
@@ -1097,6 +1105,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
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;
+ params.infill_overhang_angle = surface_fill.params.infill_overhang_angle;
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 619f67036c..3b2f5bcc5c 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -40,6 +40,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
switch (type) {
case ipConcentric: return new FillConcentric();
case ipHoneycomb: return new FillHoneycomb();
+ case ip2DHoneycomb: return new Fill2DHoneycomb();
case ip3DHoneycomb: return new Fill3DHoneycomb();
case ipGyroid: return new FillGyroid();
case ipTpmsD: return new FillTpmsD();//from creality print
diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp
index 01aaf38d28..62eeb9000e 100644
--- a/src/libslic3r/Fill/FillBase.hpp
+++ b/src/libslic3r/Fill/FillBase.hpp
@@ -73,6 +73,9 @@ struct FillParams
coordf_t lattice_angle_1 { 0.f };
coordf_t lattice_angle_2 { 0.f };
+ // For 2D Honeycomb
+ float infill_overhang_angle { 60 };
+
// BBS
Flow flow;
ExtrusionRole extrusion_role{ ExtrusionRole(0) };
diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp
index 7fe310e14b..6948cfd799 100644
--- a/src/libslic3r/Fill/FillRectilinear.cpp
+++ b/src/libslic3r/Fill/FillRectilinear.cpp
@@ -3093,6 +3093,66 @@ Polylines FillQuarterCubic::fill_surface(const Surface* surface, const FillParam
return polylines_out;
}
+Polylines Fill2DHoneycomb::fill_surface(const Surface *surface, const FillParams ¶ms)
+{
+ // the 2D honeycomb is generated based on a base pattern of an inverted Y with its junction at height zero
+ // |
+ // |
+ // 0 --+--
+ // / \
+ // why inverted?
+ // it makes determining some of the properties easier
+ // and the two angled legs provide additional horizontal stiffness
+ // the additional horizontal stiffness is not required close to the bed (unless you don't have any kind of bottom or flange)
+
+ using namespace boost::math::float_constants;
+
+ // lets begin calculating some base properties of the honeycomb pattern
+ const float half_horizontal_period = .5f * (1*(2/3.f) + 2*(1/3.f)) * float(spacing) / params.density;
+ const float vertical_period = 3 * half_horizontal_period / tanf(degree * float(params.infill_overhang_angle));
+
+ // we want to align the base pattern with its knot on height 0
+ // therefore the double line part is 1/3 below and the single line is 2/3 above 0
+ const float vertical_thirds_float = 3 * float(z) / vertical_period;
+ const int vertical_thirds_int = vertical_thirds_float; // converstion to int does implicit floor wich is desired here
+ const bool single_line = (vertical_thirds_int + 1) % 3;
+
+ // the base pattern needs to be horizontally shifted by half every odd pattern layer
+ const bool odd_layer = ((vertical_thirds_int + 1) / 3) % 2;
+ const float horizontal_offset = odd_layer ? half_horizontal_period : 0;
+
+ Polylines polylines_out;
+
+ if (single_line)
+ {
+ FillParams multiline_params = params;
+ multiline_params.density *= 1 / (1*(2/3.) + 2*(1/3.));
+
+ if (!fill_surface_by_multilines(
+ surface, multiline_params,
+ { { half_pi, horizontal_offset } },
+ polylines_out))
+ BOOST_LOG_TRIVIAL(error) << "Fill2DHoneycomb::fill_surface() failed to fill a region.";
+ } else {
+ FillParams multiline_params = params;
+ multiline_params.density *= 2 / (1*(2/3.) + 2*(1/3.));
+
+ const float horizontal_position = (1 - (vertical_thirds_float - vertical_thirds_int)) * half_horizontal_period;
+
+ if (!fill_surface_by_multilines(
+ surface, multiline_params,
+ { { half_pi, -horizontal_position + horizontal_offset }, { half_pi, horizontal_position + horizontal_offset } },
+ polylines_out))
+ BOOST_LOG_TRIVIAL(error) << "Fill2DHoneycomb::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 FillSupportBase::fill_surface(const Surface *surface, const FillParams ¶ms)
{
assert(! params.full_infill());
diff --git a/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp
index 58f9afb1df..2dbcad3e90 100644
--- a/src/libslic3r/Fill/FillRectilinear.hpp
+++ b/src/libslic3r/Fill/FillRectilinear.hpp
@@ -132,6 +132,14 @@ protected:
float _layer_angle(size_t idx) const override { return 0.f; }
};
+class Fill2DHoneycomb : public FillAlignedRectilinear
+{
+public:
+ Fill* clone() const override { return new Fill2DHoneycomb(*this); }
+ ~Fill2DHoneycomb() override = default;
+ Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
+};
+
class FillSupportBase : public FillRectilinear
{
diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp
index f6047fbbb1..e419b5497b 100644
--- a/src/libslic3r/Layer.cpp
+++ b/src/libslic3r/Layer.cpp
@@ -387,6 +387,7 @@ coordf_t Layer::get_sparse_infill_max_void_area()
case ipAlignedRectilinear:
case ipOctagramSpiral:
case ipHilbertCurve:
+ case ip2DHoneycomb:
case ip3DHoneycomb:
case ipArchimedeanChords:
max_void_area = std::max(max_void_area, spacing * spacing);
diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index 2b9119ad5c..5586c4fcff 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -785,7 +785,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", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "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", "lattice_angle_1", "lattice_angle_2", "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", "infill_overhang_angle", "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 650018208b..f134902819 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -152,6 +152,7 @@ static t_config_enum_values s_keys_map_InfillPattern {
{ "monotonic", ipMonotonic },
{ "monotonicline", ipMonotonicLine },
{ "alignedrectilinear", ipAlignedRectilinear },
+ { "2dhoneycomb", ip2DHoneycomb },
{ "3dhoneycomb", ip3DHoneycomb },
{ "hilbertcurve", ipHilbertCurve },
{ "archimedeanchords", ipArchimedeanChords },
@@ -2390,6 +2391,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("honeycomb");
def->enum_values.push_back("adaptivecubic");
def->enum_values.push_back("alignedrectilinear");
+ def->enum_values.push_back("2dhoneycomb");
def->enum_values.push_back("3dhoneycomb");
def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords");
@@ -2411,6 +2413,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Honeycomb"));
def->enum_labels.push_back(L("Adaptive Cubic"));
def->enum_labels.push_back(L("Aligned Rectilinear"));
+ def->enum_labels.push_back(L("2D Honeycomb"));
def->enum_labels.push_back(L("3D Honeycomb"));
def->enum_labels.push_back(L("Hilbert Curve"));
def->enum_labels.push_back(L("Archimedean Chords"));
@@ -2441,6 +2444,16 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(45));
+ def = this->add("infill_overhang_angle", coFloat);
+ def->label = L("Infill overhang angle");
+ def->category = L("Strength");
+ def->tooltip = L("The angle of the infill angled lines. 60° will result in a pure honeycomb.");
+ def->sidetext = L("°");
+ def->min = 15;
+ def->max = 75;
+ def->mode = comAdvanced;
+ def->set_default_value(new ConfigOptionFloat(60));
+
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 fade4a9e3f..92f96761cd 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -58,7 +58,7 @@ enum AuthorizationType {
};
enum InfillPattern : int {
- ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipTpmsD, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
+ ipConcentric, ipRectilinear, ipGrid, ip2DLattice, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipTpmsD, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip2DHoneycomb, ip3DHoneycomb,
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
ipLightning, ipCrossHatch, ipQuarterCubic,
ipCount,
@@ -947,6 +947,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionEnum, sparse_infill_pattern))
((ConfigOptionFloat, lattice_angle_1))
((ConfigOptionFloat, lattice_angle_2))
+ ((ConfigOptionFloat, infill_overhang_angle))
((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 9d12806122..f7f9bca8ce 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -1090,7 +1090,8 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "initial_layer_line_width"
|| opt_key == "small_area_infill_flow_compensation"
|| opt_key == "lattice_angle_1"
- || opt_key == "lattice_angle_2") {
+ || opt_key == "lattice_angle_2"
+ || opt_key == "infill_overhang_angle") {
steps.emplace_back(posInfill);
} else if (opt_key == "sparse_infill_pattern") {
steps.emplace_back(posPrepareInfill);
@@ -3769,7 +3770,8 @@ void PrintObject::combine_infill()
infill_pattern == ipGrid ||
infill_pattern == ip2DLattice ||
infill_pattern == ipLine ||
- infill_pattern == ipHoneycomb) ? 1.5f : 0.5f) *
+ infill_pattern == ipHoneycomb ||
+ infill_pattern == ip2DHoneycomb) ? 1.5f : 0.5f) *
layerms.back()->flow(frSolidInfill).scaled_width();
for (ExPolygon &expoly : intersection)
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index 048cb065fe..78d8aaeff0 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -804,6 +804,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
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);
+
+ toggle_line("infill_overhang_angle", config->opt_enum("sparse_infill_pattern") == InfillPattern::ip2DHoneycomb);
}
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 15c0023cc4..ad32fc6d6c 100644
--- a/src/slic3r/GUI/GUI_Factories.cpp
+++ b/src/slic3r/GUI/GUI_Factories.cpp
@@ -106,7 +106,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},{"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},
+ {"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"lattice_angle_1", "",1},{"lattice_angle_2", "",1},{"infill_overhang_angle", "",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 3ba87e3c40..8ee8b60c77 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -2168,6 +2168,7 @@ void TabPrint::build()
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_overhang_angle");
optgroup->append_single_option_line("infill_anchor_max");
optgroup->append_single_option_line("infill_anchor");
optgroup->append_single_option_line("internal_solid_infill_pattern");