Adopt XS containers everywhere (incomplete work)

This commit is contained in:
Alessandro Ranellucci 2013-07-16 09:49:34 +02:00
parent 339ba9e5c3
commit 9b582a11ff
30 changed files with 130 additions and 311 deletions

View File

@ -110,10 +110,16 @@ sub parallelize {
sub thread_cleanup {
# prevent destruction of shared objects
no warnings 'redefine';
*Slic3r::ExPolygon::DESTROY = sub {};
*Slic3r::ExPolygon::Collection::DESTROY = sub {};
*Slic3r::ExPolygon::XS::DESTROY = sub {};
*Slic3r::Point::DESTROY = sub {};
*Slic3r::Surface::DESTROY = sub {};
*Slic3r::ExtrusionLoop::DESTROY = sub {};
*Slic3r::ExtrusionPath::DESTROY = sub {};
*Slic3r::Line::DESTROY = sub {};
*Slic3r::Point::DESTROY = sub {};
*Slic3r::Polygon::DESTROY = sub {};
*Slic3r::Polyline::DESTROY = sub {};
*Slic3r::Surface::DESTROY = sub {};
*Slic3r::Surface::Collection::DESTROY = sub {};
}
sub encode_path {

View File

@ -1,4 +1,4 @@
gpackage Slic3r::ExPolygon;
package Slic3r::ExPolygon;
use strict;
use warnings;
@ -9,32 +9,6 @@ use List::Util qw(first);
use Math::Geometry::Voronoi;
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon);
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
use Storable qw();
# the constructor accepts an array of polygons
# or a Math::Clipper ExPolygon (hashref)
sub new {
my $class = shift;
my $self;
if (@_ == 1 && ref $_[0] eq 'HASH') {
$self = [
Slic3r::Polygon->new(@{$_[0]{outer}}),
map Slic3r::Polygon->new(@$_), @{$_[0]{holes}},
];
} else {
$self = [ map Slic3r::Polygon->new(@$_), @_ ];
}
bless $self, $class;
$self;
}
sub clone {
Storable::dclone($_[0])
}
# no-op for legacy with ::XS
sub arrayref { $_[0] }
sub pp { [ map $_->pp, @{$_[0]} ] }
sub contour {
my $self = shift;
@ -46,19 +20,6 @@ sub holes {
return @$self[1..$#$self];
}
sub lines {
my $self = shift;
return map $_->lines, @$self;
}
sub clipper_expolygon {
my $self = shift;
return {
outer => $self->contour,
holes => [ $self->holes ],
};
}
sub is_valid {
my $self = shift;
return (!first { !$_->is_valid } @$self)
@ -155,23 +116,6 @@ sub simplify {
return @{ Slic3r::Geometry::Clipper::union_ex([ @simplified ]) };
}
sub scale {
my $self = shift;
$_->scale(@_) for @$self;
}
sub translate {
my $self = shift;
$_->translate(@_) for @$self;
$self;
}
sub rotate {
my $self = shift;
$_->rotate(@_) for @$self;
$self;
}
sub area {
my $self = shift;
my $area = $self->contour->area;
@ -298,9 +242,6 @@ sub medial_axis {
return @result;
}
package Slic3r::ExPolygon::XS;
use parent 'Slic3r::ExPolygon';
package Slic3r::ExPolygon::Collection;
use Slic3r::Geometry qw(X1 Y1);

View File

@ -2,51 +2,17 @@ package Slic3r::ExtrusionLoop;
use strict;
use warnings;
use Slic3r::Geometry qw(same_point);
sub polygon { $_[0] }
# class or object method
sub pack {
my $self = shift;
if (ref $self) {
return $self;
} else {
return $self->new(@_);
}
}
# no-op
sub unpack { $_[0] }
sub split_at_index {
my $self = shift;
return Slic3r::ExtrusionPath->new(
polyline => $self->as_polygon->split_at_index(@_),
role => $self->role,
flow_spacing => $self->flow_spacing,
height => $self->height,
);
}
sub split_at {
my $self = shift;
return Slic3r::ExtrusionPath->new(
polyline => $self->as_polygon->split_at(@_),
polyline => $self->polygon->split_at(@_),
role => $self->role,
flow_spacing => $self->flow_spacing,
height => $self->height,
);
}
sub split_at_first_point {
my $self = shift;
return $self->split_at_index(0);
}
sub first_point {
my $self = shift;
return $self->polygon->[0];

View File

@ -2,7 +2,6 @@ package Slic3r::ExtrusionPath;
use strict;
use warnings;
use parent -norequire, qw(Slic3r::Polyline::XS);
use parent qw(Exporter);
our @EXPORT_OK = qw(EXTR_ROLE_PERIMETER EXTR_ROLE_EXTERNAL_PERIMETER
@ -12,21 +11,6 @@ our @EXPORT_OK = qw(EXTR_ROLE_PERIMETER EXTR_ROLE_EXTERNAL_PERIMETER
our %EXPORT_TAGS = (roles => \@EXPORT_OK);
use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points);
sub polyline { $_[0] }
# class or object method
sub pack {
my $self = shift;
if (ref $self) {
return $self;
} else {
return $self->new(@_);
}
}
# no-op, this allows to use both packed and non-packed objects in Collections
sub unpack { $_[0] }
sub clip_with_polygon {
my $self = shift;
@ -40,7 +24,7 @@ sub clip_with_expolygon {
my ($expolygon) = @_;
return map $self->clone(polyline => $_),
$self->as_polyline->clip_with_expolygon($expolygon);
$self->polyline->clip_with_expolygon($expolygon);
}
sub intersect_expolygons {
@ -61,7 +45,7 @@ sub subtract_expolygons {
sub simplify {
my $self = shift;
$self->set_polyline($self->as_polyline->simplify(@_));
$self->set_polyline($self->polyline->simplify(@_));
}
sub points {

View File

@ -9,7 +9,7 @@ sub unpack { $_[0] }
sub first_point {
my $self = shift;
return $self->paths->[0]->unpack->polyline->[0];
return $self->paths->[0]->polyline->[0];
}
sub chained_path {
@ -21,7 +21,7 @@ sub chained_path {
# make sure we pass the same path objects to the Collection constructor
# and the ->chained_path() method because the latter will reverse the
# paths in-place when needed and we need to return them that way
my @paths = map $_->unpack, @{$self->paths};
my @paths = @{$self->paths};
my $collection = Slic3r::Polyline::Collection->new(
polylines => [ map $_->polyline, @paths ],
);

View File

@ -178,7 +178,7 @@ sub make_fill {
push @fills, Slic3r::ExtrusionPath::Collection->new(
no_sort => $params->{no_sort},
paths => [
map Slic3r::ExtrusionPath->pack(
map Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polyline->new(@$_),
role => ($surface->surface_type == S_TYPE_INTERNALBRIDGE
? EXTR_ROLE_INTERNALBRIDGE
@ -197,7 +197,7 @@ sub make_fill {
# add thin fill regions
push @fills, @{$layerm->thin_fills};
push @fills_ordering_points, map $_->unpack->points->[0], @{$layerm->thin_fills};
push @fills_ordering_points, map $_->points->[0], @{$layerm->thin_fills};
# organize infill paths using a nearest-neighbor search
@fills = @fills[ chained_path(\@fills_ordering_points) ];

View File

@ -67,7 +67,7 @@ sub fill_surface {
# are kept even if the expolygon has vertical sides
my @paths = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
+($expolygon->offset_ex(scaled_epsilon))[0]->pp, # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object
[ @{ $self->cache->{$cache_id} } ],
[ map $_->pp, @{ $self->cache->{$cache_id} } ],
) };
# connect lines

View File

@ -152,7 +152,7 @@ sub extrude_loop {
my ($loop, $description) = @_;
# extrude all loops ccw
my $polygon = $loop->as_polygon;
my $polygon = $loop->polygon;
my $was_clockwise = $polygon->make_counter_clockwise;
# find candidate starting points

View File

@ -124,24 +124,22 @@ sub process_layer {
push @islands, { perimeters => [], fills => [] }
for 1 .. (@{$layer->slices} || 1); # make sure we have at least one island hash to avoid failure of the -1 subscript below
PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) {
my $p = $perimeter->unpack;
for my $i (0 .. $#{$layer->slices}-1) {
if ($layer->slices->[$i]->contour->encloses_point($p->first_point)) {
push @{ $islands[$i]{perimeters} }, $p;
if ($layer->slices->[$i]->contour->encloses_point($perimeter->first_point)) {
push @{ $islands[$i]{perimeters} }, $perimeter;
next PERIMETER;
}
}
push @{ $islands[-1]{perimeters} }, $p; # optimization
push @{ $islands[-1]{perimeters} }, $perimeter; # optimization
}
FILL: foreach my $fill (@{$layerm->fills}) {
my $f = $fill->unpack;
for my $i (0 .. $#{$layer->slices}-1) {
if ($layer->slices->[$i]->contour->encloses_point($f->first_point)) {
push @{ $islands[$i]{fills} }, $f;
if ($layer->slices->[$i]->contour->encloses_point($fill->first_point)) {
push @{ $islands[$i]{fills} }, $fill;
next FILL;
}
}
push @{ $islands[-1]{fills} }, $f; # optimization
push @{ $islands[-1]{fills} }, $fill; # optimization
}
} else {
push @islands, {

View File

@ -53,7 +53,6 @@ sub BUILD {
# offset the island outwards to make the boundaries for external movements
$self->_outer->[$i] = [ offset([ $self->islands->[$i]->contour], $self->_outer_margin) ];
bless $_, 'Slic3r::Polygon' for @{ $self->_outer->[$i] };
# if internal motion is enabled, build a set of utility expolygons representing
# the outer boundaries (as contours) and the inner boundaries (as holes). whenever

View File

@ -15,12 +15,13 @@ our $clipper = Math::Clipper->new;
sub safety_offset {
my ($polygons, $factor) = @_;
return Math::Clipper::int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2);
return [ map Slic3r::Polygon->new(@$_),
@{Math::Clipper::int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)} ];
}
sub safety_offset_ex {
my ($polygons, $factor) = @_;
return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
@{Math::Clipper::ex_int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)};
}
@ -51,7 +52,7 @@ sub offset_ex {
$miterLimit //= 3;
my $offsets = Math::Clipper::ex_int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit);
return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @$offsets;
return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @$offsets;
}
sub offset2_ex {
@ -61,7 +62,7 @@ sub offset2_ex {
$miterLimit //= 3;
my $offsets = Math::Clipper::ex_int_offset2(_convert($polygons), $delta1, $delta2, $scale, $joinType, $miterLimit);
return map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}), @$offsets;
return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @$offsets;
}
sub diff_ex {
@ -69,9 +70,9 @@ sub diff_ex {
$clipper->clear;
$clipper->add_subject_polygons(_convert($subject));
$clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip));
$clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip));
return [
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
@{ $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
];
}
@ -81,7 +82,7 @@ sub diff {
$clipper->clear;
$clipper->add_subject_polygons(_convert($subject));
$clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip));
$clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip));
return [
map Slic3r::Polygon->new(@$_),
@{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
@ -92,10 +93,10 @@ sub union_ex {
my ($polygons, $jointype, $safety_offset) = @_;
$jointype = PFT_NONZERO unless defined $jointype;
$clipper->clear;
$polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon::XS';
$clipper->add_subject_polygons($safety_offset ? safety_offset(_convert($polygons)) : _convert($polygons));
$polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon';
$clipper->add_subject_polygons($safety_offset ? _convert(safety_offset($polygons)) : _convert($polygons));
return [
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
@{ $clipper->ex_execute(CT_UNION, $jointype, $jointype) },
];
}
@ -104,7 +105,7 @@ sub union_pt {
my ($polygons, $jointype, $safety_offset) = @_;
$jointype = PFT_NONZERO unless defined $jointype;
$clipper->clear;
$clipper->add_subject_polygons($safety_offset ? safety_offset(_convert($polygons)) : _convert($polygons));
$clipper->add_subject_polygons($safety_offset ? _convert(safety_offset($polygons)) : _convert($polygons));
return $clipper->pt_execute(CT_UNION, $jointype, $jointype);
}
@ -113,9 +114,9 @@ sub intersection_ex {
$jointype = PFT_NONZERO unless defined $jointype;
$clipper->clear;
$clipper->add_subject_polygons(_convert($subject));
$clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip));
$clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip));
return [
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
@{ $clipper->ex_execute(CT_INTERSECTION, $jointype, $jointype) },
];
}
@ -125,7 +126,7 @@ sub intersection {
$jointype = PFT_NONZERO unless defined $jointype;
$clipper->clear;
$clipper->add_subject_polygons(_convert($subject));
$clipper->add_clip_polygons($safety_offset ? safety_offset(_convert($clip)) : _convert($clip));
$clipper->add_clip_polygons($safety_offset ? _convert(safety_offset($clip)) : _convert($clip));
return [
map Slic3r::Polygon->new(@$_),
@{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) },
@ -139,7 +140,7 @@ sub xor_ex {
$clipper->add_subject_polygons(_convert($subject));
$clipper->add_clip_polygons(_convert($clip));
return [
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
@{ $clipper->ex_execute(CT_XOR, $jointype, $jointype) },
];
}
@ -178,10 +179,9 @@ sub traverse_pt {
}
sub _convert {
my $polygons = shift;
$polygons = $polygons->pp if ref $polygons eq 'Slic3r::ExPolygon::XS';
$polygons = [ map $_->pp, @$polygons ] if @$polygons && ref $polygons->[0] eq 'Slic3r::Polygon';
return $polygons;
my $p = shift;
$p = $p->pp if ref($p) ne 'ARRAY' && $p->can('pp');
return [ map { ref($_) ne 'ARRAY' && $_->can('pp') ? $_->pp : $_ } @$p ];
}
1;

View File

@ -81,7 +81,7 @@ sub make_slices {
my $slices = union_ex([ map $_->p, map @{$_->slices}, @{$self->regions} ]);
$self->slices->clear;
$self->slices->append(map Slic3r::ExPolygon::XS->new(@$_), @$slices);
$self->slices->append(map Slic3r::ExPolygon->new(@$_), @$slices);
}
sub make_perimeters {

View File

@ -135,8 +135,7 @@ sub _merge_loops {
$safety_offset //= scale 0.0499;
@loops = @{ safety_offset(\@loops, $safety_offset) };
my $expolygons = [];
while (my $loop = shift @loops) {
bless $loop, 'Slic3r::Polygon';
while (defined (my $loop = shift @loops)) {
if ($loop->is_counter_clockwise) {
$expolygons = union_ex([ $loop, map @$_, @$expolygons ]);
} else {
@ -148,7 +147,7 @@ sub _merge_loops {
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
return map Slic3r::Surface->new(expolygon => Slic3r::ExPolygon::XS->new(@$_), surface_type => S_TYPE_INTERNAL), @$expolygons;
return map Slic3r::Surface->new(expolygon => Slic3r::ExPolygon->new(@$_), surface_type => S_TYPE_INTERNAL), @$expolygons;
}
sub make_perimeters {
@ -257,7 +256,7 @@ sub make_perimeters {
$role = EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER;
}
push @loops, Slic3r::ExtrusionLoop->pack(
push @loops, Slic3r::ExtrusionLoop->new(
polygon => $polygon,
role => $role,
flow_spacing => $self->perimeter_flow->spacing,
@ -285,7 +284,7 @@ sub make_perimeters {
# add thin walls as perimeters
push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new(paths => [
map {
Slic3r::ExtrusionPath->pack(
Slic3r::ExtrusionPath->new(
polyline => ($_->isa('Slic3r::Polygon') ? $_->split_at_first_point : $_),
role => EXTR_ROLE_EXTERNAL_PERIMETER,
flow_spacing => $self->perimeter_flow->spacing,
@ -337,8 +336,8 @@ sub _fill_gaps {
);
push @{ $self->thin_fills }, map {
$_->isa('Slic3r::Polygon')
? (map $_->pack, Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point) # we should keep these as loops
: Slic3r::ExtrusionPath->pack(polyline => $_, %path_args),
? Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point # we should keep these as loops
: Slic3r::ExtrusionPath->new(polyline => $_, %path_args),
} map $_->medial_axis($flow->scaled_width), @this_width;
Slic3r::debugf " %d gaps filled with extrusion width = %s\n", scalar @this_width, $width
@ -361,7 +360,7 @@ sub _fill_gaps {
push @{ $self->thin_fills },
map {
$_->simplify($flow->scaled_width/3);
$_->pack;
$_;
}
map Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polyline->new(@$_),

View File

@ -7,14 +7,6 @@ use parent 'Slic3r::Polyline';
use Slic3r::Geometry qw(A B X Y);
sub new {
my $class = shift;
my $self;
$self = [ @_ ];
bless $self, $class;
return $self;
}
sub coincides_with {
my $self = shift;
my ($line) = @_;

View File

@ -5,16 +5,11 @@ use warnings;
# a polygon is a closed polyline.
use parent 'Slic3r::Polyline';
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon
use Slic3r::Geometry qw(polygon_remove_parallel_continuous_edges
polygon_remove_acute_vertices polygon_segment_having_point
PI X1 X2 Y1 Y2 epsilon);
use Slic3r::Geometry::Clipper qw(JT_MITER);
sub lines {
my $self = shift;
return polygon_lines($self);
}
sub wkt {
my $self = shift;
return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self;
@ -46,7 +41,9 @@ sub make_clockwise {
sub merge_continuous_lines {
my $self = shift;
polygon_remove_parallel_continuous_edges($self);
my $p = $self->pp;
polygon_remove_parallel_continuous_edges($p);
return (ref $self)->new(@$p);
}
sub remove_acute_vertices {
@ -120,16 +117,6 @@ sub is_valid {
return @$self >= 3;
}
sub split_at_index {
my $self = shift;
my ($index) = @_;
return Slic3r::Polyline->new(
@$self[$index .. $#$self],
@$self[0 .. $index],
);
}
sub split_at {
my $self = shift;
my ($point) = @_;
@ -147,11 +134,6 @@ sub split_at {
return $self->split_at_index($i);
}
sub split_at_first_point {
my $self = shift;
return $self->split_at_index(0);
}
# for cw polygons this will return convex points!
sub concave_points {
my $self = shift;
@ -161,7 +143,4 @@ sub concave_points {
-1 .. ($#$self-1);
}
package Slic3r::Polygon::XS;
use parent -norequire, qw(Slic3r::Polygon Slic3r::Polyline::XS);
1;

View File

@ -2,53 +2,10 @@ package Slic3r::Polyline;
use strict;
use warnings;
use Scalar::Util qw(reftype);
use Slic3r::Geometry qw(A B X Y X1 X2 Y1 Y2 polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
polyline_lines move_points same_point);
use Slic3r::Geometry qw(A B X Y X1 X2 Y1 Y2 polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices);
use Slic3r::Geometry::Clipper qw(JT_SQUARE);
use Storable qw();
# the constructor accepts an array(ref) of points
sub new {
my $class = shift;
my $self = [ map { ref($_) eq 'Slic3r::Point' ? $_ : Slic3r::Point->new(@$_) } @_ ];
bless $self, $class;
$self;
}
sub arrayref { $_[0] }
sub pp {
my $self = shift;
if (ref($self->[0]) eq 'Slic3r::Point') {
return [ map $_->arrayref, @$self ];
} else {
return $self;
}
}
sub clone {
Storable::dclone($_[0])
}
sub serialize {
my $self = shift;
return pack 'l*', map @$_, @$self;
}
sub deserialize {
my $class = shift;
my ($s) = @_;
my @v = unpack '(l2)*', $s;
return $class->new(map [ $v[2*$_], $v[2*$_+1] ], 0 .. int($#v/2));
}
sub lines {
my $self = shift;
return polyline_lines($self);
}
sub wkt {
my $self = shift;
return sprintf "LINESTRING((%s))", join ',', map "$_->[0] $_->[1]", @$self;
@ -72,11 +29,6 @@ sub simplify {
return (ref $self)->new(@$simplified);
}
sub reverse {
my $self = shift;
@$self = CORE::reverse @$self;
}
sub length {
my $self = shift;
return Boost::Geometry::Utils::linestring_length($self->pp);
@ -120,7 +72,6 @@ sub clip_with_expolygon {
my ($expolygon) = @_;
my $result = Boost::Geometry::Utils::polygon_multi_linestring_intersection($expolygon->pp, [$self->pp]);
bless $_, 'Slic3r::Polyline' for @$result;
return @$result;
}
@ -140,37 +91,6 @@ sub align_to_origin {
return $self->translate(-$bb->x_min, -$bb->y_min);
}
sub rotate {
my $self = shift;
my ($angle, $center) = @_;
$_->rotate($angle, $center) for @$self;
return $self;
}
sub translate {
my $self = shift;
my ($x, $y) = @_;
$_->translate($x, $y) for @$self;
return $self;
}
sub scale {
my $self = shift;
my ($factor) = @_;
$_->scale($factor) for @$self;
return $self;
}
sub pop_back {
my $self = shift;
return pop @$self;
}
sub append {
my $self = shift;
push @$self, @_;
}
# removes the given distance from the end of the polyline
sub clip_end {
my $self = shift;
@ -255,7 +175,4 @@ sub chained_path {
return map $items_map{"$_"}, @paths;
}
package Slic3r::Polyline::XS;
use parent qw(Slic3r::Polyline);
1;

View File

@ -587,7 +587,7 @@ sub make_skirt {
my @layer_points = (
(map @$_, map @$_, map @{$_->slices}, @layers),
(map @$_, map @{$_->thin_walls}, map @{$_->regions}, @layers),
(map @{$_->unpack->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers),
(map @{$_->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers),
);
push @points, map move_points($_, @layer_points), @{$self->objects->[$obj_idx]->copies};
}
@ -611,14 +611,13 @@ sub make_skirt {
for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) {
$distance += scale $spacing;
my ($loop) = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND);
push @{$self->skirt}, Slic3r::ExtrusionLoop->pack(
push @{$self->skirt}, Slic3r::ExtrusionLoop->new(
polygon => Slic3r::Polygon->new(@$loop),
role => EXTR_ROLE_SKIRT,
flow_spacing => $spacing,
);
if ($Slic3r::Config->min_skirt_length > 0) {
bless $loop, 'Slic3r::Polygon';
$extruded_length[$extruder_idx] ||= 0;
$extruders_e_per_mm[$extruder_idx] ||= $self->extruders->[$extruder_idx]->e_per_mm($spacing, $first_layer_height);
$extruded_length[$extruder_idx] += unscale $loop->length * $extruders_e_per_mm[$extruder_idx];
@ -648,7 +647,7 @@ sub make_brim {
my @object_islands = (
(map $_->contour, @{$layer0->slices}),
(map { $_->isa('Slic3r::Polygon') ? $_ : $_->grow($grow_distance) } map @{$_->thin_walls}, @{$layer0->regions}),
(map $_->unpack->polyline->grow($grow_distance), map @{$_->support_fills->paths}, grep $_->support_fills, $layer0),
(map $_->polyline->grow($grow_distance), map @{$_->support_fills->paths}, grep $_->support_fills, $layer0),
);
foreach my $copy (@{$self->objects->[$obj_idx]->copies}) {
push @islands, map $_->clone->translate(@$copy), @object_islands;
@ -658,7 +657,7 @@ sub make_brim {
# if brim touches skirt, make it around skirt too
# TODO: calculate actual skirt width (using each extruder's flow in multi-extruder setups)
if ($Slic3r::Config->skirt_distance + (($Slic3r::Config->skirts - 1) * $flow->spacing) <= $Slic3r::Config->brim_width) {
push @islands, map $_->unpack->split_at_first_point->polyline->grow($grow_distance), @{$self->skirt};
push @islands, map $_->split_at_first_point->polyline->grow($grow_distance), @{$self->skirt};
}
my @loops = ();
@ -670,7 +669,7 @@ sub make_brim {
push @loops, offset2(\@islands, ($i - 1.5) * $flow->scaled_spacing, +1.0 * $flow->scaled_spacing, undef, JT_SQUARE);
}
@{$self->brim} = map Slic3r::ExtrusionLoop->pack(
@{$self->brim} = map Slic3r::ExtrusionLoop->new(
polygon => Slic3r::Polygon->new(@$_),
role => EXTR_ROLE_SKIRT,
flow_spacing => $flow->spacing,

View File

@ -969,7 +969,6 @@ sub generate_support_material {
my @paths = ();
foreach my $expolygon (@$expolygons) {
push @paths,
map $_->pack,
map {
$_->height($height);

View File

@ -45,7 +45,7 @@ sub simplify {
sub p {
my $self = shift;
return @{$self->expolygon};
return @{$self->expolygon->pp};
}
sub is_solid {

View File

@ -16,7 +16,7 @@ use Slic3r;
[5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0],
);
$polygon->merge_continuous_lines;
$polygon = $polygon->merge_continuous_lines;
is scalar(@$polygon), 3, 'merge_continuous_lines';
}
@ -69,7 +69,7 @@ use Slic3r;
[180.595,296.0487], [161.7854,297.4248], [156.8058,297.6214], [154.3395,317.8592],
];
my $polygon = Slic3r::Polygon->new(@$gear);
$polygon->merge_continuous_lines;
$polygon = $polygon->merge_continuous_lines;
note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@$polygon);
ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines';
@ -114,7 +114,7 @@ use Slic3r;
];
my $polygon = Slic3r::Polygon->new(@$circle);
$polygon->merge_continuous_lines;
$polygon = $polygon->merge_continuous_lines;
note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@$polygon);
ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines';
}

View File

@ -81,7 +81,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
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 $_->unpack, @{$layerm->thin_fills};
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';

View File

@ -33,7 +33,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
}
{
my $expolygon = Slic3r::ExPolygon::XS->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]);
my $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]);
my $filler = Slic3r::Fill::Rectilinear->new(
bounding_box => $expolygon->bounding_box,
);
@ -72,24 +72,24 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
{
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [
map Slic3r::ExtrusionPath->pack(polyline => $_, role => 0),
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0),
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
]);
is_deeply
[ map $_->[Y], map @{$_->unpack->polyline}, $collection->chained_path(Slic3r::Point->new(0,30)) ],
[ map $_->[Y], map @{$_->polyline}, $collection->chained_path(Slic3r::Point->new(0,30)) ],
[20, 18, 15, 10, 8, 5],
'chained path';
}
{
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [
map Slic3r::ExtrusionPath->pack(polyline => $_, role => 0),
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0),
Slic3r::Polyline->new([15,0], [10,0], [4,0]),
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
]);
is_deeply
[ map $_->[X], map @{$_->unpack->polyline}, $collection->chained_path(Slic3r::Point->new(30,0)) ],
[ map $_->[X], map @{$_->polyline}, $collection->chained_path(Slic3r::Point->new(30,0)) ],
[reverse 4, 10, 15, 10, 15, 20],
'chained path';
}

View File

@ -48,7 +48,7 @@ sub clone {
my ($self, %args) = @_;
return (ref $self)->_new(
$args{polygon} // $self->as_polygon,
$args{polygon} // $self->polygon,
$args{role} // $self->role,
$args{height} // $self->height,
$args{flow_spacing} // $self->flow_spacing,
@ -75,7 +75,7 @@ sub clone {
my ($self, %args) = @_;
return (ref $self)->_new(
$args{polyline} // $self->as_polyline,
$args{polyline} // $self->polyline,
$args{role} // $self->role,
$args{height} // $self->height,
$args{flow_spacing} // $self->flow_spacing,

View File

@ -16,11 +16,11 @@ my $path = Slic3r::ExtrusionPath->new(
polyline => Slic3r::Polyline->new(@$points),
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
);
isa_ok $path->as_polyline, 'Slic3r::Polyline', 'path polyline';
is_deeply $path->as_polyline->pp, $points, 'path points roundtrip';
isa_ok $path->polyline, 'Slic3r::Polyline', 'path polyline';
is_deeply $path->polyline->pp, $points, 'path points roundtrip';
$path->reverse;
is_deeply $path->as_polyline->pp, [ reverse @$points ], 'reverse path';
is_deeply $path->polyline->pp, [ reverse @$points ], 'reverse path';
$path->append([ 150, 150 ]);
is scalar(@$path), 4, 'append to path';

View File

@ -17,8 +17,8 @@ my $loop = Slic3r::ExtrusionLoop->new(
polygon => Slic3r::Polygon->new(@$square),
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
);
isa_ok $loop->as_polygon, 'Slic3r::Polygon', 'loop polygon';
is_deeply $loop->as_polygon->pp, $square, 'polygon points roundtrip';
isa_ok $loop->polygon, 'Slic3r::Polygon', 'loop polygon';
is_deeply $loop->polygon->pp, $square, 'polygon points roundtrip';
$loop = $loop->clone;
@ -28,10 +28,10 @@ is $loop->role, Slic3r::ExtrusionPath::EXTR_ROLE_FILL, 'modify role';
{
my $path = $loop->split_at_first_point;
is_deeply $path->as_polyline->pp, $square, 'split_at_first_point';
is_deeply $path->polyline->pp, $square, 'split_at_first_point';
is $path->role, $loop->role, 'role preserved after split';
is_deeply $loop->split_at_index(2)->as_polyline->pp, [ @$square[2,3,0,1] ], 'split_at_index';
is_deeply $loop->split_at_index(2)->polyline->pp, [ @$square[2,3,0,1] ], 'split_at_index';
}
__END__

View File

@ -11,10 +11,6 @@
%code{% RETVAL = THIS->polygon.to_SV(); %};
SV* pp()
%code{% RETVAL = THIS->polygon.to_SV_pureperl(); %};
Polygon* as_polygon()
%code{% const char* CLASS = "Slic3r::Polygon"; RETVAL = new Polygon(THIS->polygon); %};
void set_polygon(SV* polygon_sv)
%code{% THIS->polygon.from_SV_check(polygon_sv); %};
ExtrusionPath* split_at_index(int index)
%code{% const char* CLASS = "Slic3r::ExtrusionPath"; RETVAL = THIS->split_at_index(index); %};
ExtrusionPath* split_at_first_point()
@ -37,6 +33,18 @@ _new(CLASS, polygon_sv, role, height, flow_spacing)
OUTPUT:
RETVAL
Polygon*
ExtrusionLoop::polygon(...)
PREINIT:
const char* CLASS = "Slic3r::Polygon";
CODE:
if (items > 1) {
THIS->polygon.from_SV_check( ST(1) );
}
RETVAL = new Polygon(THIS->polygon);
OUTPUT:
RETVAL
ExtrusionRole
ExtrusionLoop::role(...)
CODE:

View File

@ -11,10 +11,6 @@
%code{% RETVAL = THIS->polyline.to_SV(); %};
SV* pp()
%code{% RETVAL = THIS->polyline.to_SV_pureperl(); %};
Polyline* as_polyline()
%code{% const char* CLASS = "Slic3r::Polyline"; RETVAL = new Polyline(THIS->polyline); %};
void set_polyline(SV* polyline_sv)
%code{% THIS->polyline.from_SV_check(polyline_sv); %};
void pop_back()
%code{% THIS->polyline.points.pop_back(); %};
void reverse();
@ -36,6 +32,18 @@ _new(CLASS, polyline_sv, role, height, flow_spacing)
OUTPUT:
RETVAL
Polyline*
ExtrusionPath::polyline(...)
PREINIT:
const char* CLASS = "Slic3r::Polyline";
CODE:
if (items > 1) {
THIS->polyline.from_SV_check( ST(1) );
}
RETVAL = new Polyline(THIS->polyline);
OUTPUT:
RETVAL
ExtrusionRole
ExtrusionPath::role(...)
CODE:

View File

@ -13,6 +13,10 @@
%code{% RETVAL = THIS->to_SV(); %};
SV* pp()
%code{% RETVAL = THIS->to_SV_pureperl(); %};
Point* a()
%code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(THIS->a); %};
Point* b()
%code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(THIS->b); %};
void reverse();
%{

View File

@ -34,5 +34,14 @@ Polygon::new(...)
OUTPUT:
RETVAL
void
Polygon::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
center.from_SV_check(center_sv);
THIS->rotate(angle, &center);
%}
};

View File

@ -13,6 +13,8 @@
%code{% RETVAL = THIS->to_SV(); %};
SV* pp()
%code{% RETVAL = THIS->to_SV_pureperl(); %};
void scale(double factor);
void translate(double x, double y);
void pop_back()
%code{% THIS->points.pop_back(); %};
void reverse();
@ -40,5 +42,14 @@ Polyline::append(...)
THIS->points.push_back(p);
}
void
Polyline::rotate(angle, center_sv)
double angle;
SV* center_sv;
CODE:
Point center;
center.from_SV_check(center_sv);
THIS->rotate(angle, &center);
%}
};