diff options
-rw-r--r-- | xs/src/libslic3r/Fill/FillBase.cpp | 4 | ||||
-rw-r--r-- | xs/src/libslic3r/Fill/FillRectilinear2.cpp | 87 | ||||
-rw-r--r-- | xs/src/libslic3r/PrintObject.cpp | 10 | ||||
-rw-r--r-- | xs/src/libslic3r/Surface.hpp | 9 |
4 files changed, 97 insertions, 13 deletions
diff --git a/xs/src/libslic3r/Fill/FillBase.cpp b/xs/src/libslic3r/Fill/FillBase.cpp index 6cd508acb..d19615aa9 100644 --- a/xs/src/libslic3r/Fill/FillBase.cpp +++ b/xs/src/libslic3r/Fill/FillBase.cpp @@ -69,10 +69,10 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance) assert(width >= 0); assert(distance > 0); // floor(width / distance) - coord_t number_of_intervals = width / distance; + coord_t number_of_intervals = (width - EPSILON) / distance; coord_t distance_new = (number_of_intervals == 0) ? distance : - (width / number_of_intervals); + ((width - EPSILON) / number_of_intervals); const coordf_t factor = coordf_t(distance_new) / coordf_t(distance); assert(factor > 1. - 1e-5); // How much could the extrusion width be increased? By 20%. diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp index 20709cbde..766f389b0 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp @@ -768,6 +768,74 @@ static inline void emit_perimeter_segment_on_vertical_line( out.points.push_back(Point(il.pos, itsct2.pos())); } +//TBD: For precise infill, measure the area of a slab spanned by an infill line. +/* +static inline float measure_outer_contour_slab( + const ExPolygonWithOffset &poly_with_offset, + const std::vector<SegmentedIntersectionLine> &segs, + size_t i_vline, + size_t iIntersection) +{ + const SegmentedIntersectionLine &il = segs[i_vline]; + const SegmentIntersection &itsct = il.intersections[i_vline]; + const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; + const Polygon &poly = poly_with_offset.contour((itsct.iContour); + myassert(itsct.is_outer()); + myassert(itsct2.is_outer()); + myassert(itsct.type != itsct2.type); + myassert(itsct.iContour == itsct2.iContour); + if (! itsct.is_outer() || ! itsct2.is_outer() || itsct.type == itsct2.type || itsct.iContour != itsct2.iContour) + // Error, return zero area. + return 0.f; + + // Find possible connection points on the previous / next vertical line. + int iPrev = intersection_on_prev_vertical_line(poly_with_offset, segs, i_vline, itsct.iContour, i_intersection); + int iNext = intersection_on_next_vertical_line(poly_with_offset, segs, i_vline, itsct.iContour, i_intersection); + // Find possible connection points on the same vertical line. + int iAbove = iBelow = -1; + // Does the perimeter intersect the current vertical line above intrsctn? + for (size_t i = i_intersection + 1; i + 1 < seg.intersections.size(); ++ i) + if (seg.intersections[i].iContour == itsct.iContour) + { iAbove = i; break; } + // Does the perimeter intersect the current vertical line below intrsctn? + for (int i = int(i_intersection) - 1; i > 0; -- i) + if (seg.intersections[i].iContour == itsct.iContour) + { iBelow = i; break; } + + if (iSegAbove != -1 && seg.intersections[iAbove].type == SegmentIntersection::OUTER_HIGH) { + // Invalidate iPrev resp. iNext, if the perimeter crosses the current vertical line earlier than iPrev resp. iNext. + // The perimeter contour orientation. + const Polygon &poly = poly_with_offset.contour(itsct.iContour); + { + int d_horiz = (iPrev == -1) ? std::numeric_limits<int>::max() : + distance_of_segmens(poly, segs[i_vline-1].intersections[iPrev].iSegment, itsct.iSegment, true); + int d_down = (iBelow == -1) ? std::numeric_limits<int>::max() : + distance_of_segmens(poly, iSegBelow, itsct.iSegment, true); + int d_up = (iAbove == -1) ? std::numeric_limits<int>::max() : + distance_of_segmens(poly, iSegAbove, itsct.iSegment, true); + if (intrsctn_type_prev == INTERSECTION_TYPE_OTHER_VLINE_OK && d_horiz > std::min(d_down, d_up)) + // The vertical crossing comes eralier than the prev crossing. + // Disable the perimeter going back. + intrsctn_type_prev = INTERSECTION_TYPE_OTHER_VLINE_NOT_FIRST; + if (d_up > std::min(d_horiz, d_down)) + // The horizontal crossing comes earlier than the vertical crossing. + vert_seg_dir_valid_mask &= ~DIR_BACKWARD; + } + { + int d_horiz = (iNext == -1) ? std::numeric_limits<int>::max() : + distance_of_segmens(poly, itsct.iSegment, segs[i_vline+1].intersections[iNext].iSegment, true); + int d_down = (iSegBelow == -1) ? std::numeric_limits<int>::max() : + distance_of_segmens(poly, itsct.iSegment, iSegBelow, true); + int d_up = (iSegAbove == -1) ? std::numeric_limits<int>::max() : + distance_of_segmens(poly, itsct.iSegment, iSegAbove, true); + if (d_up > std::min(d_horiz, d_down)) + // The horizontal crossing comes earlier than the vertical crossing. + vert_seg_dir_valid_mask &= ~DIR_FORWARD; + } + } +} +*/ + enum DirectionMask { DIR_FORWARD = 1, @@ -826,7 +894,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // Intersect a set of euqally spaced vertical lines wiht expolygon. // n_vlines = ceil(bbox_width / line_spacing) size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing; - coord_t x0 = bounding_box.min.x + line_spacing / 2; + coord_t x0 = bounding_box.min.x + (line_spacing + SCALED_EPSILON) / 2; #ifdef SLIC3R_DEBUG static int iRun = 0; @@ -1111,13 +1179,20 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP svg.Close(); #endif /* SLIC3R_DEBUG */ - // Mark an outer only chord as consumed, so there will be no tiny pieces emitted. + // For each outer only chords, measure their maximum distance to the bow of the outer contour. + // Mark an outer only chord as consumed, if the distance is low. for (size_t i_vline = 0; i_vline < segs.size(); ++ i_vline) { SegmentedIntersectionLine &seg = segs[i_vline]; - for (size_t i = 0; i + 1 < seg.intersections.size(); ++ i) { - if (seg.intersections[i].type == SegmentIntersection::OUTER_LOW && - seg.intersections[i+1].type == SegmentIntersection::OUTER_HIGH) - seg.intersections[i].consumed_vertical_up = true; + for (size_t i_intersection = 0; i_intersection + 1 < seg.intersections.size(); ++ i_intersection) { + if (seg.intersections[i_intersection].type == SegmentIntersection::OUTER_LOW && + seg.intersections[i_intersection+1].type == SegmentIntersection::OUTER_HIGH) { + bool consumed = false; +// if (full_infill) { +// measure_outer_contour_slab(poly_with_offset, segs, i_vline, i_ntersection); +// } else + consumed = true; + seg.intersections[i_intersection].consumed_vertical_up = consumed; + } } } diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 64a46c06c..f19caadc9 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -498,6 +498,7 @@ PrintObject::discover_vertical_shells() #ifdef SLIC3R_DEBUG_SLICE_PROCESSING ExPolygons shell_ex; #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + float min_perimeter_infill_spacing = float(infill_line_spacing) * 1.05f; if (1) { #ifdef SLIC3R_DEBUG_SLICE_PROCESSING @@ -531,13 +532,13 @@ PrintObject::discover_vertical_shells() polygons_append(shell, neighbor_layer.perimeter_expolygons.expolygons); if (n > int(idx_layer)) { // Collect top surfaces. - polygons_append(shell, to_polygons(neighbor_region.slices.filter_by_type(stTop))); - polygons_append(shell, to_polygons(neighbor_region.fill_surfaces.filter_by_type(stTop))); + polygons_append(shell, offset(to_expolygons(neighbor_region.slices.filter_by_type(stTop)), min_perimeter_infill_spacing)); + polygons_append(shell, offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing)); } else if (n < int(idx_layer)) { // Collect bottom and bottom bridge surfaces. - polygons_append(shell, to_polygons(neighbor_region.slices.filter_by_types(surfaces_bottom, 2))); - polygons_append(shell, to_polygons(neighbor_region.fill_surfaces.filter_by_types(surfaces_bottom, 2))); + polygons_append(shell, offset(to_expolygons(neighbor_region.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing)); + polygons_append(shell, offset(to_expolygons(neighbor_region.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing)); } } #ifdef SLIC3R_DEBUG_SLICE_PROCESSING @@ -615,7 +616,6 @@ PrintObject::discover_vertical_shells() Polygons shell_before = shell; #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ #if 1 - float min_perimeter_infill_spacing = float(infill_line_spacing) * 1.05f; // Intentionally inflate a bit more than how much the region has been shrunk, // so there will be some overlap between this solid infill and the other infill regions (mainly the sparse infill). shell = offset2(shell, - 0.5f * min_perimeter_infill_spacing, 0.8f * min_perimeter_infill_spacing, diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 9ef710741..d87c9b695 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -97,6 +97,15 @@ inline Polygons to_polygons(const SurfacesPtr &src) return polygons; } +inline ExPolygons to_expolygons(const SurfacesPtr &src) +{ + ExPolygons expolygons; + expolygons.reserve(src.size()); + for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it) + expolygons.push_back((*it)->expolygon); + return expolygons; +} + // Count a nuber of polygons stored inside the vector of expolygons. // Useful for allocating space for polygons when converting expolygons to polygons. inline size_t number_polygons(const Surfaces &surfaces) |