Generate boundaries of areas to fill (includes some refactoring)

This commit is contained in:
Alessandro Ranellucci 2011-09-04 12:04:01 +02:00
parent 416ad241ea
commit 428006264d
6 changed files with 82 additions and 24 deletions

View File

@ -3,6 +3,7 @@ package Slic3r;
use strict; use strict;
use warnings; use warnings;
use Slic3r::ExtrusionPath;
use Slic3r::Layer; use Slic3r::Layer;
use Slic3r::Line; use Slic3r::Line;
use Slic3r::Perimeter; use Slic3r::Perimeter;

View File

@ -0,0 +1,6 @@
package Slic3r::ExtrusionPath;
use Moose;
extends 'Slic3r::Polyline';
1;

View File

@ -3,12 +3,16 @@ use Moose;
use XXX; use XXX;
# a sequential number of layer, starting at 0
has 'id' => ( has 'id' => (
is => 'ro', is => 'ro',
isa => 'Int', isa => 'Int',
required => 1, required => 1,
); );
# index of points generated by slicing the original geometry
# keys are stringified coordinates (example: "0,0")
# each points connects exactly two segments
has 'pointmap' => ( has 'pointmap' => (
traits => ['Hash'], traits => ['Hash'],
is => 'rw', is => 'rw',
@ -19,12 +23,15 @@ has 'pointmap' => (
}, },
); );
# collection of segments generated by slicing the original geometry
# each segment is part of a closed polyline
has 'lines' => ( has 'lines' => (
is => 'rw', is => 'rw',
isa => 'ArrayRef[Slic3r::Line]', isa => 'ArrayRef[Slic3r::Line]',
default => sub { [] }, default => sub { [] },
); );
# collection of surfaces generated by slicing the original geometry
has 'surfaces' => ( has 'surfaces' => (
traits => ['Array'], traits => ['Array'],
is => 'rw', is => 'rw',
@ -32,9 +39,19 @@ has 'surfaces' => (
default => sub { [] }, default => sub { [] },
); );
# ordered collection of extrusion paths to build all perimeters
has 'perimeters' => ( has 'perimeters' => (
is => 'rw', is => 'rw',
isa => 'ArrayRef[Slic3r::Polyline]', isa => 'ArrayRef[Slic3r::ExtrusionPath]',
default => sub { [] },
);
# collection of surfaces generated by offsetting the innermost perimeter(s)
# they represent boundaries of areas to fill
has 'fill_surfaces' => (
traits => ['Array'],
is => 'rw',
isa => 'ArrayRef[Slic3r::Surface]',
default => sub { [] }, default => sub { [] },
); );

View File

@ -29,34 +29,22 @@ sub make_perimeter {
# create other offsets # create other offsets
for (my $loop = 1; $loop < $Slic3r::perimeter_offsets; $loop++) { for (my $loop = 1; $loop < $Slic3r::perimeter_offsets; $loop++) {
my ($contour_p, @holes_p) = map $self->_mgp_from_points_ref($_), @{ $perimeters[-1]->polygons };
# generate offsets # offsetting a polygon can result in one or many offset polygons
my $contour_offsets = $contour_p->offset_polygon($Slic3r::flow_width / $Slic3r::resolution); my @offsets = $self->offset_polygon($perimeters[-1]);
my @hole_offsets = map @$_, map $_->offset_polygon(- $Slic3r::flow_width / $Slic3r::resolution), @holes_p;
# now we subtract perimeter offsets from the contour offset polygon foreach my $offset_polygon (@offsets) {
# this will generate a single polygon with correct holes and also my ($contour_p, @holes_p) = @{ $offset_polygon->polygons };
# will take care of collisions between contour offset and holes
foreach my $contour_points (@$contour_offsets) {
my $tmp = $self->_mgp_from_points_ref($contour_points)->convert2gpc;
foreach my $hole_points (@hole_offsets) {
$hole_points = $self->_mgp_from_points_ref($hole_points)->convert2gpc;
$tmp = GpcClip('DIFFERENCE', $tmp, $hole_points);
}
my ($result) = Gpc2Polygons($tmp);
# now we've got $result, which is a Math::Geometry::Planar
# representing the inner surface including hole perimeters
my $result_polylines = $result->polygons;
($contour_p, @holes_p) = @$result_polylines;
push @{ $contours{$surface} }, $contour_p; push @{ $contours{$surface} }, $contour_p;
push @{ $holes{$surface} }, @holes_p; push @{ $holes{$surface} }, @holes_p;
push @perimeters, $result; push @perimeters, $offset_polygon;
} }
} }
# create one more offset to be used as boundary for fill
push @{ $layer->fill_surfaces },
map Slic3r::Surface->new_from_mgp($_), $self->offset_polygon($perimeters[-1]);
} }
# generate paths for holes # generate paths for holes
@ -82,10 +70,42 @@ sub make_perimeter {
# away from it to avoid the extruder to get two times there # away from it to avoid the extruder to get two times there
push @path_points, @$points, $points->[0]; push @path_points, @$points, $points->[0];
} }
push @{ $layer->perimeters }, Slic3r::Polyline->new_from_points(reverse @path_points); push @{ $layer->perimeters }, Slic3r::ExtrusionPath->new_from_points(reverse @path_points);
} }
} }
sub offset_polygon {
my $self = shift;
my ($polygon) = @_;
# $polygon holds a Math::Geometry::Planar object representing
# a polygon and its holes
my ($contour_p, @holes_p) = map $self->_mgp_from_points_ref($_), @{ $polygon->polygons };
# generate offsets
my $contour_offsets = $contour_p->offset_polygon($Slic3r::flow_width / $Slic3r::resolution);
my @hole_offsets = map @$_, map $_->offset_polygon(- $Slic3r::flow_width / $Slic3r::resolution), @holes_p;
# now we subtract perimeter offsets from the contour offset polygon
# this will generate a single polygon with correct holes and also
# will take care of collisions between contour offset and holes
my @resulting_offsets = ();
foreach my $contour_points (@$contour_offsets) {
my $tmp = $self->_mgp_from_points_ref($contour_points)->convert2gpc;
foreach my $hole_points (@hole_offsets) {
$hole_points = $self->_mgp_from_points_ref($hole_points)->convert2gpc;
$tmp = GpcClip('DIFFERENCE', $tmp, $hole_points);
}
my ($result) = Gpc2Polygons($tmp);
# now we've got $result, which is a Math::Geometry::Planar
# representing the inner surface including hole perimeters
push @resulting_offsets, $result;
}
return @resulting_offsets;
}
sub _mgp_from_points_ref { sub _mgp_from_points_ref {
my $self = shift; my $self = shift;
my ($points) = @_; my ($points) = @_;

View File

@ -40,7 +40,7 @@ sub new_from_points {
: $_ : $_
} @points; } @points;
my $polyline = __PACKAGE__->new; my $polyline = $class->new;
my $previous_point; my $previous_point;
$previous_point = $points[-1] if $class eq 'Slic3r::Polyline::Closed'; $previous_point = $points[-1] if $class eq 'Slic3r::Polyline::Closed';
foreach my $point (@points) { foreach my $point (@points) {

View File

@ -42,6 +42,20 @@ sub BUILD {
$_->hole_of($self) for @{ $self->holes }; $_->hole_of($self) for @{ $self->holes };
} }
sub new_from_mgp {
my $self = shift;
my ($polygon) = @_;
my ($contour_p, @holes_p) = @{ $polygon->polygons };
return __PACKAGE__->new(
contour => Slic3r::Polyline::Closed->new_from_points(@$contour_p),
holes => [
map Slic3r::Polyline::Closed->new_from_points(@$_), @holes_p
],
);
}
sub id { sub id {
my $self = shift; my $self = shift;
return $self->contour->id; return $self->contour->id;