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(
|
||||
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_version => '0.1',
|
||||
license => 'perl',
|
||||
requires => {
|
||||
'Boost::Geometry::Utils' => '0',
|
||||
'File::Basename' => '0',
|
||||
'Getopt::Long' => '0',
|
||||
'Math::Clipper' => '1.05',
|
||||
|
@ -4,6 +4,7 @@ use warnings;
|
||||
|
||||
# an ExPolygon is a polygon with holes
|
||||
|
||||
use Boost::Geometry::Utils;
|
||||
use Math::Geometry::Voronoi;
|
||||
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line);
|
||||
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 {
|
||||
my $self = shift;
|
||||
my ($distance, $scale, $joinType, $miterLimit) = @_;
|
||||
@ -131,32 +137,10 @@ sub clip_line {
|
||||
my $self = shift;
|
||||
my ($line) = @_; # line must be a Slic3r::Line object
|
||||
|
||||
my @intersections = grep $_, map $_->intersection($line, 1), map $_->lines, @$self;
|
||||
my @dir = (
|
||||
$line->[B][X] <=> $line->[A][X],
|
||||
$line->[B][Y] <=> $line->[A][Y],
|
||||
return Boost::Geometry::Utils::polygon_linestring_intersection(
|
||||
$self->boost_polygon,
|
||||
$line->boost_linestring,
|
||||
);
|
||||
|
||||
@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 {
|
||||
|
@ -34,23 +34,26 @@ sub fill_surface {
|
||||
|
||||
my $overlap_distance = scale $Slic3r::flow_width * 0.4;
|
||||
|
||||
my @paths = ();
|
||||
my $x = $bounding_box->[X1];
|
||||
my $is_line_pattern = $self->isa('Slic3r::Fill::Line');
|
||||
my @vertical_lines = ();
|
||||
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]]);
|
||||
if ($is_line_pattern && $i % 2) {
|
||||
$vertical_line->[A][X] += $line_oscillation;
|
||||
$vertical_line->[B][X] -= $line_oscillation;
|
||||
}
|
||||
my @clipped_lines = @{ $expolygon->clip_line($vertical_line) };
|
||||
for (@clipped_lines) {
|
||||
$_->[0][Y] += $overlap_distance;
|
||||
$_->[-1][Y] -= $overlap_distance;
|
||||
}
|
||||
push @paths, @clipped_lines;
|
||||
push @vertical_lines, $vertical_line;
|
||||
$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
|
||||
{
|
||||
@ -75,7 +78,7 @@ sub fill_surface {
|
||||
# TODO: we should also check that both points are on a fill_boundary to avoid
|
||||
# connecting paths on the boundaries of internal regions
|
||||
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};
|
||||
next;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package Slic3r::Line;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Boost::Geometry::Utils;
|
||||
use Slic3r::Geometry qw(A B X Y);
|
||||
|
||||
sub new {
|
||||
@ -31,6 +32,11 @@ sub coordinates {
|
||||
return ($self->a->coordinates, $self->b->coordinates);
|
||||
}
|
||||
|
||||
sub boost_linestring {
|
||||
my $self = shift;
|
||||
return Boost::Geometry::Utils::linestring($self);
|
||||
}
|
||||
|
||||
sub coincides_with {
|
||||
my $self = shift;
|
||||
my ($line) = @_;
|
||||
|
@ -40,6 +40,11 @@ sub lines {
|
||||
return @lines;
|
||||
}
|
||||
|
||||
sub boost_linestring {
|
||||
my $self = shift;
|
||||
return Boost::Geometry::Utils::linestring($self);
|
||||
}
|
||||
|
||||
sub merge_continuous_lines {
|
||||
my $self = shift;
|
||||
|
||||
@ -95,47 +100,12 @@ sub clip_with_expolygon {
|
||||
my $self = shift;
|
||||
my ($expolygon) = @_;
|
||||
|
||||
#printf "Clipping polyline of %d points to expolygon of %d polygons and %d points\n",
|
||||
# scalar(@$self), scalar(@$expolygon), scalar(map @$_, @$expolygon);
|
||||
|
||||
my @polylines = ();
|
||||
my $current_polyline = [];
|
||||
foreach my $line ($self->lines) {
|
||||
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;
|
||||
my $result = Boost::Geometry::Utils::polygon_linestring_intersection(
|
||||
$expolygon->boost_polygon,
|
||||
$self->boost_linestring,
|
||||
);
|
||||
bless $_, 'Slic3r::Polyline' for @$result;
|
||||
return @$result;
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
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);
|
||||
is_deeply $intersections, [
|
||||
[ [152.741724, 288.086671142818], [152.741724, 215.178806915206], ],
|
||||
[ [152.741724, 108.087543109156], [152.741724, 35.166466971035] ],
|
||||
[ [152.742, 288.087], [152.742, 215.179], ],
|
||||
[ [152.742, 108.088], [152.742, 35.1665] ],
|
||||
], 'line is clipped to square with hole';
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user