Fix of #8932 Hang while slicing interlocking chainmail model
Reworked the Archimedean Chords, Hilbert and Octagram Spiral infill generators to 1) Generate solid infill as not aligned with other solid infill layers. This may surprise some users as the pattern over multiple islands will be different, maybe not that nice. This may change in the future. 2) Sparse infill is always aligned and generated over the whole object, however newly the generated lines are trimmed with a snug bounding box while being generated. 3) For Archimedean chords the accuracy was not applied correctly, leading to higher accuracy for dense infill and lower accuracy for sparse infill.
This commit is contained in:
parent
32b2c90538
commit
d7d849a02c
4 changed files with 184 additions and 62 deletions
|
@ -710,6 +710,8 @@ Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygon
|
||||||
{ return _clipper_pl_closed(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip)); }
|
{ return _clipper_pl_closed(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip)); }
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip)
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip)
|
||||||
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::SinglePathProvider(clip.points)); }
|
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::SinglePathProvider(clip.points)); }
|
||||||
|
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygon &clip)
|
||||||
|
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::ExPolygonProvider(clip)); }
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip)
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip)
|
||||||
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::ExPolygonProvider(clip)); }
|
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::ExPolygonProvider(clip)); }
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip)
|
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip)
|
||||||
|
|
|
@ -437,6 +437,7 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r
|
||||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r::Surfaces &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip);
|
||||||
|
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygon &clip);
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip);
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip);
|
||||||
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygons &clip);
|
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygons &clip);
|
||||||
|
|
|
@ -6,6 +6,66 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class InfillPolylineClipper : public FillPlanePath::InfillPolylineOutput {
|
||||||
|
public:
|
||||||
|
InfillPolylineClipper(const BoundingBox bbox, const double scale_out) : FillPlanePath::InfillPolylineOutput(scale_out), m_bbox(bbox) {}
|
||||||
|
|
||||||
|
void add_point(const Vec2d &pt);
|
||||||
|
Points&& result() { return std::move(m_out); }
|
||||||
|
bool clips() const override { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Side {
|
||||||
|
Left = 1,
|
||||||
|
Right = 2,
|
||||||
|
Top = 4,
|
||||||
|
Bottom = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
int sides(const Point &p) const {
|
||||||
|
return int(p.x() < m_bbox.min.x()) * int(Side::Left) +
|
||||||
|
int(p.x() > m_bbox.max.x()) * int(Side::Right) +
|
||||||
|
int(p.y() < m_bbox.min.y()) * int(Side::Bottom) +
|
||||||
|
int(p.y() > m_bbox.max.y()) * int(Side::Top);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bounding box to clip the polyline with.
|
||||||
|
BoundingBox m_bbox;
|
||||||
|
|
||||||
|
// Classification of the two last points processed.
|
||||||
|
int m_sides_prev;
|
||||||
|
int m_sides_this;
|
||||||
|
};
|
||||||
|
|
||||||
|
void InfillPolylineClipper::add_point(const Vec2d &fpt)
|
||||||
|
{
|
||||||
|
const Point pt{ this->scaled(fpt) };
|
||||||
|
|
||||||
|
if (m_out.size() < 2) {
|
||||||
|
// Collect the two first points and their status.
|
||||||
|
(m_out.empty() ? m_sides_prev : m_sides_this) = sides(pt);
|
||||||
|
m_out.emplace_back(pt);
|
||||||
|
} else {
|
||||||
|
// Classify the last inserted point, possibly remove it.
|
||||||
|
int sides_next = sides(pt);
|
||||||
|
if (// This point is inside. Take it.
|
||||||
|
m_sides_this == 0 ||
|
||||||
|
// Either this point is outside and previous or next is inside, or
|
||||||
|
// the edge possibly cuts corner of the bounding box.
|
||||||
|
(m_sides_prev & m_sides_this & sides_next) == 0) {
|
||||||
|
// Keep the last point.
|
||||||
|
m_sides_prev = m_sides_this;
|
||||||
|
} else {
|
||||||
|
// All the three points (this, prev, next) are outside at the same side.
|
||||||
|
// Ignore the last point.
|
||||||
|
m_out.pop_back();
|
||||||
|
}
|
||||||
|
// And save the current point.
|
||||||
|
m_out.emplace_back(pt);
|
||||||
|
m_sides_this = sides_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FillPlanePath::_fill_surface_single(
|
void FillPlanePath::_fill_surface_single(
|
||||||
const FillParams ¶ms,
|
const FillParams ¶ms,
|
||||||
unsigned int thickness_layers,
|
unsigned int thickness_layers,
|
||||||
|
@ -15,35 +75,50 @@ void FillPlanePath::_fill_surface_single(
|
||||||
{
|
{
|
||||||
expolygon.rotate(-direction.first);
|
expolygon.rotate(-direction.first);
|
||||||
|
|
||||||
coord_t distance_between_lines = coord_t(scale_(this->spacing) / params.density);
|
//FIXME Vojtech: We are not sure whether the user expects the fill patterns on visible surfaces to be aligned across all the islands of a single layer.
|
||||||
|
// One may align for this->centered() to align the patterns for Archimedean Chords and Octagram Spiral patterns.
|
||||||
|
const bool align = params.density < 0.995;
|
||||||
|
|
||||||
// align infill across layers using the object's bounding box
|
BoundingBox snug_bounding_box = get_extents(expolygon).inflated(SCALED_EPSILON);
|
||||||
// Rotated bounding box of the whole object.
|
|
||||||
BoundingBox bounding_box = this->bounding_box.rotated(- direction.first);
|
|
||||||
|
|
||||||
Point shift = this->_centered() ?
|
// Rotated bounding box of the area to fill in with the pattern.
|
||||||
|
BoundingBox bounding_box = align ?
|
||||||
|
// Sparse infill needs to be aligned across layers. Align infill across layers using the object's bounding box.
|
||||||
|
this->bounding_box.rotated(-direction.first) :
|
||||||
|
// Solid infill does not need to be aligned across layers, generate the infill pattern
|
||||||
|
// around the clipping expolygon only.
|
||||||
|
snug_bounding_box;
|
||||||
|
|
||||||
|
Point shift = this->centered() ?
|
||||||
bounding_box.center() :
|
bounding_box.center() :
|
||||||
bounding_box.min;
|
bounding_box.min;
|
||||||
expolygon.translate(-shift.x(), -shift.y());
|
expolygon.translate(-shift.x(), -shift.y());
|
||||||
bounding_box.translate(-shift.x(), -shift.y());
|
bounding_box.translate(-shift.x(), -shift.y());
|
||||||
|
|
||||||
Pointfs pts = _generate(
|
Polyline polyline;
|
||||||
coord_t(ceil(coordf_t(bounding_box.min.x()) / distance_between_lines)),
|
{
|
||||||
coord_t(ceil(coordf_t(bounding_box.min.y()) / distance_between_lines)),
|
auto distance_between_lines = scaled<double>(this->spacing) / params.density;
|
||||||
coord_t(ceil(coordf_t(bounding_box.max.x()) / distance_between_lines)),
|
auto min_x = coord_t(ceil(coordf_t(bounding_box.min.x()) / distance_between_lines));
|
||||||
coord_t(ceil(coordf_t(bounding_box.max.y()) / distance_between_lines)),
|
auto min_y = coord_t(ceil(coordf_t(bounding_box.min.y()) / distance_between_lines));
|
||||||
params.resolution);
|
auto max_x = coord_t(ceil(coordf_t(bounding_box.max.x()) / distance_between_lines));
|
||||||
|
auto max_y = coord_t(ceil(coordf_t(bounding_box.max.y()) / distance_between_lines));
|
||||||
|
auto resolution = scaled<double>(params.resolution) / distance_between_lines;
|
||||||
|
if (align) {
|
||||||
|
// Filling in a bounding box over the whole object, clip generated polyline against the snug bounding box.
|
||||||
|
snug_bounding_box.translate(-shift.x(), -shift.y());
|
||||||
|
InfillPolylineClipper output(snug_bounding_box, distance_between_lines);
|
||||||
|
this->generate(min_x, min_y, max_x, max_y, resolution, output);
|
||||||
|
polyline.points = std::move(output.result());
|
||||||
|
} else {
|
||||||
|
// Filling in a snug bounding box, no need to clip.
|
||||||
|
InfillPolylineOutput output(distance_between_lines);
|
||||||
|
this->generate(min_x, min_y, max_x, max_y, resolution, output);
|
||||||
|
polyline.points = std::move(output.result());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pts.size() >= 2) {
|
if (polyline.size() >= 2) {
|
||||||
// Convert points to a polyline, upscale.
|
Polylines polylines = intersection_pl(polyline, expolygon);
|
||||||
Polylines polylines(1, Polyline());
|
|
||||||
Polyline &polyline = polylines.front();
|
|
||||||
polyline.points.reserve(pts.size());
|
|
||||||
for (const Vec2d &pt : pts)
|
|
||||||
polyline.points.emplace_back(
|
|
||||||
coord_t(floor(pt.x() * distance_between_lines + 0.5)),
|
|
||||||
coord_t(floor(pt.y() * distance_between_lines + 0.5)));
|
|
||||||
polylines = intersection_pl(polylines, expolygon);
|
|
||||||
Polylines chained;
|
Polylines chained;
|
||||||
if (params.dont_connect() || params.density > 0.5 || polylines.size() <= 1)
|
if (params.dont_connect() || params.density > 0.5 || polylines.size() <= 1)
|
||||||
chained = chain_polylines(std::move(polylines));
|
chained = chain_polylines(std::move(polylines));
|
||||||
|
@ -59,7 +134,8 @@ void FillPlanePath::_fill_surface_single(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Follow an Archimedean spiral, in polar coordinates: r=a+b\theta
|
// Follow an Archimedean spiral, in polar coordinates: r=a+b\theta
|
||||||
Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution)
|
template<typename Output>
|
||||||
|
static void generate_archimedean_chords(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution, Output &output)
|
||||||
{
|
{
|
||||||
// Radius to achieve.
|
// Radius to achieve.
|
||||||
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
||||||
|
@ -70,15 +146,22 @@ Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t m
|
||||||
coordf_t r = 1;
|
coordf_t r = 1;
|
||||||
Pointfs out;
|
Pointfs out;
|
||||||
//FIXME Vojtech: If used as a solid infill, there is a gap left at the center.
|
//FIXME Vojtech: If used as a solid infill, there is a gap left at the center.
|
||||||
out.emplace_back(0, 0);
|
output.add_point({ 0, 0 });
|
||||||
out.emplace_back(1, 0);
|
output.add_point({ 1, 0 });
|
||||||
while (r < rmax) {
|
while (r < rmax) {
|
||||||
// Discretization angle to achieve a discretization error lower than resolution.
|
// Discretization angle to achieve a discretization error lower than resolution.
|
||||||
theta += 2. * acos(1. - resolution / r);
|
theta += 2. * acos(1. - resolution / r);
|
||||||
r = a + b * theta;
|
r = a + b * theta;
|
||||||
out.emplace_back(r * cos(theta), r * sin(theta));
|
output.add_point({ r * cos(theta), r * sin(theta) });
|
||||||
}
|
}
|
||||||
return out;
|
}
|
||||||
|
|
||||||
|
void FillArchimedeanChords::generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution, InfillPolylineOutput &output)
|
||||||
|
{
|
||||||
|
if (output.clips())
|
||||||
|
generate_archimedean_chords(min_x, min_y, max_x, max_y, resolution, static_cast<InfillPolylineClipper&>(output));
|
||||||
|
else
|
||||||
|
generate_archimedean_chords(min_x, min_y, max_x, max_y, resolution, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapted from
|
// Adapted from
|
||||||
|
@ -126,7 +209,8 @@ static inline Point hilbert_n_to_xy(const size_t n)
|
||||||
return Point(x, y);
|
return Point(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double /* resolution */)
|
template<typename Output>
|
||||||
|
static void generate_hilbert_curve(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, Output &output)
|
||||||
{
|
{
|
||||||
// Minimum power of two square to fit the domain.
|
// Minimum power of two square to fit the domain.
|
||||||
size_t sz = 2;
|
size_t sz = 2;
|
||||||
|
@ -140,46 +224,59 @@ Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x,
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sz2 = sz * sz;
|
size_t sz2 = sz * sz;
|
||||||
Pointfs line;
|
output.reserve(sz2);
|
||||||
line.reserve(sz2);
|
|
||||||
for (size_t i = 0; i < sz2; ++ i) {
|
for (size_t i = 0; i < sz2; ++ i) {
|
||||||
Point p = hilbert_n_to_xy(i);
|
Point p = hilbert_n_to_xy(i);
|
||||||
line.emplace_back(p.x() + min_x, p.y() + min_y);
|
output.add_point({ p.x() + min_x, p.y() + min_y });
|
||||||
}
|
}
|
||||||
return line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double /* resolution */)
|
void FillHilbertCurve::generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double /* resolution */, InfillPolylineOutput &output)
|
||||||
|
{
|
||||||
|
if (output.clips())
|
||||||
|
generate_hilbert_curve(min_x, min_y, max_x, max_y, static_cast<InfillPolylineClipper&>(output));
|
||||||
|
else
|
||||||
|
generate_hilbert_curve(min_x, min_y, max_x, max_y, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Output>
|
||||||
|
static void generate_octagram_spiral(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, Output &output)
|
||||||
{
|
{
|
||||||
// Radius to achieve.
|
// Radius to achieve.
|
||||||
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5;
|
||||||
// Now unwind the spiral.
|
// Now unwind the spiral.
|
||||||
coordf_t r = 0;
|
coordf_t r = 0;
|
||||||
coordf_t r_inc = sqrt(2.);
|
coordf_t r_inc = sqrt(2.);
|
||||||
Pointfs out;
|
output.add_point({ 0., 0. });
|
||||||
out.emplace_back(0., 0.);
|
|
||||||
while (r < rmax) {
|
while (r < rmax) {
|
||||||
r += r_inc;
|
r += r_inc;
|
||||||
coordf_t rx = r / sqrt(2.);
|
coordf_t rx = r / sqrt(2.);
|
||||||
coordf_t r2 = r + rx;
|
coordf_t r2 = r + rx;
|
||||||
out.emplace_back( r, 0.);
|
output.add_point({ r, 0. });
|
||||||
out.emplace_back( r2, rx);
|
output.add_point({ r2, rx });
|
||||||
out.emplace_back( rx, rx);
|
output.add_point({ rx, rx });
|
||||||
out.emplace_back( rx, r2);
|
output.add_point({ rx, r2 });
|
||||||
out.emplace_back( 0., r);
|
output.add_point({ 0., r });
|
||||||
out.emplace_back(-rx, r2);
|
output.add_point({-rx, r2 });
|
||||||
out.emplace_back(-rx, rx);
|
output.add_point({-rx, rx });
|
||||||
out.emplace_back(-r2, rx);
|
output.add_point({-r2, rx });
|
||||||
out.emplace_back(- r, 0.);
|
output.add_point({- r, 0. });
|
||||||
out.emplace_back(-r2, -rx);
|
output.add_point({-r2, -rx });
|
||||||
out.emplace_back(-rx, -rx);
|
output.add_point({-rx, -rx });
|
||||||
out.emplace_back(-rx, -r2);
|
output.add_point({-rx, -r2 });
|
||||||
out.emplace_back( 0., -r);
|
output.add_point({ 0., -r });
|
||||||
out.emplace_back( rx, -r2);
|
output.add_point({ rx, -r2 });
|
||||||
out.emplace_back( rx, -rx);
|
output.add_point({ rx, -rx });
|
||||||
out.emplace_back( r2+r_inc, -rx);
|
output.add_point({ r2+r_inc, -rx });
|
||||||
}
|
}
|
||||||
return out;
|
}
|
||||||
|
|
||||||
|
void FillOctagramSpiral::generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double /* resolution */, InfillPolylineOutput &output)
|
||||||
|
{
|
||||||
|
if (output.clips())
|
||||||
|
generate_octagram_spiral(min_x, min_y, max_x, max_y, static_cast<InfillPolylineClipper&>(output));
|
||||||
|
else
|
||||||
|
generate_octagram_spiral(min_x, min_y, max_x, max_y, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -27,8 +27,30 @@ protected:
|
||||||
Polylines &polylines_out) override;
|
Polylines &polylines_out) override;
|
||||||
|
|
||||||
float _layer_angle(size_t idx) const override { return 0.f; }
|
float _layer_angle(size_t idx) const override { return 0.f; }
|
||||||
virtual bool _centered() const = 0;
|
virtual bool centered() const = 0;
|
||||||
virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) = 0;
|
|
||||||
|
friend class InfillPolylineClipper;
|
||||||
|
class InfillPolylineOutput {
|
||||||
|
public:
|
||||||
|
InfillPolylineOutput(const double scale_out) : m_scale_out(scale_out) {}
|
||||||
|
|
||||||
|
void reserve(size_t n) { m_out.reserve(n); }
|
||||||
|
void add_point(const Vec2d& pt) { m_out.emplace_back(this->scaled(pt)); }
|
||||||
|
Points&& result() { return std::move(m_out); }
|
||||||
|
virtual bool clips() const { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const Point scaled(const Vec2d &fpt) const { return { coord_t(floor(fpt.x() * m_scale_out + 0.5)), coord_t(floor(fpt.y() * m_scale_out + 0.5)) }; }
|
||||||
|
|
||||||
|
// Output polyline.
|
||||||
|
Points m_out;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Scaling coefficient of the generated points before tested against m_bbox and clipped by bbox.
|
||||||
|
double m_scale_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution, InfillPolylineOutput &output) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillArchimedeanChords : public FillPlanePath
|
class FillArchimedeanChords : public FillPlanePath
|
||||||
|
@ -38,8 +60,8 @@ public:
|
||||||
~FillArchimedeanChords() override = default;
|
~FillArchimedeanChords() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _centered() const override { return true; }
|
bool centered() const override { return true; }
|
||||||
Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) override;
|
void generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution, InfillPolylineOutput &output) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillHilbertCurve : public FillPlanePath
|
class FillHilbertCurve : public FillPlanePath
|
||||||
|
@ -49,8 +71,8 @@ public:
|
||||||
~FillHilbertCurve() override = default;
|
~FillHilbertCurve() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _centered() const override { return false; }
|
bool centered() const override { return false; }
|
||||||
Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) override;
|
void generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution, InfillPolylineOutput &output) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FillOctagramSpiral : public FillPlanePath
|
class FillOctagramSpiral : public FillPlanePath
|
||||||
|
@ -60,8 +82,8 @@ public:
|
||||||
~FillOctagramSpiral() override = default;
|
~FillOctagramSpiral() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _centered() const override { return true; }
|
bool centered() const override { return true; }
|
||||||
Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) override;
|
void generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution, InfillPolylineOutput &output) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
Loading…
Reference in a new issue