diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index ce5ff7a91..ef5443231 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -304,7 +304,8 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) //params.flow_mult = layerm.region()->config().over_bridge_flow_ratio; } - f->fill_surface_extrusion(&surface, params, flow, erNone, out.entities); + params.flow = &flow; + f->fill_surface_extrusion(&surface, params, out.entities); } // add thin fill regions diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 61fe00375..4968f3306 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -138,14 +138,14 @@ std::pair Fill::_infill_direction(const Surface *surface) const return std::pair(out_angle, out_shift); } -void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) { +void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) { //add overlap & call fill_surface Polylines polylines = this->fill_surface(surface, params); if (polylines.empty()) return; // ensure it doesn't over or under-extrude double multFlow = 1; - if (!params.dont_adjust && params.full_infill() && !flow.bridge && params.fill_exactly){ + if (!params.dont_adjust && params.full_infill() && !params.flow->bridge && params.fill_exactly){ // compute the path of the nozzle -> extruded volume double lengthTot = 0; int nbLines = 0; @@ -156,17 +156,17 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ nbLines++; } } - double extrudedVolume = flow.mm3_per_mm() * lengthTot; + double extrudedVolume = params.flow->mm3_per_mm() * lengthTot; // compute real volume double poylineVolume = 0; for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) { - poylineVolume += flow.height*unscaled(unscaled(poly->area())); + poylineVolume += params.flow->height*unscaled(unscaled(poly->area())); // add external "perimeter gap" - double perimeterRoundGap = unscaled(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; + double perimeterRoundGap = unscaled(poly->contour.length()) * params.flow->height * (1 - 0.25*PI) * 0.5; // add holes "perimeter gaps" double holesGaps = 0; for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) { - holesGaps += unscaled(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; + holesGaps += unscaled(hole->length()) * params.flow->height * (1 - 0.25*PI) * 0.5; } poylineVolume += perimeterRoundGap + holesGaps; } @@ -188,9 +188,9 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ /// add it into the collection out.push_back(eec); //get the role - ExtrusionRole good_role = role; + ExtrusionRole good_role = params.role; if (good_role == erNone || good_role == erCustom) { - good_role = (flow.bridge ? erBridgeInfill : + good_role = (params.flow->bridge ? erBridgeInfill : (surface->is_solid() ? ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : erInternalInfill)); @@ -199,9 +199,9 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ extrusion_entities_append_paths( eec->entities, std::move(polylines), good_role, - flow.mm3_per_mm() * params.flow_mult * multFlow, - flow.width * params.flow_mult * multFlow, - flow.height); + params.flow->mm3_per_mm() * params.flow_mult * multFlow, + params.flow->width * params.flow_mult * multFlow, + params.flow->height); } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 11006a6b7..dbb700b58 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -24,17 +24,19 @@ struct FillParams memset(this, 0, sizeof(FillParams)); // Adjustment does not work. dont_adjust = true; - flow_mult = 1.f; + flow_mult = 1.f; fill_exactly = false; + role = erNone; + flow = NULL; } bool full_infill() const { return density > 0.9999f && density < 1.0001f; } - // Fill density, fraction in <0, 1> - float density; + // Fill density, fraction in <0, 1> + float density; - // Fill extruding flow multiplier, fraction in <0, 1>. Used by "over bridge compensation" - float flow_mult; + // Fill extruding flow multiplier, fraction in <0, 1>. Used by "over bridge compensation" + float flow_mult; // Don't connect the fill lines around the inner perimeter. bool dont_connect; @@ -49,6 +51,12 @@ struct FillParams // we were requested to complete each loop; // in this case we don't try to make more continuous paths bool complete; + + // if role == erNone or ERCustom, this method have to choose the best role itself, else it must use the argument's role. + ExtrusionRole role; + + //flow to use + Flow const *flow; }; static_assert(IsTriviallyCopyable::value, "FillParams class is not POD (and it should be - see constructor)."); @@ -90,10 +98,8 @@ public: virtual bool no_sort() const { return false; } // This method have to fill the ExtrusionEntityCollection. It call fill_surface by default - // if role == erNone or ERCustom, this method have to choose the best role itself, else it must use the argument's role. - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); - + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out); + // Perform the fill. virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); @@ -136,8 +142,8 @@ public: // 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; + ((coord - spacing + 1) / spacing) * spacing : + (coord / spacing) * spacing; assert(aligned <= coord); return aligned; } diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp index b3e01b361..b47470de6 100644 --- a/src/libslic3r/Fill/FillConcentric.cpp +++ b/src/libslic3r/Fill/FillConcentric.cpp @@ -65,7 +65,7 @@ void FillConcentric::_fill_surface_single( } void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) { + ExtrusionEntitiesPtr &out) { // Perform offset. Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(scale_(0 - 0.5 * this->spacing))); @@ -112,9 +112,9 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, cons //get the role - ExtrusionRole good_role = role; + ExtrusionRole good_role = params.role; if (good_role == erNone || good_role == erCustom) { - good_role = (flow.bridge ? erBridgeInfill : + good_role = (params.flow->bridge ? erBridgeInfill : (surface->is_solid() ? ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : erInternalInfill)); @@ -125,9 +125,9 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, cons extrusion_entities_append_loops( coll_nosort->entities, loops, good_role, - flow.mm3_per_mm() * params.flow_mult, - flow.width * params.flow_mult, - flow.height); + params.flow->mm3_per_mm() * params.flow_mult, + params.flow->width * params.flow_mult, + params.flow->height); //add gapfills if (!gaps.empty() && params.density >= 1) { @@ -143,11 +143,11 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, cons //remove too small gaps that are too hard to fill. //ie one that are smaller than an extrusion with width of min and a length of max. if (ex.area() > min*max) { - ex.medial_axis(ex, max, min, &polylines, flow.height); + ex.medial_axis(ex, max, min, &polylines, params.flow->height); } } if (!polylines.empty()) { - ExtrusionEntityCollection gap_fill = thin_variable_width(polylines, erGapFill, flow); + ExtrusionEntityCollection gap_fill = thin_variable_width(polylines, erGapFill, *params.flow); coll_nosort->append(gap_fill.entities); } } diff --git a/src/libslic3r/Fill/FillConcentric.hpp b/src/libslic3r/Fill/FillConcentric.hpp index 918a370a7..593dfaff5 100644 --- a/src/libslic3r/Fill/FillConcentric.hpp +++ b/src/libslic3r/Fill/FillConcentric.hpp @@ -29,8 +29,7 @@ public: protected: virtual Fill* clone() const { return new FillConcentricWGapFill(*this); }; - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override; virtual bool no_sort() const { return true; } }; diff --git a/src/libslic3r/Fill/FillPlanePath.hpp b/src/libslic3r/Fill/FillPlanePath.hpp index 49fb2b387..fef375b11 100644 --- a/src/libslic3r/Fill/FillPlanePath.hpp +++ b/src/libslic3r/Fill/FillPlanePath.hpp @@ -24,7 +24,7 @@ protected: unsigned int thickness_layers, const std::pair &direction, ExPolygon &expolygon, - Polylines &polylines_out); + Polylines &polylines_out) override; virtual float _layer_angle(size_t idx) const { return 0.f; } virtual bool _centered() const = 0; diff --git a/src/libslic3r/Fill/FillRectilinear2.cpp b/src/libslic3r/Fill/FillRectilinear2.cpp index 23a404098..41dd81538 100644 --- a/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/src/libslic3r/Fill/FillRectilinear2.cpp @@ -299,13 +299,13 @@ public: polygons_inner = offset(polygons_outer, aoffset2 - aoffset1, ClipperLib::jtMiter, mitterLimit); - // Filter out contours with zero area or small area, contours with 2 points only. + // Filter out contours with zero area or small area, contours with 2 points only. const double min_area_threshold = 0.01 * aoffset2 * aoffset2; remove_small(polygons_outer, min_area_threshold); remove_small(polygons_inner, min_area_threshold); remove_sticks(polygons_outer); remove_sticks(polygons_inner); - n_contours_outer = polygons_outer.size(); + n_contours_outer = polygons_outer.size(); n_contours_inner = polygons_inner.size(); n_contours = n_contours_outer + n_contours_inner; polygons_ccw.assign(n_contours, false); @@ -660,32 +660,32 @@ static inline coordf_t measure_perimeter_segment_on_vertical_line_length( // The first point (the point of iIntersection) will not be inserted, // the last point will be inserted. static inline void emit_perimeter_segment_on_vertical_line( - const ExPolygonWithOffset &poly_with_offset, - const std::vector &segs, - size_t iVerticalLine, - size_t iInnerContour, - size_t iIntersection, - size_t iIntersection2, - Polyline &out, - bool forward) + const ExPolygonWithOffset &poly_with_offset, + const std::vector &segs, + size_t iVerticalLine, + size_t iInnerContour, + size_t iIntersection, + size_t iIntersection2, + Polyline &out, + bool forward) { - const SegmentedIntersectionLine &il = segs[iVerticalLine]; - const SegmentIntersection &itsct = il.intersections[iIntersection]; - const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; - const Polygon &poly = poly_with_offset.contour(iInnerContour); - assert(itsct.is_inner()); - assert(itsct2.is_inner()); - assert(itsct.type != itsct2.type); + const SegmentedIntersectionLine &il = segs[iVerticalLine]; + const SegmentIntersection &itsct = il.intersections[iIntersection]; + const SegmentIntersection &itsct2 = il.intersections[iIntersection2]; + const Polygon &poly = poly_with_offset.contour(iInnerContour); + assert(itsct.is_inner()); + assert(itsct2.is_inner()); + assert(itsct.type != itsct2.type); assert(itsct.iContour == iInnerContour); - assert(itsct.iContour == itsct2.iContour); - // Do not append the first point. - // out.points.push_back(Point(il.pos, itsct.pos)); - if (forward) - polygon_segment_append(out.points, poly, itsct.iSegment, itsct2.iSegment); - else - polygon_segment_append_reversed(out.points, poly, itsct.iSegment, itsct2.iSegment); - // Append the last point. - out.points.push_back(Point(il.pos, itsct2.pos())); + assert(itsct.iContour == itsct2.iContour); + // Do not append the first point. + // out.points.push_back(Point(il.pos, itsct.pos)); + if (forward) + polygon_segment_append(out.points, poly, itsct.iSegment, itsct2.iSegment); + else + polygon_segment_append_reversed(out.points, poly, itsct.iSegment, itsct2.iSegment); + // Append the last point. + out.points.push_back(Point(il.pos, itsct2.pos())); } //TBD: For precise infill, measure the area of a slab spanned by an infill line. @@ -767,9 +767,9 @@ std::vector FillRectilinear2::_vert_lines_for_polygon { // n_vlines = ceil(bbox_width / line_spacing) size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing; - coord_t x0 = bounding_box.min(0); - if (params.full_infill()) - x0 += (line_spacing + SCALED_EPSILON) / 2; + coord_t x0 = bounding_box.min(0); + if (params.full_infill()) + x0 += (line_spacing + SCALED_EPSILON) / 2; #ifdef SLIC3R_DEBUG static int iRun = 0; @@ -820,7 +820,7 @@ std::vector FillRectilinear2::_vert_lines_for_polygon assert(ir >= 0 && ir < segs.size()); for (int i = il; i <= ir; ++ i) { coord_t this_x = segs[i].pos; - assert(this_x == i * line_spacing + x0); + assert(this_x == i * line_spacing + x0); SegmentIntersection is; is.iContour = iContour; is.iSegment = iSegment; @@ -1198,7 +1198,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP // 3) Sort the intersection points, clear iPrev / iNext / iSegBelow / iSegAbove, // if it is preceded by any other intersection point along the contour. - unsigned int vert_seg_dir_valid_mask = + unsigned int vert_seg_dir_valid_mask = (going_up ? (iSegAbove != -1 && seg.intersections[iAbove].type == SegmentIntersection::INNER_LOW) : (iSegBelow != -1 && seg.intersections[iBelow].type == SegmentIntersection::INNER_HIGH)) ? @@ -1287,23 +1287,23 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP if (vert_seg_dir_valid_mask) { bool valid = true; // Verify, that there is no intersection with the inner contour up to the end of the contour segment. - // Verify, that the successive segment has not been consumed yet. - if (going_up) { - if (seg.intersections[iAbove].consumed_vertical_up) { - valid = false; - } else { - for (int i = (int)i_intersection + 1; i < iAbove && valid; ++i) - if (seg.intersections[i].is_inner()) - valid = false; - } + // Verify, that the successive segment has not been consumed yet. + if (going_up) { + if (seg.intersections[iAbove].consumed_vertical_up) { + valid = false; + } else { + for (int i = (int)i_intersection + 1; i < iAbove && valid; ++i) + if (seg.intersections[i].is_inner()) + valid = false; + } } else { - if (seg.intersections[iBelow-1].consumed_vertical_up) { - valid = false; - } else { - for (int i = iBelow + 1; i < (int)i_intersection && valid; ++i) - if (seg.intersections[i].is_inner()) - valid = false; - } + if (seg.intersections[iBelow-1].consumed_vertical_up) { + valid = false; + } else { + for (int i = iBelow + 1; i < (int)i_intersection && valid; ++i) + if (seg.intersections[i].is_inner()) + valid = false; + } } if (valid) { const Polygon &poly = poly_with_offset.contour(intrsctn->iContour); @@ -1372,9 +1372,9 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP assert(! polyline_current->has_duplicate_points()); // Handle nearly zero length edges. if (polyline_current->points.size() <= 1 || - (polyline_current->points.size() == 2 && - std::abs(polyline_current->points.front()(0) - polyline_current->points.back()(0)) < SCALED_EPSILON && - std::abs(polyline_current->points.front()(1) - polyline_current->points.back()(1)) < SCALED_EPSILON)) + (polyline_current->points.size() == 2 && + std::abs(polyline_current->points.front()(0) - polyline_current->points.back()(0)) < SCALED_EPSILON && + std::abs(polyline_current->points.front()(1) - polyline_current->points.back()(1)) < SCALED_EPSILON)) polylines_out.pop_back(); intrsctn = NULL; i_intersection = -1; @@ -1491,8 +1491,7 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶ void -FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) +FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) { ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection(); //you don't want to sort the extrusions: big infill first, small second @@ -1519,9 +1518,9 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP /// add it into the collection eecroot->entities.push_back(eec); //get the role - ExtrusionRole good_role = role; + ExtrusionRole good_role = params.role; if (good_role == erNone || good_role == erCustom) { - good_role = flow.bridge ? + good_role = params.flow->bridge ? erBridgeInfill : (surface->is_solid() ? ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : @@ -1532,9 +1531,9 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP eec->entities, polylines_1, good_role, - flow.mm3_per_mm() * params.flow_mult, - flow.width * params.flow_mult, - flow.height); + params.flow->mm3_per_mm() * params.flow_mult, + params.flow->width * params.flow_mult, + params.flow->height); } @@ -1558,9 +1557,9 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP /// add it into the collection eecroot->entities.push_back(eec); //get the role - ExtrusionRole good_role = role; + ExtrusionRole good_role = params.role; if (good_role == erNone || good_role == erCustom) { - good_role = flow.bridge ? + good_role = params.flow->bridge ? erBridgeInfill : (surface->is_solid() ? ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : @@ -1571,9 +1570,9 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP eec->entities, polylines_2, good_role, - flow.mm3_per_mm() * params.flow_mult, - flow.width * params.flow_mult, - flow.height); + params.flow->mm3_per_mm() * params.flow_mult, + params.flow->width * params.flow_mult, + params.flow->height); } // === end === diff --git a/src/libslic3r/Fill/FillRectilinear2.hpp b/src/libslic3r/Fill/FillRectilinear2.hpp index 21afacc71..879fbbfa4 100644 --- a/src/libslic3r/Fill/FillRectilinear2.hpp +++ b/src/libslic3r/Fill/FillRectilinear2.hpp @@ -16,13 +16,13 @@ class FillRectilinear2 : public Fill public: virtual Fill* clone() const { return new FillRectilinear2(*this); }; virtual ~FillRectilinear2() {} - virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override; protected: virtual std::vector _vert_lines_for_polygon(const ExPolygonWithOffset &poly_with_offset, const BoundingBox &bounding_box, const FillParams ¶ms, coord_t line_spacing) const; virtual coord_t _line_spacing_for_density(float density) const; - bool fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out); + bool fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out); }; class FillGrid2 : public FillRectilinear2 @@ -30,10 +30,10 @@ class FillGrid2 : public FillRectilinear2 public: virtual Fill* clone() const { return new FillGrid2(*this); }; virtual ~FillGrid2() {} - virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + virtual 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. + // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. virtual float _layer_angle(size_t idx) const { return 0.f; } }; @@ -42,10 +42,10 @@ class FillTriangles : public FillRectilinear2 public: virtual Fill* clone() const { return new FillTriangles(*this); }; virtual ~FillTriangles() {} - virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + virtual 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. + // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. virtual float _layer_angle(size_t idx) const { return 0.f; } }; @@ -54,7 +54,7 @@ class FillStars : public FillRectilinear2 public: virtual Fill* clone() const { return new FillStars(*this); }; virtual ~FillStars() {} - virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + virtual 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. @@ -66,14 +66,15 @@ class FillCubic : public FillRectilinear2 public: virtual Fill* clone() const { return new FillCubic(*this); }; virtual ~FillCubic() {} - virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + virtual 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. + // The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill. virtual float _layer_angle(size_t idx) const { return 0.f; } }; -class FillRectilinear2Peri : public FillRectilinear2 { +class FillRectilinear2Peri : public FillRectilinear2 +{ public: // require bridge flow since it's a pre-bridge over very sparse infill virtual bool use_bridge_flow() const { return true; } @@ -81,8 +82,7 @@ public: virtual Fill* clone() const { return new FillRectilinear2Peri(*this); }; virtual ~FillRectilinear2Peri() {} //virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override; }; @@ -90,9 +90,9 @@ public: class FillScatteredRectilinear : public FillRectilinear2 { public: - virtual Fill* clone() const { return new FillScatteredRectilinear(*this); }; + virtual Fill* clone() const override{ return new FillScatteredRectilinear(*this); }; virtual ~FillScatteredRectilinear() {} -virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override; protected: virtual float _layer_angle(size_t idx) const; diff --git a/src/libslic3r/Fill/FillSmooth.cpp b/src/libslic3r/Fill/FillSmooth.cpp index 6497af7f6..c93e0dffc 100644 --- a/src/libslic3r/Fill/FillSmooth.cpp +++ b/src/libslic3r/Fill/FillSmooth.cpp @@ -18,31 +18,100 @@ namespace Slic3r { return polylines_out; } + void FillSmooth::performSingleFill(const int idx, ExtrusionEntityCollection &eecroot, const Surface &srf_source, + const FillParams ¶ms, const double volume){ + if (srf_source.expolygon.empty()) return; + + // Save into layer smoothing path. + ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); + eec->no_sort = false; + FillParams params_modifided = params; + params_modifided.density *= percentWidth[idx]; + + if ((params.flow->bridge && idx == 0) || has_overlap[idx]){ + this->fillExPolygon(idx, *eec, srf_source, params_modifided, volume); + } + else{ + Surface surfaceNoOverlap(srf_source); + for (ExPolygon &poly : this->no_overlap_expolygons) { + if (poly.empty()) continue; + surfaceNoOverlap.expolygon = poly; + this->fillExPolygon(idx, *eec, surfaceNoOverlap, params_modifided, volume); + } + } + + if (eec->entities.empty()) delete eec; + else eecroot.entities.push_back(eec); + } + + void FillSmooth::fillExPolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill, + const FillParams ¶ms, const double volume){ + + std::unique_ptr f2 = std::unique_ptr(Fill::new_from_type(fillPattern[idx])); + f2->bounding_box = this->bounding_box; + f2->spacing = this->spacing; + f2->layer_id = this->layer_id; + f2->z = this->z; + f2->angle = anglePass[idx] + this->angle; + // Maximum length of the perimeter segment linking two infill lines. + f2->link_max_length = this->link_max_length; + // Used by the concentric infill pattern to clip the loops to create extrusion paths. + f2->loop_clipping = this->loop_clipping; + Polylines polylines_layer = f2->fill_surface(&srf_to_fill, params); - void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) + if (!polylines_layer.empty()){ + /*if (fillPattern[idx] == InfillPattern::ipRectilinear && polylines_layer[0].points.size() > 3){ + polylines_layer[0].points.erase(polylines_layer[0].points.begin()); + polylines_layer[polylines_layer.size() - 1].points.pop_back(); + }*/ + + //compute the path of the nozzle + double lengthTot = 0; + int nbLines = 0; + for (Polyline &pline : polylines_layer){ + Lines lines = pline.lines(); + for (Line &line : lines){ + lengthTot += unscaled(line.length()); + nbLines++; + } + } + double extrudedVolume = params.flow->mm3_per_mm() * lengthTot; + if (extrudedVolume == 0) extrudedVolume = volume; + + //get the role + ExtrusionRole good_role = params.role; + if (good_role == erNone || good_role == erCustom) { + good_role = params.flow->bridge && idx==0 ? erBridgeInfill : rolePass[idx]; + } + // print thin + extrusion_entities_append_paths( + eec.entities, std::move(polylines_layer), + good_role, + params.flow_mult * params.flow->mm3_per_mm() * percentFlow[idx] * + (params.fill_exactly ? std::min(2., volume / extrudedVolume) : 1), + //min-reduced flow width for a better view (it's only a gui thing) + (float)(params.flow->width*(percentFlow[idx] < 0.1 ? 0.1 : percentFlow[idx])), (float)params.flow->height); + } + else{ + return; + } + } + + + void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) { coordf_t init_spacing = this->spacing; - //printf("FillSmooth::fill_surface() : you call the right method (fill_surface instead of fill_surface_extrusion).\n"); - //second pass with half layer width - FillParams params1 = params; - FillParams params2 = params; - FillParams params3 = params; - params1.density *= percentWidth[0]; - params2.density *= percentWidth[1]; - params3.density *= percentWidth[2]; - // compute the volume to extrude double volumeToOccupy = 0; for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) { // add external "perimeter gap" - double poylineVolume = flow.height*unscaled(unscaled(poly->area())); - double perimeterRoundGap = unscaled(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; + double poylineVolume = params.flow->height*unscaled(unscaled(poly->area())); + double perimeterRoundGap = unscaled(poly->contour.length()) * params.flow->height * (1 - 0.25*PI) * 0.5; // add holes "perimeter gaps" double holesGaps = 0; for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) { - holesGaps += unscaled(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; + holesGaps += unscaled(hole->length()) * params.flow->height * (1 - 0.25*PI) * 0.5; } poylineVolume += perimeterRoundGap + holesGaps; @@ -61,214 +130,18 @@ namespace Slic3r { // first infill - std::unique_ptr f1 = std::unique_ptr(Fill::new_from_type(fillPattern[0])); - f1->bounding_box = this->bounding_box; - f1->spacing = init_spacing; - f1->layer_id = this->layer_id; - f1->z = this->z; - f1->angle = anglePass[0]; - // Maximum length of the perimeter segment linking two infill lines. - f1->link_max_length = this->link_max_length; - // Used by the concentric infill pattern to clip the loops to create extrusion paths. - f1->loop_clipping = this->loop_clipping; - Surface surfaceNoOverlap(*surface); - if (flow.bridge) { - - Polylines polylines_layer1 = f1->fill_surface(surface, params1); - - if (!polylines_layer1.empty()) { - if (fillPattern[2] == InfillPattern::ipRectilinear && polylines_layer1[0].points.size() > 3) { - polylines_layer1[0].points.erase(polylines_layer1[0].points.begin()); - polylines_layer1[polylines_layer1.size() - 1].points.pop_back(); - } - - //compute the path of the nozzle - double lengthTot = 0; - int nbLines = 0; - for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) { - Lines lines = pline->lines(); - for (auto line = lines.begin(); line != lines.end(); ++line) { - lengthTot += unscaled(line->length()); - nbLines++; - } - } - double extrudedVolume = flow.mm3_per_mm() * lengthTot; - if (extrudedVolume == 0) extrudedVolume = 1; - - // Save into layer smoothing path. - // print thin - - eec = new ExtrusionEntityCollection(); - eecroot->entities.push_back(eec); - eec->no_sort = false; //can be sorted inside the pass - extrusion_entities_append_paths( - eec->entities, std::move(polylines_layer1), - flow.bridge ? erBridgeInfill : rolePass[0], - //reduced flow height for a better view (it's only a gui thing) - params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1), - (float)(flow.width*percentFlow[0] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1)), (float)flow.height*0.8); - } else { - return; - } - - } else { - for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) { - surfaceNoOverlap.expolygon = *poly; - Polylines polylines_layer1 = f1->fill_surface(&surfaceNoOverlap, params1); - if (!polylines_layer1.empty()) { - - double lengthTot = 0; - int nbLines = 0; - for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) { - Lines lines = pline->lines(); - for (auto line = lines.begin(); line != lines.end(); ++line) { - lengthTot += unscaled(line->length()); - nbLines++; - } - } - - // add external "perimeter gap" - double poylineVolume = flow.height*unscaled(unscaled(poly->area())); - double perimeterRoundGap = unscaled(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; - // add holes "perimeter gaps" - double holesGaps = 0; - for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) { - holesGaps += unscaled(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; - } - poylineVolume += perimeterRoundGap + holesGaps; - - //extruded volume: see http://manual.slic3r.org/advanced/flow-math, and we need to remove a circle at an end (as the flow continue) - double extrudedVolume = flow.mm3_per_mm() * lengthTot; - - eec = new ExtrusionEntityCollection(); - eecroot->entities.push_back(eec); - eec->no_sort = false; //can be sorted inside the pass - //get the role - ExtrusionRole good_role = role; - if (good_role == erNone || good_role == erCustom) { - good_role = flow.bridge ? erBridgeInfill : rolePass[0]; - } - extrusion_entities_append_paths( - eec->entities, std::move(polylines_layer1), - good_role, - //reduced flow height for a better view (it's only a gui thing) - params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1), - (float)(flow.width*percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1)), (float)flow.height*0.8); - } else { - return; - } - } - } + performSingleFill(0, *eecroot, *surface, params, volumeToOccupy); //second infill if (nbPass > 1){ - - std::unique_ptr f2 = std::unique_ptr(Fill::new_from_type(fillPattern[1])); - f2->bounding_box = this->bounding_box; - f2->spacing = init_spacing; - f2->layer_id = this->layer_id; - f2->z = this->z; - f2->angle = anglePass[1]; - // Maximum length of the perimeter segment linking two infill lines. - f2->link_max_length = this->link_max_length; - // Used by the concentric infill pattern to clip the loops to create extrusion paths. - f2->loop_clipping = this->loop_clipping; - Polylines polylines_layer2 = f2->fill_surface(surface, params2); - - if (!polylines_layer2.empty()){ - if (fillPattern[2] == InfillPattern::ipRectilinear && polylines_layer2[0].points.size() > 3){ - polylines_layer2[0].points.erase(polylines_layer2[0].points.begin()); - polylines_layer2[polylines_layer2.size() - 1].points.pop_back(); - } - - //compute the path of the nozzle - double lengthTot = 0; - int nbLines = 0; - for (auto pline = polylines_layer2.begin(); pline != polylines_layer2.end(); ++pline){ - Lines lines = pline->lines(); - for (auto line = lines.begin(); line != lines.end(); ++line){ - lengthTot += unscaled(line->length()); - nbLines++; - } - } - double extrudedVolume = flow.mm3_per_mm() * lengthTot; - if (extrudedVolume == 0) extrudedVolume = 1; - - // Save into layer smoothing path. - eec = new ExtrusionEntityCollection(); - eecroot->entities.push_back(eec); - eec->no_sort = false; - //get the role - ExtrusionRole good_role = role; - if (good_role == erNone || good_role == erCustom) { - good_role = rolePass[1]; - } - // print thin - extrusion_entities_append_paths( - eec->entities, std::move(polylines_layer2), - good_role, - params.flow_mult * flow.mm3_per_mm() * percentFlow[1] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1), - //min-reduced flow width for a better view (it's only a gui thing) - (float)(flow.width*(percentFlow[1] < 0.1 ? 0.1 : percentFlow[1])), (float)flow.height); - } - else{ - return; - } + performSingleFill(1, *eecroot, *surface, params, volumeToOccupy); } // third infill if (nbPass > 2){ - std::unique_ptr f3 = std::unique_ptr(Fill::new_from_type(fillPattern[0])); - f3->bounding_box = this->bounding_box; - f3->spacing = init_spacing; - f3->layer_id = this->layer_id; - f3->z = this->z; - f3->angle = anglePass[2]; - // Maximum length of the perimeter segment linking two infill lines. - f3->link_max_length = this->link_max_length; - // Used by the concentric infill pattern to clip the loops to create extrusion paths. - f3->loop_clipping = this->loop_clipping; - Polylines polylines_layer3 = f3->fill_surface(surface, params1); - - if (!polylines_layer3.empty()){ - - //remove some points that are not inside the area - if (fillPattern[2] == InfillPattern::ipRectilinear && polylines_layer3[0].points.size() > 3){ - polylines_layer3[0].points.erase(polylines_layer3[0].points.begin()); - polylines_layer3[polylines_layer3.size() - 1].points.pop_back(); - } - - //compute the path of the nozzle - double lengthTot = 0; - int nbLines = 0; - for (auto pline = polylines_layer3.begin(); pline != polylines_layer3.end(); ++pline){ - Lines lines = pline->lines(); - for (auto line = lines.begin(); line != lines.end(); ++line){ - lengthTot += unscaled(line->length()); - nbLines++; - } - } - double extrudedVolume = flow.mm3_per_mm() * lengthTot; - - // Save into layer smoothing path. layer 3 - eec = new ExtrusionEntityCollection(); - eecroot->entities.push_back(eec); - eec->no_sort = false; - //get the role - ExtrusionRole good_role = role; - if (good_role == erNone || good_role == erCustom) { - good_role = rolePass[2]; - } - // print thin - extrusion_entities_append_paths( - eec->entities, std::move(polylines_layer3), - good_role, //slow (if last) - //reduced flow width for a better view (it's only a gui thing) - params.flow_mult * flow.mm3_per_mm() * percentFlow[2] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1), - (float)(flow.width*(percentFlow[2] < 0.1 ? 0.1 : percentFlow[2])), (float)flow.height); - } + performSingleFill(2, *eecroot, *surface, params, volumeToOccupy); } - + if (!eecroot->entities.empty()) out.push_back(eecroot); else delete eecroot; diff --git a/src/libslic3r/Fill/FillSmooth.hpp b/src/libslic3r/Fill/FillSmooth.hpp index eb558f088..9bbd25a57 100644 --- a/src/libslic3r/Fill/FillSmooth.hpp +++ b/src/libslic3r/Fill/FillSmooth.hpp @@ -11,98 +11,114 @@ class FillSmooth : public Fill { public: FillSmooth() { - nbPass = 2; - anglePass[0] = float(M_PI/4); - anglePass[1] = -float(M_PI/4); - anglePass[2] = 0; - fillPattern[0] = InfillPattern::ipRectilinear; - fillPattern[1] = InfillPattern::ipRectilinear; - fillPattern[2] = InfillPattern::ipRectilinear; - rolePass[0] = erSolidInfill; - rolePass[1] = erTopSolidInfill; - rolePass[2] = erSolidInfill; - percentWidth[0] = 0.9; - percentWidth[1] = 2; - percentWidth[2] = 1.0; - percentFlow[0] = 0.7; - percentFlow[1] = 0.3; - percentFlow[2] = 0.0; - double extrusionMult = 1.0; - percentFlow[0] *= extrusionMult; - percentFlow[1] *= extrusionMult; - percentFlow[2] *= extrusionMult; - } - virtual Fill* clone() const { return new FillSmooth(*this); } + nbPass = 2; + anglePass[0] = 0; + anglePass[1] = float(M_PI/2); + anglePass[2] = 0; + fillPattern[0] = InfillPattern::ipRectilinear; + fillPattern[1] = InfillPattern::ipRectilinear; + fillPattern[2] = InfillPattern::ipRectilinear; + rolePass[0] = erSolidInfill; + rolePass[1] = erTopSolidInfill; + rolePass[2] = erSolidInfill; + percentWidth[0] = 0.9; + percentWidth[1] = 2; + percentWidth[2] = 1.0; + percentFlow[0] = 0.7; + percentFlow[1] = 0.3; + percentFlow[2] = 0.0; + double extrusionMult = 1.0; + percentFlow[0] *= extrusionMult; + percentFlow[1] *= extrusionMult; + percentFlow[2] *= extrusionMult; + has_overlap[0] = false; + has_overlap[1] = true; + has_overlap[2] = false; + } + virtual Fill* clone() const{ return new FillSmooth(*this); } - virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, - const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); - + virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override; + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override; + protected: - int nbPass=2; - double percentWidth[3]; - double percentFlow[3]; - float anglePass[3]; - ExtrusionRole rolePass[3]; - InfillPattern fillPattern[3]; + int nbPass=2; + double percentWidth[3]; + double percentFlow[3]; + float anglePass[3]; + bool has_overlap[3]; + ExtrusionRole rolePass[3]; + InfillPattern fillPattern[3]; + + void FillSmooth::performSingleFill(const int idx, ExtrusionEntityCollection &eecroot, const Surface &srf_source, + const FillParams ¶ms, const double volume); + void FillSmooth::fillExPolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill, + const FillParams ¶ms, const double volume); }; class FillSmoothTriple : public FillSmooth { public: - FillSmoothTriple() { - nbPass = 3; - anglePass[0] = float(M_PI / 4); - anglePass[1] = -float(M_PI / 4); - anglePass[2] = float(M_PI / 12); //align with nothing - fillPattern[0] = InfillPattern::ipRectilinear; - fillPattern[1] = InfillPattern::ipConcentric; - fillPattern[2] = InfillPattern::ipRectilinear; - rolePass[0] = erSolidInfill; - rolePass[1] = erSolidInfill; - rolePass[2] = erTopSolidInfill; - percentWidth[0] = 0.8; - percentWidth[1] = 1.5; - percentWidth[2] = 2.8; - percentFlow[0] = 0.7; - percentFlow[1] = 0.2; - percentFlow[2] = 0.1; - double extrusionMult = 1.0; - percentFlow[0] *= extrusionMult; - percentFlow[1] *= extrusionMult; - percentFlow[2] *= extrusionMult; - } - virtual Fill* clone() const { return new FillSmoothTriple(*this); } + FillSmoothTriple() { + nbPass = 1; //3 + anglePass[0] = 0; + anglePass[1] = float(M_PI / 2); + anglePass[2] = float(M_PI / 12); //align with nothing + fillPattern[0] = InfillPattern::ipHilbertCurve; //ipRectilinear + fillPattern[1] = InfillPattern::ipConcentric; + fillPattern[2] = InfillPattern::ipRectilinear; + rolePass[0] = erTopSolidInfill;//erSolidInfill + rolePass[1] = erSolidInfill; + rolePass[2] = erTopSolidInfill; + percentWidth[0] = 1.4; //0.8 + percentWidth[1] = 1.5; + percentWidth[2] = 2.8; + percentFlow[0] = 1; //0.7 + percentFlow[1] = 0.25; + percentFlow[2] = 0.15; + double extrusionMult = 1.0; //slight over-extrusion + percentFlow[0] *= extrusionMult; + percentFlow[1] *= extrusionMult; + percentFlow[2] *= extrusionMult; + has_overlap[0] = true; + has_overlap[1] = true; + has_overlap[2] = true; + + } + virtual Fill* clone() const { return new FillSmoothTriple(*this); } }; class FillSmoothHilbert : public FillSmooth { public: - FillSmoothHilbert() { - nbPass = 2; - anglePass[0] = 0; - anglePass[1] = -float(M_PI / 4); - anglePass[2] = float(M_PI / 4); - fillPattern[0] = InfillPattern::ipHilbertCurve; //ipHilbertCurve - fillPattern[1] = InfillPattern::ipRectilinear; - fillPattern[2] = InfillPattern::ipRectilinear; - rolePass[0] = erSolidInfill; - rolePass[1] = erSolidInfill; - rolePass[2] = erTopSolidInfill; - percentWidth[0] = 1.0; - percentWidth[1] = 1.0; - percentWidth[2] = 1.0; - percentFlow[0] = 0.8; - percentFlow[1] = 0.1; - percentFlow[2] = 0.1; - double extrusionMult = 1.0; - percentFlow[0] *= extrusionMult; - percentFlow[1] *= extrusionMult; - percentFlow[2] *= extrusionMult; - } - virtual Fill* clone() const { return new FillSmoothHilbert(*this); } + FillSmoothHilbert() { + nbPass = 2; + anglePass[0] = 0; + anglePass[1] = float(M_PI / 4); + anglePass[2] = float(M_PI / 4); + fillPattern[0] = InfillPattern::ipHilbertCurve; //ipHilbertCurve + fillPattern[1] = InfillPattern::ipHilbertCurve; + fillPattern[2] = InfillPattern::ipRectilinear; + rolePass[0] = erSolidInfill; + rolePass[1] = erTopSolidInfill; + rolePass[2] = erTopSolidInfill; + percentWidth[0] = 1; + percentWidth[1] = 1.5; + percentWidth[2] = 1.0; + percentFlow[0] = 1; + percentFlow[1] = 0.0; + percentFlow[2] = 0.0; + double extrusionMult = 1.0; + percentFlow[0] *= extrusionMult; + percentFlow[1] *= extrusionMult; + percentFlow[2] *= extrusionMult; + has_overlap[0] = true; + has_overlap[1] = false; + has_overlap[2] = true; + + } + virtual Fill* clone() const { return new FillSmoothHilbert(*this); } }; diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index b1acce773..4a5c3ce71 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -629,7 +629,7 @@ public: } // Deserialization constructor - bool deserialize_(const std::string &path, int which = -1) + bool deserialize_(const std::string &path, int which = -1) { FILE *file = ::fopen(path.c_str(), "rb"); if (file == nullptr) @@ -793,8 +793,9 @@ namespace SupportMaterialInternal { { for (const ExtrusionEntity *ee : perimeters.entities) { if (ee->is_collection()) { + const ExtrusionEntityCollection * eec = static_cast(ee); for (const ExtrusionEntity *ee2 : static_cast(ee)->entities) { - assert(! ee2->is_collection()); + //assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !! if (ee2->is_loop()) if (has_bridging_perimeters(*static_cast(ee2))) return true; @@ -807,11 +808,12 @@ namespace SupportMaterialInternal { static bool has_bridging_fills(const ExtrusionEntityCollection &fills) { for (const ExtrusionEntity *ee : fills.entities) { - assert(ee->is_collection()); - for (const ExtrusionEntity *ee2 : static_cast(ee)->entities) { - assert(! ee2->is_collection()); - assert(! ee2->is_loop()); - if (ee2->role() == erBridgeInfill) + if (ee->is_collection()) { + if(has_bridging_fills(*static_cast(ee))) + return true; + } else { + assert(! ee->is_loop()); + if (ee->role() == erBridgeInfill) return true; } } @@ -2330,9 +2332,11 @@ static inline void fill_expolygons_generate_paths( fill_params.density = density; fill_params.complete = true; fill_params.dont_adjust = true; + fill_params.flow = &flow; + fill_params.role = role; for (const ExPolygon &expoly : expolygons) { Surface surface(stInternal, expoly); - filler->fill_surface_extrusion(&surface, fill_params, flow, role, dst); + filler->fill_surface_extrusion(&surface, fill_params, dst); } } @@ -2348,9 +2352,11 @@ static inline void fill_expolygons_generate_paths( fill_params.density = density; fill_params.complete = true; fill_params.dont_adjust = true; + fill_params.flow = &flow; + fill_params.role = role; for (ExPolygon &expoly : expolygons) { Surface surface(stInternal, std::move(expoly)); - filler->fill_surface_extrusion(&surface, fill_params, flow, role, dst); + filler->fill_surface_extrusion(&surface, fill_params, dst); } }