mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 00:55:54 +08:00
Restored/updated the tests about adaptive extrusion width
This commit is contained in:
parent
ab278f03e1
commit
5c21237e51
@ -30,13 +30,6 @@ sub offset_ex {
|
|||||||
return Slic3r::Geometry::Clipper::offset_ex(\@$self, @_);
|
return Slic3r::Geometry::Clipper::offset_ex(\@$self, @_);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub noncollapsing_offset_ex {
|
|
||||||
my $self = shift;
|
|
||||||
my ($distance, @params) = @_;
|
|
||||||
|
|
||||||
return $self->offset_ex($distance + 1, @params);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub bounding_box {
|
sub bounding_box {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return $self->contour->bounding_box;
|
return $self->contour->bounding_box;
|
||||||
|
92
t/adaptive_width.t
Normal file
92
t/adaptive_width.t
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use Test::More;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
plan tests => 32;
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
use FindBin;
|
||||||
|
use lib "$FindBin::Bin/../lib";
|
||||||
|
use local::lib "$FindBin::Bin/../local-lib";
|
||||||
|
}
|
||||||
|
|
||||||
|
use List::Util qw(first);
|
||||||
|
use Slic3r;
|
||||||
|
use Slic3r::Geometry qw(X Y scale epsilon);
|
||||||
|
use Slic3r::Surface ':types';
|
||||||
|
|
||||||
|
sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
||||||
|
|
||||||
|
{
|
||||||
|
my $test = sub {
|
||||||
|
my ($expolygon, $fw, $expected, $descr) = @_;
|
||||||
|
|
||||||
|
my $flow = Slic3r::Flow->new(
|
||||||
|
nozzle_diameter => 0.5,
|
||||||
|
height => 0.4,
|
||||||
|
width => $fw,
|
||||||
|
);
|
||||||
|
my $slices = Slic3r::Surface::Collection->new;
|
||||||
|
$slices->append(Slic3r::Surface->new(
|
||||||
|
surface_type => S_TYPE_INTERNAL,
|
||||||
|
expolygon => $expolygon,
|
||||||
|
));
|
||||||
|
my $config = Slic3r::Config::Full->new;
|
||||||
|
my $loops = Slic3r::ExtrusionPath::Collection->new;
|
||||||
|
my $gap_fill = Slic3r::ExtrusionPath::Collection->new;
|
||||||
|
my $fill_surfaces = Slic3r::Surface::Collection->new;
|
||||||
|
my $pg = Slic3r::Layer::PerimeterGenerator->new(
|
||||||
|
$slices, $flow->height, $flow,
|
||||||
|
$config, $config, $config,
|
||||||
|
$loops, $gap_fill, $fill_surfaces,
|
||||||
|
);
|
||||||
|
$pg->process;
|
||||||
|
|
||||||
|
$loops = $loops->flatten;
|
||||||
|
my @single = grep $_->isa('Slic3r::ExtrusionPath'), @$loops;
|
||||||
|
my @loops = grep $_->isa('Slic3r::ExtrusionLoop'), @$loops;
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
require "Slic3r/SVG.pm";
|
||||||
|
Slic3r::SVG::output(
|
||||||
|
"output.svg",
|
||||||
|
expolygons => [$expolygon],
|
||||||
|
polylines => [ map $_->isa('Slic3r::ExtrusionPath') ? $_->polyline : $_->polygon->split_at_first_point, @$loops ],
|
||||||
|
red_polylines => [ map $_->polyline, @$gap_fill ],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
is scalar(@single), $expected->{single} // 0, "expected number of single lines ($descr)";
|
||||||
|
is scalar(@loops), $expected->{loops} // 0, "expected number of loops ($descr)";
|
||||||
|
is scalar(@$gap_fill), $expected->{gaps} // 0, "expected number of gap fills ($descr)";
|
||||||
|
|
||||||
|
if ($expected->{single}) {
|
||||||
|
ok abs($loops->[0]->width - $expected->{width}) < epsilon, "single line covers the full width ($descr)";
|
||||||
|
}
|
||||||
|
if ($expected->{loops}) {
|
||||||
|
my $loop_width = $loops[0][0]->width;
|
||||||
|
my $gap_fill_width = @$gap_fill ? $gap_fill->[0]->width : 0;
|
||||||
|
ok $loop_width * $expected->{loops} * 2 + $gap_fill_width > $expected->{width} - epsilon,
|
||||||
|
"loop total width + gap fill covers the full width ($descr)";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
my $fw = 0.7;
|
||||||
|
my $test_rect = sub {
|
||||||
|
my ($width, $expected) = @_;
|
||||||
|
|
||||||
|
my $e = Slic3r::ExPolygon->new([ scale_points [0,0], [100,0], [100,$width], [0,$width] ]);
|
||||||
|
$expected->{width} = $width;
|
||||||
|
$test->($e, $fw, $expected, $width);
|
||||||
|
};
|
||||||
|
$test_rect->($fw * 1, { single => 1, gaps => 0 });
|
||||||
|
$test_rect->($fw * 1.3, { single => 1, gaps => 0 });
|
||||||
|
$test_rect->($fw * 1.5, { single => 1, gaps => 0 });
|
||||||
|
$test_rect->($fw * 2, { loops => 1, gaps => 0 });
|
||||||
|
$test_rect->($fw * 2.5, { loops => 1, gaps => 1 });
|
||||||
|
$test_rect->($fw * 3, { loops => 1, gaps => 1 });
|
||||||
|
$test_rect->($fw * 3.5, { loops => 2, gaps => 0 });
|
||||||
|
$test_rect->($fw * 4, { loops => 2, gaps => 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
__END__
|
93
t/dynamic.t
93
t/dynamic.t
@ -1,93 +0,0 @@
|
|||||||
use Test::More;
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
plan skip_all => 'variable-width paths are currently disabled';
|
|
||||||
plan tests => 20;
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
use FindBin;
|
|
||||||
use lib "$FindBin::Bin/../lib";
|
|
||||||
use local::lib "$FindBin::Bin/../local-lib";
|
|
||||||
}
|
|
||||||
|
|
||||||
use List::Util qw(first);
|
|
||||||
use Slic3r;
|
|
||||||
use Slic3r::Geometry qw(X Y scale epsilon);
|
|
||||||
use Slic3r::Surface ':types';
|
|
||||||
|
|
||||||
sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|
||||||
|
|
||||||
{
|
|
||||||
my $square = Slic3r::ExPolygon->new([
|
|
||||||
scale_points [0,0], [10,0], [10,10], [0,10],
|
|
||||||
]);
|
|
||||||
|
|
||||||
my @offsets = @{$square->noncollapsing_offset_ex(- scale 5)};
|
|
||||||
is scalar @offsets, 1, 'non-collapsing offset';
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
local $Slic3r::Config = Slic3r::Config->new(
|
|
||||||
perimeters => 3,
|
|
||||||
);
|
|
||||||
my $w = 0.7;
|
|
||||||
my $perimeter_flow = Slic3r::Flow->new(
|
|
||||||
nozzle_diameter => 0.5,
|
|
||||||
layer_height => 0.4,
|
|
||||||
width => $w,
|
|
||||||
);
|
|
||||||
|
|
||||||
my $print = Slic3r::Print->new;
|
|
||||||
my $region = Slic3r::Print::Region->new(
|
|
||||||
print => $print,
|
|
||||||
flows => { perimeter => $perimeter_flow },
|
|
||||||
);
|
|
||||||
push @{$print->regions}, $region;
|
|
||||||
my $object = Slic3r::Print::Object->new(
|
|
||||||
print => $print,
|
|
||||||
size => [1,1],
|
|
||||||
);
|
|
||||||
my $make_layer = sub {
|
|
||||||
my ($width) = @_;
|
|
||||||
my $layer = Slic3r::Layer->new(
|
|
||||||
object => $object,
|
|
||||||
id => 1,
|
|
||||||
slices => [
|
|
||||||
Slic3r::Surface->new(
|
|
||||||
surface_type => S_TYPE_INTERNAL,
|
|
||||||
expolygon => Slic3r::ExPolygon->new([ scale_points [0,0], [50,0], [50,$width], [0,$width] ]),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
thin_walls => [],
|
|
||||||
);
|
|
||||||
my $layerm = $layer->region(0);
|
|
||||||
$layer->make_perimeters;
|
|
||||||
return $layerm;
|
|
||||||
};
|
|
||||||
|
|
||||||
my %widths = (
|
|
||||||
1 * $w => { perimeters => 1, gaps => 0 },
|
|
||||||
1.3 * $w => { perimeters => 1, gaps => 1, gap_flow_spacing => $perimeter_flow->clone(width => 0.2 * $w)->spacing },
|
|
||||||
1.5 * $w => { perimeters => 1, gaps => 1, gap_flow_spacing => $perimeter_flow->clone(width => 0.5 * $w)->spacing },
|
|
||||||
2 * $w => { perimeters => 1, gaps => 1, gap_flow_spacing => $perimeter_flow->spacing },
|
|
||||||
2.5 * $w => { perimeters => 1, gaps => 1, gap_flow_spacing => $perimeter_flow->clone(width => 1.5 * $w)->spacing },
|
|
||||||
3 * $w => { perimeters => 2, gaps => 0 },
|
|
||||||
4 * $w => { perimeters => 2, gaps => 1, gap_flow_spacing => $perimeter_flow->spacing },
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach my $width (sort keys %widths) {
|
|
||||||
my $layerm = $make_layer->($width);
|
|
||||||
is scalar @{$layerm->perimeters}, $widths{$width}{perimeters}, 'right number of perimeters';
|
|
||||||
is scalar @{$layerm->thin_fills} ? 1 : 0, $widths{$width}{gaps},
|
|
||||||
($widths{$width}{gaps} ? 'gaps were filled' : 'no gaps detected'); # TODO: we should check the exact number of gaps, but we need a better medial axis algorithm
|
|
||||||
|
|
||||||
my @gaps = map $_, @{$layerm->thin_fills};
|
|
||||||
if (@gaps) {
|
|
||||||
ok +(!first { abs($_->flow_spacing - $widths{$width}{gap_flow_spacing}) > epsilon } @gaps),
|
|
||||||
'flow spacing was dynamically adjusted';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__END__
|
|
@ -142,7 +142,6 @@ class ExtrusionLoop : public ExtrusionEntity
|
|||||||
void split_at(const Point &point, bool prefer_non_overhang = false);
|
void split_at(const Point &point, bool prefer_non_overhang = false);
|
||||||
void clip_end(double distance, ExtrusionPaths* paths) const;
|
void clip_end(double distance, ExtrusionPaths* paths) const;
|
||||||
// Test, whether the point is extruded by a bridging flow.
|
// Test, whether the point is extruded by a bridging flow.
|
||||||
// This used to be used to avoid placing seams on overhangs, but now the EdgeGrid is used instead.
|
|
||||||
bool has_overhang_point(const Point &point) const;
|
bool has_overhang_point(const Point &point) const;
|
||||||
bool is_perimeter() const {
|
bool is_perimeter() const {
|
||||||
return this->paths.front().role == erPerimeter
|
return this->paths.front().role == erPerimeter
|
||||||
|
@ -37,7 +37,7 @@ SV*
|
|||||||
ExtrusionLoop::arrayref()
|
ExtrusionLoop::arrayref()
|
||||||
CODE:
|
CODE:
|
||||||
AV* av = newAV();
|
AV* av = newAV();
|
||||||
av_fill(av, THIS->paths.size()-1);
|
if (!THIS->paths.empty()) av_extend(av, THIS->paths.size()-1);
|
||||||
for (ExtrusionPaths::iterator it = THIS->paths.begin(); it != THIS->paths.end(); ++it) {
|
for (ExtrusionPaths::iterator it = THIS->paths.begin(); it != THIS->paths.end(); ++it) {
|
||||||
av_store(av, it - THIS->paths.begin(), perl_to_SV_ref(*it));
|
av_store(av, it - THIS->paths.begin(), perl_to_SV_ref(*it));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user