Ported ExtrusionPath to XS. Failing test for Surface

This commit is contained in:
Alessandro Ranellucci 2013-07-15 12:14:22 +02:00
parent 8c1e1cc3ea
commit f612d4c64e
24 changed files with 501 additions and 143 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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"),

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -163,4 +163,7 @@ sub concave_points {
-1 .. ($#$self-1);
}
package Slic3r::Polygon::XS;
use parent -norequire, qw(Slic3r::Polygon Slic3r::Polyline::XS);
1;

View file

@ -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;

View file

@ -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);
}
}
}