Add 2D honeycomb infill pattern (#9483)

* Add 2D honeycomb infill pattern

* Reverted change of 2D lattice infill void area estimation

---------

Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
Henk
2025-06-18 02:48:48 +02:00
committed by GitHub
parent dd6b0fb793
commit 0010dc6bb4
14 changed files with 131 additions and 26 deletions

View File

@@ -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<SurfaceFill> 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.

View File

@@ -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

View File

@@ -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) };

View File

@@ -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 &params)
{
// 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 &params)
{
assert(! params.full_infill());

View File

@@ -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 &params) override;
};
class FillSupportBase : public FillRectilinear
{