Ported ExtrusionPath to XS. Failing test for Surface
This commit is contained in:
parent
8c1e1cc3ea
commit
f612d4c64e
@ -298,7 +298,7 @@ sub medial_axis {
|
||||
}
|
||||
|
||||
package Slic3r::ExPolygon::XS;
|
||||
use base 'Slic3r::ExPolygon';
|
||||
use parent 'Slic3r::ExPolygon';
|
||||
|
||||
package Slic3r::ExPolygon::Collection;
|
||||
use Slic3r::Geometry qw(X1 Y1);
|
||||
|
@ -1,8 +1,10 @@
|
||||
package Slic3r::ExtrusionPath;
|
||||
use Moo;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent -norequire, qw(Slic3r::Polyline::XS);
|
||||
use parent qw(Exporter);
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT_OK = qw(EXTR_ROLE_PERIMETER EXTR_ROLE_EXTERNAL_PERIMETER
|
||||
EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER EXTR_ROLE_OVERHANG_PERIMETER
|
||||
EXTR_ROLE_FILL EXTR_ROLE_SOLIDFILL EXTR_ROLE_TOPSOLIDFILL EXTR_ROLE_BRIDGE
|
||||
@ -10,67 +12,22 @@ 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);
|
||||
|
||||
# the underlying Slic3r::Polyline objects holds the geometry
|
||||
has 'polyline' => (
|
||||
is => 'rw',
|
||||
required => 1,
|
||||
handles => [qw(merge_continuous_lines lines length reverse clip_end)],
|
||||
);
|
||||
|
||||
# height is the vertical thickness of the extrusion expressed in mm
|
||||
has 'height' => (is => 'rw');
|
||||
has 'flow_spacing' => (is => 'rw', required => 1);
|
||||
has 'role' => (is => 'rw', required => 1);
|
||||
|
||||
use constant EXTR_ROLE_PERIMETER => 0;
|
||||
use constant EXTR_ROLE_EXTERNAL_PERIMETER => 1;
|
||||
use constant EXTR_ROLE_OVERHANG_PERIMETER => 2;
|
||||
use constant EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER => 3;
|
||||
use constant EXTR_ROLE_FILL => 4;
|
||||
use constant EXTR_ROLE_SOLIDFILL => 5;
|
||||
use constant EXTR_ROLE_TOPSOLIDFILL => 6;
|
||||
use constant EXTR_ROLE_BRIDGE => 7;
|
||||
use constant EXTR_ROLE_INTERNALBRIDGE => 8;
|
||||
use constant EXTR_ROLE_SKIRT => 9;
|
||||
use constant EXTR_ROLE_SUPPORTMATERIAL => 10;
|
||||
use constant EXTR_ROLE_GAPFILL => 11;
|
||||
|
||||
use constant PACK_FMT => 'ffca*';
|
||||
sub polyline { $_[0] }
|
||||
|
||||
# class or object method
|
||||
sub pack {
|
||||
my $self = shift;
|
||||
my %args = @_;
|
||||
|
||||
if (ref $self) {
|
||||
%args = map { $_ => $self->$_ } qw(height flow_spacing role polyline);
|
||||
return $self;
|
||||
} else {
|
||||
return $self->new(@_);
|
||||
}
|
||||
|
||||
my $o = \ pack PACK_FMT,
|
||||
$args{height} // -1,
|
||||
$args{flow_spacing} || -1,
|
||||
$args{role} // (die "Missing mandatory attribute 'role'"), #/
|
||||
$args{polyline}->serialize;
|
||||
|
||||
bless $o, 'Slic3r::ExtrusionPath::Packed';
|
||||
return $o;
|
||||
}
|
||||
|
||||
# no-op, this allows to use both packed and non-packed objects in Collections
|
||||
sub unpack { $_[0] }
|
||||
|
||||
sub clone {
|
||||
my $self = shift;
|
||||
my %p = @_;
|
||||
|
||||
$p{polyline} ||= $self->polyline->clone;
|
||||
return (ref $self)->new(
|
||||
(map { $_ => $self->$_ } qw(polyline height flow_spacing role)),
|
||||
%p,
|
||||
);
|
||||
}
|
||||
|
||||
sub clip_with_polygon {
|
||||
my $self = shift;
|
||||
my ($polygon) = @_;
|
||||
@ -91,7 +48,7 @@ sub intersect_expolygons {
|
||||
my ($expolygons) = @_;
|
||||
|
||||
return map $self->clone(polyline => Slic3r::Polyline->new(@$_)),
|
||||
@{Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection($expolygons, [$self->polyline])};
|
||||
@{Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection($expolygons, [$self->arrayref])};
|
||||
}
|
||||
|
||||
sub subtract_expolygons {
|
||||
@ -99,12 +56,12 @@ sub subtract_expolygons {
|
||||
my ($expolygons) = @_;
|
||||
|
||||
return map $self->clone(polyline => Slic3r::Polyline->new(@$_)),
|
||||
@{Boost::Geometry::Utils::multi_linestring_multi_polygon_difference([$self->polyline], $expolygons)};
|
||||
@{Boost::Geometry::Utils::multi_linestring_multi_polygon_difference([$self->arrayref], $expolygons)};
|
||||
}
|
||||
|
||||
sub simplify {
|
||||
my $self = shift;
|
||||
$self->polyline($self->polyline->simplify(@_));
|
||||
$self->set_polyline($self->as_polyline->simplify(@_));
|
||||
}
|
||||
|
||||
sub points {
|
||||
@ -285,19 +242,4 @@ sub detect_arcs {
|
||||
return @paths;
|
||||
}
|
||||
|
||||
package Slic3r::ExtrusionPath::Packed;
|
||||
sub unpack {
|
||||
my $self = shift;
|
||||
|
||||
my ($height, $flow_spacing, $role, $polyline_s)
|
||||
= unpack Slic3r::ExtrusionPath::PACK_FMT, $$self;
|
||||
|
||||
return Slic3r::ExtrusionPath->new(
|
||||
height => ($height == -1) ? undef : $height,
|
||||
flow_spacing => ($flow_spacing == -1) ? undef : $flow_spacing,
|
||||
role => $role,
|
||||
polyline => Slic3r::Polyline->deserialize($polyline_s),
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -185,7 +185,7 @@ sub make_fill {
|
||||
: $is_bridge
|
||||
? EXTR_ROLE_BRIDGE
|
||||
: $is_solid
|
||||
? ($surface->surface_type == S_TYPE_TOP ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL)
|
||||
? (($surface->surface_type == S_TYPE_TOP) ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL)
|
||||
: EXTR_ROLE_FILL),
|
||||
height => $surface->thickness,
|
||||
flow_spacing => $params->{flow_spacing} || (warn "Warning: no flow_spacing was returned by the infill engine, please report this to the developer\n"),
|
||||
|
@ -27,7 +27,7 @@ sub infill_direction {
|
||||
}
|
||||
|
||||
# use bridge angle
|
||||
if (defined $surface->bridge_angle) {
|
||||
if ($surface->bridge_angle != -1) {
|
||||
Slic3r::debugf "Filling bridge with angle %d\n", $surface->bridge_angle;
|
||||
$rotate[0] = Slic3r::Geometry::deg2rad($surface->bridge_angle);
|
||||
}
|
||||
|
@ -256,7 +256,6 @@ sub extrude_path {
|
||||
my $self = shift;
|
||||
my ($path, $description, %params) = @_;
|
||||
|
||||
$path = $path->unpack if $path->isa('Slic3r::ExtrusionPath::Packed');
|
||||
$path->simplify(&Slic3r::SCALED_RESOLUTION);
|
||||
|
||||
# detect arcs
|
||||
@ -293,7 +292,7 @@ sub extrude_path {
|
||||
$area = ($s**2) * PI/4;
|
||||
} else {
|
||||
my $s = $path->flow_spacing;
|
||||
my $h = $path->height // $self->layer->height;
|
||||
my $h = (defined $path->height && $path->height != -1) ? $path->height : $self->layer->height;
|
||||
$area = $self->extruder->mm3_per_mm($s, $h);
|
||||
}
|
||||
|
||||
|
@ -228,8 +228,9 @@ sub point_is_on_left_of_segment {
|
||||
}
|
||||
|
||||
sub polyline_lines {
|
||||
my ($polygon) = @_;
|
||||
return map Slic3r::Line->new($polygon->[$_], $polygon->[$_+1]), 0 .. $#$polygon-1;
|
||||
my ($polyline) = @_;
|
||||
my @points = @$polyline;
|
||||
return map Slic3r::Line->new(@points[$_, $_+1]), 0 .. $#points-1;
|
||||
}
|
||||
|
||||
sub polygon_lines {
|
||||
|
@ -352,7 +352,7 @@ sub _fill_gaps {
|
||||
|
||||
foreach my $expolygon (@infill) {
|
||||
my @paths = $filler->fill_surface(
|
||||
Slic3r::Surface->new(expolygon => $expolygon),
|
||||
Slic3r::Surface->new(expolygon => $expolygon, surface_type => S_TYPE_INTERNALSOLID),
|
||||
density => 1,
|
||||
flow_spacing => $flow->spacing,
|
||||
);
|
||||
@ -573,7 +573,7 @@ sub _detect_bridges {
|
||||
Slic3r::debugf " Optimal infill angle of bridge on layer %d is %d degrees\n",
|
||||
$self->id, $bridge_angle if defined $bridge_angle;
|
||||
|
||||
$surface->bridge_angle($bridge_angle);
|
||||
$surface->bridge_angle($bridge_angle // -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,4 +163,7 @@ sub concave_points {
|
||||
-1 .. ($#$self-1);
|
||||
}
|
||||
|
||||
package Slic3r::Polygon::XS;
|
||||
use parent -norequire, qw(Slic3r::Polygon Slic3r::Polyline::XS);
|
||||
|
||||
1;
|
@ -22,6 +22,9 @@ sub clone {
|
||||
Storable::dclone($_[0])
|
||||
}
|
||||
|
||||
# compability with ::XS
|
||||
sub arrayref { $_[0] }
|
||||
|
||||
sub serialize {
|
||||
my $self = shift;
|
||||
return pack 'l*', map @$_, @$self;
|
||||
@ -59,7 +62,7 @@ sub simplify {
|
||||
my $self = shift;
|
||||
my $tolerance = shift || 10;
|
||||
|
||||
my $simplified = Boost::Geometry::Utils::linestring_simplify($self, $tolerance);
|
||||
my $simplified = Boost::Geometry::Utils::linestring_simplify($self->arrayref, $tolerance);
|
||||
return (ref $self)->new(@$simplified);
|
||||
}
|
||||
|
||||
@ -70,7 +73,7 @@ sub reverse {
|
||||
|
||||
sub length {
|
||||
my $self = shift;
|
||||
return Boost::Geometry::Utils::linestring_length($self);
|
||||
return Boost::Geometry::Utils::linestring_length($self->arrayref);
|
||||
}
|
||||
|
||||
sub grow {
|
||||
@ -161,14 +164,25 @@ sub scale {
|
||||
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;
|
||||
my ($distance) = @_;
|
||||
|
||||
while ($distance > 0) {
|
||||
my $last_point = pop @$self;
|
||||
last if !@$self;
|
||||
my $last_point = $self->[-1];
|
||||
$self->pop_back;
|
||||
last if @$self == 0;
|
||||
|
||||
my $last_segment_length = $last_point->distance_to($self->[-1]);
|
||||
if ($last_segment_length <= $distance) {
|
||||
@ -177,7 +191,7 @@ sub clip_end {
|
||||
}
|
||||
|
||||
my $new_point = Slic3r::Geometry::point_along_segment($last_point, $self->[-1], $distance);
|
||||
push @$self, Slic3r::Point->new($new_point);
|
||||
$self->append(Slic3r::Point->new($new_point));
|
||||
$distance = 0;
|
||||
}
|
||||
}
|
||||
@ -244,4 +258,7 @@ sub chained_path {
|
||||
return map $items_map{"$_"}, @paths;
|
||||
}
|
||||
|
||||
package Slic3r::Polyline::XS;
|
||||
use parent qw(Slic3r::Polyline);
|
||||
|
||||
1;
|
||||
|
@ -589,14 +589,14 @@ sub discover_horizontal_shells {
|
||||
# and the latter contains the enlarged external surfaces
|
||||
my $solid = [ map $_->expolygon, grep $_->surface_type == $type, @{$layerm->slices}, @{$layerm->fill_surfaces} ];
|
||||
next if !@$solid;
|
||||
Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP ? 'top' : 'bottom');
|
||||
Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
||||
|
||||
my $solid_layers = ($type == S_TYPE_TOP)
|
||||
? $Slic3r::Config->top_solid_layers
|
||||
: $Slic3r::Config->bottom_solid_layers;
|
||||
for (my $n = $type == S_TYPE_TOP ? $i-1 : $i+1;
|
||||
for (my $n = ($type == S_TYPE_TOP) ? $i-1 : $i+1;
|
||||
abs($n - $i) <= $solid_layers-1;
|
||||
$type == S_TYPE_TOP ? $n-- : $n++) {
|
||||
($type == S_TYPE_TOP) ? $n-- : $n++) {
|
||||
|
||||
next if $n < 0 || $n >= $self->layer_count;
|
||||
Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
|
||||
@ -607,7 +607,7 @@ sub discover_horizontal_shells {
|
||||
# intersections have contours and holes
|
||||
my $new_internal_solid = intersection_ex(
|
||||
[ map @$_, @$solid ],
|
||||
[ map $_->p, grep { $_->surface_type == S_TYPE_INTERNAL || $_->surface_type == S_TYPE_INTERNALSOLID } @neighbor_fill_surfaces ],
|
||||
[ map $_->p, grep { ($_->surface_type == S_TYPE_INTERNAL) || ($_->surface_type == S_TYPE_INTERNALSOLID) } @neighbor_fill_surfaces ],
|
||||
undef, 1,
|
||||
);
|
||||
next if !@$new_internal_solid;
|
||||
@ -658,25 +658,22 @@ sub discover_horizontal_shells {
|
||||
|
||||
# assign resulting internal surfaces to layer
|
||||
my $neighbor_fill_surfaces = $self->layers->[$n]->regions->[$region_id]->fill_surfaces;
|
||||
@$neighbor_fill_surfaces = ();
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => S_TYPE_INTERNAL)
|
||||
for @$internal;
|
||||
$neighbor_fill_surfaces->clear;
|
||||
$neighbor_fill_surfaces->append(map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => S_TYPE_INTERNAL), @$internal);
|
||||
|
||||
# assign new internal-solid surfaces to layer
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => S_TYPE_INTERNALSOLID)
|
||||
for @$internal_solid;
|
||||
$neighbor_fill_surfaces->append(map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => S_TYPE_INTERNALSOLID), @$internal_solid);
|
||||
|
||||
# assign top and bottom surfaces to layer
|
||||
foreach my $s (Slic3r::Surface->group(grep { $_->surface_type == S_TYPE_TOP || $_->surface_type == S_TYPE_BOTTOM } @neighbor_fill_surfaces)) {
|
||||
foreach my $s (Slic3r::Surface->group(grep { ($_->surface_type == S_TYPE_TOP) || ($_->surface_type == S_TYPE_BOTTOM) } @neighbor_fill_surfaces)) {
|
||||
my $solid_surfaces = diff_ex(
|
||||
[ map $_->p, @$s ],
|
||||
[ map @$_, @$internal_solid, @$internal ],
|
||||
1,
|
||||
);
|
||||
push @$neighbor_fill_surfaces, $s->[0]->clone(expolygon => $_)
|
||||
for @$solid_surfaces;
|
||||
$neighbor_fill_surfaces->append(map $s->[0]->clone(expolygon => $_), @$solid_surfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
t/fill.t
2
t/fill.t
@ -33,7 +33,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
||||
}
|
||||
|
||||
{
|
||||
my $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]);
|
||||
my $expolygon = Slic3r::ExPolygon::XS->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]);
|
||||
my $filler = Slic3r::Fill::Rectilinear->new(
|
||||
bounding_box => $expolygon->bounding_box,
|
||||
);
|
||||
|
30
t/freeze.t
30
t/freeze.t
@ -1,30 +0,0 @@
|
||||
use Test::More tests => 1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
}
|
||||
|
||||
use Slic3r;
|
||||
use Slic3r::Test;
|
||||
use Storable qw(nstore retrieve);
|
||||
use Time::HiRes qw(gettimeofday tv_interval);
|
||||
|
||||
{
|
||||
my $t0 = [gettimeofday];
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', scale => 2);
|
||||
my $gcode = Slic3r::Test::gcode($print);
|
||||
###diag sprintf 'Slicing took %s seconds', tv_interval($t0);
|
||||
|
||||
my $t1 = [gettimeofday];
|
||||
nstore $print, 'print.dat';
|
||||
$print = retrieve 'print.dat';
|
||||
unlink 'print.dat';
|
||||
###diag sprintf 'Freezing and retrieving took %s seconds', tv_interval($t1);
|
||||
|
||||
isa_ok $print, 'Slic3r::Print', 'restored Print object';
|
||||
}
|
||||
|
||||
__END__
|
26
t/shells.t
26
t/shells.t
@ -1,4 +1,4 @@
|
||||
use Test::More tests => 3;
|
||||
use Test::More tests => 4;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
@ -15,6 +15,10 @@ use Slic3r::Test;
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('skirts', 0);
|
||||
$config->set('perimeters', 0);
|
||||
$config->set('solid_infill_speed', 99);
|
||||
$config->set('top_solid_infill_speed', 99);
|
||||
$config->set('first_layer_speed', '100%');
|
||||
$config->set('cooling', 0);
|
||||
|
||||
my $test = sub {
|
||||
my ($conf) = @_;
|
||||
@ -28,20 +32,31 @@ use Slic3r::Test;
|
||||
|
||||
if ($self->Z > 0) {
|
||||
$layers_with_shells{$self->Z} //= 0;
|
||||
$layers_with_shells{$self->Z} = 1 if $info->{extruding} && $info->{dist_XY} > 0;
|
||||
$layers_with_shells{$self->Z} = 1
|
||||
if $info->{extruding}
|
||||
&& $info->{dist_XY} > 0
|
||||
&& ($args->{F} // $self->F) == $config->solid_infill_speed*60;
|
||||
}
|
||||
});
|
||||
my @shells = @layers_with_shells{sort { $a <=> $b } keys %layers_with_shells};
|
||||
fail "wrong number of bottom solid layers"
|
||||
fail "insufficient number of bottom solid layers"
|
||||
unless !defined(first { !$_ } @shells[0..$config->bottom_solid_layers-1]);
|
||||
fail "wrong number of top solid layers"
|
||||
fail "excessive number of bottom solid layers"
|
||||
unless scalar(grep $_, @shells[0 .. $#shells/2]) != $config->bottom_solid_layers;
|
||||
fail "insufficient number of top solid layers"
|
||||
unless !defined(first { !$_ } @shells[-$config->top_solid_layers..-1]);
|
||||
fail "excessive number of top solid layers"
|
||||
unless scalar(grep $_, @shells[($#shells/2)..$#shells]) != $config->top_solid_layers;
|
||||
1;
|
||||
};
|
||||
|
||||
ok $test->(), "proper number of shells is applied";
|
||||
$config->set('fill_density', 0);
|
||||
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
ok $test->(), "no shells are applied when both top and bottom are set to zero";
|
||||
|
||||
$config->set('fill_density', 0);
|
||||
ok $test->(), "proper number of shells is applied even when fill density is none";
|
||||
}
|
||||
|
||||
@ -55,6 +70,7 @@ use Slic3r::Test;
|
||||
$config->set('cooling', 0);
|
||||
$config->set('solid_infill_speed', 99);
|
||||
$config->set('top_solid_infill_speed', 99);
|
||||
$config->set('first_layer_speed', '100%');
|
||||
|
||||
my $print = Slic3r::Test::init_print('V', config => $config);
|
||||
my %layers_with_solid_infill = (); # Z => 1
|
||||
|
@ -15,10 +15,78 @@ package Slic3r::ExPolygon::XS;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref };
|
||||
|
||||
package Slic3r::Polyline::XS;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref },
|
||||
'fallback' => 1;
|
||||
|
||||
package Slic3r::Polygon::XS;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref };
|
||||
|
||||
package Slic3r::ExPolygon::Collection;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref };
|
||||
|
||||
package Slic3r::ExtrusionLoop;
|
||||
|
||||
sub new {
|
||||
my ($class, %args) = @_;
|
||||
|
||||
my $polygon = ref($args{polygon}) eq 'Slic3r::Polygon::XS'
|
||||
? $args{polygon}
|
||||
: Slic3r::Polygon::XS->new(@{$args{polygon}});
|
||||
|
||||
return $class->_new(
|
||||
$polygon, # required
|
||||
$args{role}, # required
|
||||
$args{height} // -1,
|
||||
$args{flow_spacing} // -1,
|
||||
);
|
||||
}
|
||||
|
||||
sub clone {
|
||||
my ($self, %args) = @_;
|
||||
|
||||
return (ref $self)->_new(
|
||||
$args{polygon} // $self->polygon->clone,
|
||||
$args{role} // $self->role,
|
||||
$args{height} // $self->height,
|
||||
$args{flow_spacing} // $self->flow_spacing,
|
||||
);
|
||||
}
|
||||
|
||||
package Slic3r::ExtrusionPath;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref },
|
||||
'fallback' => 1;
|
||||
|
||||
sub new {
|
||||
my ($class, %args) = @_;
|
||||
|
||||
my $polyline = ref($args{polyline}) eq 'Slic3r::Polyline::XS'
|
||||
? $args{polyline}
|
||||
: Slic3r::Polyline::XS->new(@{$args{polyline}});
|
||||
|
||||
return $class->_new(
|
||||
$polyline, # required
|
||||
$args{role}, # required
|
||||
$args{height} // -1,
|
||||
$args{flow_spacing} // -1,
|
||||
);
|
||||
}
|
||||
|
||||
sub clone {
|
||||
my ($self, %args) = @_;
|
||||
|
||||
return (ref $self)->_new(
|
||||
$args{polyline} // $self->as_polyline,
|
||||
$args{role} // $self->role,
|
||||
$args{height} // $self->height,
|
||||
$args{flow_spacing} // $self->flow_spacing,
|
||||
);
|
||||
}
|
||||
|
||||
package Slic3r::Surface;
|
||||
|
||||
sub new {
|
||||
@ -29,12 +97,12 @@ sub new {
|
||||
if defined $args{bridge_angle} && $args{bridge_angle} < 0;
|
||||
|
||||
return $class->_new(
|
||||
delete $args{expolygon}, # required
|
||||
delete $args{surface_type}, # required
|
||||
delete $args{thickness} // -1,
|
||||
delete $args{thickness_layers} // 1,
|
||||
delete $args{bridge_angle} // -1,
|
||||
delete $args{extra_perimeters} // 0,
|
||||
$args{expolygon} // (die "Missing required expolygon\n"),
|
||||
$args{surface_type} // (die "Missing required surface_type\n"),
|
||||
$args{thickness} // -1,
|
||||
$args{thickness_layers} // 1,
|
||||
$args{bridge_angle} // -1,
|
||||
$args{extra_perimeters} // 0,
|
||||
);
|
||||
}
|
||||
|
||||
|
60
xs/src/ExtrusionEntity.hpp
Normal file
60
xs/src/ExtrusionEntity.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef slic3r_ExtrusionEntity_hpp_
|
||||
#define slic3r_ExtrusionEntity_hpp_
|
||||
|
||||
extern "C" {
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
#include "ppport.h"
|
||||
}
|
||||
|
||||
#include "Polygon.hpp"
|
||||
#include "Polyline.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum ExtrusionRole {
|
||||
erPerimeter,
|
||||
erExternalPerimeter,
|
||||
erOverhangPerimeter,
|
||||
erContourInternalPerimeter,
|
||||
erFill,
|
||||
erSolidFill,
|
||||
erTopSolidFill,
|
||||
erBrige,
|
||||
erInternalBridge,
|
||||
erSkirt,
|
||||
erSupportMaterial,
|
||||
erGapFill,
|
||||
};
|
||||
|
||||
class ExtrusionEntity
|
||||
{
|
||||
public:
|
||||
ExtrusionRole role;
|
||||
double height; // vertical thickness of the extrusion expressed in mm
|
||||
double flow_spacing;
|
||||
};
|
||||
|
||||
class ExtrusionPath : public ExtrusionEntity
|
||||
{
|
||||
public:
|
||||
Polyline polyline;
|
||||
void reverse();
|
||||
};
|
||||
|
||||
class ExtrusionLoop : public ExtrusionEntity
|
||||
{
|
||||
public:
|
||||
Polygon polygon;
|
||||
};
|
||||
|
||||
void
|
||||
ExtrusionPath::reverse()
|
||||
{
|
||||
this->polyline.reverse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "Point.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -19,6 +20,7 @@ class Polyline
|
||||
void scale(double factor);
|
||||
void translate(double x, double y);
|
||||
void rotate(double angle, Point* center);
|
||||
void reverse();
|
||||
};
|
||||
|
||||
typedef std::vector<Polyline> Polylines;
|
||||
@ -49,6 +51,12 @@ Polyline::rotate(double angle, Point* center)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Polyline::reverse()
|
||||
{
|
||||
std::reverse(this->points.begin(), this->points.end());
|
||||
}
|
||||
|
||||
void
|
||||
perl2polyline(SV* poly_sv, Polyline& poly)
|
||||
{
|
||||
|
@ -4,7 +4,7 @@ use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 10;
|
||||
use Test::More tests => 11;
|
||||
|
||||
my $square = [ # ccw
|
||||
[100, 100],
|
||||
@ -49,6 +49,10 @@ is $surface->extra_perimeters, 2, 'extra_perimeters';
|
||||
is scalar(@$collection), 0, 'clear collection';
|
||||
$collection->append($surface);
|
||||
is scalar(@$collection), 1, 'append to collection';
|
||||
|
||||
my $item = $collection->[0];
|
||||
$item->surface_type(Slic3r::Surface::S_TYPE_INTERNAL);
|
||||
is $item->surface_type, $collection->[0]->surface_type, 'changing item affects actual item';
|
||||
}
|
||||
|
||||
__END__
|
||||
|
22
xs/t/06_polygon.t
Normal file
22
xs/t/06_polygon.t
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 3;
|
||||
|
||||
my $square = [ # ccw
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
[100, 200],
|
||||
];
|
||||
|
||||
my $polygon = Slic3r::Polygon::XS->new(@$square);
|
||||
is_deeply [ @$polygon ], [ @$square ], 'polygon roundtrip';
|
||||
|
||||
isa_ok $polygon->arrayref, 'Slic3r::Polygon', 'Perl polygon is blessed';
|
||||
isa_ok $polygon->[0], 'Slic3r::Point', 'Perl points are blessed';
|
||||
|
||||
__END__
|
37
xs/t/07_extrusionpath.t
Normal file
37
xs/t/07_extrusionpath.t
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 7;
|
||||
|
||||
my $points = [
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
];
|
||||
|
||||
my $path = Slic3r::ExtrusionPath->new(
|
||||
polyline => Slic3r::Polyline::XS->new(@$points),
|
||||
role => Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||
);
|
||||
isa_ok $path->as_polyline, 'Slic3r::Polyline::XS', 'path polyline';
|
||||
is_deeply [ @{ $path->as_polyline } ], [ @$points ], 'path points roundtrip';
|
||||
|
||||
$path->reverse;
|
||||
is_deeply [ @{ $path->as_polyline } ], [ reverse @$points ], 'reverse path';
|
||||
|
||||
$path->append([ 150, 150 ]);
|
||||
is scalar(@{ $path }), 4, 'append to path';
|
||||
|
||||
$path->pop_back;
|
||||
is scalar(@{ $path }), 3, 'pop_back from path';
|
||||
|
||||
$path = $path->clone;
|
||||
|
||||
is $path->role, Slic3r::ExtrusionPath::EXTR_ROLE_EXTERNAL_PERIMETER, 'role';
|
||||
$path->role(Slic3r::ExtrusionPath::EXTR_ROLE_FILL);
|
||||
is $path->role, Slic3r::ExtrusionPath::EXTR_ROLE_FILL, 'modify role';
|
||||
|
||||
__END__
|
126
xs/xsp/ExtrusionPath.xsp
Normal file
126
xs/xsp/ExtrusionPath.xsp
Normal file
@ -0,0 +1,126 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <myinit.h>
|
||||
#include "ExtrusionEntity.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::ExtrusionPath} class ExtrusionPath {
|
||||
~ExtrusionPath();
|
||||
SV* arrayref()
|
||||
%code{% RETVAL = polyline2perl(THIS->polyline); %};
|
||||
void pop_back()
|
||||
%code{% THIS->polyline.points.pop_back(); %};
|
||||
void reverse();
|
||||
%{
|
||||
|
||||
ExtrusionPath*
|
||||
_new(CLASS, polyline_sv, role, height, flow_spacing)
|
||||
char* CLASS;
|
||||
SV* polyline_sv;
|
||||
ExtrusionRole role;
|
||||
double height;
|
||||
double flow_spacing;
|
||||
CODE:
|
||||
RETVAL = new ExtrusionPath ();
|
||||
if (sv_isobject(polyline_sv) && (SvTYPE(SvRV(polyline_sv)) == SVt_PVMG)) {
|
||||
RETVAL->polyline = *(Polyline*)SvIV((SV*)SvRV( polyline_sv ));
|
||||
} else {
|
||||
perl2polyline(polyline_sv, RETVAL->polyline);
|
||||
}
|
||||
RETVAL->role = role;
|
||||
RETVAL->height = height;
|
||||
RETVAL->flow_spacing = flow_spacing;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polyline*
|
||||
ExtrusionPath::as_polyline()
|
||||
PREINIT:
|
||||
const char* CLASS = "Slic3r::Polyline::XS";
|
||||
CODE:
|
||||
RETVAL = new Polyline(THIS->polyline);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
ExtrusionPath::set_polyline(polyline_sv)
|
||||
SV* polyline_sv;
|
||||
CODE:
|
||||
if (sv_isobject(polyline_sv) && (SvTYPE(SvRV(polyline_sv)) == SVt_PVMG)) {
|
||||
THIS->polyline = *(Polyline*)SvIV((SV*)SvRV( polyline_sv ));
|
||||
} else {
|
||||
perl2polyline(polyline_sv, THIS->polyline);
|
||||
}
|
||||
|
||||
ExtrusionRole
|
||||
ExtrusionPath::role(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->role = (ExtrusionRole)SvUV(ST(1));
|
||||
}
|
||||
RETVAL = THIS->role;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
double
|
||||
ExtrusionPath::height(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->height = (double)SvNV(ST(1));
|
||||
}
|
||||
RETVAL = THIS->height;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
double
|
||||
ExtrusionPath::flow_spacing(...)
|
||||
CODE:
|
||||
if (items > 1) {
|
||||
THIS->flow_spacing = (double)SvNV(ST(1));
|
||||
}
|
||||
RETVAL = THIS->flow_spacing;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
ExtrusionPath::append(...)
|
||||
CODE:
|
||||
for (unsigned int i = 1; i < items; i++) {
|
||||
Point p;
|
||||
if (sv_isobject(ST(i)) && (SvTYPE(SvRV(ST(i))) == SVt_PVMG)) {
|
||||
p = *(Point*)SvIV((SV*)SvRV( ST(i) ));
|
||||
} else {
|
||||
perl2point(ST(i), p);
|
||||
}
|
||||
THIS->polyline.points.push_back(p);
|
||||
}
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
%package{Slic3r::ExtrusionPath};
|
||||
%{
|
||||
|
||||
IV
|
||||
_constant()
|
||||
ALIAS:
|
||||
EXTR_ROLE_PERIMETER = erPerimeter
|
||||
EXTR_ROLE_EXTERNAL_PERIMETER = erExternalPerimeter
|
||||
EXTR_ROLE_OVERHANG_PERIMETER = erOverhangPerimeter
|
||||
EXTR_ROLE_CONTOUR_INTERNAL_PERIMETER = erContourInternalPerimeter
|
||||
EXTR_ROLE_FILL = erFill
|
||||
EXTR_ROLE_SOLIDFILL = erSolidFill
|
||||
EXTR_ROLE_TOPSOLIDFILL = erTopSolidFill
|
||||
EXTR_ROLE_BRIDGE = erBrige
|
||||
EXTR_ROLE_INTERNALBRIDGE = erInternalBridge
|
||||
EXTR_ROLE_SKIRT = erSkirt
|
||||
EXTR_ROLE_SUPPORTMATERIAL = erSupportMaterial
|
||||
EXTR_ROLE_GAPFILL = erGapFill
|
||||
PROTOTYPE:
|
||||
CODE:
|
||||
RETVAL = ix;
|
||||
OUTPUT: RETVAL
|
||||
|
||||
%}
|
||||
|
29
xs/xsp/Polygon.xsp
Normal file
29
xs/xsp/Polygon.xsp
Normal file
@ -0,0 +1,29 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <myinit.h>
|
||||
#include "Polygon.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::Polygon::XS} class Polygon {
|
||||
~Polygon();
|
||||
Polygon* clone()
|
||||
%code{% const char* CLASS = "Slic3r::Polygon::XS"; RETVAL = new Polygon(*THIS); %};
|
||||
SV* arrayref()
|
||||
%code{% RETVAL = polygon2perl(*THIS); %};
|
||||
%{
|
||||
|
||||
Polygon*
|
||||
Polygon::new(...)
|
||||
CODE:
|
||||
RETVAL = new Polygon ();
|
||||
// ST(0) is class name, ST(1) is first point
|
||||
RETVAL->points.resize(items-1);
|
||||
for (unsigned int i = 1; i < items; i++) {
|
||||
perl2point(ST(i), RETVAL->points[i-1]);
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
45
xs/xsp/Polyline.xsp
Normal file
45
xs/xsp/Polyline.xsp
Normal file
@ -0,0 +1,45 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <myinit.h>
|
||||
#include "Polyline.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::Polyline::XS} class Polyline {
|
||||
~Polyline();
|
||||
Polyline* clone()
|
||||
%code{% const char* CLASS = "Slic3r::Polyline::XS"; RETVAL = new Polyline(*THIS); %};
|
||||
SV* arrayref()
|
||||
%code{% RETVAL = polyline2perl(*THIS); %};
|
||||
void pop_back()
|
||||
%code{% THIS->points.pop_back(); %};
|
||||
void reverse();
|
||||
%{
|
||||
|
||||
Polyline*
|
||||
Polyline::new(...)
|
||||
CODE:
|
||||
RETVAL = new Polyline ();
|
||||
// ST(0) is class name, ST(1) is first point
|
||||
RETVAL->points.resize(items-1);
|
||||
for (unsigned int i = 1; i < items; i++) {
|
||||
perl2point(ST(i), RETVAL->points[i-1]);
|
||||
}
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
void
|
||||
Polyline::append(...)
|
||||
CODE:
|
||||
for (unsigned int i = 1; i < items; i++) {
|
||||
Point p;
|
||||
if (sv_isobject(ST(i)) && (SvTYPE(SvRV(ST(i))) == SVt_PVMG)) {
|
||||
p = *(Point*)SvIV((SV*)SvRV( ST(i) ));
|
||||
} else {
|
||||
perl2point(ST(i), p);
|
||||
}
|
||||
THIS->points.push_back(p);
|
||||
}
|
||||
|
||||
%}
|
||||
};
|
@ -1,8 +1,14 @@
|
||||
ZTable* O_OBJECT
|
||||
TriangleMesh* O_OBJECT
|
||||
Point* O_OBJECT
|
||||
Polyline* O_OBJECT
|
||||
Polygon* O_OBJECT
|
||||
ExPolygon* O_OBJECT
|
||||
ExPolygonCollection* O_OBJECT
|
||||
SurfaceType T_UV
|
||||
ExtrusionPath* O_OBJECT
|
||||
ExtrusionLoop* O_OBJECT
|
||||
Surface* O_OBJECT
|
||||
SurfaceCollection* O_OBJECT
|
||||
|
||||
ExtrusionRole T_UV
|
||||
SurfaceType T_UV
|
||||
|
@ -4,9 +4,17 @@
|
||||
%typemap{AV*};
|
||||
%typemap{Point*};
|
||||
%typemap{ExPolygon*};
|
||||
%typemap{Polyline*};
|
||||
%typemap{Polygon*};
|
||||
%typemap{SurfaceType}{parsed}{
|
||||
%cpp_type{SurfaceType};
|
||||
%precall_code{%
|
||||
$CVar = (SurfaceType)SvUV($PerlVar);
|
||||
%};
|
||||
};
|
||||
};
|
||||
%typemap{ExtrusionRole}{parsed}{
|
||||
%cpp_type{ExtrusionRole};
|
||||
%precall_code{%
|
||||
$CVar = (ExtrusionRole)SvUV($PerlVar);
|
||||
%};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user