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:
parent
91df890100
commit
ff7eb25c54
|
@ -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 |
|
@ -53,6 +53,13 @@ BoundingBox BoundingBox::rotated(double angle, const Point ¢er) 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -543,23 +543,24 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
|
||||||
//case ipEnsuring: continue; break;
|
//case ipEnsuring: continue; break;
|
||||||
case ipLightning:
|
case ipLightning:
|
||||||
case ipAdaptiveCubic:
|
case ipAdaptiveCubic:
|
||||||
case ipSupportCubic:
|
case ipSupportCubic:
|
||||||
case ipRectilinear:
|
case ipRectilinear:
|
||||||
case ipMonotonic:
|
case ipMonotonic:
|
||||||
case ipAlignedRectilinear:
|
case ipAlignedRectilinear:
|
||||||
case ipGrid:
|
case ipGrid:
|
||||||
case ipTriangles:
|
case ipTriangles:
|
||||||
case ipStars:
|
case ipStars:
|
||||||
case ipCubic:
|
case ipCubic:
|
||||||
case ipLine:
|
case ipLine:
|
||||||
case ipConcentric:
|
case ipConcentric:
|
||||||
case ipHoneycomb:
|
case ipHoneycomb:
|
||||||
case ip3DHoneycomb:
|
case ip3DHoneycomb:
|
||||||
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.
|
||||||
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(surface_fill.params.pattern));
|
std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(surface_fill.params.pattern));
|
||||||
|
|
|
@ -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 ¶ms,
|
const FillParams ¶ms,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +168,7 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||||
|
|
||||||
// Calculate a new spacing to fill width with possibly integer number of lines,
|
// Calculate a new spacing to fill width with possibly integer number of lines,
|
||||||
// the first and last line being centered at the interval ends.
|
// the first and last line being centered at the interval ends.
|
||||||
// This function possibly increases the spacing, never decreases,
|
// This function possibly increases the spacing, never decreases,
|
||||||
// and for a narrow width the increase in spacing may become severe,
|
// and for a narrow width the increase in spacing may become severe,
|
||||||
// therefore the adjustment is limited to 20% increase.
|
// therefore the adjustment is limited to 20% increase.
|
||||||
coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
||||||
|
@ -176,8 +177,8 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
||||||
assert(distance > 0);
|
assert(distance > 0);
|
||||||
// floor(width / distance)
|
// floor(width / distance)
|
||||||
const auto number_of_intervals = coord_t((width - EPSILON) / distance);
|
const auto number_of_intervals = coord_t((width - EPSILON) / distance);
|
||||||
coord_t distance_new = (number_of_intervals == 0) ?
|
coord_t distance_new = (number_of_intervals == 0) ?
|
||||||
distance :
|
distance :
|
||||||
coord_t((width - EPSILON) / number_of_intervals);
|
coord_t((width - EPSILON) / number_of_intervals);
|
||||||
const coordf_t factor = coordf_t(distance_new) / coordf_t(distance);
|
const coordf_t factor = coordf_t(distance_new) / coordf_t(distance);
|
||||||
assert(factor > 1. - 1e-5);
|
assert(factor > 1. - 1e-5);
|
||||||
|
@ -203,8 +204,8 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
||||||
|
|
||||||
// Bounding box is the bounding box of a perl object Slic3r::Print::Object (c++ object Slic3r::PrintObject)
|
// Bounding box is the bounding box of a perl object Slic3r::Print::Object (c++ object Slic3r::PrintObject)
|
||||||
// The bounding box is only undefined in unit tests.
|
// The bounding box is only undefined in unit tests.
|
||||||
Point out_shift = empty(this->bounding_box) ?
|
Point out_shift = empty(this->bounding_box) ?
|
||||||
surface->expolygon.contour.bounding_box().center() :
|
surface->expolygon.contour.bounding_box().center() :
|
||||||
this->bounding_box.center();
|
this->bounding_box.center();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -278,10 +279,10 @@ struct ContourIntersectionPoint {
|
||||||
bool could_take_next() const throw() { return ! this->consumed && this->contour_not_taken_length_next > SCALED_EPSILON; }
|
bool could_take_next() const throw() { return ! this->consumed && this->contour_not_taken_length_next > SCALED_EPSILON; }
|
||||||
|
|
||||||
// Could extrude a complete segment from this to this->prev_on_contour.
|
// Could extrude a complete segment from this to this->prev_on_contour.
|
||||||
bool could_connect_prev() const throw()
|
bool could_connect_prev() const throw()
|
||||||
{ return ! this->consumed && this->prev_on_contour != this && ! this->prev_on_contour->consumed && ! this->prev_trimmed && ! this->prev_on_contour->next_trimmed; }
|
{ return ! this->consumed && this->prev_on_contour != this && ! this->prev_on_contour->consumed && ! this->prev_trimmed && ! this->prev_on_contour->next_trimmed; }
|
||||||
// Could extrude a complete segment from this to this->next_on_contour.
|
// Could extrude a complete segment from this to this->next_on_contour.
|
||||||
bool could_connect_next() const throw()
|
bool could_connect_next() const throw()
|
||||||
{ return ! this->consumed && this->next_on_contour != this && ! this->next_on_contour->consumed && ! this->next_trimmed && ! this->next_on_contour->prev_trimmed; }
|
{ return ! this->consumed && this->next_on_contour != this && ! this->next_on_contour->consumed && ! this->next_trimmed && ! this->next_on_contour->prev_trimmed; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -490,7 +491,7 @@ static void take(Polyline &pl1, const Polyline &pl2, const Points &contour, Cont
|
||||||
}
|
}
|
||||||
|
|
||||||
static void take_limited(
|
static void take_limited(
|
||||||
Polyline &pl1, const Points &contour, const std::vector<double> ¶ms,
|
Polyline &pl1, const Points &contour, const std::vector<double> ¶ms,
|
||||||
ContourIntersectionPoint *cp_start, ContourIntersectionPoint *cp_end, bool clockwise, double take_max_length, double line_half_width)
|
ContourIntersectionPoint *cp_start, ContourIntersectionPoint *cp_end, bool clockwise, double take_max_length, double line_half_width)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -654,8 +655,8 @@ static inline SegmentPoint clip_end_segment_and_point(const Points &polyline, do
|
||||||
// Calculate intersection of a line with a thick segment.
|
// Calculate intersection of a line with a thick segment.
|
||||||
// Returns Eucledian parameters of the line / thick segment overlap.
|
// Returns Eucledian parameters of the line / thick segment overlap.
|
||||||
static inline bool line_rounded_thick_segment_collision(
|
static inline bool line_rounded_thick_segment_collision(
|
||||||
const Vec2d &line_a, const Vec2d &line_b,
|
const Vec2d &line_a, const Vec2d &line_b,
|
||||||
const Vec2d &segment_a, const Vec2d &segment_b, const double offset,
|
const Vec2d &segment_a, const Vec2d &segment_b, const double offset,
|
||||||
std::pair<double, double> &out_interval)
|
std::pair<double, double> &out_interval)
|
||||||
{
|
{
|
||||||
const Vec2d line_v0 = line_b - line_a;
|
const Vec2d line_v0 = line_b - line_a;
|
||||||
|
@ -718,8 +719,8 @@ static inline bool line_rounded_thick_segment_collision(
|
||||||
std::pair<double, double> interval;
|
std::pair<double, double> interval;
|
||||||
if (Geometry::liang_barsky_line_clipping_interval(
|
if (Geometry::liang_barsky_line_clipping_interval(
|
||||||
Vec2d(line_p0.dot(dir_x), line_p0.dot(dir_y)),
|
Vec2d(line_p0.dot(dir_x), line_p0.dot(dir_y)),
|
||||||
Vec2d(line_v0.dot(dir_x), line_v0.dot(dir_y)),
|
Vec2d(line_v0.dot(dir_x), line_v0.dot(dir_y)),
|
||||||
BoundingBoxf(Vec2d(0., - offset), Vec2d(segment_l, offset)),
|
BoundingBoxf(Vec2d(0., - offset), Vec2d(segment_l, offset)),
|
||||||
interval))
|
interval))
|
||||||
extend_interval(interval.first, interval.second);
|
extend_interval(interval.first, interval.second);
|
||||||
} else
|
} else
|
||||||
|
@ -1079,7 +1080,7 @@ void mark_boundary_segments_touching_infill(
|
||||||
// Clip the infill polyline by the Eucledian distance along the polyline.
|
// Clip the infill polyline by the Eucledian distance along the polyline.
|
||||||
SegmentPoint start_point = clip_start_segment_and_point(polyline.points, clip_distance);
|
SegmentPoint start_point = clip_start_segment_and_point(polyline.points, clip_distance);
|
||||||
SegmentPoint end_point = clip_end_segment_and_point(polyline.points, clip_distance);
|
SegmentPoint end_point = clip_end_segment_and_point(polyline.points, clip_distance);
|
||||||
if (start_point.valid() && end_point.valid() &&
|
if (start_point.valid() && end_point.valid() &&
|
||||||
(start_point.idx_segment < end_point.idx_segment || (start_point.idx_segment == end_point.idx_segment && start_point.t < end_point.t))) {
|
(start_point.idx_segment < end_point.idx_segment || (start_point.idx_segment == end_point.idx_segment && start_point.t < end_point.t))) {
|
||||||
// The clipped polyline is non-empty.
|
// The clipped polyline is non-empty.
|
||||||
#ifdef INFILL_DEBUG_OUTPUT
|
#ifdef INFILL_DEBUG_OUTPUT
|
||||||
|
@ -1219,21 +1220,21 @@ struct BoundaryInfillGraph
|
||||||
};
|
};
|
||||||
|
|
||||||
static Direction dir(const Point &p1, const Point &p2) {
|
static Direction dir(const Point &p1, const Point &p2) {
|
||||||
return p1.x() == p2.x() ?
|
return p1.x() == p2.x() ?
|
||||||
(p1.y() < p2.y() ? Up : Down) :
|
(p1.y() < p2.y() ? Up : Down) :
|
||||||
(p1.x() < p2.x() ? Right : Left);
|
(p1.x() < p2.x() ? Right : Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Direction dir_prev(const ContourIntersectionPoint &cp) const {
|
const Direction dir_prev(const ContourIntersectionPoint &cp) const {
|
||||||
assert(cp.prev_on_contour);
|
assert(cp.prev_on_contour);
|
||||||
return cp.could_take_prev() ?
|
return cp.could_take_prev() ?
|
||||||
dir(this->point(cp), this->point(*cp.prev_on_contour)) :
|
dir(this->point(cp), this->point(*cp.prev_on_contour)) :
|
||||||
Taken;
|
Taken;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Direction dir_next(const ContourIntersectionPoint &cp) const {
|
const Direction dir_next(const ContourIntersectionPoint &cp) const {
|
||||||
assert(cp.next_on_contour);
|
assert(cp.next_on_contour);
|
||||||
return cp.could_take_next() ?
|
return cp.could_take_next() ?
|
||||||
dir(this->point(cp), this->point(*cp.next_on_contour)) :
|
dir(this->point(cp), this->point(*cp.next_on_contour)) :
|
||||||
Taken;
|
Taken;
|
||||||
}
|
}
|
||||||
|
@ -1291,7 +1292,7 @@ static inline void mark_boundary_segments_overlapping_infill(
|
||||||
assert(interval.first == 0.);
|
assert(interval.first == 0.);
|
||||||
double len_out = closed_contour_distance_ccw(contour_params[cp.point_idx], contour_params[i], contour_params.back()) + interval.second;
|
double len_out = closed_contour_distance_ccw(contour_params[cp.point_idx], contour_params[i], contour_params.back()) + interval.second;
|
||||||
if (len_out < cp.contour_not_taken_length_next) {
|
if (len_out < cp.contour_not_taken_length_next) {
|
||||||
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
||||||
// thus at least some of the contour is outside and we will extrude this segment.
|
// thus at least some of the contour is outside and we will extrude this segment.
|
||||||
inside = false;
|
inside = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1323,7 +1324,7 @@ static inline void mark_boundary_segments_overlapping_infill(
|
||||||
assert(interval.first == 0.);
|
assert(interval.first == 0.);
|
||||||
double len_out = closed_contour_distance_cw(contour_params[cp.point_idx], contour_params[i], contour_params.back()) + interval.second;
|
double len_out = closed_contour_distance_cw(contour_params[cp.point_idx], contour_params[i], contour_params.back()) + interval.second;
|
||||||
if (len_out < cp.contour_not_taken_length_prev) {
|
if (len_out < cp.contour_not_taken_length_prev) {
|
||||||
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
// Leaving the infill line region before exiting cp.contour_not_taken_length_next,
|
||||||
// thus at least some of the contour is outside and we will extrude this segment.
|
// thus at least some of the contour is outside and we will extrude this segment.
|
||||||
inside = false;
|
inside = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1420,7 +1421,7 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
||||||
ContourIntersectionPoint *pthis = &out.map_infill_end_point_to_boundary[it->second];
|
ContourIntersectionPoint *pthis = &out.map_infill_end_point_to_boundary[it->second];
|
||||||
if (pprev) {
|
if (pprev) {
|
||||||
pprev->next_on_contour = pthis;
|
pprev->next_on_contour = pthis;
|
||||||
pthis->prev_on_contour = pprev;
|
pthis->prev_on_contour = pprev;
|
||||||
} else
|
} else
|
||||||
pfirst = pthis;
|
pfirst = pthis;
|
||||||
contour_intersection_points.emplace_back(pthis);
|
contour_intersection_points.emplace_back(pthis);
|
||||||
|
@ -1445,7 +1446,7 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
||||||
ip->param = contour_params[ip->point_idx];
|
ip->param = contour_params[ip->point_idx];
|
||||||
// and measure distance to the previous and next intersection point.
|
// and measure distance to the previous and next intersection point.
|
||||||
const double contour_length = contour_params.back();
|
const double contour_length = contour_params.back();
|
||||||
for (ContourIntersectionPoint *ip : contour_intersection_points)
|
for (ContourIntersectionPoint *ip : contour_intersection_points)
|
||||||
if (ip->next_on_contour == ip) {
|
if (ip->next_on_contour == ip) {
|
||||||
assert(ip->prev_on_contour == ip);
|
assert(ip->prev_on_contour == ip);
|
||||||
ip->contour_not_taken_length_prev = ip->contour_not_taken_length_next = contour_length;
|
ip->contour_not_taken_length_prev = ip->contour_not_taken_length_next = contour_length;
|
||||||
|
@ -1839,14 +1840,14 @@ static inline void base_support_extend_infill_lines(Polylines &infill, BoundaryI
|
||||||
// The contour is supposed to enter the "forbidden" zone outside of the (left, right) band at tbegin and also at tend.
|
// The contour is supposed to enter the "forbidden" zone outside of the (left, right) band at tbegin and also at tend.
|
||||||
static inline void emit_loops_in_band(
|
static inline void emit_loops_in_band(
|
||||||
// Vertical band, which will trim the contour between tbegin and tend.
|
// Vertical band, which will trim the contour between tbegin and tend.
|
||||||
coord_t left,
|
coord_t left,
|
||||||
coord_t right,
|
coord_t right,
|
||||||
// Contour and its parametrization.
|
// Contour and its parametrization.
|
||||||
const Points &contour,
|
const Points &contour,
|
||||||
const std::vector<double> &contour_params,
|
const std::vector<double> &contour_params,
|
||||||
// Span of the parameters of an arch to trim with the vertical band.
|
// Span of the parameters of an arch to trim with the vertical band.
|
||||||
double tbegin,
|
double tbegin,
|
||||||
double tend,
|
double tend,
|
||||||
// Minimum arch length to put into polylines_out. Shorter arches are not necessary to support a dense support infill.
|
// Minimum arch length to put into polylines_out. Shorter arches are not necessary to support a dense support infill.
|
||||||
double min_length,
|
double min_length,
|
||||||
Polylines &polylines_out)
|
Polylines &polylines_out)
|
||||||
|
@ -1902,13 +1903,13 @@ static inline void emit_loops_in_band(
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InOutBand {
|
enum InOutBand {
|
||||||
Entering,
|
Entering,
|
||||||
Leaving,
|
Leaving,
|
||||||
};
|
};
|
||||||
|
|
||||||
class State {
|
class State {
|
||||||
public:
|
public:
|
||||||
State(coord_t left, coord_t right, double min_length, Polylines &polylines_out) :
|
State(coord_t left, coord_t right, double min_length, Polylines &polylines_out) :
|
||||||
m_left(left), m_right(right), m_min_length(min_length), m_polylines_out(polylines_out) {}
|
m_left(left), m_right(right), m_min_length(min_length), m_polylines_out(polylines_out) {}
|
||||||
|
|
||||||
void add_inner_point(const Point* p)
|
void add_inner_point(const Point* p)
|
||||||
|
@ -2209,7 +2210,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
||||||
#endif // INFILL_DEBUG_OUTPUT
|
#endif // INFILL_DEBUG_OUTPUT
|
||||||
|
|
||||||
base_support_extend_infill_lines(infill_ordered, graph, spacing, params);
|
base_support_extend_infill_lines(infill_ordered, graph, spacing, params);
|
||||||
|
|
||||||
#ifdef INFILL_DEBUG_OUTPUT
|
#ifdef INFILL_DEBUG_OUTPUT
|
||||||
export_partial_infill_to_svg(debug_out_path("connect_base_support-extended-%03d.svg", iRun), graph, infill_ordered, polylines_out);
|
export_partial_infill_to_svg(debug_out_path("connect_base_support-extended-%03d.svg", iRun), graph, infill_ordered, polylines_out);
|
||||||
#endif // INFILL_DEBUG_OUTPUT
|
#endif // INFILL_DEBUG_OUTPUT
|
||||||
|
@ -2244,7 +2245,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
||||||
};
|
};
|
||||||
|
|
||||||
// Connect infill lines at cp and cpo_next_on_contour.
|
// Connect infill lines at cp and cpo_next_on_contour.
|
||||||
// If the complete arch cannot be taken, then
|
// If the complete arch cannot be taken, then
|
||||||
// if (take_first)
|
// if (take_first)
|
||||||
// take the infill line at cp and an arc from cp towards cp.next_on_contour.
|
// take the infill line at cp and an arc from cp towards cp.next_on_contour.
|
||||||
// else
|
// else
|
||||||
|
@ -2538,7 +2539,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
||||||
for (ContourIntersectionPoint &cp : graph.map_infill_end_point_to_boundary) {
|
for (ContourIntersectionPoint &cp : graph.map_infill_end_point_to_boundary) {
|
||||||
const SupportArcCost &cost_prev = arches[(&cp - graph.map_infill_end_point_to_boundary.data()) * 2];
|
const SupportArcCost &cost_prev = arches[(&cp - graph.map_infill_end_point_to_boundary.data()) * 2];
|
||||||
const SupportArcCost &cost_next = *(&cost_prev + 1);
|
const SupportArcCost &cost_next = *(&cost_prev + 1);
|
||||||
if (cp.contour_not_taken_length_prev > SCALED_EPSILON &&
|
if (cp.contour_not_taken_length_prev > SCALED_EPSILON &&
|
||||||
(cost_prev.self_loop ?
|
(cost_prev.self_loop ?
|
||||||
cost_prev.cost > cap_cost :
|
cost_prev.cost > cap_cost :
|
||||||
cost_prev.cost > cost_veryhigh)) {
|
cost_prev.cost > cost_veryhigh)) {
|
||||||
|
@ -2555,7 +2556,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
||||||
polylines_out.emplace_back(std::move(pl));
|
polylines_out.emplace_back(std::move(pl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cp.contour_not_taken_length_next > SCALED_EPSILON &&
|
if (cp.contour_not_taken_length_next > SCALED_EPSILON &&
|
||||||
(cost_next.self_loop ?
|
(cost_next.self_loop ?
|
||||||
cost_next.cost > cap_cost :
|
cost_next.cost > cap_cost :
|
||||||
cost_next.cost > cost_veryhigh)) {
|
cost_next.cost > cost_veryhigh)) {
|
||||||
|
|
|
@ -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 ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
|
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
|
||||||
|
@ -148,11 +153,11 @@ protected:
|
||||||
|
|
||||||
// The expolygon may be modified by the method to avoid a copy.
|
// The expolygon may be modified by the method to avoid a copy.
|
||||||
virtual void _fill_surface_single(
|
virtual void _fill_surface_single(
|
||||||
const FillParams & /* params */,
|
const FillParams & /* params */,
|
||||||
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,
|
||||||
|
|
|
@ -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); };
|
||||||
|
|
|
@ -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 ¶ms, ExtrusionEntitiesPtr &out) override;
|
void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, 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); };
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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); };
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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 ¶ms,
|
||||||
|
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,34 +1389,28 @@ 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;
|
i_vline = i_vline2;
|
||||||
if (! consumed) {
|
i_intersection = intrsctn_idx;
|
||||||
coordf_t dist2 = sqr(coordf_t(pointLast(0) - vline.pos)) + sqr(coordf_t(pointLast(1) - intrsctn.pos()));
|
goto found;
|
||||||
if (dist2 < dist2min) {
|
|
||||||
dist2min = dist2;
|
|
||||||
i_vline = i_vline2;
|
|
||||||
i_intersection = i;
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out)
|
bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, 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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶ms) override;
|
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) 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 ¶ms, ExtrusionEntitiesPtr &out) override;
|
void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, 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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue