Huge speed Boost (pun intended). Also fixes a problem where infill was escaping perimeters sometimes (#305).
This commit is contained in:
parent
a800b97fdd
commit
5bfe19a8b9
3
Build.PL
3
Build.PL
@ -2,11 +2,12 @@ use Module::Build;
|
|||||||
|
|
||||||
my $build = Module::Build->new(
|
my $build = Module::Build->new(
|
||||||
module_name => 'Slic3r',
|
module_name => 'Slic3r',
|
||||||
dist_abstract => 'STL-to-GCODE translator',
|
dist_abstract => 'G-code generator for 3D printers',
|
||||||
dist_author => 'Alessandro Ranellucci <aar@cpan.org>',
|
dist_author => 'Alessandro Ranellucci <aar@cpan.org>',
|
||||||
dist_version => '0.1',
|
dist_version => '0.1',
|
||||||
license => 'perl',
|
license => 'perl',
|
||||||
requires => {
|
requires => {
|
||||||
|
'Boost::Geometry::Utils' => '0',
|
||||||
'File::Basename' => '0',
|
'File::Basename' => '0',
|
||||||
'Getopt::Long' => '0',
|
'Getopt::Long' => '0',
|
||||||
'Math::Clipper' => '1.05',
|
'Math::Clipper' => '1.05',
|
||||||
|
@ -4,6 +4,7 @@ use warnings;
|
|||||||
|
|
||||||
# an ExPolygon is a polygon with holes
|
# an ExPolygon is a polygon with holes
|
||||||
|
|
||||||
|
use Boost::Geometry::Utils;
|
||||||
use Math::Geometry::Voronoi;
|
use Math::Geometry::Voronoi;
|
||||||
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line);
|
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line);
|
||||||
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
|
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
|
||||||
@ -53,6 +54,11 @@ sub clipper_expolygon {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub boost_polygon {
|
||||||
|
my $self = shift;
|
||||||
|
return Boost::Geometry::Utils::polygon(@$self);
|
||||||
|
}
|
||||||
|
|
||||||
sub offset {
|
sub offset {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($distance, $scale, $joinType, $miterLimit) = @_;
|
my ($distance, $scale, $joinType, $miterLimit) = @_;
|
||||||
@ -131,32 +137,10 @@ sub clip_line {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($line) = @_; # line must be a Slic3r::Line object
|
my ($line) = @_; # line must be a Slic3r::Line object
|
||||||
|
|
||||||
my @intersections = grep $_, map $_->intersection($line, 1), map $_->lines, @$self;
|
return Boost::Geometry::Utils::polygon_linestring_intersection(
|
||||||
my @dir = (
|
$self->boost_polygon,
|
||||||
$line->[B][X] <=> $line->[A][X],
|
$line->boost_linestring,
|
||||||
$line->[B][Y] <=> $line->[A][Y],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@intersections = sort {
|
|
||||||
(($a->[X] <=> $b->[X]) == $dir[X]) && (($a->[Y] <=> $b->[Y]) == $dir[Y]) ? 1 : -1
|
|
||||||
} @intersections, @$line;
|
|
||||||
|
|
||||||
shift @intersections if $intersections[0]->coincides_with($intersections[1]);
|
|
||||||
pop @intersections if $intersections[-1]->coincides_with($intersections[-2]);
|
|
||||||
|
|
||||||
shift @intersections
|
|
||||||
if !$self->encloses_point($intersections[0])
|
|
||||||
&& !$self->point_on_segment($intersections[0]);
|
|
||||||
|
|
||||||
my @lines = ();
|
|
||||||
while (@intersections) {
|
|
||||||
# skip tangent points
|
|
||||||
my @points = splice @intersections, 0, 2;
|
|
||||||
next if !$points[1];
|
|
||||||
next if $points[0]->coincides_with($points[1]);
|
|
||||||
push @lines, [ @points ];
|
|
||||||
}
|
|
||||||
return [@lines];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub simplify {
|
sub simplify {
|
||||||
|
@ -34,23 +34,26 @@ sub fill_surface {
|
|||||||
|
|
||||||
my $overlap_distance = scale $Slic3r::flow_width * 0.4;
|
my $overlap_distance = scale $Slic3r::flow_width * 0.4;
|
||||||
|
|
||||||
my @paths = ();
|
|
||||||
my $x = $bounding_box->[X1];
|
my $x = $bounding_box->[X1];
|
||||||
my $is_line_pattern = $self->isa('Slic3r::Fill::Line');
|
my $is_line_pattern = $self->isa('Slic3r::Fill::Line');
|
||||||
|
my @vertical_lines = ();
|
||||||
for (my $i = 0; $x <= $bounding_box->[X2] + scale epsilon; $i++) {
|
for (my $i = 0; $x <= $bounding_box->[X2] + scale epsilon; $i++) {
|
||||||
my $vertical_line = Slic3r::Line->new([$x, $bounding_box->[Y2]], [$x, $bounding_box->[Y1]]);
|
my $vertical_line = Slic3r::Line->new([$x, $bounding_box->[Y2]], [$x, $bounding_box->[Y1]]);
|
||||||
if ($is_line_pattern && $i % 2) {
|
if ($is_line_pattern && $i % 2) {
|
||||||
$vertical_line->[A][X] += $line_oscillation;
|
$vertical_line->[A][X] += $line_oscillation;
|
||||||
$vertical_line->[B][X] -= $line_oscillation;
|
$vertical_line->[B][X] -= $line_oscillation;
|
||||||
}
|
}
|
||||||
my @clipped_lines = @{ $expolygon->clip_line($vertical_line) };
|
push @vertical_lines, $vertical_line;
|
||||||
for (@clipped_lines) {
|
|
||||||
$_->[0][Y] += $overlap_distance;
|
|
||||||
$_->[-1][Y] -= $overlap_distance;
|
|
||||||
}
|
|
||||||
push @paths, @clipped_lines;
|
|
||||||
$x += $distance_between_lines;
|
$x += $distance_between_lines;
|
||||||
}
|
}
|
||||||
|
my @paths = @{ Boost::Geometry::Utils::polygon_linestring_intersection(
|
||||||
|
$expolygon->boost_polygon,
|
||||||
|
Boost::Geometry::Utils::linestring(@vertical_lines),
|
||||||
|
) };
|
||||||
|
for (@paths) {
|
||||||
|
$_->[0][Y] += $overlap_distance;
|
||||||
|
$_->[-1][Y] -= $overlap_distance;
|
||||||
|
}
|
||||||
|
|
||||||
# connect lines
|
# connect lines
|
||||||
{
|
{
|
||||||
@ -75,7 +78,7 @@ sub fill_surface {
|
|||||||
# TODO: we should also check that both points are on a fill_boundary to avoid
|
# TODO: we should also check that both points are on a fill_boundary to avoid
|
||||||
# connecting paths on the boundaries of internal regions
|
# connecting paths on the boundaries of internal regions
|
||||||
if ($can_connect->(@distance, $paths[-1][-1], $path->points->[0])
|
if ($can_connect->(@distance, $paths[-1][-1], $path->points->[0])
|
||||||
&& $expolygon_off->encloses_line([ $paths[-1][-1], $path->points->[0] ])) {
|
&& $expolygon_off->encloses_line(Slic3r::Line->new($paths[-1][-1], $path->points->[0]))) {
|
||||||
push @{$paths[-1]}, @{$path->points};
|
push @{$paths[-1]}, @{$path->points};
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package Slic3r::Line;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
|
use Boost::Geometry::Utils;
|
||||||
use Slic3r::Geometry qw(A B X Y);
|
use Slic3r::Geometry qw(A B X Y);
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
@ -31,6 +32,11 @@ sub coordinates {
|
|||||||
return ($self->a->coordinates, $self->b->coordinates);
|
return ($self->a->coordinates, $self->b->coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub boost_linestring {
|
||||||
|
my $self = shift;
|
||||||
|
return Boost::Geometry::Utils::linestring($self);
|
||||||
|
}
|
||||||
|
|
||||||
sub coincides_with {
|
sub coincides_with {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($line) = @_;
|
my ($line) = @_;
|
||||||
|
@ -40,6 +40,11 @@ sub lines {
|
|||||||
return @lines;
|
return @lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub boost_linestring {
|
||||||
|
my $self = shift;
|
||||||
|
return Boost::Geometry::Utils::linestring($self);
|
||||||
|
}
|
||||||
|
|
||||||
sub merge_continuous_lines {
|
sub merge_continuous_lines {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
@ -95,47 +100,12 @@ sub clip_with_expolygon {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($expolygon) = @_;
|
my ($expolygon) = @_;
|
||||||
|
|
||||||
#printf "Clipping polyline of %d points to expolygon of %d polygons and %d points\n",
|
my $result = Boost::Geometry::Utils::polygon_linestring_intersection(
|
||||||
# scalar(@$self), scalar(@$expolygon), scalar(map @$_, @$expolygon);
|
$expolygon->boost_polygon,
|
||||||
|
$self->boost_linestring,
|
||||||
my @polylines = ();
|
);
|
||||||
my $current_polyline = [];
|
bless $_, 'Slic3r::Polyline' for @$result;
|
||||||
foreach my $line ($self->lines) {
|
return @$result;
|
||||||
my ($first_line, @other_lines) = @{ $expolygon->clip_line($line) };
|
|
||||||
next unless $first_line;
|
|
||||||
|
|
||||||
if (!@$current_polyline) {
|
|
||||||
push @$current_polyline, @$first_line;
|
|
||||||
} elsif ($first_line->[A]->coincides_with($current_polyline->[-1])) {
|
|
||||||
push @$current_polyline, $first_line->[B];
|
|
||||||
} else {
|
|
||||||
push @polylines, $current_polyline;
|
|
||||||
$current_polyline = [ @$first_line ];
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $other_line (@other_lines) {
|
|
||||||
if (@$current_polyline) {
|
|
||||||
push @polylines, $current_polyline;
|
|
||||||
$current_polyline = [];
|
|
||||||
}
|
|
||||||
push @polylines, [ @$other_line ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (@$current_polyline) {
|
|
||||||
push @polylines, $current_polyline;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (@polylines > 1 && same_point($polylines[-1][-1], $polylines[0][0])) {
|
|
||||||
if (scalar(@{$polylines[-1]}) == 2) {
|
|
||||||
unshift @{$polylines[0]}, $polylines[-1][0];
|
|
||||||
pop @polylines;
|
|
||||||
} else {
|
|
||||||
push @{$polylines[-1]}, $polylines[0][-1];
|
|
||||||
shift @polylines;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return map Slic3r::Polyline->new($_), @polylines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub bounding_box {
|
sub bounding_box {
|
||||||
|
@ -140,12 +140,12 @@ is_deeply $intersection, [ [12, 12], [18, 16] ], 'internal lines are preserved';
|
|||||||
is is_counter_clockwise($small_circle), 0, "hole is clockwise";
|
is is_counter_clockwise($small_circle), 0, "hole is clockwise";
|
||||||
|
|
||||||
my $expolygon = Slic3r::ExPolygon->new($large_circle, $small_circle);
|
my $expolygon = Slic3r::ExPolygon->new($large_circle, $small_circle);
|
||||||
$line = Slic3r::Line->new([152.741724,288.086671142818], [152.741724,34.166466971035]);
|
$line = Slic3r::Line->new([152.742,288.086671142818], [152.742,34.166466971035]);
|
||||||
|
|
||||||
my $intersections = $expolygon->clip_line($line);
|
my $intersections = $expolygon->clip_line($line);
|
||||||
is_deeply $intersections, [
|
is_deeply $intersections, [
|
||||||
[ [152.741724, 288.086671142818], [152.741724, 215.178806915206], ],
|
[ [152.742, 288.087], [152.742, 215.179], ],
|
||||||
[ [152.741724, 108.087543109156], [152.741724, 35.166466971035] ],
|
[ [152.742, 108.088], [152.742, 35.1665] ],
|
||||||
], 'line is clipped to square with hole';
|
], 'line is clipped to square with hole';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user