Adopt XS containers everywhere (incomplete work)
This commit is contained in:
parent
339ba9e5c3
commit
9b582a11ff
@ -110,10 +110,16 @@ sub parallelize {
|
|||||||
sub thread_cleanup {
|
sub thread_cleanup {
|
||||||
# prevent destruction of shared objects
|
# prevent destruction of shared objects
|
||||||
no warnings 'redefine';
|
no warnings 'redefine';
|
||||||
|
*Slic3r::ExPolygon::DESTROY = sub {};
|
||||||
*Slic3r::ExPolygon::Collection::DESTROY = sub {};
|
*Slic3r::ExPolygon::Collection::DESTROY = sub {};
|
||||||
*Slic3r::ExPolygon::XS::DESTROY = sub {};
|
*Slic3r::ExtrusionLoop::DESTROY = sub {};
|
||||||
*Slic3r::Point::DESTROY = sub {};
|
*Slic3r::ExtrusionPath::DESTROY = sub {};
|
||||||
*Slic3r::Surface::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 {
|
sub encode_path {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
gpackage Slic3r::ExPolygon;
|
package Slic3r::ExPolygon;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
@ -9,32 +9,6 @@ use List::Util qw(first);
|
|||||||
use Math::Geometry::Voronoi;
|
use Math::Geometry::Voronoi;
|
||||||
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon);
|
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon);
|
||||||
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
|
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 {
|
sub contour {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -46,19 +20,6 @@ sub holes {
|
|||||||
return @$self[1..$#$self];
|
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 {
|
sub is_valid {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return (!first { !$_->is_valid } @$self)
|
return (!first { !$_->is_valid } @$self)
|
||||||
@ -155,23 +116,6 @@ sub simplify {
|
|||||||
return @{ Slic3r::Geometry::Clipper::union_ex([ @simplified ]) };
|
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 {
|
sub area {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $area = $self->contour->area;
|
my $area = $self->contour->area;
|
||||||
@ -298,9 +242,6 @@ sub medial_axis {
|
|||||||
return @result;
|
return @result;
|
||||||
}
|
}
|
||||||
|
|
||||||
package Slic3r::ExPolygon::XS;
|
|
||||||
use parent 'Slic3r::ExPolygon';
|
|
||||||
|
|
||||||
package Slic3r::ExPolygon::Collection;
|
package Slic3r::ExPolygon::Collection;
|
||||||
use Slic3r::Geometry qw(X1 Y1);
|
use Slic3r::Geometry qw(X1 Y1);
|
||||||
|
|
||||||
|
@ -2,51 +2,17 @@ package Slic3r::ExtrusionLoop;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
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 {
|
sub split_at {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
return Slic3r::ExtrusionPath->new(
|
return Slic3r::ExtrusionPath->new(
|
||||||
polyline => $self->as_polygon->split_at(@_),
|
polyline => $self->polygon->split_at(@_),
|
||||||
role => $self->role,
|
role => $self->role,
|
||||||
flow_spacing => $self->flow_spacing,
|
flow_spacing => $self->flow_spacing,
|
||||||
height => $self->height,
|
height => $self->height,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub split_at_first_point {
|
|
||||||
my $self = shift;
|
|
||||||
return $self->split_at_index(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub first_point {
|
sub first_point {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return $self->polygon->[0];
|
return $self->polygon->[0];
|
||||||
|
@ -2,7 +2,6 @@ package Slic3r::ExtrusionPath;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use parent -norequire, qw(Slic3r::Polyline::XS);
|
|
||||||
use parent qw(Exporter);
|
use parent qw(Exporter);
|
||||||
|
|
||||||
our @EXPORT_OK = qw(EXTR_ROLE_PERIMETER EXTR_ROLE_EXTERNAL_PERIMETER
|
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);
|
our %EXPORT_TAGS = (roles => \@EXPORT_OK);
|
||||||
|
|
||||||
use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points);
|
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 {
|
sub clip_with_polygon {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -40,7 +24,7 @@ sub clip_with_expolygon {
|
|||||||
my ($expolygon) = @_;
|
my ($expolygon) = @_;
|
||||||
|
|
||||||
return map $self->clone(polyline => $_),
|
return map $self->clone(polyline => $_),
|
||||||
$self->as_polyline->clip_with_expolygon($expolygon);
|
$self->polyline->clip_with_expolygon($expolygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub intersect_expolygons {
|
sub intersect_expolygons {
|
||||||
@ -61,7 +45,7 @@ sub subtract_expolygons {
|
|||||||
|
|
||||||
sub simplify {
|
sub simplify {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
$self->set_polyline($self->as_polyline->simplify(@_));
|
$self->set_polyline($self->polyline->simplify(@_));
|
||||||
}
|
}
|
||||||
|
|
||||||
sub points {
|
sub points {
|
||||||
|
@ -9,7 +9,7 @@ sub unpack { $_[0] }
|
|||||||
|
|
||||||
sub first_point {
|
sub first_point {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return $self->paths->[0]->unpack->polyline->[0];
|
return $self->paths->[0]->polyline->[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
sub chained_path {
|
sub chained_path {
|
||||||
@ -21,7 +21,7 @@ sub chained_path {
|
|||||||
# make sure we pass the same path objects to the Collection constructor
|
# make sure we pass the same path objects to the Collection constructor
|
||||||
# and the ->chained_path() method because the latter will reverse the
|
# and the ->chained_path() method because the latter will reverse the
|
||||||
# paths in-place when needed and we need to return them that way
|
# 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(
|
my $collection = Slic3r::Polyline::Collection->new(
|
||||||
polylines => [ map $_->polyline, @paths ],
|
polylines => [ map $_->polyline, @paths ],
|
||||||
);
|
);
|
||||||
|
@ -178,7 +178,7 @@ sub make_fill {
|
|||||||
push @fills, Slic3r::ExtrusionPath::Collection->new(
|
push @fills, Slic3r::ExtrusionPath::Collection->new(
|
||||||
no_sort => $params->{no_sort},
|
no_sort => $params->{no_sort},
|
||||||
paths => [
|
paths => [
|
||||||
map Slic3r::ExtrusionPath->pack(
|
map Slic3r::ExtrusionPath->new(
|
||||||
polyline => Slic3r::Polyline->new(@$_),
|
polyline => Slic3r::Polyline->new(@$_),
|
||||||
role => ($surface->surface_type == S_TYPE_INTERNALBRIDGE
|
role => ($surface->surface_type == S_TYPE_INTERNALBRIDGE
|
||||||
? EXTR_ROLE_INTERNALBRIDGE
|
? EXTR_ROLE_INTERNALBRIDGE
|
||||||
@ -197,7 +197,7 @@ sub make_fill {
|
|||||||
|
|
||||||
# add thin fill regions
|
# add thin fill regions
|
||||||
push @fills, @{$layerm->thin_fills};
|
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
|
# organize infill paths using a nearest-neighbor search
|
||||||
@fills = @fills[ chained_path(\@fills_ordering_points) ];
|
@fills = @fills[ chained_path(\@fills_ordering_points) ];
|
||||||
|
@ -67,7 +67,7 @@ sub fill_surface {
|
|||||||
# are kept even if the expolygon has vertical sides
|
# are kept even if the expolygon has vertical sides
|
||||||
my @paths = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
|
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
|
+($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
|
# connect lines
|
||||||
|
@ -152,7 +152,7 @@ sub extrude_loop {
|
|||||||
my ($loop, $description) = @_;
|
my ($loop, $description) = @_;
|
||||||
|
|
||||||
# extrude all loops ccw
|
# extrude all loops ccw
|
||||||
my $polygon = $loop->as_polygon;
|
my $polygon = $loop->polygon;
|
||||||
my $was_clockwise = $polygon->make_counter_clockwise;
|
my $was_clockwise = $polygon->make_counter_clockwise;
|
||||||
|
|
||||||
# find candidate starting points
|
# find candidate starting points
|
||||||
|
@ -124,24 +124,22 @@ sub process_layer {
|
|||||||
push @islands, { perimeters => [], fills => [] }
|
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
|
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}) {
|
PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) {
|
||||||
my $p = $perimeter->unpack;
|
|
||||||
for my $i (0 .. $#{$layer->slices}-1) {
|
for my $i (0 .. $#{$layer->slices}-1) {
|
||||||
if ($layer->slices->[$i]->contour->encloses_point($p->first_point)) {
|
if ($layer->slices->[$i]->contour->encloses_point($perimeter->first_point)) {
|
||||||
push @{ $islands[$i]{perimeters} }, $p;
|
push @{ $islands[$i]{perimeters} }, $perimeter;
|
||||||
next PERIMETER;
|
next PERIMETER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
push @{ $islands[-1]{perimeters} }, $p; # optimization
|
push @{ $islands[-1]{perimeters} }, $perimeter; # optimization
|
||||||
}
|
}
|
||||||
FILL: foreach my $fill (@{$layerm->fills}) {
|
FILL: foreach my $fill (@{$layerm->fills}) {
|
||||||
my $f = $fill->unpack;
|
|
||||||
for my $i (0 .. $#{$layer->slices}-1) {
|
for my $i (0 .. $#{$layer->slices}-1) {
|
||||||
if ($layer->slices->[$i]->contour->encloses_point($f->first_point)) {
|
if ($layer->slices->[$i]->contour->encloses_point($fill->first_point)) {
|
||||||
push @{ $islands[$i]{fills} }, $f;
|
push @{ $islands[$i]{fills} }, $fill;
|
||||||
next FILL;
|
next FILL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
push @{ $islands[-1]{fills} }, $f; # optimization
|
push @{ $islands[-1]{fills} }, $fill; # optimization
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
push @islands, {
|
push @islands, {
|
||||||
|
@ -53,7 +53,6 @@ sub BUILD {
|
|||||||
|
|
||||||
# offset the island outwards to make the boundaries for external movements
|
# offset the island outwards to make the boundaries for external movements
|
||||||
$self->_outer->[$i] = [ offset([ $self->islands->[$i]->contour], $self->_outer_margin) ];
|
$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
|
# if internal motion is enabled, build a set of utility expolygons representing
|
||||||
# the outer boundaries (as contours) and the inner boundaries (as holes). whenever
|
# the outer boundaries (as contours) and the inner boundaries (as holes). whenever
|
||||||
|
@ -15,12 +15,13 @@ our $clipper = Math::Clipper->new;
|
|||||||
|
|
||||||
sub safety_offset {
|
sub safety_offset {
|
||||||
my ($polygons, $factor) = @_;
|
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 {
|
sub safety_offset_ex {
|
||||||
my ($polygons, $factor) = @_;
|
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)};
|
@{Math::Clipper::ex_int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ sub offset_ex {
|
|||||||
$miterLimit //= 3;
|
$miterLimit //= 3;
|
||||||
|
|
||||||
my $offsets = Math::Clipper::ex_int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit);
|
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 {
|
sub offset2_ex {
|
||||||
@ -61,7 +62,7 @@ sub offset2_ex {
|
|||||||
$miterLimit //= 3;
|
$miterLimit //= 3;
|
||||||
|
|
||||||
my $offsets = Math::Clipper::ex_int_offset2(_convert($polygons), $delta1, $delta2, $scale, $joinType, $miterLimit);
|
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 {
|
sub diff_ex {
|
||||||
@ -69,9 +70,9 @@ sub diff_ex {
|
|||||||
|
|
||||||
$clipper->clear;
|
$clipper->clear;
|
||||||
$clipper->add_subject_polygons(_convert($subject));
|
$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 [
|
return [
|
||||||
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
|
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
|
||||||
@{ $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
|
@{ $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -81,7 +82,7 @@ sub diff {
|
|||||||
|
|
||||||
$clipper->clear;
|
$clipper->clear;
|
||||||
$clipper->add_subject_polygons(_convert($subject));
|
$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 [
|
return [
|
||||||
map Slic3r::Polygon->new(@$_),
|
map Slic3r::Polygon->new(@$_),
|
||||||
@{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
|
@{ $clipper->execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO) },
|
||||||
@ -92,10 +93,10 @@ sub union_ex {
|
|||||||
my ($polygons, $jointype, $safety_offset) = @_;
|
my ($polygons, $jointype, $safety_offset) = @_;
|
||||||
$jointype = PFT_NONZERO unless defined $jointype;
|
$jointype = PFT_NONZERO unless defined $jointype;
|
||||||
$clipper->clear;
|
$clipper->clear;
|
||||||
$polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon::XS';
|
$polygons = $polygons->arrayref if ref $polygons eq 'Slic3r::ExPolygon';
|
||||||
$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 [
|
return [
|
||||||
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
|
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
|
||||||
@{ $clipper->ex_execute(CT_UNION, $jointype, $jointype) },
|
@{ $clipper->ex_execute(CT_UNION, $jointype, $jointype) },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -104,7 +105,7 @@ sub union_pt {
|
|||||||
my ($polygons, $jointype, $safety_offset) = @_;
|
my ($polygons, $jointype, $safety_offset) = @_;
|
||||||
$jointype = PFT_NONZERO unless defined $jointype;
|
$jointype = PFT_NONZERO unless defined $jointype;
|
||||||
$clipper->clear;
|
$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);
|
return $clipper->pt_execute(CT_UNION, $jointype, $jointype);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,9 +114,9 @@ sub intersection_ex {
|
|||||||
$jointype = PFT_NONZERO unless defined $jointype;
|
$jointype = PFT_NONZERO unless defined $jointype;
|
||||||
$clipper->clear;
|
$clipper->clear;
|
||||||
$clipper->add_subject_polygons(_convert($subject));
|
$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 [
|
return [
|
||||||
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
|
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
|
||||||
@{ $clipper->ex_execute(CT_INTERSECTION, $jointype, $jointype) },
|
@{ $clipper->ex_execute(CT_INTERSECTION, $jointype, $jointype) },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ sub intersection {
|
|||||||
$jointype = PFT_NONZERO unless defined $jointype;
|
$jointype = PFT_NONZERO unless defined $jointype;
|
||||||
$clipper->clear;
|
$clipper->clear;
|
||||||
$clipper->add_subject_polygons(_convert($subject));
|
$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 [
|
return [
|
||||||
map Slic3r::Polygon->new(@$_),
|
map Slic3r::Polygon->new(@$_),
|
||||||
@{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) },
|
@{ $clipper->execute(CT_INTERSECTION, $jointype, $jointype) },
|
||||||
@ -139,7 +140,7 @@ sub xor_ex {
|
|||||||
$clipper->add_subject_polygons(_convert($subject));
|
$clipper->add_subject_polygons(_convert($subject));
|
||||||
$clipper->add_clip_polygons(_convert($clip));
|
$clipper->add_clip_polygons(_convert($clip));
|
||||||
return [
|
return [
|
||||||
map Slic3r::ExPolygon::XS->new($_->{outer}, @{$_->{holes}}),
|
map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}),
|
||||||
@{ $clipper->ex_execute(CT_XOR, $jointype, $jointype) },
|
@{ $clipper->ex_execute(CT_XOR, $jointype, $jointype) },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -178,10 +179,9 @@ sub traverse_pt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub _convert {
|
sub _convert {
|
||||||
my $polygons = shift;
|
my $p = shift;
|
||||||
$polygons = $polygons->pp if ref $polygons eq 'Slic3r::ExPolygon::XS';
|
$p = $p->pp if ref($p) ne 'ARRAY' && $p->can('pp');
|
||||||
$polygons = [ map $_->pp, @$polygons ] if @$polygons && ref $polygons->[0] eq 'Slic3r::Polygon';
|
return [ map { ref($_) ne 'ARRAY' && $_->can('pp') ? $_->pp : $_ } @$p ];
|
||||||
return $polygons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -81,7 +81,7 @@ sub make_slices {
|
|||||||
|
|
||||||
my $slices = union_ex([ map $_->p, map @{$_->slices}, @{$self->regions} ]);
|
my $slices = union_ex([ map $_->p, map @{$_->slices}, @{$self->regions} ]);
|
||||||
$self->slices->clear;
|
$self->slices->clear;
|
||||||
$self->slices->append(map Slic3r::ExPolygon::XS->new(@$_), @$slices);
|
$self->slices->append(map Slic3r::ExPolygon->new(@$_), @$slices);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub make_perimeters {
|
sub make_perimeters {
|
||||||
|
@ -135,8 +135,7 @@ sub _merge_loops {
|
|||||||
$safety_offset //= scale 0.0499;
|
$safety_offset //= scale 0.0499;
|
||||||
@loops = @{ safety_offset(\@loops, $safety_offset) };
|
@loops = @{ safety_offset(\@loops, $safety_offset) };
|
||||||
my $expolygons = [];
|
my $expolygons = [];
|
||||||
while (my $loop = shift @loops) {
|
while (defined (my $loop = shift @loops)) {
|
||||||
bless $loop, 'Slic3r::Polygon';
|
|
||||||
if ($loop->is_counter_clockwise) {
|
if ($loop->is_counter_clockwise) {
|
||||||
$expolygons = union_ex([ $loop, map @$_, @$expolygons ]);
|
$expolygons = union_ex([ $loop, map @$_, @$expolygons ]);
|
||||||
} else {
|
} else {
|
||||||
@ -148,7 +147,7 @@ sub _merge_loops {
|
|||||||
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
|
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
|
||||||
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
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 {
|
sub make_perimeters {
|
||||||
@ -257,7 +256,7 @@ sub make_perimeters {
|
|||||||
$role = EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER;
|
$role = EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
push @loops, Slic3r::ExtrusionLoop->pack(
|
push @loops, Slic3r::ExtrusionLoop->new(
|
||||||
polygon => $polygon,
|
polygon => $polygon,
|
||||||
role => $role,
|
role => $role,
|
||||||
flow_spacing => $self->perimeter_flow->spacing,
|
flow_spacing => $self->perimeter_flow->spacing,
|
||||||
@ -285,7 +284,7 @@ sub make_perimeters {
|
|||||||
# add thin walls as perimeters
|
# add thin walls as perimeters
|
||||||
push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new(paths => [
|
push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new(paths => [
|
||||||
map {
|
map {
|
||||||
Slic3r::ExtrusionPath->pack(
|
Slic3r::ExtrusionPath->new(
|
||||||
polyline => ($_->isa('Slic3r::Polygon') ? $_->split_at_first_point : $_),
|
polyline => ($_->isa('Slic3r::Polygon') ? $_->split_at_first_point : $_),
|
||||||
role => EXTR_ROLE_EXTERNAL_PERIMETER,
|
role => EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||||
flow_spacing => $self->perimeter_flow->spacing,
|
flow_spacing => $self->perimeter_flow->spacing,
|
||||||
@ -337,8 +336,8 @@ sub _fill_gaps {
|
|||||||
);
|
);
|
||||||
push @{ $self->thin_fills }, map {
|
push @{ $self->thin_fills }, map {
|
||||||
$_->isa('Slic3r::Polygon')
|
$_->isa('Slic3r::Polygon')
|
||||||
? (map $_->pack, Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point) # we should keep these as loops
|
? Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point # we should keep these as loops
|
||||||
: Slic3r::ExtrusionPath->pack(polyline => $_, %path_args),
|
: Slic3r::ExtrusionPath->new(polyline => $_, %path_args),
|
||||||
} map $_->medial_axis($flow->scaled_width), @this_width;
|
} map $_->medial_axis($flow->scaled_width), @this_width;
|
||||||
|
|
||||||
Slic3r::debugf " %d gaps filled with extrusion width = %s\n", scalar @this_width, $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 },
|
push @{ $self->thin_fills },
|
||||||
map {
|
map {
|
||||||
$_->simplify($flow->scaled_width/3);
|
$_->simplify($flow->scaled_width/3);
|
||||||
$_->pack;
|
$_;
|
||||||
}
|
}
|
||||||
map Slic3r::ExtrusionPath->new(
|
map Slic3r::ExtrusionPath->new(
|
||||||
polyline => Slic3r::Polyline->new(@$_),
|
polyline => Slic3r::Polyline->new(@$_),
|
||||||
|
@ -7,14 +7,6 @@ use parent 'Slic3r::Polyline';
|
|||||||
|
|
||||||
use Slic3r::Geometry qw(A B X Y);
|
use Slic3r::Geometry qw(A B X Y);
|
||||||
|
|
||||||
sub new {
|
|
||||||
my $class = shift;
|
|
||||||
my $self;
|
|
||||||
$self = [ @_ ];
|
|
||||||
bless $self, $class;
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub coincides_with {
|
sub coincides_with {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($line) = @_;
|
my ($line) = @_;
|
||||||
|
@ -5,16 +5,11 @@ use warnings;
|
|||||||
# a polygon is a closed polyline.
|
# a polygon is a closed polyline.
|
||||||
use parent 'Slic3r::Polyline';
|
use parent 'Slic3r::Polyline';
|
||||||
|
|
||||||
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
|
use Slic3r::Geometry qw(polygon_remove_parallel_continuous_edges
|
||||||
polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon
|
polygon_remove_acute_vertices polygon_segment_having_point
|
||||||
PI X1 X2 Y1 Y2 epsilon);
|
PI X1 X2 Y1 Y2 epsilon);
|
||||||
use Slic3r::Geometry::Clipper qw(JT_MITER);
|
use Slic3r::Geometry::Clipper qw(JT_MITER);
|
||||||
|
|
||||||
sub lines {
|
|
||||||
my $self = shift;
|
|
||||||
return polygon_lines($self);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub wkt {
|
sub wkt {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self;
|
return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self;
|
||||||
@ -46,7 +41,9 @@ sub make_clockwise {
|
|||||||
sub merge_continuous_lines {
|
sub merge_continuous_lines {
|
||||||
my $self = shift;
|
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 {
|
sub remove_acute_vertices {
|
||||||
@ -120,16 +117,6 @@ sub is_valid {
|
|||||||
return @$self >= 3;
|
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 {
|
sub split_at {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($point) = @_;
|
my ($point) = @_;
|
||||||
@ -147,11 +134,6 @@ sub split_at {
|
|||||||
return $self->split_at_index($i);
|
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!
|
# for cw polygons this will return convex points!
|
||||||
sub concave_points {
|
sub concave_points {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -161,7 +143,4 @@ sub concave_points {
|
|||||||
-1 .. ($#$self-1);
|
-1 .. ($#$self-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
package Slic3r::Polygon::XS;
|
|
||||||
use parent -norequire, qw(Slic3r::Polygon Slic3r::Polyline::XS);
|
|
||||||
|
|
||||||
1;
|
1;
|
@ -2,53 +2,10 @@ package Slic3r::Polyline;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
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);
|
||||||
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::Clipper qw(JT_SQUARE);
|
use Slic3r::Geometry::Clipper qw(JT_SQUARE);
|
||||||
use Storable qw();
|
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 {
|
sub wkt {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return sprintf "LINESTRING((%s))", join ',', map "$_->[0] $_->[1]", @$self;
|
return sprintf "LINESTRING((%s))", join ',', map "$_->[0] $_->[1]", @$self;
|
||||||
@ -72,11 +29,6 @@ sub simplify {
|
|||||||
return (ref $self)->new(@$simplified);
|
return (ref $self)->new(@$simplified);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub reverse {
|
|
||||||
my $self = shift;
|
|
||||||
@$self = CORE::reverse @$self;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub length {
|
sub length {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return Boost::Geometry::Utils::linestring_length($self->pp);
|
return Boost::Geometry::Utils::linestring_length($self->pp);
|
||||||
@ -120,7 +72,6 @@ sub clip_with_expolygon {
|
|||||||
my ($expolygon) = @_;
|
my ($expolygon) = @_;
|
||||||
|
|
||||||
my $result = Boost::Geometry::Utils::polygon_multi_linestring_intersection($expolygon->pp, [$self->pp]);
|
my $result = Boost::Geometry::Utils::polygon_multi_linestring_intersection($expolygon->pp, [$self->pp]);
|
||||||
bless $_, 'Slic3r::Polyline' for @$result;
|
|
||||||
return @$result;
|
return @$result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,37 +91,6 @@ sub align_to_origin {
|
|||||||
return $self->translate(-$bb->x_min, -$bb->y_min);
|
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
|
# removes the given distance from the end of the polyline
|
||||||
sub clip_end {
|
sub clip_end {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -255,7 +175,4 @@ sub chained_path {
|
|||||||
return map $items_map{"$_"}, @paths;
|
return map $items_map{"$_"}, @paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
package Slic3r::Polyline::XS;
|
|
||||||
use parent qw(Slic3r::Polyline);
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -587,7 +587,7 @@ sub make_skirt {
|
|||||||
my @layer_points = (
|
my @layer_points = (
|
||||||
(map @$_, map @$_, map @{$_->slices}, @layers),
|
(map @$_, map @$_, map @{$_->slices}, @layers),
|
||||||
(map @$_, map @{$_->thin_walls}, map @{$_->regions}, @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};
|
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--) {
|
for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) {
|
||||||
$distance += scale $spacing;
|
$distance += scale $spacing;
|
||||||
my ($loop) = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND);
|
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),
|
polygon => Slic3r::Polygon->new(@$loop),
|
||||||
role => EXTR_ROLE_SKIRT,
|
role => EXTR_ROLE_SKIRT,
|
||||||
flow_spacing => $spacing,
|
flow_spacing => $spacing,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($Slic3r::Config->min_skirt_length > 0) {
|
if ($Slic3r::Config->min_skirt_length > 0) {
|
||||||
bless $loop, 'Slic3r::Polygon';
|
|
||||||
$extruded_length[$extruder_idx] ||= 0;
|
$extruded_length[$extruder_idx] ||= 0;
|
||||||
$extruders_e_per_mm[$extruder_idx] ||= $self->extruders->[$extruder_idx]->e_per_mm($spacing, $first_layer_height);
|
$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];
|
$extruded_length[$extruder_idx] += unscale $loop->length * $extruders_e_per_mm[$extruder_idx];
|
||||||
@ -648,7 +647,7 @@ sub make_brim {
|
|||||||
my @object_islands = (
|
my @object_islands = (
|
||||||
(map $_->contour, @{$layer0->slices}),
|
(map $_->contour, @{$layer0->slices}),
|
||||||
(map { $_->isa('Slic3r::Polygon') ? $_ : $_->grow($grow_distance) } map @{$_->thin_walls}, @{$layer0->regions}),
|
(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}) {
|
foreach my $copy (@{$self->objects->[$obj_idx]->copies}) {
|
||||||
push @islands, map $_->clone->translate(@$copy), @object_islands;
|
push @islands, map $_->clone->translate(@$copy), @object_islands;
|
||||||
@ -658,7 +657,7 @@ sub make_brim {
|
|||||||
# if brim touches skirt, make it around skirt too
|
# if brim touches skirt, make it around skirt too
|
||||||
# TODO: calculate actual skirt width (using each extruder's flow in multi-extruder setups)
|
# 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) {
|
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 = ();
|
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);
|
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(@$_),
|
polygon => Slic3r::Polygon->new(@$_),
|
||||||
role => EXTR_ROLE_SKIRT,
|
role => EXTR_ROLE_SKIRT,
|
||||||
flow_spacing => $flow->spacing,
|
flow_spacing => $flow->spacing,
|
||||||
|
@ -969,7 +969,6 @@ sub generate_support_material {
|
|||||||
my @paths = ();
|
my @paths = ();
|
||||||
foreach my $expolygon (@$expolygons) {
|
foreach my $expolygon (@$expolygons) {
|
||||||
push @paths,
|
push @paths,
|
||||||
map $_->pack,
|
|
||||||
map {
|
map {
|
||||||
$_->height($height);
|
$_->height($height);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ sub simplify {
|
|||||||
|
|
||||||
sub p {
|
sub p {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return @{$self->expolygon};
|
return @{$self->expolygon->pp};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_solid {
|
sub is_solid {
|
||||||
|
@ -16,7 +16,7 @@ use Slic3r;
|
|||||||
[5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0],
|
[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';
|
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],
|
[180.595,296.0487], [161.7854,297.4248], [156.8058,297.6214], [154.3395,317.8592],
|
||||||
];
|
];
|
||||||
my $polygon = Slic3r::Polygon->new(@$gear);
|
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);
|
note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@$polygon);
|
||||||
ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines';
|
ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines';
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ use Slic3r;
|
|||||||
];
|
];
|
||||||
|
|
||||||
my $polygon = Slic3r::Polygon->new(@$circle);
|
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);
|
note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@$polygon);
|
||||||
ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines';
|
ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines';
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||||||
is scalar @{$layerm->thin_fills} ? 1 : 0, $widths{$width}{gaps},
|
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
|
($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) {
|
if (@gaps) {
|
||||||
ok +(!first { abs($_->flow_spacing - $widths{$width}{gap_flow_spacing}) > epsilon } @gaps),
|
ok +(!first { abs($_->flow_spacing - $widths{$width}{gap_flow_spacing}) > epsilon } @gaps),
|
||||||
'flow spacing was dynamically adjusted';
|
'flow spacing was dynamically adjusted';
|
||||||
|
10
t/fill.t
10
t/fill.t
@ -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(
|
my $filler = Slic3r::Fill::Rectilinear->new(
|
||||||
bounding_box => $expolygon->bounding_box,
|
bounding_box => $expolygon->bounding_box,
|
||||||
);
|
);
|
||||||
@ -72,24 +72,24 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||||||
|
|
||||||
{
|
{
|
||||||
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [
|
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,15], [0,18], [0,20]),
|
||||||
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
||||||
]);
|
]);
|
||||||
is_deeply
|
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],
|
[20, 18, 15, 10, 8, 5],
|
||||||
'chained path';
|
'chained path';
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [
|
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([15,0], [10,0], [4,0]),
|
||||||
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
||||||
]);
|
]);
|
||||||
is_deeply
|
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],
|
[reverse 4, 10, 15, 10, 15, 20],
|
||||||
'chained path';
|
'chained path';
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ sub clone {
|
|||||||
my ($self, %args) = @_;
|
my ($self, %args) = @_;
|
||||||
|
|
||||||
return (ref $self)->_new(
|
return (ref $self)->_new(
|
||||||
$args{polygon} // $self->as_polygon,
|
$args{polygon} // $self->polygon,
|
||||||
$args{role} // $self->role,
|
$args{role} // $self->role,
|
||||||
$args{height} // $self->height,
|
$args{height} // $self->height,
|
||||||
$args{flow_spacing} // $self->flow_spacing,
|
$args{flow_spacing} // $self->flow_spacing,
|
||||||
@ -75,7 +75,7 @@ sub clone {
|
|||||||
my ($self, %args) = @_;
|
my ($self, %args) = @_;
|
||||||
|
|
||||||
return (ref $self)->_new(
|
return (ref $self)->_new(
|
||||||
$args{polyline} // $self->as_polyline,
|
$args{polyline} // $self->polyline,
|
||||||
$args{role} // $self->role,
|
$args{role} // $self->role,
|
||||||
$args{height} // $self->height,
|
$args{height} // $self->height,
|
||||||
$args{flow_spacing} // $self->flow_spacing,
|
$args{flow_spacing} // $self->flow_spacing,
|
||||||
|
@ -16,11 +16,11 @@ my $path = Slic3r::ExtrusionPath->new(
|
|||||||
polyline => Slic3r::Polyline->new(@$points),
|
polyline => Slic3r::Polyline->new(@$points),
|
||||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||||
);
|
);
|
||||||
isa_ok $path->as_polyline, 'Slic3r::Polyline', 'path polyline';
|
isa_ok $path->polyline, 'Slic3r::Polyline', 'path polyline';
|
||||||
is_deeply $path->as_polyline->pp, $points, 'path points roundtrip';
|
is_deeply $path->polyline->pp, $points, 'path points roundtrip';
|
||||||
|
|
||||||
$path->reverse;
|
$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 ]);
|
$path->append([ 150, 150 ]);
|
||||||
is scalar(@$path), 4, 'append to path';
|
is scalar(@$path), 4, 'append to path';
|
||||||
|
@ -17,8 +17,8 @@ my $loop = Slic3r::ExtrusionLoop->new(
|
|||||||
polygon => Slic3r::Polygon->new(@$square),
|
polygon => Slic3r::Polygon->new(@$square),
|
||||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||||
);
|
);
|
||||||
isa_ok $loop->as_polygon, 'Slic3r::Polygon', 'loop polygon';
|
isa_ok $loop->polygon, 'Slic3r::Polygon', 'loop polygon';
|
||||||
is_deeply $loop->as_polygon->pp, $square, 'polygon points roundtrip';
|
is_deeply $loop->polygon->pp, $square, 'polygon points roundtrip';
|
||||||
|
|
||||||
$loop = $loop->clone;
|
$loop = $loop->clone;
|
||||||
|
|
||||||
@ -28,10 +28,10 @@ is $loop->role, Slic3r::ExtrusionPath::EXTR_ROLE_FILL, 'modify role';
|
|||||||
|
|
||||||
{
|
{
|
||||||
my $path = $loop->split_at_first_point;
|
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 $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__
|
__END__
|
||||||
|
@ -11,10 +11,6 @@
|
|||||||
%code{% RETVAL = THIS->polygon.to_SV(); %};
|
%code{% RETVAL = THIS->polygon.to_SV(); %};
|
||||||
SV* pp()
|
SV* pp()
|
||||||
%code{% RETVAL = THIS->polygon.to_SV_pureperl(); %};
|
%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)
|
ExtrusionPath* split_at_index(int index)
|
||||||
%code{% const char* CLASS = "Slic3r::ExtrusionPath"; RETVAL = THIS->split_at_index(index); %};
|
%code{% const char* CLASS = "Slic3r::ExtrusionPath"; RETVAL = THIS->split_at_index(index); %};
|
||||||
ExtrusionPath* split_at_first_point()
|
ExtrusionPath* split_at_first_point()
|
||||||
@ -37,6 +33,18 @@ _new(CLASS, polygon_sv, role, height, flow_spacing)
|
|||||||
OUTPUT:
|
OUTPUT:
|
||||||
RETVAL
|
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
|
ExtrusionRole
|
||||||
ExtrusionLoop::role(...)
|
ExtrusionLoop::role(...)
|
||||||
CODE:
|
CODE:
|
||||||
|
@ -11,10 +11,6 @@
|
|||||||
%code{% RETVAL = THIS->polyline.to_SV(); %};
|
%code{% RETVAL = THIS->polyline.to_SV(); %};
|
||||||
SV* pp()
|
SV* pp()
|
||||||
%code{% RETVAL = THIS->polyline.to_SV_pureperl(); %};
|
%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()
|
void pop_back()
|
||||||
%code{% THIS->polyline.points.pop_back(); %};
|
%code{% THIS->polyline.points.pop_back(); %};
|
||||||
void reverse();
|
void reverse();
|
||||||
@ -36,6 +32,18 @@ _new(CLASS, polyline_sv, role, height, flow_spacing)
|
|||||||
OUTPUT:
|
OUTPUT:
|
||||||
RETVAL
|
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
|
ExtrusionRole
|
||||||
ExtrusionPath::role(...)
|
ExtrusionPath::role(...)
|
||||||
CODE:
|
CODE:
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
%code{% RETVAL = THIS->to_SV(); %};
|
%code{% RETVAL = THIS->to_SV(); %};
|
||||||
SV* pp()
|
SV* pp()
|
||||||
%code{% RETVAL = THIS->to_SV_pureperl(); %};
|
%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();
|
void reverse();
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
@ -34,5 +34,14 @@ Polygon::new(...)
|
|||||||
OUTPUT:
|
OUTPUT:
|
||||||
RETVAL
|
RETVAL
|
||||||
|
|
||||||
|
void
|
||||||
|
Polygon::rotate(angle, center_sv)
|
||||||
|
double angle;
|
||||||
|
SV* center_sv;
|
||||||
|
CODE:
|
||||||
|
Point center;
|
||||||
|
center.from_SV_check(center_sv);
|
||||||
|
THIS->rotate(angle, ¢er);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
%code{% RETVAL = THIS->to_SV(); %};
|
%code{% RETVAL = THIS->to_SV(); %};
|
||||||
SV* pp()
|
SV* pp()
|
||||||
%code{% RETVAL = THIS->to_SV_pureperl(); %};
|
%code{% RETVAL = THIS->to_SV_pureperl(); %};
|
||||||
|
void scale(double factor);
|
||||||
|
void translate(double x, double y);
|
||||||
void pop_back()
|
void pop_back()
|
||||||
%code{% THIS->points.pop_back(); %};
|
%code{% THIS->points.pop_back(); %};
|
||||||
void reverse();
|
void reverse();
|
||||||
@ -40,5 +42,14 @@ Polyline::append(...)
|
|||||||
THIS->points.push_back(p);
|
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, ¢er);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user