From 611f022a0c2b56c66e7bbc796224b0bfa3c8b37d Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Thu, 13 Mar 2025 21:45:38 +0800 Subject: [PATCH] FIX: fix slice error: invalid infill Reason: sorting errors caused by precision jira: STUDIO-10841 Change-Id: I64dbbcf9e35477b597c4755863f307cf444f50d9 --- src/libslic3r/Fill/FillRectilinear.cpp | 90 +++++++++++++------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 860114530..20e08bc1b 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -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 &segs, - size_t iVerticalLine, + const std::vector &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 &segs, - size_t iVerticalLine, + const std::vector &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 &segs, size_t iVerticalLine, size_t iIntersection, @@ -859,7 +859,7 @@ static std::vector 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 ®ions, - const ExPolygonWithOffset &poly_with_offset, + const std::vector ®ions, + const ExPolygonWithOffset &poly_with_offset, const std::vector &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 ®ion, 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 ®ion, 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 ®ion, 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 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 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 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 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 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 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 &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 &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 &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 ¶ 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 ¶ms) @@ -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 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) {