mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-07 05:54:03 -06:00
Ported ExtrusionPath to XS. Failing test for Surface
This commit is contained in:
parent
8c1e1cc3ea
commit
f612d4c64e
24 changed files with 501 additions and 143 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue