mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-19 16:12:21 -06:00
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
33dc7bc1f2
commit
1321cf040a
20 changed files with 291 additions and 67 deletions
|
@ -64,6 +64,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||
// BBS: for bottom and top surface only
|
||||
// Orca: Replace BBS implementation with Prusa implementation
|
||||
case ipMonotonicLine: return new FillMonotonicLines();
|
||||
case ipZigZag: return new FillZigZag();
|
||||
default: throw Slic3r::InvalidArgument("unknown type");
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, Ex
|
|||
|
||||
// Calculate a new spacing to fill width with possibly integer number of lines,
|
||||
// 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,
|
||||
// therefore the adjustment is limited to 20% increase.
|
||||
coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
||||
|
@ -249,8 +250,8 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance)
|
|||
assert(distance > 0);
|
||||
// floor(width / distance)
|
||||
const auto number_of_intervals = coord_t((width - EPSILON) / distance);
|
||||
coord_t distance_new = (number_of_intervals == 0) ?
|
||||
distance :
|
||||
coord_t distance_new = (number_of_intervals == 0) ?
|
||||
distance :
|
||||
coord_t((width - EPSILON) / number_of_intervals);
|
||||
const coordf_t factor = coordf_t(distance_new) / coordf_t(distance);
|
||||
assert(factor > 1. - 1e-5);
|
||||
|
@ -276,8 +277,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)
|
||||
// The bounding box is only undefined in unit tests.
|
||||
Point out_shift = empty(this->bounding_box) ?
|
||||
surface->expolygon.contour.bounding_box().center() :
|
||||
Point out_shift = empty(this->bounding_box) ?
|
||||
surface->expolygon.contour.bounding_box().center() :
|
||||
this->bounding_box.center();
|
||||
|
||||
#if 0
|
||||
|
@ -351,10 +352,10 @@ struct ContourIntersectionPoint {
|
|||
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.
|
||||
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; }
|
||||
// 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; }
|
||||
};
|
||||
|
||||
|
@ -563,7 +564,7 @@ static void take(Polyline &pl1, const Polyline &pl2, const Points &contour, Cont
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
@ -727,8 +728,8 @@ static inline SegmentPoint clip_end_segment_and_point(const Points &polyline, do
|
|||
// Calculate intersection of a line with a thick segment.
|
||||
// Returns Eucledian parameters of the line / thick segment overlap.
|
||||
static inline bool line_rounded_thick_segment_collision(
|
||||
const Vec2d &line_a, const Vec2d &line_b,
|
||||
const Vec2d &segment_a, const Vec2d &segment_b, const double offset,
|
||||
const Vec2d &line_a, const Vec2d &line_b,
|
||||
const Vec2d &segment_a, const Vec2d &segment_b, const double offset,
|
||||
std::pair<double, double> &out_interval)
|
||||
{
|
||||
const Vec2d line_v0 = line_b - line_a;
|
||||
|
@ -791,8 +792,8 @@ static inline bool line_rounded_thick_segment_collision(
|
|||
std::pair<double, double> interval;
|
||||
if (Geometry::liang_barsky_line_clipping_interval(
|
||||
Vec2d(line_p0.dot(dir_x), line_p0.dot(dir_y)),
|
||||
Vec2d(line_v0.dot(dir_x), line_v0.dot(dir_y)),
|
||||
BoundingBoxf(Vec2d(0., - offset), Vec2d(segment_l, offset)),
|
||||
Vec2d(line_v0.dot(dir_x), line_v0.dot(dir_y)),
|
||||
BoundingBoxf(Vec2d(0., - offset), Vec2d(segment_l, offset)),
|
||||
interval))
|
||||
extend_interval(interval.first, interval.second);
|
||||
} else
|
||||
|
@ -1152,7 +1153,7 @@ void mark_boundary_segments_touching_infill(
|
|||
// Clip the infill polyline by the Eucledian distance along the polyline.
|
||||
SegmentPoint start_point = clip_start_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))) {
|
||||
// The clipped polyline is non-empty.
|
||||
#ifdef INFILL_DEBUG_OUTPUT
|
||||
|
@ -1292,21 +1293,21 @@ struct BoundaryInfillGraph
|
|||
};
|
||||
|
||||
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.x() < p2.x() ? Right : Left);
|
||||
}
|
||||
|
||||
const Direction dir_prev(const ContourIntersectionPoint &cp) const {
|
||||
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)) :
|
||||
Taken;
|
||||
}
|
||||
|
||||
const Direction dir_next(const ContourIntersectionPoint &cp) const {
|
||||
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)) :
|
||||
Taken;
|
||||
}
|
||||
|
@ -1364,7 +1365,7 @@ static inline void mark_boundary_segments_overlapping_infill(
|
|||
assert(interval.first == 0.);
|
||||
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) {
|
||||
// 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.
|
||||
inside = false;
|
||||
break;
|
||||
|
@ -1396,7 +1397,7 @@ static inline void mark_boundary_segments_overlapping_infill(
|
|||
assert(interval.first == 0.);
|
||||
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) {
|
||||
// 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.
|
||||
inside = false;
|
||||
break;
|
||||
|
@ -1493,7 +1494,7 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
|||
ContourIntersectionPoint *pthis = &out.map_infill_end_point_to_boundary[it->second];
|
||||
if (pprev) {
|
||||
pprev->next_on_contour = pthis;
|
||||
pthis->prev_on_contour = pprev;
|
||||
pthis->prev_on_contour = pprev;
|
||||
} else
|
||||
pfirst = pthis;
|
||||
contour_intersection_points.emplace_back(pthis);
|
||||
|
@ -1518,7 +1519,7 @@ BoundaryInfillGraph create_boundary_infill_graph(const Polylines &infill_ordered
|
|||
ip->param = contour_params[ip->point_idx];
|
||||
// and measure distance to the previous and next intersection point.
|
||||
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) {
|
||||
assert(ip->prev_on_contour == ip);
|
||||
ip->contour_not_taken_length_prev = ip->contour_not_taken_length_next = contour_length;
|
||||
|
@ -1924,14 +1925,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.
|
||||
static inline void emit_loops_in_band(
|
||||
// Vertical band, which will trim the contour between tbegin and tend.
|
||||
coord_t left,
|
||||
coord_t left,
|
||||
coord_t right,
|
||||
// Contour and its parametrization.
|
||||
const Points &contour,
|
||||
const std::vector<double> &contour_params,
|
||||
// Span of the parameters of an arch to trim with the vertical band.
|
||||
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.
|
||||
double min_length,
|
||||
Polylines &polylines_out)
|
||||
|
@ -1987,13 +1988,13 @@ static inline void emit_loops_in_band(
|
|||
};
|
||||
|
||||
enum InOutBand {
|
||||
Entering,
|
||||
Entering,
|
||||
Leaving,
|
||||
};
|
||||
|
||||
class State {
|
||||
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) {}
|
||||
|
||||
void add_inner_point(const Point* p)
|
||||
|
@ -2294,7 +2295,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
#endif // INFILL_DEBUG_OUTPUT
|
||||
|
||||
base_support_extend_infill_lines(infill_ordered, graph, spacing, params);
|
||||
|
||||
|
||||
#ifdef INFILL_DEBUG_OUTPUT
|
||||
export_partial_infill_to_svg(debug_out_path("connect_base_support-extended-%03d.svg", iRun), graph, infill_ordered, polylines_out);
|
||||
#endif // INFILL_DEBUG_OUTPUT
|
||||
|
@ -2329,7 +2330,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
};
|
||||
|
||||
// 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)
|
||||
// take the infill line at cp and an arc from cp towards cp.next_on_contour.
|
||||
// else
|
||||
|
@ -2623,7 +2624,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
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_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.cost > cap_cost :
|
||||
cost_prev.cost > cost_veryhigh)) {
|
||||
|
@ -2640,7 +2641,7 @@ void Fill::connect_base_support(Polylines &&infill_ordered, const std::vector<co
|
|||
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.cost > cap_cost :
|
||||
cost_next.cost > cost_veryhigh)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue