diff --git a/resources/images/param_flippingline.svg b/resources/images/param_flippingline.svg
new file mode 100644
index 000000000..03a1f04a7
--- /dev/null
+++ b/resources/images/param_flippingline.svg
@@ -0,0 +1,570 @@
+
+
diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt
index f93f233d2..b63f58ec0 100644
--- a/src/libslic3r/CMakeLists.txt
+++ b/src/libslic3r/CMakeLists.txt
@@ -84,6 +84,8 @@ set(lisbslic3r_sources
Fill/FillConcentric.hpp
Fill/FillConcentricInternal.cpp
Fill/FillConcentricInternal.hpp
+ Fill/FillFlippingLine.cpp
+ Fill/FillFlippingLine.hpp
Fill/FillHoneycomb.cpp
Fill/FillHoneycomb.hpp
Fill/FillGyroid.cpp
diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp
index 49a715c43..19d535e1e 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -23,6 +23,7 @@
#include "FillLightning.hpp"
// BBS: new infill pattern header
#include "FillConcentricInternal.hpp"
+#include "FillFlippingLine.hpp"
// #define INFILL_DEBUG_OUTPUT
@@ -37,6 +38,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipGyroid: return new FillGyroid();
case ipRectilinear: return new FillRectilinear();
case ipAlignedRectilinear: return new FillAlignedRectilinear();
+ case ipFlippingLine: return new FillFlippingLine();
case ipMonotonic: return new FillMonotonic();
case ipLine: return new FillLine();
case ipGrid: return new FillGrid();
diff --git a/src/libslic3r/Fill/FillFlippingLine.cpp b/src/libslic3r/Fill/FillFlippingLine.cpp
new file mode 100644
index 000000000..fe6f56759
--- /dev/null
+++ b/src/libslic3r/Fill/FillFlippingLine.cpp
@@ -0,0 +1,235 @@
+#include "../ClipperUtils.hpp"
+#include "../ShortestPath.hpp"
+#include "../Surface.hpp"
+
+#include "FillFlippingLine.hpp"
+
+namespace Slic3r {
+
+// FlipLines Infill: Enhances 3D Printing Speed & Reduces Noise
+// FlipLines, as its name hints, alternates line direction by 90 degrees every few layers to improve adhesion.
+// It introduces transform layers between direction shifts for better line cohesion, which fixes the weakness of line infill.
+// The transform technique is inspired by David Eccles, improved 3D honeycomb but also a more flexible implementation.
+// This method notably increases printing speed, meeting the demands of modern high-speed 3D printers, and reduces noise for most layers.
+// By Bambu Lab
+
+// graph credits: David Eccles (gringer).
+// But we made a different definition for points.
+/* o---o
+ * / \
+ * / \
+ * \ /
+ * \ /
+ * o---o
+ * p1 p2 p3 p4
+ *
+ * // X1 = progress * (1/8) * period
+ * // X2 = ( (1/2 - progress) * (1/8) ) * period
+ * // X3 = X1 + (1/2) * period
+ * // X4 = ( (1 - progress) * (1/8) ) * period
+ * // Y1 = X1
+ * // Y2 = X1
+ * // Y3 = -X1
+ * // Y4 = -X1
+ */
+
+static Pointfs generate_one_cycle(double progress, coordf_t period)
+{
+ Pointfs out;
+ double offset = progress * 1. / 8. * period;
+ out.reserve(4);
+ out.push_back(Vec2d(offset, offset));
+ out.push_back(Vec2d(0.5 * period - offset, offset));
+ out.push_back(Vec2d(0.5 * period + offset, -offset));
+ out.push_back(Vec2d(1. * period - offset, -offset));
+ return out;
+}
+
+static Polylines generate_transform_pattern(double inprogress, int direction, coordf_t ingrid_size, coordf_t inwidth, coordf_t inheight)
+{
+ coordf_t width = inwidth;
+ coordf_t height = inheight;
+ coordf_t grid_size = ingrid_size * 2; // we due with odd and even saparately.
+ double progress = inprogress;
+ Polylines out_polylines;
+
+ // generate template patterns;
+ Pointfs one_cycle_points = generate_one_cycle(progress, grid_size);
+
+ Polyline one_cycle;
+ one_cycle.points.reserve(one_cycle_points.size());
+ for (size_t i = 0; i < one_cycle_points.size(); i++) one_cycle.points.push_back(Point(one_cycle_points[i]));
+
+ // swap if vertical
+ if (direction < 0) {
+ width = height;
+ height = inwidth;
+ }
+
+ // replicate polylines;
+ Polylines odd_polylines;
+ Polyline odd_poly;
+ int num_of_cycle = width / grid_size + 2;
+ odd_poly.points.reserve(num_of_cycle * one_cycle.size());
+
+ // replicate to odd line
+ Point translate = Point(0, 0);
+ for (size_t i = 0; i < num_of_cycle; i++) {
+ Polyline odd_points;
+ odd_points = Polyline(one_cycle);
+ odd_points.translate(Point(i * grid_size, 0.0));
+ odd_poly.points.insert(odd_poly.points.end(), odd_points.begin(), odd_points.end());
+ }
+
+ // fill the height
+ int num_of_lines = height / grid_size + 2;
+ odd_polylines.reserve(num_of_lines * odd_poly.size());
+ for (size_t i = 0; i < num_of_lines; i++) {
+ Polyline poly = odd_poly;
+ poly.translate(Point(0.0, grid_size * i));
+ odd_polylines.push_back(poly);
+ }
+ // save to output
+ out_polylines.insert(out_polylines.end(), odd_polylines.begin(), odd_polylines.end());
+
+ // replicate to even lines
+ Polylines even_polylines;
+ even_polylines.reserve(odd_polylines.size());
+ for (size_t i = 0; i < odd_polylines.size(); i++) {
+ Polyline even = odd_poly;
+ even.translate(Point(-0.5 * grid_size, (i + 0.5) * grid_size));
+ even_polylines.push_back(even);
+ }
+
+ // save for output
+ out_polylines.insert(out_polylines.end(), even_polylines.begin(), even_polylines.end());
+
+ // change to vertical if need
+ if (direction < 0) {
+ // swap xy, see if we need better performance method
+ for (Polyline &poly : out_polylines) {
+ for (Point &p : poly) { std::swap(p.x(), p.y()); }
+ }
+ }
+
+ return out_polylines;
+}
+
+static Polylines generate_repeat_pattern(int direction, coordf_t grid_size, coordf_t inwidth, coordf_t inheight)
+{
+ coordf_t width = inwidth;
+ coordf_t height = inheight;
+ Polylines out_polylines;
+
+ // swap if vertical
+ if (direction < 0) {
+ width = height;
+ height = inwidth;
+ }
+
+ int num_of_lines = height / grid_size + 1;
+ out_polylines.reserve(num_of_lines);
+
+ for (int i = 0; i < num_of_lines; i++) {
+ Polyline poly;
+ poly.points.reserve(2);
+ poly.append(Point(coordf_t(0), coordf_t(grid_size * i)));
+ poly.append(Point(width, coordf_t(grid_size * i)));
+ out_polylines.push_back(poly);
+ }
+
+ // change to vertical if needed
+ if (direction < 0) {
+ // swap xy
+ for (Polyline &poly : out_polylines) {
+ for (Point &p : poly) { std::swap(p.x(), p.y()); }
+ }
+ }
+
+ return out_polylines;
+}
+
+// it makes the real patterns that overlap the bounding box
+// repeat_ratio define the ratio between the height of repeat pattern and grid
+static Polylines generate_infill_layers(coordf_t z_height, double repeat_ratio, coordf_t grid_size, coordf_t width, coordf_t height)
+{
+ Polylines result;
+ coordf_t trans_layer_size = grid_size * 0.3; // upper.
+ coordf_t repeat_layer_size = grid_size * repeat_ratio; // lower.
+ coordf_t period = trans_layer_size + repeat_layer_size;
+ coordf_t remains = z_height - std::floor(z_height / period) * period;
+ coordf_t trans_z = remains - repeat_layer_size; // put repeat layer first.
+ coordf_t repeat_z = remains;
+
+ int phase = fmod(z_height, period * 2) - (period - 1); // add epsilon
+ int direction = phase <= 0 ? -1 : 1;
+
+ // this is a repeat layer
+ if (trans_z < 0) {
+ result = generate_repeat_pattern(direction, grid_size, width, height);
+ }
+ // this is a transform layer
+ else {
+ double progress = fmod(trans_z, trans_layer_size) / trans_layer_size;
+
+ // split the progress to forward and backward, with a opposite direction.
+ if (progress < 0.5)
+ result = generate_transform_pattern(progress * 2, direction, grid_size, width, height);
+ else
+ result = generate_transform_pattern((1 - progress) * 2, -1 * direction, grid_size, width, height);
+ }
+
+ return result;
+}
+
+void FillFlippingLine ::_fill_surface_single(
+ const FillParams ¶ms, unsigned int thickness_layers, const std::pair &direction, ExPolygon expolygon, Polylines &polylines_out)
+{
+ // rotate angle
+ auto infill_angle = float(this->angle);
+ if (std::abs(infill_angle) >= EPSILON) expolygon.rotate(-infill_angle);
+
+ // get the rotated bounding box
+ BoundingBox bb = expolygon.contour.bounding_box();
+
+ // linespace modifier
+ coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
+
+ // reduce density
+ if (params.density < 0.999) line_spacing *= 1.5;
+
+ bb.merge(align_to_grid(bb.min, Point(line_spacing * 4, line_spacing * 4)));
+
+ // generate pattern
+ Polylines polylines = generate_infill_layers(scale_(this->z), 1, line_spacing, bb.size()(0), bb.size()(1));
+
+ // shift the pattern to the actual space
+ for (Polyline &pl : polylines) { pl.translate(bb.min); }
+
+ polylines = intersection_pl(polylines, to_polygons(expolygon));
+
+ // --- remove small remains from gyroid infill
+ if (!polylines.empty()) {
+ // Remove very small bits, but be careful to not remove infill lines connecting thin walls!
+ // The infill perimeter lines should be separated by around a single infill line width.
+ const double minlength = scale_(0.8 * this->spacing);
+ polylines.erase(std::remove_if(polylines.begin(), polylines.end(), [minlength](const Polyline &pl)
+ { return pl.length() < minlength; }), polylines.end());
+ }
+
+ if (!polylines.empty()) {
+ int infill_start_idx = polylines_out.size(); // only rotate what belongs to us.
+ // connect lines
+ if (params.dont_connect() || polylines.size() <= 1)
+ append(polylines_out, chain_polylines(std::move(polylines)));
+ else
+ this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
+
+ // rotate back
+ if (std::abs(infill_angle) >= EPSILON) {
+ for (auto it = polylines_out.begin() + infill_start_idx; it != polylines_out.end(); ++it) it->rotate(infill_angle);
+ }
+ }
+}
+
+} // namespace Slic3r
\ No newline at end of file
diff --git a/src/libslic3r/Fill/FillFlippingLine.hpp b/src/libslic3r/Fill/FillFlippingLine.hpp
new file mode 100644
index 000000000..3bf576c14
--- /dev/null
+++ b/src/libslic3r/Fill/FillFlippingLine.hpp
@@ -0,0 +1,29 @@
+#ifndef slic3r_FillFlippingLines_hpp_
+#define slic3r_FillFlippingLines_hpp_
+
+#include