Skip to content

Commit

Permalink
Huge speed Boost (pun intended). Also fixes a problem where infill wa…
Browse files Browse the repository at this point in the history
…s escaping perimeters sometimes (slic3r#305).
  • Loading branch information
alranel committed Apr 9, 2012
1 parent a800b97 commit 5bfe19a
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 78 deletions.
3 changes: 2 additions & 1 deletion Build.PL
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>',
dist_version => '0.1',
license => 'perl',
requires => {
'Boost::Geometry::Utils' => '0',
'File::Basename' => '0',
'Getopt::Long' => '0',
'Math::Clipper' => '1.05',
Expand Down
34 changes: 9 additions & 25 deletions lib/Slic3r/ExPolygon.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) = @_;
Expand Down Expand Up @@ -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 {
Expand Down
19 changes: 11 additions & 8 deletions lib/Slic3r/Fill/Rectilinear.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions lib/Slic3r/Line.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) = @_;
Expand Down
52 changes: 11 additions & 41 deletions lib/Slic3r/Polyline.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions t/polyclip.t
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}

Expand Down

0 comments on commit 5bfe19a

Please sign in to comment.