mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-25 09:24:26 +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
|
||||
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
|
||||
|
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');
|
||||
$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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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; %};
|
||||
|
Loading…
x
Reference in New Issue
Block a user