Bugfix: adjusted solid infill could become very large in thin areas. #3215

This commit is contained in:
Alessandro Ranellucci 2016-12-21 17:12:37 +01:00
parent 4a25b3e8be
commit b33d04fd2d
11 changed files with 46 additions and 31 deletions

View File

@ -681,7 +681,7 @@ sub generate_toolpaths {
# interface and contact infill # interface and contact infill
if (@$interface || @$contact_infill) { if (@$interface || @$contact_infill) {
$fillers{interface}->set_angle($interface_angle); $fillers{interface}->set_angle($interface_angle);
$fillers{interface}->set_spacing($_interface_flow->spacing); $fillers{interface}->set_min_spacing($_interface_flow->spacing);
# find centerline of the external loop # find centerline of the external loop
$interface = offset2($interface, +scaled_epsilon, -(scaled_epsilon + $_interface_flow->scaled_width/2)); $interface = offset2($interface, +scaled_epsilon, -(scaled_epsilon + $_interface_flow->scaled_width/2));
@ -734,7 +734,7 @@ sub generate_toolpaths {
# We don't use $base_flow->spacing because we need a constant spacing # We don't use $base_flow->spacing because we need a constant spacing
# value that guarantees that all layers are correctly aligned. # value that guarantees that all layers are correctly aligned.
$filler->set_spacing($flow->spacing); $filler->set_min_spacing($flow->spacing);
my $density = $support_density; my $density = $support_density;
my $base_flow = $_flow; my $base_flow = $_flow;
@ -753,7 +753,7 @@ sub generate_toolpaths {
# use the proper spacing for first layer as we don't need to align # use the proper spacing for first layer as we don't need to align
# its pattern to the other layers # its pattern to the other layers
$filler->set_spacing($base_flow->spacing); $filler->set_min_spacing($base_flow->spacing);
} else { } else {
# draw a perimeter all around support infill # draw a perimeter all around support infill
# TODO: use brim ordering algorithm # TODO: use brim ordering algorithm

View File

@ -30,7 +30,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
{ {
my $filler = Slic3r::Filler->new_from_type('rectilinear'); my $filler = Slic3r::Filler->new_from_type('rectilinear');
$filler->set_angle(-(PI)/2); $filler->set_angle(-(PI)/2);
$filler->set_spacing(5); $filler->set_min_spacing(5);
$filler->set_dont_adjust(1); $filler->set_dont_adjust(1);
$filler->set_endpoints_overlap(0); $filler->set_endpoints_overlap(0);
@ -44,7 +44,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
}; };
# square # square
$filler->set_density($filler->spacing / 50); $filler->set_density($filler->min_spacing / 50);
for my $i (0..3) { for my $i (0..3) {
# check that it works regardless of the points order # check that it works regardless of the points order
my @points = ([0,0], [100,0], [100,100], [0,100]); my @points = ([0,0], [100,0], [100,100], [0,100]);
@ -64,7 +64,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
# square with hole # square with hole
for my $angle (-(PI/2), -(PI/4), -(PI), PI/2, PI) { for my $angle (-(PI/2), -(PI/4), -(PI), PI/2, PI) {
for my $spacing (25, 5, 7.5, 8.5) { for my $spacing (25, 5, 7.5, 8.5) {
$filler->set_density($filler->spacing / $spacing); $filler->set_density($filler->min_spacing / $spacing);
$filler->set_angle($angle); $filler->set_angle($angle);
my $paths = $test->(my $e = Slic3r::ExPolygon->new( my $paths = $test->(my $e = Slic3r::ExPolygon->new(
[ scale_points [0,0], [100,0], [100,100], [0,100] ], [ scale_points [0,0], [100,0], [100,100], [0,100] ],
@ -102,7 +102,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
height => 0.4, height => 0.4,
nozzle_diameter => 0.50, nozzle_diameter => 0.50,
); );
$filler->set_spacing($flow->spacing); $filler->set_min_spacing($flow->spacing);
$filler->set_density(1); $filler->set_density(1);
foreach my $angle (0, 45) { foreach my $angle (0, 45) {
$surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]); $surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]);
@ -128,7 +128,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
height => 0.4, height => 0.4,
nozzle_diameter => $flow_spacing, nozzle_diameter => $flow_spacing,
); );
$filler->set_spacing($flow->spacing); $filler->set_min_spacing($flow->spacing);
my $paths = $filler->fill_surface( my $paths = $filler->fill_surface(
$surface, $surface,
layer_height => $flow->height, layer_height => $flow->height,

View File

@ -52,7 +52,10 @@ Fill::fill_surface(const Surface &surface)
if (this->density == 0) return Polylines(); if (this->density == 0) return Polylines();
// Perform offset. // Perform offset.
ExPolygons expp = offset_ex(surface.expolygon, -scale_(this->spacing)/2); ExPolygons expp = offset_ex(surface.expolygon, -scale_(this->min_spacing)/2);
// Implementations can change this if they adjust the flow.
this->_spacing = this->min_spacing;
// Create the infills for each of the regions. // Create the infills for each of the regions.
Polylines polylines_out; Polylines polylines_out;
@ -85,6 +88,8 @@ Fill::adjust_solid_spacing(const coord_t width, const coord_t distance)
assert(factor > 1. - 1e-5); assert(factor > 1. - 1e-5);
// How much could the extrusion width be increased? By 20%. // How much could the extrusion width be increased? By 20%.
// Because of this limit, this method is not idempotent: each run
// will increment distance by 20%.
const coordf_t factor_max = 1.2; const coordf_t factor_max = 1.2;
if (factor > factor_max) if (factor > factor_max)
distance_new = floor((double)distance * factor_max + 0.5); distance_new = floor((double)distance * factor_max + 0.5);

View File

@ -27,7 +27,7 @@ public:
coordf_t z; coordf_t z;
// in unscaled coordinates // in unscaled coordinates
coordf_t spacing; coordf_t min_spacing;
// overlap over spacing for extrusion endpoints // overlap over spacing for extrusion endpoints
float endpoints_overlap; float endpoints_overlap;
@ -78,11 +78,16 @@ public:
// Perform the fill. // Perform the fill.
virtual Polylines fill_surface(const Surface &surface); virtual Polylines fill_surface(const Surface &surface);
coordf_t spacing() const { return this->_spacing; };
protected: protected:
// the actual one in unscaled coordinates, we fill this while generating paths
coordf_t _spacing;
Fill() : Fill() :
layer_id(size_t(-1)), layer_id(size_t(-1)),
z(0.f), z(0.f),
spacing(0.f), min_spacing(0.f),
endpoints_overlap(0.3f), endpoints_overlap(0.3f),
angle(0), angle(0),
link_max_length(0), link_max_length(0),
@ -90,7 +95,8 @@ protected:
density(0), density(0),
dont_connect(false), dont_connect(false),
dont_adjust(false), dont_adjust(false),
complete(false) complete(false),
_spacing(0.f)
{}; {};
typedef std::pair<float, Point> direction_t; typedef std::pair<float, Point> direction_t;

View File

@ -156,7 +156,7 @@ Fill3DHoneycomb::_fill_surface_single(
{ {
// no rotation is supported for this infill pattern // no rotation is supported for this infill pattern
BoundingBox bb = expolygon.contour.bounding_box(); BoundingBox bb = expolygon.contour.bounding_box();
const coord_t distance = coord_t(scale_(this->spacing) / this->density); const coord_t distance = coord_t(scale_(this->min_spacing) / this->density);
// align bounding box to a multiple of our honeycomb grid module // align bounding box to a multiple of our honeycomb grid module
// (a module is 2*$distance since one $distance half-module is // (a module is 2*$distance since one $distance half-module is

View File

@ -15,13 +15,13 @@ FillConcentric::_fill_surface_single(
{ {
// no rotation is supported for this infill pattern // no rotation is supported for this infill pattern
const coord_t min_spacing = scale_(this->spacing); const coord_t min_spacing = scale_(this->min_spacing);
coord_t distance = coord_t(min_spacing / this->density); coord_t distance = coord_t(min_spacing / this->density);
if (this->density > 0.9999f && !this->dont_adjust) { if (this->density > 0.9999f && !this->dont_adjust) {
BoundingBox bounding_box = expolygon.contour.bounding_box(); BoundingBox bounding_box = expolygon.contour.bounding_box();
distance = this->adjust_solid_spacing(bounding_box.size().x, distance); distance = this->adjust_solid_spacing(bounding_box.size().x, distance);
this->spacing = unscale(distance); this->_spacing = unscale(distance);
} }
Polygons loops = (Polygons)expolygon; Polygons loops = (Polygons)expolygon;

View File

@ -14,12 +14,12 @@ FillHoneycomb::_fill_surface_single(
Polylines* polylines_out) Polylines* polylines_out)
{ {
// cache hexagons math // cache hexagons math
CacheID cache_id = std::make_pair(this->density, this->spacing); CacheID cache_id = std::make_pair(this->density, this->min_spacing);
Cache::iterator it_m = this->cache.find(cache_id); Cache::iterator it_m = this->cache.find(cache_id);
if (it_m == this->cache.end()) { if (it_m == this->cache.end()) {
it_m = this->cache.insert(it_m, std::pair<CacheID,CacheData>(cache_id, CacheData())); it_m = this->cache.insert(it_m, std::pair<CacheID,CacheData>(cache_id, CacheData()));
CacheData &m = it_m->second; CacheData &m = it_m->second;
coord_t min_spacing = scale_(this->spacing); coord_t min_spacing = scale_(this->min_spacing);
m.distance = min_spacing / this->density; m.distance = min_spacing / this->density;
m.hex_side = m.distance / (sqrt(3)/2); m.hex_side = m.distance / (sqrt(3)/2);
m.hex_width = m.distance * 2; // $m->{hex_width} == $m->{hex_side} * sqrt(3); m.hex_width = m.distance * 2; // $m->{hex_width} == $m->{hex_side} * sqrt(3);

View File

@ -14,7 +14,7 @@ void FillPlanePath::_fill_surface_single(
{ {
expolygon.rotate(-direction.first); expolygon.rotate(-direction.first);
const coord_t distance_between_lines = scale_(this->spacing) / this->density; const coord_t distance_between_lines = scale_(this->min_spacing) / this->density;
// align infill across layers using the object's bounding box (if available) // align infill across layers using the object's bounding box (if available)
BoundingBox bounding_box = this->bounding_box.defined BoundingBox bounding_box = this->bounding_box.defined

View File

@ -22,7 +22,7 @@ FillRectilinear::_fill_single_direction(ExPolygon expolygon,
expolygon.rotate(-direction.first); expolygon.rotate(-direction.first);
assert(this->density > 0.0001f && this->density <= 1.f); assert(this->density > 0.0001f && this->density <= 1.f);
const coord_t min_spacing = scale_(this->spacing); const coord_t min_spacing = scale_(this->min_spacing);
coord_t line_spacing = (double) min_spacing / this->density; coord_t line_spacing = (double) min_spacing / this->density;
// We ignore this->bounding_box because it doesn't matter; we're doing align_to_grid below. // We ignore this->bounding_box because it doesn't matter; we're doing align_to_grid below.
@ -36,7 +36,7 @@ FillRectilinear::_fill_single_direction(ExPolygon expolygon,
// define flow spacing according to requested density // define flow spacing according to requested density
if (this->density > 0.9999f && !this->dont_adjust) { if (this->density > 0.9999f && !this->dont_adjust) {
line_spacing = this->adjust_solid_spacing(bounding_box.size().x, line_spacing); line_spacing = this->adjust_solid_spacing(bounding_box.size().x, line_spacing);
this->spacing = unscale(line_spacing); this->_spacing = unscale(line_spacing);
} else { } else {
// extend bounding box so that our pattern will be aligned with other layers // extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system. // Transform the reference point to the rotated coordinate system.
@ -451,7 +451,7 @@ void FillStars::_fill_surface_single(
fill2._fill_single_direction(expolygon, direction2, 0, out); fill2._fill_single_direction(expolygon, direction2, 0, out);
direction2.first += PI/3; direction2.first += PI/3;
const coord_t x_shift = 0.5 * scale_(fill2.spacing) / fill2.density; const coord_t x_shift = 0.5 * scale_(fill2.min_spacing) / fill2.density;
fill2._fill_single_direction(expolygon, direction2, x_shift, out); fill2._fill_single_direction(expolygon, direction2, x_shift, out);
} }
@ -465,7 +465,7 @@ void FillCubic::_fill_surface_single(
fill2.density /= 3.; fill2.density /= 3.;
direction_t direction2 = direction; direction_t direction2 = direction;
const coord_t range = scale_(this->spacing / this->density); const coord_t range = scale_(this->min_spacing / this->density);
const coord_t x_shift = abs(( (coord_t)(scale_(this->z) + range) % (coord_t)(range * 2)) - range); const coord_t x_shift = abs(( (coord_t)(scale_(this->z) + range) % (coord_t)(range * 2)) - range);
fill2._fill_single_direction(expolygon, direction2, -x_shift, out); fill2._fill_single_direction(expolygon, direction2, -x_shift, out);

View File

@ -211,13 +211,14 @@ LayerRegion::make_fill()
-1, // auto width -1, // auto width
*this->layer()->object() *this->layer()->object()
); );
f->spacing = internal_flow.spacing(); f->min_spacing = internal_flow.spacing();
using_internal_flow = true; using_internal_flow = true;
} else { } else {
f->spacing = flow.spacing(); f->min_spacing = flow.spacing();
} }
f->endpoints_overlap = this->region()->config.get_abs_value("infill_overlap", f->endpoints_overlap = this->region()->config.get_abs_value("infill_overlap",
(perimeter_spacing + scale_(f->spacing))/2); (perimeter_spacing + scale_(f->min_spacing))/2);
f->layer_id = this->layer()->id(); f->layer_id = this->layer()->id();
f->z = this->layer()->print_z; f->z = this->layer()->print_z;
@ -225,7 +226,7 @@ LayerRegion::make_fill()
// Maximum length of the perimeter segment linking two infill lines. // Maximum length of the perimeter segment linking two infill lines.
f->link_max_length = (!is_bridge && density > 80) f->link_max_length = (!is_bridge && density > 80)
? scale_(3 * f->spacing) ? scale_(3 * f->min_spacing)
: 0; : 0;
// Used by the concentric infill pattern to clip the loops to create extrusion paths. // Used by the concentric infill pattern to clip the loops to create extrusion paths.
@ -243,9 +244,9 @@ LayerRegion::make_fill()
if (using_internal_flow) { if (using_internal_flow) {
// if we used the internal flow we're not doing a solid infill // if we used the internal flow we're not doing a solid infill
// so we can safely ignore the slight variation that might have // so we can safely ignore the slight variation that might have
// been applied to f->spacing // been applied to f->spacing()
} else { } else {
flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow()); flow = Flow::new_from_spacing(f->spacing(), flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow());
} }
// Save into layer. // Save into layer.

View File

@ -14,10 +14,13 @@
void set_bounding_box(BoundingBox *bbox) void set_bounding_box(BoundingBox *bbox)
%code{% THIS->fill->bounding_box = *bbox; %}; %code{% THIS->fill->bounding_box = *bbox; %};
void set_spacing(coordf_t spacing) void set_min_spacing(coordf_t spacing)
%code{% THIS->fill->spacing = spacing; %}; %code{% THIS->fill->min_spacing = spacing; %};
coordf_t min_spacing()
%code{% RETVAL = THIS->fill->min_spacing; %};
coordf_t spacing() coordf_t spacing()
%code{% RETVAL = THIS->fill->spacing; %}; %code{% RETVAL = THIS->fill->spacing(); %};
void set_endpoints_overlap(float overlap) void set_endpoints_overlap(float overlap)
%code{% THIS->fill->endpoints_overlap = overlap; %}; %code{% THIS->fill->endpoints_overlap = overlap; %};