mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-28 01:42:02 +08:00
Bugfix: adjusted solid infill could become very large in thin areas. #3215
This commit is contained in:
parent
4a25b3e8be
commit
b33d04fd2d
@ -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
|
||||||
|
10
t/fill.t
10
t/fill.t
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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; %};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user