NEW: port Zig Zag infill from Prusa

Thanks to Prusa!
jira: none

original commit message:
ceb13b1faa33ac096fe7ffd89aa222abca119e02
SPE-2405: Add Zig Zag infill that is rectilinear infill but with a consistent pattern between layers.

This Zig Zag infill is inspired by the Zig Zag infill in Cura.

Change-Id: I798affa99f4b5c3bd67f47643e67530fb7c3e0cb
(cherry picked from commit 2808d04d5deef6f99f9618648e46f11de03efc98)
This commit is contained in:
Lukáš Hejl 2024-07-16 15:26:29 +02:00 committed by lane.wei
parent 91df890100
commit ff7eb25c54
20 changed files with 307 additions and 83 deletions

View File

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="10"
height="10"
viewBox="0 0 10 10"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="param_zigzag.svg"
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="81.3"
inkscape:cx="5"
inkscape:cy="5"
inkscape:window-width="2560"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg5" />
<g
clip-path="url(#clip0_8991_35043)"
id="g5">
<rect
x="0.75"
y="0.75"
width="8.5"
height="8.5"
rx="0.25"
stroke="#262E30"
stroke-width="0.5"
id="rect1" />
<path
d="M0.872559 0.918608L9.08702 9.13218"
stroke="#262E30"
stroke-width="0.5"
stroke-linecap="round"
id="path1" />
<path
d="M0.872559 3.73519L6.27013 9.13218"
stroke="#262E30"
stroke-width="0.5"
stroke-linecap="round"
id="path2" />
<path
d="M0.87207 6.43369L3.57086 9.13218"
stroke="#262E30"
stroke-width="0.5"
stroke-linecap="round"
id="path3" />
<path
d="M9.20605 6.19391L3.80848 0.796919"
stroke="#262E30"
stroke-width="0.5"
stroke-linecap="round"
id="path4" />
<path
d="M9.20605 3.49542L6.50727 0.796921"
stroke="#262E30"
stroke-width="0.5"
stroke-linecap="round"
id="path5" />
</g>
<g
clip-path="url(#clip0_8991_35043-1)"
id="g5-5"
transform="rotate(-90,4.9876999,5.0055351)"
style="stroke:#000000;stroke-opacity:1">
<rect
x="0.75"
y="0.75"
width="8.5"
height="8.5"
rx="0.25"
stroke="#262e30"
stroke-width="0.5"
id="rect1-3"
style="stroke:#000000;stroke-opacity:1" />
<path
d="M 0.872559,0.918608 9.08702,9.13218"
stroke="#262e30"
stroke-width="0.5"
stroke-linecap="round"
id="path1-4"
style="stroke:#000000;stroke-opacity:1" />
<path
d="M 0.872559,3.73519 6.27013,9.13218"
stroke="#262e30"
stroke-width="0.5"
stroke-linecap="round"
id="path2-4"
style="stroke:#000000;stroke-opacity:1" />
<path
d="M 0.87207,6.43369 3.57086,9.13218"
stroke="#262e30"
stroke-width="0.5"
stroke-linecap="round"
id="path3-0"
style="stroke:#000000;stroke-opacity:1" />
<path
d="M 9.20605,6.19391 3.80848,0.796919"
stroke="#262e30"
stroke-width="0.5"
stroke-linecap="round"
id="path4-1"
style="stroke:#000000;stroke-opacity:1" />
<path
d="M 9.20605,3.49542 6.50727,0.796921"
stroke="#262e30"
stroke-width="0.5"
stroke-linecap="round"
id="path5-0"
style="stroke:#000000;stroke-opacity:1" />
</g>
<defs
id="defs5">
<clipPath
id="clip0_8991_35043">
<rect
width="10"
height="10"
fill="white"
id="rect5" />
</clipPath>
<clipPath
id="clip0_8991_35043-9">
<rect
width="10"
height="10"
fill="#ffffff"
id="rect5-5"
x="0"
y="0" />
</clipPath>
<clipPath
id="clip0_8991_35043-1">
<rect
width="10"
height="10"
fill="#ffffff"
id="rect5-0"
x="0"
y="0" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -53,6 +53,13 @@ BoundingBox BoundingBox::rotated(double angle, const Point &center) const
return out; return out;
} }
BoundingBox BoundingBox::scaled(double factor) const
{
BoundingBox out(*this);
out.scale(factor);
return out;
}
template <class PointClass> void template <class PointClass> void
BoundingBoxBase<PointClass>::scale(double factor) BoundingBoxBase<PointClass>::scale(double factor)
{ {

View File

@ -211,7 +211,9 @@ public:
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {} BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {}
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {} BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {}
BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; } BoundingBox inflated(coordf_t delta) const noexcept { BoundingBox out(*this); out.offset(delta); return out; }
BoundingBox scaled(double factor) const;
friend BoundingBox get_extents_rotated(const Points &points, double angle); friend BoundingBox get_extents_rotated(const Points &points, double angle);
}; };

View File

@ -558,7 +558,8 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
case ipGyroid: case ipGyroid:
case ipHilbertCurve: case ipHilbertCurve:
case ipArchimedeanChords: case ipArchimedeanChords:
case ipOctagramSpiral: break; case ipOctagramSpiral:
case ipZigZag: break;
} }
// Create the filler object. // Create the filler object.

View File

@ -15,6 +15,10 @@ public:
Fill* clone() const override { return new Fill3DHoneycomb(*this); }; Fill* clone() const override { return new Fill3DHoneycomb(*this); };
~Fill3DHoneycomb() override {} ~Fill3DHoneycomb() override {}
// require bridge flow since most of this pattern hangs in air
bool use_bridge_flow() const override { return true; }
bool is_self_crossing() override { return false; }
protected: protected:
void _fill_surface_single( void _fill_surface_single(
const FillParams &params, const FillParams &params,

View File

@ -71,6 +71,7 @@ protected:
// may not be optimal as the internal infill lines may get extruded before the long infill // may not be optimal as the internal infill lines may get extruded before the long infill
// lines to which the short infill lines are supposed to anchor. // lines to which the short infill lines are supposed to anchor.
bool no_sort() const override { return false; } bool no_sort() const override { return false; }
bool is_self_crossing() override { return true; }
}; };
} // namespace FillAdaptive } // namespace FillAdaptive

View File

@ -56,6 +56,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipConcentricInternal: return new FillConcentricInternal(); case ipConcentricInternal: return new FillConcentricInternal();
// BBS: for bottom and top surface only // BBS: for bottom and top surface only
case ipMonotonicLine: return new FillMonotonicLineWGapFill(); case ipMonotonicLine: return new FillMonotonicLineWGapFill();
case ipZigZag: return new FillZigZag();
default: throw Slic3r::InvalidArgument("unknown type"); default: throw Slic3r::InvalidArgument("unknown type");
} }
} }

View File

@ -123,6 +123,11 @@ public:
// Do not sort the fill lines to optimize the print head path? // Do not sort the fill lines to optimize the print head path?
virtual bool no_sort() const { return false; } virtual bool no_sort() const { return false; }
virtual bool is_self_crossing() = 0;
// Return true if infill has a consistent pattern between layers.
virtual bool has_consistent_pattern() const { return false; }
// Perform the fill. // Perform the fill.
virtual Polylines fill_surface(const Surface *surface, const FillParams &params); virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params); virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
@ -152,7 +157,7 @@ protected:
unsigned int /* thickness_layers */, unsigned int /* thickness_layers */,
const std::pair<float, Point> & /* direction */, const std::pair<float, Point> & /* direction */,
ExPolygon /* expolygon */, ExPolygon /* expolygon */,
Polylines & /* polylines_out */) {}; Polylines & /* polylines_out */) {}
// Used for concentric infill to generate ThickPolylines using Arachne. // Used for concentric infill to generate ThickPolylines using Arachne.
virtual void _fill_surface_single(const FillParams& params, virtual void _fill_surface_single(const FillParams& params,

View File

@ -9,6 +9,7 @@ class FillConcentric : public Fill
{ {
public: public:
~FillConcentric() override = default; ~FillConcentric() override = default;
bool is_self_crossing() override { return false; }
protected: protected:
Fill* clone() const override { return new FillConcentric(*this); }; Fill* clone() const override { return new FillConcentric(*this); };

View File

@ -10,6 +10,7 @@ class FillConcentricInternal : public Fill
public: public:
~FillConcentricInternal() override = default; ~FillConcentricInternal() override = default;
void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) override; void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) override;
bool is_self_crossing() override { return false; }
protected: protected:
Fill* clone() const override { return new FillConcentricInternal(*this); }; Fill* clone() const override { return new FillConcentricInternal(*this); };

View File

@ -14,6 +14,7 @@ class FillCrossHatch : public Fill
public: public:
Fill *clone() const override { return new FillCrossHatch(*this); }; Fill *clone() const override { return new FillCrossHatch(*this); };
~FillCrossHatch() override {} ~FillCrossHatch() override {}
bool is_self_crossing() override { return false; }
protected: protected:
void _fill_surface_single( void _fill_surface_single(

View File

@ -15,6 +15,7 @@ public:
// require bridge flow since most of this pattern hangs in air // require bridge flow since most of this pattern hangs in air
bool use_bridge_flow() const override { return false; } bool use_bridge_flow() const override { return false; }
bool is_self_crossing() override { return false; }
// Correction applied to regular infill angle to maximize printing // Correction applied to regular infill angle to maximize printing
// speed in default configuration (degrees) // speed in default configuration (degrees)

View File

@ -13,6 +13,7 @@ class FillHoneycomb : public Fill
{ {
public: public:
~FillHoneycomb() override {} ~FillHoneycomb() override {}
bool is_self_crossing() override { return false; }
protected: protected:
Fill* clone() const override { return new FillHoneycomb(*this); }; Fill* clone() const override { return new FillHoneycomb(*this); };

View File

@ -20,6 +20,7 @@ class Filler : public Slic3r::Fill
{ {
public: public:
~Filler() override = default; ~Filler() override = default;
bool is_self_crossing() override { return false; }
Generator *generator { nullptr }; Generator *generator { nullptr };
protected: protected:

View File

@ -14,6 +14,7 @@ class FillLine : public Fill
public: public:
Fill* clone() const override { return new FillLine(*this); }; Fill* clone() const override { return new FillLine(*this); };
~FillLine() override = default; ~FillLine() override = default;
bool is_self_crossing() override { return false; }
protected: protected:
void _fill_surface_single( void _fill_surface_single(

View File

@ -37,6 +37,7 @@ class FillPlanePath : public Fill
{ {
public: public:
~FillPlanePath() override = default; ~FillPlanePath() override = default;
bool is_self_crossing() override { return false; }
protected: protected:
void _fill_surface_single( void _fill_surface_single(

View File

@ -1351,8 +1351,11 @@ static SegmentIntersection& end_of_vertical_run(SegmentedIntersectionLine &il, S
return const_cast<SegmentIntersection&>(end_of_vertical_run(std::as_const(il), std::as_const(start))); return const_cast<SegmentIntersection&>(end_of_vertical_run(std::as_const(il), std::as_const(start)));
} }
static void traverse_graph_generate_polylines( static void traverse_graph_generate_polylines(const ExPolygonWithOffset &poly_with_offset,
const ExPolygonWithOffset& poly_with_offset, const FillParams& params, const coord_t link_max_length, std::vector<SegmentedIntersectionLine>& segs, Polylines& polylines_out) const FillParams &params,
std::vector<SegmentedIntersectionLine> &segs,
const bool consistent_pattern,
Polylines &polylines_out)
{ {
// For each outer only chords, measure their maximum distance to the bow of the outer contour. // For each outer only chords, measure their maximum distance to the bow of the outer contour.
// Mark an outer only chord as consumed, if the distance is low. // Mark an outer only chord as consumed, if the distance is low.
@ -1386,39 +1389,33 @@ static void traverse_graph_generate_polylines(
pointLast = polylines_out.back().points.back(); pointLast = polylines_out.back().points.back();
for (;;) { for (;;) {
if (i_intersection == -1) { if (i_intersection == -1) {
// The path has been interrupted. Find a next starting point, closest to the previous extruder position. // The path has been interrupted. Find a next starting point.
coordf_t dist2min = std::numeric_limits<coordf_t>().max(); for (int i_vline2 = 0; i_vline2 < int(segs.size()); ++i_vline2) {
for (int i_vline2 = 0; i_vline2 < int(segs.size()); ++ i_vline2) {
const SegmentedIntersectionLine &vline = segs[i_vline2]; const SegmentedIntersectionLine &vline = segs[i_vline2];
if (! vline.intersections.empty()) { if (!vline.intersections.empty()) {
assert(vline.intersections.size() > 1); assert(vline.intersections.size() > 1);
// Even number of intersections with the loops. // Even number of intersections with the loops.
assert((vline.intersections.size() & 1) == 0); assert((vline.intersections.size() & 1) == 0);
assert(vline.intersections.front().type == SegmentIntersection::OUTER_LOW); assert(vline.intersections.front().type == SegmentIntersection::OUTER_LOW);
for (int i = 0; i < int(vline.intersections.size()); ++ i) {
const SegmentIntersection& intrsctn = vline.intersections[i]; // For infill that needs to be consistent between layers (like Zig Zag),
// we are switching between forward and backward passes based on the line index.
const bool forward_pass = !consistent_pattern || (i_vline2 % 2 == 0);
for (int i = 0; i < int(vline.intersections.size()); ++i) {
const int intrsctn_idx = forward_pass ? i : int(vline.intersections.size()) - i - 1;
const SegmentIntersection &intrsctn = vline.intersections[intrsctn_idx];
if (intrsctn.is_outer()) { if (intrsctn.is_outer()) {
assert(intrsctn.is_low() || i > 0); assert(intrsctn.is_low() || intrsctn_idx > 0);
bool consumed = intrsctn.is_low() ? const bool consumed = intrsctn.is_low() ? intrsctn.consumed_vertical_up : vline.intersections[intrsctn_idx - 1].consumed_vertical_up;
intrsctn.consumed_vertical_up : if (!consumed) {
vline.intersections[i - 1].consumed_vertical_up;
if (! consumed) {
coordf_t dist2 = sqr(coordf_t(pointLast(0) - vline.pos)) + sqr(coordf_t(pointLast(1) - intrsctn.pos()));
if (dist2 < dist2min) {
dist2min = dist2;
i_vline = i_vline2; i_vline = i_vline2;
i_intersection = i; i_intersection = intrsctn_idx;
//FIXME We are taking the first left point always. Verify, that the caller chains the paths
// by a shortest distance, while reversing the paths if needed.
//if (polylines_out.empty())
// Initial state, take the first line, which is the first from the left.
goto found; goto found;
} }
} }
} }
} }
} }
}
if (i_intersection == -1) if (i_intersection == -1)
// We are finished. // We are finished.
break; break;
@ -1486,9 +1483,13 @@ static void traverse_graph_generate_polylines(
// 1) Find possible connection points on the previous / next vertical line. // 1) Find possible connection points on the previous / next vertical line.
int i_prev = it->left_horizontal(); int i_prev = it->left_horizontal();
int i_next = it->right_horizontal(); int i_next = it->right_horizontal();
bool intersection_prev_valid = intersection_on_prev_vertical_line_valid(segs, i_vline, i_intersection);
// To ensure pattern consistency between layers for Zig Zag infill, we always
// try to connect to the next vertical line and never to the previous vertical line.
bool intersection_prev_valid = intersection_on_prev_vertical_line_valid(segs, i_vline, i_intersection) && !consistent_pattern;
bool intersection_next_valid = intersection_on_next_vertical_line_valid(segs, i_vline, i_intersection); bool intersection_next_valid = intersection_on_next_vertical_line_valid(segs, i_vline, i_intersection);
bool intersection_horizontal_valid = intersection_prev_valid || intersection_next_valid; bool intersection_horizontal_valid = intersection_prev_valid || intersection_next_valid;
// Mark both the left and right connecting segment as consumed, because one cannot go to this intersection point as it has been consumed. // Mark both the left and right connecting segment as consumed, because one cannot go to this intersection point as it has been consumed.
if (i_prev != -1) if (i_prev != -1)
segs[i_vline - 1].intersections[i_prev].consumed_perimeter_right = true; segs[i_vline - 1].intersections[i_prev].consumed_perimeter_right = true;
@ -2736,6 +2737,17 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
} }
} }
// The extended bounding box of the whole object that covers any rotation of every layer.
BoundingBox FillRectilinear::extended_object_bounding_box() const {
BoundingBox out = this->bounding_box;
out.merge(Point(out.min.y(), out.min.x()));
out.merge(Point(out.max.y(), out.max.x()));
// The bounding box is scaled by sqrt(2.) to ensure that the bounding box
// covers any possible rotations.
return out.scaled(sqrt(2.));
}
bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams &params, float angleBase, float pattern_shift, Polylines &polylines_out) bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams &params, float angleBase, float pattern_shift, Polylines &polylines_out)
{ {
// At the end, only the new polylines will be rotated back. // At the end, only the new polylines will be rotated back.
@ -2765,11 +2777,14 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
return true; return true;
} }
BoundingBox bounding_box = poly_with_offset.bounding_box_src(); // For infill that needs to be consistent between layers (like Zig Zag),
// we use bounding box of whole object to match vertical lines between layers.
BoundingBox bounding_box_src = poly_with_offset.bounding_box_src();
BoundingBox bounding_box = this->has_consistent_pattern() ? this->extended_object_bounding_box() : bounding_box_src;
// define flow spacing according to requested density // define flow spacing according to requested density
if (params.full_infill() && !params.dont_adjust) { if (params.full_infill() && !params.dont_adjust) {
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing); line_spacing = this->_adjust_solid_spacing(bounding_box_src.size().x(), line_spacing);
this->spacing = unscale<double>(line_spacing); this->spacing = unscale<double>(line_spacing);
} else { } else {
// extend bounding box so that our pattern will be aligned with other layers // extend bounding box so that our pattern will be aligned with other layers
@ -2847,8 +2862,9 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
std::vector<MonotonicRegionLink> path = chain_monotonic_regions(regions, poly_with_offset, segs, rng); std::vector<MonotonicRegionLink> path = chain_monotonic_regions(regions, poly_with_offset, segs, rng);
polylines_from_paths(path, poly_with_offset, segs, polylines_out); polylines_from_paths(path, poly_with_offset, segs, polylines_out);
} }
} else } else {
traverse_graph_generate_polylines(poly_with_offset, params, this->link_max_length, segs, polylines_out); traverse_graph_generate_polylines(poly_with_offset, params, segs, this->has_consistent_pattern(), polylines_out);
}
#ifdef SLIC3R_DEBUG #ifdef SLIC3R_DEBUG
{ {

View File

@ -15,6 +15,7 @@ public:
Fill* clone() const override { return new FillRectilinear(*this); } Fill* clone() const override { return new FillRectilinear(*this); }
~FillRectilinear() override = default; ~FillRectilinear() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override; Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return false; }
protected: protected:
// Fill by single directional lines, interconnect the lines along perimeters. // Fill by single directional lines, interconnect the lines along perimeters.
@ -27,6 +28,9 @@ protected:
float pattern_shift; float pattern_shift;
}; };
bool fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out); bool fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out);
// The extended bounding box of the whole object that covers any rotation of every layer.
BoundingBox extended_object_bounding_box() const;
}; };
class FillAlignedRectilinear : public FillRectilinear class FillAlignedRectilinear : public FillRectilinear
@ -64,6 +68,7 @@ public:
Fill* clone() const override { return new FillGrid(*this); } Fill* clone() const override { return new FillGrid(*this); }
~FillGrid() override = default; ~FillGrid() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override; Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected: protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -76,6 +81,7 @@ public:
Fill* clone() const override { return new FillTriangles(*this); } Fill* clone() const override { return new FillTriangles(*this); }
~FillTriangles() override = default; ~FillTriangles() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override; Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected: protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -88,6 +94,7 @@ public:
Fill* clone() const override { return new FillStars(*this); } Fill* clone() const override { return new FillStars(*this); }
~FillStars() override = default; ~FillStars() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override; Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected: protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -100,6 +107,7 @@ public:
Fill* clone() const override { return new FillCubic(*this); } Fill* clone() const override { return new FillCubic(*this); }
~FillCubic() override = default; ~FillCubic() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override; Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool is_self_crossing() override { return true; }
protected: protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
@ -123,6 +131,7 @@ class FillMonotonicLineWGapFill : public Fill
public: public:
~FillMonotonicLineWGapFill() override = default; ~FillMonotonicLineWGapFill() override = default;
void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) override; void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) override;
bool is_self_crossing() override { return false; }
protected: protected:
Fill* clone() const override { return new FillMonotonicLineWGapFill(*this); }; Fill* clone() const override { return new FillMonotonicLineWGapFill(*this); };
@ -132,9 +141,18 @@ private:
void fill_surface_by_lines(const Surface* surface, const FillParams& params, Polylines& polylines_out); void fill_surface_by_lines(const Surface* surface, const FillParams& params, Polylines& polylines_out);
}; };
Points sample_grid_pattern(const ExPolygon& expolygon, coord_t spacing, const BoundingBox& global_bounding_box); class FillZigZag : public FillRectilinear
Points sample_grid_pattern(const ExPolygons& expolygons, coord_t spacing, const BoundingBox& global_bounding_box); {
Points sample_grid_pattern(const Polygons& polygons, coord_t spacing, const BoundingBox& global_bounding_box); public:
Fill* clone() const override { return new FillZigZag(*this); }
~FillZigZag() override = default;
bool has_consistent_pattern() const override { return true; }
};
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box);
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing, const BoundingBox &global_bounding_box);
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box);
} // namespace Slic3r } // namespace Slic3r

View File

@ -148,7 +148,8 @@ static t_config_enum_values s_keys_map_InfillPattern {
{ "octagramspiral", ipOctagramSpiral }, { "octagramspiral", ipOctagramSpiral },
{ "supportcubic", ipSupportCubic }, { "supportcubic", ipSupportCubic },
{ "lightning", ipLightning }, { "lightning", ipLightning },
{ "crosshatch", ipCrossHatch} { "crosshatch", ipCrossHatch},
{ "zigzag", ipZigZag }
}; };
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern) CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern)
@ -1963,6 +1964,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("supportcubic"); def->enum_values.push_back("supportcubic");
def->enum_values.push_back("lightning"); def->enum_values.push_back("lightning");
def->enum_values.push_back("crosshatch"); def->enum_values.push_back("crosshatch");
def->enum_values.push_back("zigzag");
def->enum_labels.push_back(L("Concentric")); def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Grid")); def->enum_labels.push_back(L("Grid"));
@ -1981,6 +1983,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Support Cubic")); def->enum_labels.push_back(L("Support Cubic"));
def->enum_labels.push_back(L("Lightning")); def->enum_labels.push_back(L("Lightning"));
def->enum_labels.push_back(L("Cross Hatch")); def->enum_labels.push_back(L("Cross Hatch"));
def->enum_labels.push_back(L("Zig Zag"));
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipCubic)); def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipCubic));
def = this->add("top_surface_acceleration", coFloats); def = this->add("top_surface_acceleration", coFloats);

View File

@ -54,7 +54,7 @@ enum AuthorizationType {
enum InfillPattern : int { enum InfillPattern : int {
ipConcentric, ipRectilinear, ipGrid, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb, ipConcentric, ipRectilinear, ipGrid, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
ipLightning, ipCrossHatch, ipLightning, ipCrossHatch, ipZigZag,
ipCount, ipCount,
}; };