FIX: fix slice error: invalid infill

Reason: sorting errors caused by precision
jira: STUDIO-10841
Change-Id: I64dbbcf9e35477b597c4755863f307cf444f50d9
This commit is contained in:
zhimin.zeng 2025-03-13 21:45:38 +08:00 committed by lane.wei
parent 5656c89d32
commit 611f022a0c
1 changed files with 45 additions and 45 deletions

View File

@ -135,7 +135,7 @@ struct SegmentIntersection
p -= int64_t(pos_q>>1);
else
p += int64_t(pos_q>>1);
return coord_t(p / int64_t(pos_q));
return coord_t(p / int64_t(pos_q));
}
// Left vertical line / contour intersection point.
@ -251,7 +251,7 @@ struct SegmentIntersection
int vertical_down(Side side) const { return side == Side::Left ? this->left_vertical_down() : this->right_vertical_down(); }
int vertical_outside(Side side) const { return side == Side::Left ? this->left_vertical_outside() : this->right_vertical_outside(); }
// Returns -1 if there is no link up.
int vertical_up() const {
int vertical_up() const {
return this->has_left_vertical_up() ? this->left_vertical_up() : this->right_vertical_up();
}
LinkQuality vertical_up_quality() const {
@ -322,7 +322,7 @@ struct SegmentIntersection
}
}
bool operator==(const SegmentIntersection &other) const
bool operator==(const SegmentIntersection &other) const
{
assert(pos_q > 0);
assert(other.pos_q > 0);
@ -414,7 +414,7 @@ public:
//assert(aoffset1 < 0);
assert(aoffset2 <= 0);
// assert(aoffset2 == 0 || aoffset2 < aoffset1);
// bool sticks_removed =
// bool sticks_removed =
remove_sticks(polygons_src);
// if (sticks_removed) BOOST_LOG_TRIVIAL(error) << "Sticks removed!";
polygons_outer = aoffset1 == 0 ? to_polygons(polygons_src) : offset(polygons_src, float(aoffset1), ClipperLib::jtMiter, miterLimit);
@ -454,7 +454,7 @@ public:
// Any contour with offset2
bool is_contour_inner(size_t idx) const { return idx >= n_contours_outer; }
const Polygon& contour(size_t idx) const
const Polygon& contour(size_t idx) const
{ return is_contour_outer(idx) ? polygons_outer[idx] : polygons_inner[idx - n_contours_outer]; }
Polygon& contour(size_t idx)
@ -462,11 +462,11 @@ public:
bool is_contour_ccw(size_t idx) const { return polygons_ccw[idx]; }
BoundingBox bounding_box_src() const
BoundingBox bounding_box_src() const
{ return get_extents(polygons_src); }
BoundingBox bounding_box_outer() const
BoundingBox bounding_box_outer() const
{ return get_extents(polygons_outer); }
BoundingBox bounding_box_inner() const
BoundingBox bounding_box_inner() const
{ return get_extents(polygons_inner); }
#ifdef SLIC3R_DEBUG
@ -545,16 +545,16 @@ static inline bool intersection_on_prev_next_vertical_line_valid(
}
static inline bool intersection_on_prev_vertical_line_valid(
const std::vector<SegmentedIntersectionLine> &segs,
size_t iVerticalLine,
const std::vector<SegmentedIntersectionLine> &segs,
size_t iVerticalLine,
size_t iIntersection)
{
return intersection_on_prev_next_vertical_line_valid(segs, iVerticalLine, iIntersection, SegmentIntersection::Side::Left);
}
static inline bool intersection_on_next_vertical_line_valid(
const std::vector<SegmentedIntersectionLine> &segs,
size_t iVerticalLine,
const std::vector<SegmentedIntersectionLine> &segs,
size_t iVerticalLine,
size_t iIntersection)
{
return intersection_on_prev_next_vertical_line_valid(segs, iVerticalLine, iIntersection, SegmentIntersection::Side::Right);
@ -562,7 +562,7 @@ static inline bool intersection_on_next_vertical_line_valid(
// Measure an Euclidian length of a perimeter segment when going from iIntersection to iIntersection2.
static inline coordf_t measure_perimeter_horizontal_segment_length(
const ExPolygonWithOffset &poly_with_offset,
const ExPolygonWithOffset &poly_with_offset,
const std::vector<SegmentedIntersectionLine> &segs,
size_t iVerticalLine,
size_t iIntersection,
@ -859,7 +859,7 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
// Sort the intersection points using exact rational arithmetic.
//BBS: if the LOW and HIGH has seam y pos, LOW should be first
std::sort(sil.intersections.begin(), sil.intersections.end(), [](const SegmentIntersection &l, const SegmentIntersection &r) {
if (l.pos() == r.pos() && l.iContour == r.iContour)
if (abs(l.pos() - r.pos()) < scale_(EPSILON) && l.iContour == r.iContour)
return l.type < r.type;
return l.pos() < r.pos();
@ -1134,7 +1134,7 @@ static void connect_segment_intersections_by_contours(
assert(inext >= 0);
itsct.prev_on_contour = iprev;
itsct.prev_on_contour_type = same_prev ?
itsct.prev_on_contour_type = same_prev ?
(iprev < i_intersection ? SegmentIntersection::LinkType::Down : SegmentIntersection::LinkType::Up) :
SegmentIntersection::LinkType::Horizontal;
itsct.next_on_contour = inext;
@ -1191,7 +1191,7 @@ static void connect_segment_intersections_by_contours(
} else if (link_max_length > 0) {
// Measure length of the links.
if (itsct.prev_on_contour_quality == SegmentIntersection::LinkQuality::Valid &&
(same_prev ?
(same_prev ?
measure_perimeter_segment_on_vertical_line_length(poly_with_offset, segs, i_vline, iprev, i_intersection, forward) :
measure_perimeter_horizontal_segment_length(poly_with_offset, segs, i_vline - 1, iprev, i_intersection)) > link_max_length)
itsct.prev_on_contour_quality = SegmentIntersection::LinkQuality::TooLong;
@ -1533,9 +1533,9 @@ static void traverse_graph_generate_polylines(const ExPolygonWithOffset
// Try to connect to a previous or next point on the same vertical line.
int i_vertical = it->vertical_outside();
auto vertical_link_quality = (i_vertical == -1 || vline.intersections[i_vertical + (going_up ? 0 : -1)].consumed_vertical_up) ?
auto vertical_link_quality = (i_vertical == -1 || vline.intersections[i_vertical + (going_up ? 0 : -1)].consumed_vertical_up) ?
SegmentIntersection::LinkQuality::Invalid : it->vertical_outside_quality();
#if 0
#if 0
if (vertical_link_quality == SegmentIntersection::LinkQuality::Valid ||
// Follow the link if there is no horizontal link available.
(! intersection_horizontal_valid && vertical_link_quality != SegmentIntersection::LinkQuality::Invalid)) {
@ -1642,7 +1642,7 @@ struct MonotonicRegionLink
{
MonotonicRegion *region;
bool flipped;
// Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region
// Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region
// is applied as defined.
AntPath *next;
// Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region
@ -1656,10 +1656,10 @@ class AntPathMatrix
{
public:
AntPathMatrix(
const std::vector<MonotonicRegion> &regions,
const ExPolygonWithOffset &poly_with_offset,
const std::vector<MonotonicRegion> &regions,
const ExPolygonWithOffset &poly_with_offset,
const std::vector<SegmentedIntersectionLine> &segs,
const float initial_pheromone) :
const float initial_pheromone) :
m_regions(regions),
m_poly_with_offset(poly_with_offset),
m_segs(segs),
@ -2028,7 +2028,7 @@ static float montonous_region_path_length(const MonotonicRegion &region, bool di
break;
assert(it->iContour == vline.intersections[inext].iContour);
it = vline.intersections.data() + inext;
}
}
} else {
// Going down.
assert(it->is_high());
@ -2045,7 +2045,7 @@ static float montonous_region_path_length(const MonotonicRegion &region, bool di
break;
assert(it->iContour == vline.intersections[inext].iContour);
it = vline.intersections.data() + inext;
}
}
}
if (i_vline == region.right.vline)
@ -2057,7 +2057,7 @@ static float montonous_region_path_length(const MonotonicRegion &region, bool di
// Find the end of the next overlapping vertical segment.
const SegmentedIntersectionLine &vline_right = segs[i_vline + 1];
const SegmentIntersection *right = going_up ?
const SegmentIntersection *right = going_up ?
&vertical_run_top(vline_right, vline_right.intersections[iright]) : &vertical_run_bottom(vline_right, vline_right.intersections[iright]);
i_intersection = int(right - vline_right.intersections.data());
@ -2302,7 +2302,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
} else {
if (regions_in_queue[iprev])
assert(left_neighbors_unprocessed[iprev] == 1);
else
else
assert(left_neighbors_unprocessed[iprev] > 1);
++ num_predecessors_unprocessed;
}
@ -2394,7 +2394,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
total_length += next_region->length(next_dir) + path_matrix(*path_end.region, path_end.flipped, *next_region, next_dir).length;
path_end = { next_region, next_dir };
assert(left_neighbors_unprocessed[next_region - regions.data()] == 1);
left_neighbors_unprocessed[next_region - regions.data()] = 0;
left_neighbors_unprocessed[next_region - regions.data()] = 0;
}
// Set an initial pheromone value to 10% of the greedy path's value.
@ -2421,7 +2421,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
for (int round = 0; round < num_rounds && num_rounds_no_change < num_rounds_no_change_exit; ++ round)
{
bool improved = false;
for (int ant = 0; ant < num_ants; ++ ant)
for (int ant = 0; ant < num_ants; ++ ant)
{
// Find a new path following the pheromones deposited by the previous ants.
print_ant("Round %1% ant %2%", round, ant);
@ -2440,10 +2440,10 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
assert(left_neighbors_unprocessed[path.back().region - regions.data()] == 0);
assert(validate_unprocessed());
print_ant("\tRegion (%1%:%2%,%3%) (%4%:%5%,%6%)",
path.back().region->left.vline,
path.back().region->left.vline,
path.back().flipped ? path.back().region->left.high : path.back().region->left.low,
path.back().flipped ? path.back().region->left.low : path.back().region->left.high,
path.back().region->right.vline,
path.back().region->right.vline,
path.back().flipped == path.back().region->flips ? path.back().region->right.high : path.back().region->right.low,
path.back().flipped == path.back().region->flips ? path.back().region->right.low : path.back().region->right.high);
@ -2521,11 +2521,11 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
path.emplace_back(MonotonicRegionLink{ next_region, next_dir });
assert(left_neighbors_unprocessed[next_region - regions.data()] == 1);
left_neighbors_unprocessed[next_region - regions.data()] = 0;
print_ant("\tRegion (%1%:%2%,%3%) (%4%:%5%,%6%) length to prev %7%",
next_region->left.vline,
print_ant("\tRegion (%1%:%2%,%3%) (%4%:%5%,%6%) length to prev %7%",
next_region->left.vline,
next_dir ? next_region->left.high : next_region->left.low,
next_dir ? next_region->left.low : next_region->left.high,
next_region->right.vline,
next_region->right.vline,
next_dir == next_region->flips ? next_region->right.high : next_region->right.low,
next_dir == next_region->flips ? next_region->right.low : next_region->right.high,
take_path->link->length);
@ -2552,7 +2552,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
assert(! path.empty());
float path_length = std::accumulate(path.begin(), path.end() - 1,
path.back().region->length(path.back().flipped),
[&path_matrix](const float l, const MonotonicRegionLink &r) {
[&path_matrix](const float l, const MonotonicRegionLink &r) {
const MonotonicRegionLink &next = *(&r + 1);
return l + r.region->length(r.flipped) + path_matrix(*r.region, r.flipped, *next.region, next.flipped).length;
});
@ -2682,7 +2682,7 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
assert(it->iContour == vline.intersections[inext].iContour);
emit_perimeter_segment_on_vertical_line(poly_with_offset, segs, i_vline, it->iContour, it - vline.intersections.data(), inext, *polyline, it->has_left_vertical_up());
it = vline.intersections.data() + inext;
}
}
} else {
// Going down.
assert(it->is_high());
@ -2701,7 +2701,7 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
assert(it->iContour == vline.intersections[inext].iContour);
emit_perimeter_segment_on_vertical_line(poly_with_offset, segs, i_vline, it->iContour, it - vline.intersections.data(), inext, *polyline, it->has_right_vertical_down());
it = vline.intersections.data() + inext;
}
}
}
if (i_vline == region.right.vline)
@ -2713,7 +2713,7 @@ static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, c
// Find the end of the next overlapping vertical segment.
const SegmentedIntersectionLine &vline_right = segs[i_vline + 1];
const SegmentIntersection *right = going_up ?
const SegmentIntersection *right = going_up ?
&vertical_run_top(vline_right, vline_right.intersections[iright]) : &vertical_run_bottom(vline_right, vline_right.intersections[iright]);
i_intersection = int(right - vline_right.intersections.data());
@ -2776,8 +2776,8 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
// On the polygons of poly_with_offset, the infill lines will be connected.
ExPolygonWithOffset poly_with_offset(
surface->expolygon,
- rotate_vector.first,
surface->expolygon,
- rotate_vector.first,
float(scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)),
float(scale_(this->overlap - 0.5f * this->spacing)));
if (poly_with_offset.n_contours_inner == 0) {
@ -2803,8 +2803,8 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa
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.min,
Point(line_spacing, line_spacing),
bounding_box.min,
Point(line_spacing, line_spacing),
refpt));
}
@ -3066,11 +3066,11 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams &para
Polylines polylines_out;
coordf_t dx = sqrt(0.5) * z;
if (! this->fill_surface_by_multilines(
surface, params,
surface, params,
{ { 0.f, float(dx) }, { float(M_PI / 3.), - float(dx) }, { float(M_PI * 2. / 3.), float(dx) } },
polylines_out))
BOOST_LOG_TRIVIAL(error) << "FillCubic::fill_surface() failed to fill a region.";
return polylines_out;
return polylines_out;
}
Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams &params)
@ -3106,7 +3106,7 @@ Points sample_grid_pattern(const ExPolygon& expolygon, coord_t spacing, const Bo
{
ExPolygonWithOffset poly_with_offset(expolygon, 0, 0, 0);
std::vector<SegmentedIntersectionLine> segs = slice_region_by_vertical_lines(
poly_with_offset,
poly_with_offset,
(global_bounding_box.max.x() - global_bounding_box.min.x() + spacing - 1) / spacing,
global_bounding_box.min.x(),
spacing);
@ -3248,7 +3248,7 @@ void FillMonotonicLineWGapFill::fill_surface_by_lines(const Surface* surface, co
// On the polygons of poly_with_offset, the infill lines will be connected.
ExPolygonWithOffset poly_with_offset(
surface->expolygon,
- rotate_vector.first,
- rotate_vector.first,
float(scale_(0 - (0.5 - INFILL_OVERLAP_OVER_SPACING) * params.flow.spacing())),
float(scale_(0 - 0.5f * params.flow.spacing())));
if (poly_with_offset.n_contours_inner == 0) {