Adopt XS containers everywhere (incomplete work)
This commit is contained in:
parent
339ba9e5c3
commit
9b582a11ff
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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 {
|
||||
|
@ -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 ],
|
||||
);
|
||||
|
@ -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) ];
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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(@$_),
|
||||
|
@ -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) = @_;
|
||||
|
@ -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;
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -969,7 +969,6 @@ sub generate_support_material {
|
||||
my @paths = ();
|
||||
foreach my $expolygon (@$expolygons) {
|
||||
push @paths,
|
||||
map $_->pack,
|
||||
map {
|
||||
$_->height($height);
|
||||
|
||||
|
@ -45,7 +45,7 @@ sub simplify {
|
||||
|
||||
sub p {
|
||||
my $self = shift;
|
||||
return @{$self->expolygon};
|
||||
return @{$self->expolygon->pp};
|
||||
}
|
||||
|
||||
sub is_solid {
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -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';
|
||||
|
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(
|
||||
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';
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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';
|
||||
|
@ -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__
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
%{
|
||||
|
||||
|
@ -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, ¢er);
|
||||
|
||||
%}
|
||||
};
|
||||
|
@ -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, ¢er);
|
||||
|
||||
%}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user