mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-05 04:54:08 -06:00
New FDM support sparse infill zig-zag algorithm.
Fixed some old support and infill issues. Fixes support problem #4295 Fixes Parts of interface layer extends beyond supports and cannot be printed Fixes support missing under horizontal overhang #6058 Fixes Slicer double-traces small sections of Rectilinear Supports, causes Fixes plastic buildup and nozzle crashes #4951 Fixes Add "Angle Interface layers" #2969
This commit is contained in:
parent
0db55a0699
commit
8fd731f7a0
18 changed files with 1473 additions and 285 deletions
|
@ -147,7 +147,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
|||
// align bounding box to a multiple of our honeycomb grid module
|
||||
// (a module is 2*$distance since one $distance half-module is
|
||||
// growing while the other $distance half-module is shrinking)
|
||||
bb.merge(_align_to_grid(bb.min, Point(2*distance, 2*distance)));
|
||||
bb.merge(align_to_grid(bb.min, Point(2*distance, 2*distance)));
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines = makeGrid(
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -133,26 +133,10 @@ public:
|
|||
static void connect_infill(Polylines &&infill_ordered, const Polygons &boundary, const BoundingBox& bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms);
|
||||
static void connect_infill(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary, const BoundingBox &bbox, Polylines &polylines_out, double spacing, const FillParams ¶ms);
|
||||
|
||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||
static void connect_base_support(Polylines &&infill_ordered, const std::vector<const Polygon*> &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms);
|
||||
static void connect_base_support(Polylines &&infill_ordered, const Polygons &boundary_src, const BoundingBox &bbox, Polylines &polylines_out, const double spacing, const FillParams ¶ms);
|
||||
|
||||
// Align a coordinate to a grid. The coordinate may be negative,
|
||||
// the aligned value will never be bigger than the original one.
|
||||
static coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {
|
||||
// Current C++ standard defines the result of integer division to be rounded to zero,
|
||||
// for both positive and negative numbers. Here we want to round down for negative
|
||||
// numbers as well.
|
||||
coord_t aligned = (coord < 0) ?
|
||||
((coord - spacing + 1) / spacing) * spacing :
|
||||
(coord / spacing) * spacing;
|
||||
assert(aligned <= coord);
|
||||
return aligned;
|
||||
}
|
||||
static Point _align_to_grid(Point coord, Point spacing)
|
||||
{ return Point(_align_to_grid(coord(0), spacing(0)), _align_to_grid(coord(1), spacing(1))); }
|
||||
static coord_t _align_to_grid(coord_t coord, coord_t spacing, coord_t base)
|
||||
{ return base + _align_to_grid(coord - base, spacing); }
|
||||
static Point _align_to_grid(Point coord, Point spacing, Point base)
|
||||
{ return Point(_align_to_grid(coord(0), spacing(0), base(0)), _align_to_grid(coord(1), spacing(1), base(1))); }
|
||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -166,7 +166,7 @@ void FillGyroid::_fill_surface_single(
|
|||
coord_t distance = coord_t(scale_(this->spacing) / density_adjusted);
|
||||
|
||||
// align bounding box to a multiple of our grid module
|
||||
bb.merge(_align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
|
||||
bb.merge(align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines = make_gyroid_waves(
|
||||
|
|
|
@ -47,7 +47,7 @@ void FillHoneycomb::_fill_surface_single(
|
|||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
|
||||
// The infill is not aligned to the object bounding box, but to a world coordinate system. Supposedly good enough.
|
||||
bounding_box.merge(_align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height)));
|
||||
bounding_box.merge(align_to_grid(bounding_box.min, Point(m.hex_width, m.pattern_height)));
|
||||
}
|
||||
|
||||
coord_t x = bounding_box.min(0);
|
||||
|
|
|
@ -31,7 +31,7 @@ void FillLine::_fill_surface_single(
|
|||
} else {
|
||||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// Transform the reference point to the rotated coordinate system.
|
||||
bounding_box.merge(_align_to_grid(
|
||||
bounding_box.merge(align_to_grid(
|
||||
bounding_box.min,
|
||||
Point(this->_line_spacing, this->_line_spacing),
|
||||
direction.second.rotated(- direction.first)));
|
||||
|
|
|
@ -798,33 +798,44 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
|
|||
assert(l <= this_x);
|
||||
assert(r >= this_x);
|
||||
// Calculate the intersection position in y axis. x is known.
|
||||
if (p1(0) == this_x) {
|
||||
if (p2(0) == this_x) {
|
||||
if (p1.x() == this_x) {
|
||||
if (p2.x() == this_x) {
|
||||
// Ignore strictly vertical segments.
|
||||
continue;
|
||||
}
|
||||
is.pos_p = p1(1);
|
||||
const Point &p0 = prev_value_modulo(iPrev, contour);
|
||||
if (int64_t(p0.x() - p1.x()) * int64_t(p2.x() - p1.x()) > 0) {
|
||||
// Ignore points of a contour touching the infill line from one side.
|
||||
continue;
|
||||
}
|
||||
is.pos_p = p1.y();
|
||||
is.pos_q = 1;
|
||||
} else if (p2(0) == this_x) {
|
||||
is.pos_p = p2(1);
|
||||
} else if (p2.x() == this_x) {
|
||||
const Point &p3 = next_value_modulo(iSegment, contour);
|
||||
if (int64_t(p3.x() - p2.x()) * int64_t(p1.x() - p2.x()) > 0) {
|
||||
// Ignore points of a contour touching the infill line from one side.
|
||||
continue;
|
||||
}
|
||||
is.pos_p = p2.y();
|
||||
is.pos_q = 1;
|
||||
} else {
|
||||
// First calculate the intersection parameter 't' as a rational number with non negative denominator.
|
||||
if (p2(0) > p1(0)) {
|
||||
is.pos_p = this_x - p1(0);
|
||||
is.pos_q = p2(0) - p1(0);
|
||||
if (p2.x() > p1.x()) {
|
||||
is.pos_p = this_x - p1.x();
|
||||
is.pos_q = p2.x() - p1.x();
|
||||
} else {
|
||||
is.pos_p = p1(0) - this_x;
|
||||
is.pos_q = p1(0) - p2(0);
|
||||
is.pos_p = p1.x() - this_x;
|
||||
is.pos_q = p1.x() - p2.x();
|
||||
}
|
||||
assert(is.pos_p >= 0 && is.pos_p <= is.pos_q);
|
||||
assert(is.pos_q > 1);
|
||||
assert(is.pos_p > 0 && is.pos_p < is.pos_q);
|
||||
// Make an intersection point from the 't'.
|
||||
is.pos_p *= int64_t(p2(1) - p1(1));
|
||||
is.pos_p += p1(1) * int64_t(is.pos_q);
|
||||
is.pos_p *= int64_t(p2.y() - p1.y());
|
||||
is.pos_p += p1.y() * int64_t(is.pos_q);
|
||||
}
|
||||
// +-1 to take rounding into account.
|
||||
assert(is.pos() + 1 >= std::min(p1(1), p2(1)));
|
||||
assert(is.pos() <= std::max(p1(1), p2(1)) + 1);
|
||||
assert(is.pos() + 1 >= std::min(p1.y(), p2.y()));
|
||||
assert(is.pos() <= std::max(p1.y(), p2.y()) + 1);
|
||||
segs[i].intersections.push_back(is);
|
||||
}
|
||||
}
|
||||
|
@ -844,55 +855,46 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
|
|||
size_t j = 0;
|
||||
for (size_t i = 0; i < sil.intersections.size(); ++ i) {
|
||||
// What is the orientation of the segment at the intersection point?
|
||||
size_t iContour = sil.intersections[i].iContour;
|
||||
const Points &contour = poly_with_offset.contour(iContour).points;
|
||||
size_t iSegment = sil.intersections[i].iSegment;
|
||||
size_t iPrev = ((iSegment == 0) ? contour.size() : iSegment) - 1;
|
||||
coord_t dir = contour[iSegment](0) - contour[iPrev](0);
|
||||
bool low = dir > 0;
|
||||
sil.intersections[i].type = poly_with_offset.is_contour_outer(iContour) ?
|
||||
SegmentIntersection &is = sil.intersections[i];
|
||||
const size_t iContour = is.iContour;
|
||||
const Points &contour = poly_with_offset.contour(iContour).points;
|
||||
const size_t iSegment = is.iSegment;
|
||||
const size_t iPrev = prev_idx_modulo(iSegment, contour);
|
||||
const coord_t dir = contour[iSegment].x() - contour[iPrev].x();
|
||||
const bool low = dir > 0;
|
||||
is.type = poly_with_offset.is_contour_outer(iContour) ?
|
||||
(low ? SegmentIntersection::OUTER_LOW : SegmentIntersection::OUTER_HIGH) :
|
||||
(low ? SegmentIntersection::INNER_LOW : SegmentIntersection::INNER_HIGH);
|
||||
if (j > 0 && sil.intersections[i].iContour == sil.intersections[j-1].iContour) {
|
||||
// Two successive intersection points on a vertical line with the same contour. This may be a special case.
|
||||
if (sil.intersections[i].pos() == sil.intersections[j-1].pos()) {
|
||||
// Two successive segments meet exactly at the vertical line.
|
||||
#ifdef SLIC3R_DEBUG
|
||||
// Verify that the segments of sil.intersections[i] and sil.intersections[j-1] are adjoint.
|
||||
size_t iSegment2 = sil.intersections[j-1].iSegment;
|
||||
size_t iPrev2 = ((iSegment2 == 0) ? contour.size() : iSegment2) - 1;
|
||||
assert(iSegment == iPrev2 || iSegment2 == iPrev);
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
if (sil.intersections[i].type == sil.intersections[j-1].type) {
|
||||
bool take_next = true;
|
||||
if (j > 0) {
|
||||
SegmentIntersection &is2 = sil.intersections[j - 1];
|
||||
if (iContour == is2.iContour && is.pos_q == 1 && is2.pos_q == 1) {
|
||||
// Two successive intersection points on a vertical line with the same contour, both points are end points of their respective contour segments.
|
||||
if (is.pos_p == is2.pos_p) {
|
||||
// Two successive segments meet exactly at the vertical line.
|
||||
// Verify that the segments of sil.intersections[i] and sil.intersections[j-1] are adjoint.
|
||||
assert(iSegment == prev_idx_modulo(is2.iSegment, contour) || is2.iSegment == iPrev);
|
||||
assert(is.type == is2.type);
|
||||
// Two successive segments of the same direction (both to the right or both to the left)
|
||||
// meet exactly at the vertical line.
|
||||
// Remove the second intersection point.
|
||||
} else {
|
||||
// This is a loop returning to the same point.
|
||||
// It may as well be a vertex of a loop touching this vertical line.
|
||||
// Remove both the lines.
|
||||
-- j;
|
||||
take_next = false;
|
||||
} else if (is.type == is2.type) {
|
||||
// Two non successive segments of the same direction (both to the right or both to the left)
|
||||
// meet exactly at the vertical line. That means there is a Z shaped path, where the center segment
|
||||
// of the Z shaped path is aligned with this vertical line.
|
||||
// Remove one of the intersection points while maximizing the vertical segment length.
|
||||
if (low) {
|
||||
// Remove the second intersection point, keep the first intersection point.
|
||||
} else {
|
||||
// Remove the first intersection point, keep the second intersection point.
|
||||
sil.intersections[j-1] = sil.intersections[i];
|
||||
}
|
||||
take_next = false;
|
||||
}
|
||||
} else if (sil.intersections[i].type == sil.intersections[j-1].type) {
|
||||
// Two non successive segments of the same direction (both to the right or both to the left)
|
||||
// meet exactly at the vertical line. That means there is a Z shaped path, where the center segment
|
||||
// of the Z shaped path is aligned with this vertical line.
|
||||
// Remove one of the intersection points while maximizing the vertical segment length.
|
||||
if (low) {
|
||||
// Remove the second intersection point, keep the first intersection point.
|
||||
} else {
|
||||
// Remove the first intersection point, keep the second intersection point.
|
||||
sil.intersections[j-1] = sil.intersections[i];
|
||||
}
|
||||
} else {
|
||||
// Vertical line intersects a contour segment at a general position (not at one of its end points).
|
||||
// or the contour just touches this vertical line with a vertical segment or a sequence of vertical segments.
|
||||
// Keep both intersection points.
|
||||
if (j < i)
|
||||
sil.intersections[j] = sil.intersections[i];
|
||||
++ j;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (take_next) {
|
||||
// Vertical line intersects a contour segment at a general position (not at one of its end points).
|
||||
if (j < i)
|
||||
sil.intersections[j] = sil.intersections[i];
|
||||
|
@ -905,7 +907,13 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
|
|||
}
|
||||
|
||||
// Verify the segments. If something is wrong, give up.
|
||||
#define ASSERT_THROW(CONDITION) do { assert(CONDITION); if (! (CONDITION)) throw InfillFailedException(); } while (0)
|
||||
#ifdef INFILL_DEBUG_OUTPUT
|
||||
#define INFILL_DEBUG_ASSERT(CONDITION)
|
||||
try {
|
||||
#else // INFILL_DEBUG_OUTPUT
|
||||
#define INFILL_DEBUG_ASSERT(CONDITION) assert(CONDITION)
|
||||
#endif // INFILL_DEBUG_OUTPUT
|
||||
#define ASSERT_THROW(CONDITION) do { INFILL_DEBUG_ASSERT(CONDITION); if (! (CONDITION)) throw InfillFailedException(); } while (0)
|
||||
for (size_t i_seg = 0; i_seg < segs.size(); ++ i_seg) {
|
||||
SegmentedIntersectionLine &sil = segs[i_seg];
|
||||
// The intersection points have to be even.
|
||||
|
@ -925,6 +933,56 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
|
|||
}
|
||||
}
|
||||
#undef ASSERT_THROW
|
||||
#undef INFILL_DEBUG_ASSERT
|
||||
#ifdef INFILL_DEBUG_OUTPUT
|
||||
} catch (const InfillFailedException & /* ex */) {
|
||||
// Export the buggy result into an SVG file.
|
||||
static int iRun = 0;
|
||||
BoundingBox bbox = get_extents(poly_with_offset.polygons_src);
|
||||
bbox.offset(scale_(3.));
|
||||
::Slic3r::SVG svg(debug_out_path("slice_region_by_vertical_lines-failed-%d.svg", iRun ++), bbox);
|
||||
svg.draw(poly_with_offset.polygons_src);
|
||||
svg.draw_outline(poly_with_offset.polygons_src, "green");
|
||||
svg.draw_outline(poly_with_offset.polygons_outer, "green");
|
||||
svg.draw_outline(poly_with_offset.polygons_inner, "green");
|
||||
for (size_t i_seg = 0; i_seg < segs.size(); ++i_seg) {
|
||||
SegmentedIntersectionLine &sil = segs[i_seg];
|
||||
for (size_t i = 0; i < sil.intersections.size();) {
|
||||
// An intersection segment crossing the bigger contour may cross the inner offsetted contour even number of times.
|
||||
if (sil.intersections[i].type != SegmentIntersection::OUTER_LOW) {
|
||||
svg.draw(Point(sil.pos, sil.intersections[i].pos()), "red");
|
||||
break;
|
||||
}
|
||||
size_t j = i + 1;
|
||||
if (j == sil.intersections.size()) {
|
||||
svg.draw(Point(sil.pos, sil.intersections[i].pos()), "magenta");
|
||||
break;
|
||||
}
|
||||
if (! (sil.intersections[j].type == SegmentIntersection::INNER_LOW || sil.intersections[j].type == SegmentIntersection::OUTER_HIGH)) {
|
||||
svg.draw(Point(sil.pos, sil.intersections[j].pos()), "blue");
|
||||
break;
|
||||
}
|
||||
for (; j < sil.intersections.size() && sil.intersections[j].is_inner(); ++j);
|
||||
if (j == sil.intersections.size()) {
|
||||
svg.draw(Point(sil.pos, sil.intersections[j - 1].pos()), "magenta");
|
||||
break;
|
||||
}
|
||||
if ((j & 1) != 1 || sil.intersections[j].type != SegmentIntersection::OUTER_HIGH) {
|
||||
svg.draw(Point(sil.pos, sil.intersections[j].pos()), "red");
|
||||
break;
|
||||
}
|
||||
if (! (i + 1 == j || sil.intersections[j - 1].type == SegmentIntersection::INNER_HIGH)) {
|
||||
svg.draw(Point(sil.pos, sil.intersections[j].pos()), "red");
|
||||
break;
|
||||
}
|
||||
svg.draw(Line(Point(sil.pos, sil.intersections[i].pos()), Point(sil.pos, sil.intersections[j].pos())), "black");
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
throw;
|
||||
}
|
||||
#endif //INFILL_DEBUG_OUTPUT
|
||||
|
||||
return segs;
|
||||
}
|
||||
|
@ -2714,10 +2772,10 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// Transform the reference point to the rotated coordinate system.
|
||||
Point refpt = rotate_vector.second.rotated(- rotate_vector.first);
|
||||
// _align_to_grid will not work correctly with positive pattern_shift.
|
||||
// align_to_grid will not work correctly with positive pattern_shift.
|
||||
coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing;
|
||||
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
bounding_box.merge(_align_to_grid(
|
||||
bounding_box.merge(align_to_grid(
|
||||
bounding_box.min,
|
||||
Point(line_spacing, line_spacing),
|
||||
refpt));
|
||||
|
@ -2825,6 +2883,45 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
|
|||
return true;
|
||||
}
|
||||
|
||||
void make_fill_lines(const ExPolygonWithOffset &poly_with_offset, Point refpt, double angle, coord_t x_margin, coord_t line_spacing, coord_t pattern_shift, Polylines &fill_lines)
|
||||
{
|
||||
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
|
||||
// Don't produce infill lines, which fully overlap with the infill perimeter.
|
||||
coord_t x_min = bounding_box.min.x() + x_margin;
|
||||
coord_t x_max = bounding_box.max.x() - x_margin;
|
||||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// align_to_grid will not work correctly with positive pattern_shift.
|
||||
coord_t pattern_shift_scaled = pattern_shift % line_spacing;
|
||||
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
bounding_box.merge(Slic3r::align_to_grid(bounding_box.min, Point(line_spacing, line_spacing), refpt));
|
||||
|
||||
// Intersect a set of euqally spaced vertical lines wiht expolygon.
|
||||
// n_vlines = ceil(bbox_width / line_spacing)
|
||||
const size_t n_vlines = (bounding_box.max.x() - bounding_box.min.x() + line_spacing - 1) / line_spacing;
|
||||
const double cos_a = cos(angle);
|
||||
const double sin_a = sin(angle);
|
||||
for (const SegmentedIntersectionLine &vline : slice_region_by_vertical_lines(poly_with_offset, n_vlines, bounding_box.min.x(), line_spacing))
|
||||
if (vline.pos >= x_min) {
|
||||
if (vline.pos > x_max)
|
||||
break;
|
||||
for (auto it = vline.intersections.begin(); it != vline.intersections.end();) {
|
||||
auto it_low = it ++;
|
||||
assert(it_low->type == SegmentIntersection::OUTER_LOW);
|
||||
if (it_low->type != SegmentIntersection::OUTER_LOW)
|
||||
continue;
|
||||
auto it_high = it;
|
||||
assert(it_high->type == SegmentIntersection::OUTER_HIGH);
|
||||
if (it_high->type == SegmentIntersection::OUTER_HIGH) {
|
||||
if (angle == 0.)
|
||||
fill_lines.emplace_back(Point(vline.pos, it_low->pos()), Point(vline.pos, it_high->pos()));
|
||||
else
|
||||
fill_lines.emplace_back(Point(vline.pos, it_low->pos()).rotated(cos_a, sin_a), Point(vline.pos, it_high->pos()).rotated(cos_a, sin_a));
|
||||
++ it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillParams params, const std::initializer_list<SweepParams> &sweep_params, Polylines &polylines_out)
|
||||
{
|
||||
assert(sweep_params.size() > 1);
|
||||
|
@ -2843,42 +2940,8 @@ bool FillRectilinear::fill_surface_by_multilines(const Surface *surface, FillPar
|
|||
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
|
||||
for (const SweepParams &sweep : sweep_params) {
|
||||
// Rotate polygons so that we can work with vertical lines here
|
||||
double angle = rotate_vector.first + sweep.angle_base;
|
||||
ExPolygonWithOffset poly_with_offset(poly_with_offset_base, - angle);
|
||||
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
|
||||
// Don't produce infill lines, which fully overlap with the infill perimeter.
|
||||
coord_t x_min = bounding_box.min.x() + line_width + coord_t(SCALED_EPSILON);
|
||||
coord_t x_max = bounding_box.max.x() - line_width - coord_t(SCALED_EPSILON);
|
||||
// extend bounding box so that our pattern will be aligned with other layers
|
||||
// Transform the reference point to the rotated coordinate system.
|
||||
Point refpt = rotate_vector.second.rotated(- angle);
|
||||
// _align_to_grid will not work correctly with positive pattern_shift.
|
||||
coord_t pattern_shift_scaled = coord_t(scale_(sweep.pattern_shift)) % line_spacing;
|
||||
refpt.x() -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
|
||||
bounding_box.merge(_align_to_grid(bounding_box.min, Point(line_spacing, line_spacing), refpt));
|
||||
|
||||
// Intersect a set of euqally spaced vertical lines wiht expolygon.
|
||||
// n_vlines = ceil(bbox_width / line_spacing)
|
||||
const size_t n_vlines = (bounding_box.max.x() - bounding_box.min.x() + line_spacing - 1) / line_spacing;
|
||||
const double cos_a = cos(angle);
|
||||
const double sin_a = sin(angle);
|
||||
for (const SegmentedIntersectionLine &vline : slice_region_by_vertical_lines(poly_with_offset, n_vlines, bounding_box.min.x(), line_spacing))
|
||||
if (vline.pos > x_min) {
|
||||
if (vline.pos >= x_max)
|
||||
break;
|
||||
for (auto it = vline.intersections.begin(); it != vline.intersections.end();) {
|
||||
auto it_low = it ++;
|
||||
assert(it_low->type == SegmentIntersection::OUTER_LOW);
|
||||
if (it_low->type != SegmentIntersection::OUTER_LOW)
|
||||
continue;
|
||||
auto it_high = it;
|
||||
assert(it_high->type == SegmentIntersection::OUTER_HIGH);
|
||||
if (it_high->type == SegmentIntersection::OUTER_HIGH) {
|
||||
fill_lines.emplace_back(Point(vline.pos, it_low->pos()).rotated(cos_a, sin_a), Point(vline.pos, it_high->pos()).rotated(cos_a, sin_a));
|
||||
++ it;
|
||||
}
|
||||
}
|
||||
}
|
||||
float angle = rotate_vector.first + sweep.angle_base;
|
||||
make_fill_lines(ExPolygonWithOffset(poly_with_offset_base, - angle), rotate_vector.second.rotated(-angle), angle, line_width + coord_t(SCALED_EPSILON), line_spacing, coord_t(scale_(sweep.pattern_shift)), fill_lines);
|
||||
}
|
||||
|
||||
if (params.dont_connect() || fill_lines.size() <= 1) {
|
||||
|
@ -2954,4 +3017,29 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶
|
|||
return polylines_out;
|
||||
}
|
||||
|
||||
Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams ¶ms)
|
||||
{
|
||||
assert(! params.full_infill());
|
||||
|
||||
Polylines polylines_out;
|
||||
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
|
||||
ExPolygonWithOffset poly_with_offset(surface->expolygon, - rotate_vector.first, float(scale_(this->overlap - 0.5 * this->spacing)));
|
||||
if (poly_with_offset.n_contours > 0) {
|
||||
Polylines fill_lines;
|
||||
coord_t line_spacing = coord_t(scale_(this->spacing) / params.density);
|
||||
// Create infill lines, keep them vertical.
|
||||
make_fill_lines(poly_with_offset, rotate_vector.second.rotated(- rotate_vector.first), 0, 0, line_spacing, 0, fill_lines);
|
||||
// Both the poly_with_offset and polylines_out are rotated, so the infill lines are strictly vertical.
|
||||
connect_base_support(std::move(fill_lines), poly_with_offset.polygons_outer, poly_with_offset.bounding_box_outer(), polylines_out, this->spacing, params);
|
||||
// Rotate back by rotate_vector.first
|
||||
const double cos_a = cos(rotate_vector.first);
|
||||
const double sin_a = sin(rotate_vector.first);
|
||||
for (Polyline &pl : polylines_out)
|
||||
for (Point &pt : pl.points)
|
||||
pt.rotate(cos_a, sin_a);
|
||||
}
|
||||
return polylines_out;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
|
@ -97,6 +97,17 @@ protected:
|
|||
float _layer_angle(size_t idx) const override { return 0.f; }
|
||||
};
|
||||
|
||||
class FillSupportBase : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillSupportBase(*this); }
|
||||
~FillSupportBase() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
|
||||
protected:
|
||||
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
|
||||
float _layer_angle(size_t idx) const override { return 0.f; }
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue