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
if (@$interface || @$contact_infill) {
$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
$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
# 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 $base_flow = $_flow;
@ -753,7 +753,7 @@ sub generate_toolpaths {
# use the proper spacing for first layer as we don't need to align
# its pattern to the other layers
$filler->set_spacing($base_flow->spacing);
$filler->set_min_spacing($base_flow->spacing);
} else {
# draw a perimeter all around support infill
# 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');
$filler->set_angle(-(PI)/2);
$filler->set_spacing(5);
$filler->set_min_spacing(5);
$filler->set_dont_adjust(1);
$filler->set_endpoints_overlap(0);
@ -44,7 +44,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
};
# square
$filler->set_density($filler->spacing / 50);
$filler->set_density($filler->min_spacing / 50);
for my $i (0..3) {
# check that it works regardless of the points order
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
for my $angle (-(PI/2), -(PI/4), -(PI), PI/2, PI) {
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);
my $paths = $test->(my $e = Slic3r::ExPolygon->new(
[ 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,
nozzle_diameter => 0.50,
);
$filler->set_spacing($flow->spacing);
$filler->set_min_spacing($flow->spacing);
$filler->set_density(1);
foreach my $angle (0, 45) {
$surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]);
@ -128,7 +128,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
height => 0.4,
nozzle_diameter => $flow_spacing,
);
$filler->set_spacing($flow->spacing);
$filler->set_min_spacing($flow->spacing);
my $paths = $filler->fill_surface(
$surface,
layer_height => $flow->height,

View File

@ -52,7 +52,10 @@ Fill::fill_surface(const Surface &surface)
if (this->density == 0) return Polylines();
// 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.
Polylines polylines_out;
@ -85,6 +88,8 @@ Fill::adjust_solid_spacing(const coord_t width, const coord_t distance)
assert(factor > 1. - 1e-5);
// 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;
if (factor > factor_max)
distance_new = floor((double)distance * factor_max + 0.5);

View File

@ -27,7 +27,7 @@ public:
coordf_t z;
// in unscaled coordinates
coordf_t spacing;
coordf_t min_spacing;
// overlap over spacing for extrusion endpoints
float endpoints_overlap;
@ -78,11 +78,16 @@ public:
// Perform the fill.
virtual Polylines fill_surface(const Surface &surface);
coordf_t spacing() const { return this->_spacing; };
protected:
// the actual one in unscaled coordinates, we fill this while generating paths
coordf_t _spacing;
Fill() :
layer_id(size_t(-1)),
z(0.f),
spacing(0.f),
min_spacing(0.f),
endpoints_overlap(0.3f),
angle(0),
link_max_length(0),
@ -90,7 +95,8 @@ protected:
density(0),
dont_connect(false),
dont_adjust(false),
complete(false)
complete(false),
_spacing(0.f)
{};
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
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
// (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
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);
if (this->density > 0.9999f && !this->dont_adjust) {
BoundingBox bounding_box = expolygon.contour.bounding_box();
distance = this->adjust_solid_spacing(bounding_box.size().x, distance);
this->spacing = unscale(distance);
this->_spacing = unscale(distance);
}
Polygons loops = (Polygons)expolygon;

View File

@ -14,12 +14,12 @@ FillHoneycomb::_fill_surface_single(
Polylines* polylines_out)
{
// 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);
if (it_m == this->cache.end()) {
it_m = this->cache.insert(it_m, std::pair<CacheID,CacheData>(cache_id, CacheData()));
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.hex_side = m.distance / (sqrt(3)/2);
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);
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)
BoundingBox bounding_box = this->bounding_box.defined

View File

@ -22,7 +22,7 @@ FillRectilinear::_fill_single_direction(ExPolygon expolygon,
expolygon.rotate(-direction.first);
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;
// 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
if (this->density > 0.9999f && !this->dont_adjust) {
line_spacing = this->adjust_solid_spacing(bounding_box.size().x, line_spacing);
this->spacing = unscale(line_spacing);
this->_spacing = unscale(line_spacing);
} else {
// extend bounding box so that our pattern will be aligned with other layers
// 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);
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);
}
@ -465,7 +465,7 @@ void FillCubic::_fill_surface_single(
fill2.density /= 3.;
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);
fill2._fill_single_direction(expolygon, direction2, -x_shift, out);

View File

@ -211,13 +211,14 @@ LayerRegion::make_fill()
-1, // auto width
*this->layer()->object()
);
f->spacing = internal_flow.spacing();
f->min_spacing = internal_flow.spacing();
using_internal_flow = true;
} else {
f->spacing = flow.spacing();
f->min_spacing = flow.spacing();
}
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->z = this->layer()->print_z;
@ -225,7 +226,7 @@ LayerRegion::make_fill()
// Maximum length of the perimeter segment linking two infill lines.
f->link_max_length = (!is_bridge && density > 80)
? scale_(3 * f->spacing)
? scale_(3 * f->min_spacing)
: 0;
// 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 we used the internal flow we're not doing a solid infill
// so we can safely ignore the slight variation that might have
// been applied to f->spacing
// been applied to f->spacing()
} 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.

View File

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