mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-14 21:41:57 +08:00
ironing: cleaning code (remove duplication), streamline arguments & config struct for fill_surface_extrusion.
This commit is contained in:
parent
7d4f090786
commit
fb0fe3ac39
@ -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
|
||||
|
@ -138,14 +138,14 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
||||
return std::pair<float, Point>(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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||
|
||||
@ -90,9 +98,7 @@ 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ protected:
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &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;
|
||||
|
@ -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<SegmentedIntersectionLine> &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<SegmentedIntersectionLine> &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<SegmentedIntersectionLine> 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<SegmentedIntersectionLine> 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 ===
|
||||
|
@ -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<SegmentedIntersectionLine> _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;
|
||||
|
@ -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;
|
||||
|
||||
void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms,
|
||||
const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out)
|
||||
// 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<Fill> f2 = std::unique_ptr<Fill>(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);
|
||||
|
||||
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,212 +130,16 @@ namespace Slic3r {
|
||||
|
||||
|
||||
// first infill
|
||||
std::unique_ptr<Fill> f1 = std::unique_ptr<Fill>(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<Fill> f2 = std::unique_ptr<Fill>(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<Fill> f3 = std::unique_ptr<Fill>(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())
|
||||
|
@ -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); }
|
||||
|
||||
};
|
||||
|
||||
|
@ -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<const ExtrusionEntityCollection*>(ee);
|
||||
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(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<const ExtrusionLoop*>(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<const ExtrusionEntityCollection*>(ee)->entities) {
|
||||
assert(! ee2->is_collection());
|
||||
assert(! ee2->is_loop());
|
||||
if (ee2->role() == erBridgeInfill)
|
||||
if (ee->is_collection()) {
|
||||
if(has_bridging_fills(*static_cast<const ExtrusionEntityCollection*>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user