mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-19 12:47:50 -06:00
Very large refactoring. Ditched Slic3r::Polyline::Closed and reorganized geometric classes.
This commit is contained in:
parent
2def6a9787
commit
8ed91a8ec4
20 changed files with 293 additions and 349 deletions
1
MANIFEST
1
MANIFEST
|
@ -30,7 +30,6 @@ lib/Slic3r/Perimeter.pm
|
||||||
lib/Slic3r/Point.pm
|
lib/Slic3r/Point.pm
|
||||||
lib/Slic3r/Polygon.pm
|
lib/Slic3r/Polygon.pm
|
||||||
lib/Slic3r/Polyline.pm
|
lib/Slic3r/Polyline.pm
|
||||||
lib/Slic3r/Polyline/Closed.pm
|
|
||||||
lib/Slic3r/Print.pm
|
lib/Slic3r/Print.pm
|
||||||
lib/Slic3r/Skein.pm
|
lib/Slic3r/Skein.pm
|
||||||
lib/Slic3r/STL.pm
|
lib/Slic3r/STL.pm
|
||||||
|
|
|
@ -25,7 +25,6 @@ use Slic3r::Perimeter;
|
||||||
use Slic3r::Point;
|
use Slic3r::Point;
|
||||||
use Slic3r::Polygon;
|
use Slic3r::Polygon;
|
||||||
use Slic3r::Polyline;
|
use Slic3r::Polyline;
|
||||||
use Slic3r::Polyline::Closed;
|
|
||||||
use Slic3r::Print;
|
use Slic3r::Print;
|
||||||
use Slic3r::Skein;
|
use Slic3r::Skein;
|
||||||
use Slic3r::STL;
|
use Slic3r::STL;
|
||||||
|
|
|
@ -40,6 +40,11 @@ sub holes {
|
||||||
return @$self[1..$#$self];
|
return @$self[1..$#$self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub lines {
|
||||||
|
my $self = shift;
|
||||||
|
return map $_->lines, @$self;
|
||||||
|
}
|
||||||
|
|
||||||
sub clipper_expolygon {
|
sub clipper_expolygon {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return {
|
return {
|
||||||
|
@ -106,7 +111,7 @@ sub bounding_box {
|
||||||
sub clip_line {
|
sub clip_line {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($line) = @_;
|
my ($line) = @_;
|
||||||
$line = Slic3r::Line->cast($line);
|
$line = Slic3r::Line->new($line) if ref $line eq 'ARRAY';
|
||||||
|
|
||||||
my @intersections = grep $_, map $_->intersection($line, 1), map $_->lines, @$self;
|
my @intersections = grep $_, map $_->intersection($line, 1), map $_->lines, @$self;
|
||||||
my @dir = (
|
my @dir = (
|
||||||
|
@ -203,6 +208,8 @@ sub medial_axis {
|
||||||
}
|
}
|
||||||
return undef if !@skeleton_lines;
|
return undef if !@skeleton_lines;
|
||||||
|
|
||||||
|
return undef if !@skeleton_lines;
|
||||||
|
|
||||||
# now build a single polyline
|
# now build a single polyline
|
||||||
my $polyline = [];
|
my $polyline = [];
|
||||||
{
|
{
|
||||||
|
@ -248,7 +255,7 @@ sub medial_axis {
|
||||||
if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) {
|
if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) {
|
||||||
return Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]);
|
return Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]);
|
||||||
} else {
|
} else {
|
||||||
return Slic3r::Polyline->cast($polyline);
|
return Slic3r::Polyline->new($polyline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,21 @@ use Moo;
|
||||||
|
|
||||||
use XXX;
|
use XXX;
|
||||||
|
|
||||||
extends 'Slic3r::Polyline::Closed';
|
# the underlying Slic3r::Polygon objects holds the geometry
|
||||||
|
has 'polygon' => (
|
||||||
|
is => 'ro',
|
||||||
|
required => 1,
|
||||||
|
handles => [qw(is_printable nearest_point_to)],
|
||||||
|
);
|
||||||
|
|
||||||
# perimeter/fill/solid-fill/bridge/skirt
|
# perimeter/fill/solid-fill/bridge/skirt
|
||||||
has 'role' => (is => 'rw', required => 1);
|
has 'role' => (is => 'rw', required => 1);
|
||||||
|
|
||||||
|
sub BUILD {
|
||||||
|
my $self = shift;
|
||||||
|
bless $self->polygon, 'Slic3r::Polygon';
|
||||||
|
}
|
||||||
|
|
||||||
sub split_at {
|
sub split_at {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($point) = @_;
|
my ($point) = @_;
|
||||||
|
@ -16,8 +26,8 @@ sub split_at {
|
||||||
|
|
||||||
# find index of point
|
# find index of point
|
||||||
my $i = -1;
|
my $i = -1;
|
||||||
for (my $n = 0; $n <= $#{$self->points}; $n++) {
|
for (my $n = 0; $n <= $#{$self->polygon}; $n++) {ZZZ "here" if ref $self->polygon->[$n] eq 'ARRAY';
|
||||||
if ($point->id eq $self->points->[$n]->id) {
|
if ($point->id eq $self->polygon->[$n]->id) {
|
||||||
$i = $n;
|
$i = $n;
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
@ -25,10 +35,13 @@ sub split_at {
|
||||||
die "Point not found" if $i == -1;
|
die "Point not found" if $i == -1;
|
||||||
|
|
||||||
my @new_points = ();
|
my @new_points = ();
|
||||||
push @new_points, @{$self->points}[$i .. $#{$self->points}];
|
push @new_points, @{$self->polygon}[$i .. $#{$self->polygon}];
|
||||||
push @new_points, @{$self->points}[0 .. $i];
|
push @new_points, @{$self->polygon}[0 .. $i];
|
||||||
|
|
||||||
return Slic3r::ExtrusionPath->new(points => [@new_points], role => $self->role);
|
return Slic3r::ExtrusionPath->new(
|
||||||
|
polyline => Slic3r::Polyline->new(\@new_points),
|
||||||
|
role => $self->role,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
package Slic3r::ExtrusionPath;
|
package Slic3r::ExtrusionPath;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
extends 'Slic3r::Polyline';
|
use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points);
|
||||||
|
use XXX;
|
||||||
|
|
||||||
|
# the underlying Slic3r::Polyline objects holds the geometry
|
||||||
|
has 'polyline' => (
|
||||||
|
is => 'ro',
|
||||||
|
required => 1,
|
||||||
|
handles => [qw(merge_continuous_lines lines)],
|
||||||
|
);
|
||||||
|
|
||||||
# this integer represents the vertical thickness of the extrusion
|
# this integer represents the vertical thickness of the extrusion
|
||||||
# expressed in layers
|
# expressed in layers
|
||||||
|
@ -12,8 +20,10 @@ has 'flow_spacing' => (is => 'rw');
|
||||||
# perimeter/fill/solid-fill/bridge/skirt
|
# perimeter/fill/solid-fill/bridge/skirt
|
||||||
has 'role' => (is => 'rw', required => 1);
|
has 'role' => (is => 'rw', required => 1);
|
||||||
|
|
||||||
use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points);
|
sub BUILD {
|
||||||
use XXX;
|
my $self = shift;
|
||||||
|
bless $self->polyline, 'Slic3r::Polyline';
|
||||||
|
}
|
||||||
|
|
||||||
sub clip_end {
|
sub clip_end {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
@ -35,6 +45,11 @@ sub clip_end {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub points {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->polyline;
|
||||||
|
}
|
||||||
|
|
||||||
sub endpoints {
|
sub endpoints {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return ($self->points->[0], $self->points->[-1]);
|
return ($self->points->[0], $self->points->[-1]);
|
||||||
|
@ -68,8 +83,8 @@ sub split_at_acute_angles {
|
||||||
# if the angle between $p[-2], $p[-1], $p3 is too acute
|
# if the angle between $p[-2], $p[-1], $p3 is too acute
|
||||||
# then consider $p3 only as a starting point of a new
|
# then consider $p3 only as a starting point of a new
|
||||||
# path and stop the current one as it is
|
# path and stop the current one as it is
|
||||||
push @paths, (ref $self)->cast(
|
push @paths, (ref $self)->new(
|
||||||
[@p],
|
polyline => Slic3r::Polyline->new(\@p),
|
||||||
role => $self->role,
|
role => $self->role,
|
||||||
depth_layers => $self->depth_layers,
|
depth_layers => $self->depth_layers,
|
||||||
);
|
);
|
||||||
|
@ -79,8 +94,8 @@ sub split_at_acute_angles {
|
||||||
push @p, $p3;
|
push @p, $p3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
push @paths, (ref $self)->cast(
|
push @paths, (ref $self)->new(
|
||||||
[@p],
|
polyline => Slic3r::Polyline->new(\@p),
|
||||||
role => $self->role,
|
role => $self->role,
|
||||||
depth_layers => $self->depth_layers,
|
depth_layers => $self->depth_layers,
|
||||||
) if @p > 1;
|
) if @p > 1;
|
||||||
|
@ -168,7 +183,7 @@ sub detect_arcs {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $arc = Slic3r::ExtrusionPath::Arc->new(
|
my $arc = Slic3r::ExtrusionPath::Arc->new(
|
||||||
points => [@arc_points],
|
polyline => Slic3r::Polyline->new(\@arc_points),
|
||||||
role => $self->role,
|
role => $self->role,
|
||||||
orientation => $orientation,
|
orientation => $orientation,
|
||||||
center => $arc_center,
|
center => $arc_center,
|
||||||
|
@ -177,7 +192,7 @@ sub detect_arcs {
|
||||||
|
|
||||||
# points 0..$i form a linear path
|
# points 0..$i form a linear path
|
||||||
push @paths, (ref $self)->new(
|
push @paths, (ref $self)->new(
|
||||||
points => [ @points[0..$i] ],
|
polyline => Slic3r::Polyline->new(@points[0..$i]),
|
||||||
role => $self->role,
|
role => $self->role,
|
||||||
depth_layers => $self->depth_layers,
|
depth_layers => $self->depth_layers,
|
||||||
) if $i > 0;
|
) if $i > 0;
|
||||||
|
@ -196,7 +211,7 @@ sub detect_arcs {
|
||||||
|
|
||||||
# remaining points form a linear path
|
# remaining points form a linear path
|
||||||
push @paths, (ref $self)->new(
|
push @paths, (ref $self)->new(
|
||||||
points => [@points],
|
polyline => Slic3r::Polyline->new(\@points),
|
||||||
role => $self->role,
|
role => $self->role,
|
||||||
depth_layers => $self->depth_layers,
|
depth_layers => $self->depth_layers,
|
||||||
) if @points > 1;
|
) if @points > 1;
|
||||||
|
|
|
@ -71,7 +71,8 @@ sub make_fill {
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
push @surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
push @surfaces, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $group->[0]->surface_type,
|
surface_type => $group->[0]->surface_type,
|
||||||
bridge_angle => $group->[0]->bridge_angle,
|
bridge_angle => $group->[0]->bridge_angle,
|
||||||
depth_layers => $group->[0]->depth_layers,
|
depth_layers => $group->[0]->depth_layers,
|
||||||
|
@ -100,7 +101,8 @@ sub make_fill {
|
||||||
[ @offsets ],
|
[ @offsets ],
|
||||||
);
|
);
|
||||||
|
|
||||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
push @new_surfaces, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $surface->surface_type,
|
surface_type => $surface->surface_type,
|
||||||
bridge_angle => $surface->bridge_angle,
|
bridge_angle => $surface->bridge_angle,
|
||||||
depth_layers => $surface->depth_layers,
|
depth_layers => $surface->depth_layers,
|
||||||
|
@ -111,7 +113,7 @@ sub make_fill {
|
||||||
|
|
||||||
# organize infill surfaces using a shortest path search
|
# organize infill surfaces using a shortest path search
|
||||||
@surfaces = @{shortest_path([
|
@surfaces = @{shortest_path([
|
||||||
map [ $_->contour->points->[0], $_ ], @surfaces,
|
map [ $_->contour->[0], $_ ], @surfaces,
|
||||||
])};
|
])};
|
||||||
|
|
||||||
SURFACE: foreach my $surface (@surfaces) {
|
SURFACE: foreach my $surface (@surfaces) {
|
||||||
|
@ -145,15 +147,14 @@ sub make_fill {
|
||||||
# save into layer
|
# save into layer
|
||||||
push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new(
|
push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new(
|
||||||
paths => [
|
paths => [
|
||||||
map Slic3r::ExtrusionPath->cast(
|
map Slic3r::ExtrusionPath->new(
|
||||||
[ @$_ ],
|
polyline => Slic3r::Polyline->new(@$_),
|
||||||
role => ($is_bridge ? 'bridge' : $is_solid ? 'solid-fill' : 'fill'),
|
role => ($is_bridge ? 'bridge' : $is_solid ? 'solid-fill' : 'fill'),
|
||||||
depth_layers => $surface->depth_layers,
|
depth_layers => $surface->depth_layers,
|
||||||
flow_spacing => $params->{flow_spacing},
|
flow_spacing => $params->{flow_spacing},
|
||||||
), @paths,
|
), @paths,
|
||||||
],
|
],
|
||||||
) if @paths;
|
) if @paths;
|
||||||
###$layer->fills->[-1]->cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ sub fill_surface {
|
||||||
($bounding_box->[X1] + $bounding_box->[X2]) / 2,
|
($bounding_box->[X1] + $bounding_box->[X2]) / 2,
|
||||||
($bounding_box->[Y1] + $bounding_box->[Y2]) / 2,
|
($bounding_box->[Y1] + $bounding_box->[Y2]) / 2,
|
||||||
);
|
);
|
||||||
foreach my $loop (map Slic3r::ExtrusionLoop->cast($_, role => 'fill'), @loops) {
|
foreach my $loop (map Slic3r::ExtrusionLoop->new(polygon => $_, role => 'fill'), @loops) {
|
||||||
# find the point of the loop that is closest to the current extruder position
|
# find the point of the loop that is closest to the current extruder position
|
||||||
$cur_pos = $loop->nearest_point_to($cur_pos);
|
$cur_pos = $loop->nearest_point_to($cur_pos);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ sub fill_surface {
|
||||||
my $path = "Math::PlanePath::$1"->new;
|
my $path = "Math::PlanePath::$1"->new;
|
||||||
my @n = $self->get_n($path, [map +($_ / $distance_between_lines), @$bounding_box]);
|
my @n = $self->get_n($path, [map +($_ / $distance_between_lines), @$bounding_box]);
|
||||||
|
|
||||||
my $polyline = Slic3r::Polyline->cast([
|
my $polyline = Slic3r::Polyline->new([
|
||||||
map [ map {$_*$distance_between_lines} $path->n_to_xy($_) ], @n,
|
map [ map {$_*$distance_between_lines} $path->n_to_xy($_) ], @n,
|
||||||
]);
|
]);
|
||||||
return {} if !@{$polyline->points};
|
return {} if !@{$polyline->points};
|
||||||
|
|
|
@ -55,7 +55,7 @@ sub fill_surface {
|
||||||
# connect lines
|
# connect lines
|
||||||
{
|
{
|
||||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||||
paths => [ map Slic3r::ExtrusionPath->cast([ @$_ ], role => 'bogus'), @paths ],
|
paths => [ map Slic3r::ExtrusionPath->new(polyline => Slic3r::Polyline->new(@$_), role => 'bogus'), @paths ],
|
||||||
);
|
);
|
||||||
@paths = ();
|
@paths = ();
|
||||||
|
|
||||||
|
|
|
@ -24,23 +24,15 @@ has 'lines' => (
|
||||||
);
|
);
|
||||||
|
|
||||||
# collection of surfaces generated by slicing the original geometry
|
# collection of surfaces generated by slicing the original geometry
|
||||||
has 'slices' => (
|
has 'slices' => (is => 'ro', default => sub { [] });
|
||||||
is => 'rw',
|
|
||||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
|
||||||
default => sub { [] },
|
|
||||||
);
|
|
||||||
|
|
||||||
# collection of polygons or polylines representing thin walls contained
|
# collection of polygons or polylines representing thin walls contained
|
||||||
# in the original geometry
|
# in the original geometry
|
||||||
has 'thin_walls' => (is => 'rw', default => sub { [] });
|
has 'thin_walls' => (is => 'ro', default => sub { [] });
|
||||||
|
|
||||||
# collection of surfaces generated by offsetting the innermost perimeter(s)
|
# collection of expolygons generated by offsetting the innermost perimeter(s)
|
||||||
# they represent boundaries of areas to fill
|
# they represent boundaries of areas to fill
|
||||||
has 'fill_boundaries' => (
|
has 'fill_boundaries' => (is => 'ro', default => sub { [] });
|
||||||
is => 'rw',
|
|
||||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
|
||||||
default => sub { [] },
|
|
||||||
);
|
|
||||||
|
|
||||||
# collection of surfaces generated by clipping the slices to the fill boundaries
|
# collection of surfaces generated by clipping the slices to the fill boundaries
|
||||||
has 'surfaces' => (
|
has 'surfaces' => (
|
||||||
|
@ -150,7 +142,7 @@ sub make_surfaces {
|
||||||
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
||||||
|
|
||||||
push @{$self->slices},
|
push @{$self->slices},
|
||||||
map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'),
|
map Slic3r::Surface->new(expolygon => $_, surface_type => 'internal'),
|
||||||
@$expolygons;
|
@$expolygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +152,8 @@ sub make_surfaces {
|
||||||
my @surfaces = @{$self->slices};
|
my @surfaces = @{$self->slices};
|
||||||
@{$self->slices} = ();
|
@{$self->slices} = ();
|
||||||
foreach my $surface (@surfaces) {
|
foreach my $surface (@surfaces) {
|
||||||
push @{$self->slices}, map Slic3r::Surface->cast_from_expolygon
|
push @{$self->slices}, map Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal'),
|
(expolygon => $_, surface_type => 'internal'),
|
||||||
$surface->expolygon->offset_ex(-$distance);
|
$surface->expolygon->offset_ex(-$distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +175,7 @@ sub make_surfaces {
|
||||||
if (0) {
|
if (0) {
|
||||||
require "Slic3r/SVG.pm";
|
require "Slic3r/SVG.pm";
|
||||||
Slic3r::SVG::output(undef, "surfaces.svg",
|
Slic3r::SVG::output(undef, "surfaces.svg",
|
||||||
polygons => [ map $_->contour->p, @{$self->slices} ],
|
polygons => [ map $_->contour, @{$self->slices} ],
|
||||||
red_polygons => [ map $_->p, map @{$_->holes}, @{$self->slices} ],
|
red_polygons => [ map $_->p, map @{$_->holes}, @{$self->slices} ],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -210,7 +202,7 @@ sub prepare_fill_surfaces {
|
||||||
(map $_->p, grep $_->surface_type eq 'top', @surfaces),
|
(map $_->p, grep $_->surface_type eq 'top', @surfaces),
|
||||||
(map @$_, map $_->expolygon->safety_offset, @$small_internal),
|
(map @$_, map $_->expolygon->safety_offset, @$small_internal),
|
||||||
]);
|
]);
|
||||||
my @top = map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'top'), @$union;
|
my @top = map Slic3r::Surface->new(expolygon => $_, surface_type => 'top'), @$union;
|
||||||
@surfaces = (grep($_->surface_type ne 'top', @surfaces), @top);
|
@surfaces = (grep($_->surface_type ne 'top', @surfaces), @top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +234,8 @@ sub remove_small_surfaces {
|
||||||
@offsets = map $_->offset_ex($distance), @offsets;
|
@offsets = map $_->offset_ex($distance), @offsets;
|
||||||
@offsets = @{ union_ex([ map @$_, @offsets ], undef, 1) };
|
@offsets = @{ union_ex([ map @$_, @offsets ], undef, 1) };
|
||||||
|
|
||||||
push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_,
|
push @{$self->fill_surfaces}, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $surface->surface_type), @offsets;
|
surface_type => $surface->surface_type), @offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +250,8 @@ sub remove_small_surfaces {
|
||||||
[ map $_->p, @surfaces ],
|
[ map $_->p, @surfaces ],
|
||||||
[ map $_->p, @{$self->fill_surfaces} ],
|
[ map $_->p, @{$self->fill_surfaces} ],
|
||||||
);
|
);
|
||||||
push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_,
|
push @{$self->fill_surfaces}, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => 'internal-solid'), @$diff;
|
surface_type => 'internal-solid'), @$diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,7 +376,8 @@ sub process_bridges {
|
||||||
[ $bridge_offset ],
|
[ $bridge_offset ],
|
||||||
);
|
);
|
||||||
|
|
||||||
push @bridges, map Slic3r::Surface->cast_from_expolygon($_,
|
push @bridges, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $surface->surface_type,
|
surface_type => $surface->surface_type,
|
||||||
bridge_angle => $bridge_angle,
|
bridge_angle => $bridge_angle,
|
||||||
), @$intersection;
|
), @$intersection;
|
||||||
|
@ -405,7 +400,8 @@ sub process_bridges {
|
||||||
[ map $_->p, @bridges ],
|
[ map $_->p, @bridges ],
|
||||||
);
|
);
|
||||||
|
|
||||||
push @bridges, map Slic3r::Surface->cast_from_expolygon($_,
|
push @bridges, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $surfaces->[0]->surface_type,
|
surface_type => $surfaces->[0]->surface_type,
|
||||||
bridge_angle => $surfaces->[0]->bridge_angle,
|
bridge_angle => $surfaces->[0]->bridge_angle,
|
||||||
), @$union;
|
), @$union;
|
||||||
|
@ -424,7 +420,8 @@ sub process_bridges {
|
||||||
[ $bridge->p ],
|
[ $bridge->p ],
|
||||||
);
|
);
|
||||||
|
|
||||||
push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_,
|
push @{$self->fill_surfaces}, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $bridge->surface_type,
|
surface_type => $bridge->surface_type,
|
||||||
bridge_angle => $bridge->bridge_angle,
|
bridge_angle => $bridge->bridge_angle,
|
||||||
), @$actual_bridge;
|
), @$actual_bridge;
|
||||||
|
@ -436,7 +433,8 @@ sub process_bridges {
|
||||||
[ map $_->p, @$group ],
|
[ map $_->p, @$group ],
|
||||||
[ map $_->p, @bridges ],
|
[ map $_->p, @bridges ],
|
||||||
);
|
);
|
||||||
push @{$self->fill_surfaces}, map Slic3r::Surface->cast_from_expolygon($_,
|
push @{$self->fill_surfaces}, map Slic3r::Surface->new(
|
||||||
|
expolygon => $_,
|
||||||
surface_type => $group->[0]->surface_type), @$difference;
|
surface_type => $group->[0]->surface_type), @$difference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,6 @@ sub new {
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub cast {
|
|
||||||
my $class = shift;
|
|
||||||
my ($line) = @_;
|
|
||||||
return $line if ref $line eq __PACKAGE__;
|
|
||||||
return $class->new($line);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub a { $_[0][0] }
|
sub a { $_[0][0] }
|
||||||
sub b { $_[0][1] }
|
sub b { $_[0][1] }
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ sub make_perimeter {
|
||||||
|
|
||||||
# organize perimeter surfaces using a shortest path search
|
# organize perimeter surfaces using a shortest path search
|
||||||
my @surfaces = @{shortest_path([
|
my @surfaces = @{shortest_path([
|
||||||
map [ $_->contour->points->[0], $_ ], @{$layer->slices},
|
map [ $_->contour->[0], $_ ], @{$layer->slices},
|
||||||
])};
|
])};
|
||||||
|
|
||||||
foreach my $surface (@surfaces) {
|
foreach my $surface (@surfaces) {
|
||||||
|
@ -50,9 +50,7 @@ sub make_perimeter {
|
||||||
|
|
||||||
# create one more offset to be used as boundary for fill
|
# create one more offset to be used as boundary for fill
|
||||||
{
|
{
|
||||||
my @fill_boundaries = map Slic3r::Surface->cast_from_expolygon
|
my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets;
|
||||||
($_, surface_type => $surface->surface_type),
|
|
||||||
map $_->offset_ex(-$distance), @last_offsets;
|
|
||||||
|
|
||||||
# TODO: diff(offset(@last_offsets, -$distance/2), offset(@fill_boundaries, +$distance/2))
|
# TODO: diff(offset(@last_offsets, -$distance/2), offset(@fill_boundaries, +$distance/2))
|
||||||
# this represents the small gaps that we need to treat like thin polygons,
|
# this represents the small gaps that we need to treat like thin polygons,
|
||||||
|
@ -66,12 +64,12 @@ sub make_perimeter {
|
||||||
foreach my $island (@perimeters) {
|
foreach my $island (@perimeters) {
|
||||||
# do holes starting from innermost one
|
# do holes starting from innermost one
|
||||||
foreach my $hole (map $_->holes, map @$_, @$island) {
|
foreach my $hole (map $_->holes, map @$_, @$island) {
|
||||||
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($hole, role => 'perimeter');
|
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $hole, role => 'perimeter');
|
||||||
}
|
}
|
||||||
|
|
||||||
# do contours starting from innermost one
|
# do contours starting from innermost one
|
||||||
foreach my $contour (map $_->contour, map @$_, reverse @$island) {
|
foreach my $contour (map $_->contour, map @$_, reverse @$island) {
|
||||||
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($contour, role => 'perimeter');
|
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $contour, role => 'perimeter');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,9 +81,9 @@ sub make_perimeter {
|
||||||
# add thin walls as perimeters
|
# add thin walls as perimeters
|
||||||
for (@{ $layer->thin_walls }) {
|
for (@{ $layer->thin_walls }) {
|
||||||
if ($_->isa('Slic3r::Polygon')) {
|
if ($_->isa('Slic3r::Polygon')) {
|
||||||
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($_, role => 'perimeter');
|
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $_, role => 'perimeter');
|
||||||
} else {
|
} else {
|
||||||
push @{ $layer->perimeters }, Slic3r::ExtrusionPath->cast($_->points, role => 'perimeter');
|
push @{ $layer->perimeters }, Slic3r::ExtrusionPath->new(polyline => $_->points, role => 'perimeter');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,10 @@ use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
# a polygon is a closed polyline.
|
# a polygon is a closed polyline.
|
||||||
# if you're asking why there's a Slic3r::Polygon as well
|
use parent 'Slic3r::Polyline';
|
||||||
# as a Slic3r::Polyline::Closed you're right. I plan to
|
|
||||||
# ditch the latter and port everything to this class.
|
|
||||||
|
|
||||||
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
|
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
|
||||||
|
scale polygon_remove_acute_vertices
|
||||||
polygon_segment_having_point point_in_polygon move_points rotate_points);
|
polygon_segment_having_point point_in_polygon move_points rotate_points);
|
||||||
use Slic3r::Geometry::Clipper qw(JT_MITER);
|
use Slic3r::Geometry::Clipper qw(JT_MITER);
|
||||||
|
|
||||||
|
@ -31,12 +30,6 @@ sub clone {
|
||||||
return (ref $self)->new(map $_->clone, @$self);
|
return (ref $self)->new(map $_->clone, @$self);
|
||||||
}
|
}
|
||||||
|
|
||||||
# legacy method, to be removed when we ditch Slic3r::Polyline::Closed
|
|
||||||
sub closed_polyline {
|
|
||||||
my $self = shift;
|
|
||||||
return Slic3r::Polyline::Closed->cast($self);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub lines {
|
sub lines {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return map Slic3r::Line->new($_), polygon_lines($self);
|
return map Slic3r::Line->new($_), polygon_lines($self);
|
||||||
|
@ -44,7 +37,20 @@ sub lines {
|
||||||
|
|
||||||
sub cleanup {
|
sub cleanup {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
$self->merge_continuous_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub merge_continuous_lines {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
polygon_remove_parallel_continuous_edges($self);
|
polygon_remove_parallel_continuous_edges($self);
|
||||||
|
bless $_, 'Slic3r::Point' for @$self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub remove_acute_vertices {
|
||||||
|
my $self = shift;
|
||||||
|
polygon_remove_acute_vertices($self);
|
||||||
|
bless $_, 'Slic3r::Point' for @$self;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub point_on_segment {
|
sub point_on_segment {
|
||||||
|
@ -106,7 +112,8 @@ sub subdivide {
|
||||||
|
|
||||||
# $num_points is the number of points to add between $i-1 and $i
|
# $num_points is the number of points to add between $i-1 and $i
|
||||||
my $spacing = $len / ($num_points + 1);
|
my $spacing = $len / ($num_points + 1);
|
||||||
my @new_points = map Slic3r::Geometry::point_along_segment($self->[$i-1], $self->[$i], $spacing * $_),
|
my @new_points = map Slic3r::Point->new($_),
|
||||||
|
map Slic3r::Geometry::point_along_segment($self->[$i-1], $self->[$i], $spacing * $_),
|
||||||
1..$num_points;
|
1..$num_points;
|
||||||
|
|
||||||
splice @$self, $i, 0, @new_points;
|
splice @$self, $i, 0, @new_points;
|
||||||
|
@ -114,4 +121,22 @@ sub subdivide {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# returns false if the polyline is too tight to be printed
|
||||||
|
sub is_printable {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
# try to get an inwards offset
|
||||||
|
# for a distance equal to half of the extrusion width;
|
||||||
|
# if no offset is possible, then polyline is not printable
|
||||||
|
my $p = $self->clone;
|
||||||
|
@$p = reverse @$p if !Math::Clipper::is_counter_clockwise($p);
|
||||||
|
my $offsets = Math::Clipper::offset([$p], -(scale $Slic3r::flow_spacing / 2), $Slic3r::resolution * 100000, JT_MITER, 2);
|
||||||
|
return @$offsets ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_valid {
|
||||||
|
my $self = shift;
|
||||||
|
return @{$self->points} >= 3;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
|
@ -1,38 +1,37 @@
|
||||||
package Slic3r::Polyline;
|
package Slic3r::Polyline;
|
||||||
use Moo;
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
use Math::Clipper qw();
|
use Math::Clipper qw();
|
||||||
use Slic3r::Geometry qw(A B polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
|
use Slic3r::Geometry qw(A B polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
|
||||||
polygon_remove_acute_vertices polygon_remove_parallel_continuous_edges move_points same_point);
|
move_points same_point);
|
||||||
use Sub::Quote;
|
|
||||||
use XXX;
|
use XXX;
|
||||||
|
|
||||||
# arrayref of ordered points
|
# the constructor accepts an array(ref) of points
|
||||||
has 'points' => (
|
sub new {
|
||||||
is => 'rw',
|
my $class = shift;
|
||||||
required => 1,
|
my $self;
|
||||||
default => sub { [] },
|
if (@_ == 1) {
|
||||||
isa => quote_sub q{ use Carp; confess "invalid points" if grep ref $_ ne 'Slic3r::Point', @{$_[0]} },
|
$self = [ @{$_[0]} ];
|
||||||
);
|
} else {
|
||||||
|
$self = [ @_ ];
|
||||||
|
}
|
||||||
|
|
||||||
|
bless $self, $class;
|
||||||
|
bless $_, 'Slic3r::Point' for @$self;
|
||||||
|
$self;
|
||||||
|
}
|
||||||
|
|
||||||
sub id {
|
sub id {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return join ' - ', sort map $_->id, @{$self->points};
|
return join ' - ', sort map $_->id, @$self;
|
||||||
}
|
|
||||||
|
|
||||||
sub cast {
|
|
||||||
my $class = shift;
|
|
||||||
my ($points, %args) = @_;
|
|
||||||
|
|
||||||
$points = [ map Slic3r::Point->cast($_), @$points ];
|
|
||||||
return $class->new(points => $points, %args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub lines {
|
sub lines {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my @lines = ();
|
my @lines = ();
|
||||||
my $previous_point;
|
my $previous_point;
|
||||||
foreach my $point (@{ $self->points }) {
|
foreach my $point (@$self) {
|
||||||
if ($previous_point) {
|
if ($previous_point) {
|
||||||
push @lines, Slic3r::Line->new($previous_point, $point);
|
push @lines, Slic3r::Line->new($previous_point, $point);
|
||||||
}
|
}
|
||||||
|
@ -41,43 +40,25 @@ sub lines {
|
||||||
return @lines;
|
return @lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub p {
|
|
||||||
my $self = shift;
|
|
||||||
return [ @{$self->points} ];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub merge_continuous_lines {
|
sub merge_continuous_lines {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $points = $self->p;
|
|
||||||
if ($self->isa('Slic3r::Polyline::Closed')) {
|
polyline_remove_parallel_continuous_edges($self);
|
||||||
polygon_remove_parallel_continuous_edges($points);
|
bless $_, 'Slic3r::Point' for @$self;
|
||||||
} else {
|
|
||||||
polyline_remove_parallel_continuous_edges($points);
|
|
||||||
}
|
|
||||||
@{$self->points} = map Slic3r::Point->new($_), @$points;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub remove_acute_vertices {
|
sub remove_acute_vertices {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $points = $self->p;
|
polyline_remove_acute_vertices($self);
|
||||||
if ($self->isa('Slic3r::Polyline::Closed')) {
|
bless $_, 'Slic3r::Point' for @$self;
|
||||||
polygon_remove_acute_vertices($points);
|
|
||||||
} else {
|
|
||||||
polyline_remove_acute_vertices($points);
|
|
||||||
}
|
|
||||||
@{$self->points} = map Slic3r::Point->new($_), @$points;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub cleanup {
|
sub simplify {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $tolerance = shift || 10;
|
my $tolerance = shift || 10;
|
||||||
|
|
||||||
my $points = $self->p;
|
@$self = Slic3r::Geometry::Douglas_Peucker($self, $tolerance);
|
||||||
push @$points, $points->[0] if $self->isa('Slic3r::Polyline::Closed');
|
bless $_, 'Slic3r::Point' for @$self;
|
||||||
my @clean_points = map Slic3r::Point->new($_),
|
|
||||||
Slic3r::Geometry::Douglas_Peucker($self->p, $tolerance);
|
|
||||||
pop @clean_points if $self->isa('Slic3r::Polyline::Closed');
|
|
||||||
@{$self->points} = @clean_points;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub reverse_points {
|
sub reverse_points {
|
||||||
|
@ -104,7 +85,7 @@ sub nearest_point_to {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($point) = @_;
|
my ($point) = @_;
|
||||||
|
|
||||||
$point = Slic3r::Geometry::nearest_point($point, $self->p);
|
$point = Slic3r::Geometry::nearest_point($point, $self);
|
||||||
return Slic3r::Point->new($point);
|
return Slic3r::Point->new($point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +147,7 @@ sub clip_with_expolygon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return map Slic3r::Polyline->cast($_), @polylines;
|
return map Slic3r::Polyline->new($_), @polylines;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub bounding_box {
|
sub bounding_box {
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package Slic3r::Polyline::Closed;
|
|
||||||
use Moo;
|
|
||||||
|
|
||||||
extends 'Slic3r::Polyline';
|
|
||||||
|
|
||||||
use Math::Clipper qw(JT_MITER);
|
|
||||||
use Slic3r::Geometry qw(scale);
|
|
||||||
|
|
||||||
sub lines {
|
|
||||||
my $self = shift;
|
|
||||||
my @lines = $self->SUPER::lines(@_);
|
|
||||||
|
|
||||||
# since this is a closed polyline, we just add a line at the end,
|
|
||||||
# connecting the last and the first point
|
|
||||||
push @lines, Slic3r::Line->new($self->points->[-1], $self->points->[0]);
|
|
||||||
return @lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub encloses_point {
|
|
||||||
my $self = shift;
|
|
||||||
my ($point) = @_;
|
|
||||||
|
|
||||||
return Slic3r::Geometry::point_in_polygon($point->p, $self->p);
|
|
||||||
}
|
|
||||||
|
|
||||||
# returns false if the polyline is too tight to be printed
|
|
||||||
sub is_printable {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
# try to get an inwards offset
|
|
||||||
# for a distance equal to half of the extrusion width;
|
|
||||||
# if no offset is possible, then polyline is not printable
|
|
||||||
my $p = $self->p;
|
|
||||||
@$p = reverse @$p if !Math::Clipper::is_counter_clockwise($p);
|
|
||||||
my $offsets = Math::Clipper::offset([$p], -(scale $Slic3r::flow_spacing / 2), $Slic3r::resolution * 100000, JT_MITER, 2);
|
|
||||||
return @$offsets ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_valid {
|
|
||||||
my $self = shift;
|
|
||||||
return @{$self->points} >= 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub polygon {
|
|
||||||
my $self = shift;
|
|
||||||
return Slic3r::Polygon->new($self->points);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
|
@ -125,8 +125,8 @@ sub new_from_mesh {
|
||||||
[ map $_->expolygon->holes, @upper_surfaces, @lower_surfaces, ],
|
[ map $_->expolygon->holes, @upper_surfaces, @lower_surfaces, ],
|
||||||
);
|
);
|
||||||
|
|
||||||
@{$layer->slices} = map Slic3r::Surface->cast_from_expolygon
|
@{$layer->slices} = map Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal'),
|
(expolygon => $_, surface_type => 'internal'),
|
||||||
@$diff;
|
@$diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ sub detect_surfaces_type {
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
return grep $_->contour->is_printable,
|
return grep $_->contour->is_printable,
|
||||||
map Slic3r::Surface->cast_from_expolygon($_, surface_type => $result_type),
|
map Slic3r::Surface->new(expolygon => $_, surface_type => $result_type),
|
||||||
@$expolygons;
|
@$expolygons;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ sub detect_surfaces_type {
|
||||||
@internal = $surface_difference->($layer->slices, [@top, @bottom], 'internal');
|
@internal = $surface_difference->($layer->slices, [@top, @bottom], 'internal');
|
||||||
|
|
||||||
# save surfaces to layer
|
# save surfaces to layer
|
||||||
$layer->slices([ @bottom, @top, @internal ]);
|
@{$layer->slices} = (@bottom, @top, @internal);
|
||||||
|
|
||||||
Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n",
|
Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n",
|
||||||
$layer->id, scalar(@bottom), scalar(@top), scalar(@internal);
|
$layer->id, scalar(@bottom), scalar(@top), scalar(@internal);
|
||||||
|
@ -235,10 +235,10 @@ sub detect_surfaces_type {
|
||||||
foreach my $surface (@{$layer->slices}) {
|
foreach my $surface (@{$layer->slices}) {
|
||||||
my $intersection = intersection_ex(
|
my $intersection = intersection_ex(
|
||||||
[ $surface->p ],
|
[ $surface->p ],
|
||||||
[ map $_->p, @{$layer->fill_boundaries} ],
|
[ map @$_, @{$layer->fill_boundaries} ],
|
||||||
);
|
);
|
||||||
push @{$layer->surfaces}, map Slic3r::Surface->cast_from_expolygon
|
push @{$layer->surfaces}, map Slic3r::Surface->new
|
||||||
($_, surface_type => $surface->surface_type),
|
(expolygon => $_, surface_type => $surface->surface_type),
|
||||||
@$intersection;
|
@$intersection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,13 +298,13 @@ sub discover_horizontal_shells {
|
||||||
# assign resulting inner surfaces to layer
|
# assign resulting inner surfaces to layer
|
||||||
my $neighbor_fill_surfaces = $self->layers->[$n]->fill_surfaces;
|
my $neighbor_fill_surfaces = $self->layers->[$n]->fill_surfaces;
|
||||||
@$neighbor_fill_surfaces = ();
|
@$neighbor_fill_surfaces = ();
|
||||||
push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon
|
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal')
|
(expolygon => $_, surface_type => 'internal')
|
||||||
for @$internal;
|
for @$internal;
|
||||||
|
|
||||||
# assign new internal-solid surfaces to layer
|
# assign new internal-solid surfaces to layer
|
||||||
push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon
|
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal-solid')
|
(expolygon => $_, surface_type => 'internal-solid')
|
||||||
for @$internal_solid;
|
for @$internal_solid;
|
||||||
|
|
||||||
# assign top and bottom surfaces to layer
|
# assign top and bottom surfaces to layer
|
||||||
|
@ -313,8 +313,8 @@ sub discover_horizontal_shells {
|
||||||
[ map $_->p, @$s ],
|
[ map $_->p, @$s ],
|
||||||
[ map @$_, @$internal_solid, @$internal ],
|
[ map @$_, @$internal_solid, @$internal ],
|
||||||
);
|
);
|
||||||
push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon
|
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||||
($_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle)
|
(expolygon => $_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle)
|
||||||
for @$solid_surfaces;
|
for @$solid_surfaces;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,10 @@ sub extrude_skirt {
|
||||||
for (my $i = $Slic3r::skirts - 1; $i >= 0; $i--) {
|
for (my $i = $Slic3r::skirts - 1; $i >= 0; $i--) {
|
||||||
my $distance = scale ($Slic3r::skirt_distance + ($Slic3r::flow_spacing * $i));
|
my $distance = scale ($Slic3r::skirt_distance + ($Slic3r::flow_spacing * $i));
|
||||||
my $outline = offset([$convex_hull], $distance, $Slic3r::resolution * 100, JT_ROUND);
|
my $outline = offset([$convex_hull], $distance, $Slic3r::resolution * 100, JT_ROUND);
|
||||||
push @skirts, Slic3r::ExtrusionLoop->cast([ @{$outline->[0]} ], role => 'skirt');
|
push @skirts, Slic3r::ExtrusionLoop->new(
|
||||||
|
polygon => Slic3r::Polygon->new(@{$outline->[0]}),
|
||||||
|
role => 'skirt',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
# apply skirts to all layers
|
# apply skirts to all layers
|
||||||
|
@ -387,12 +390,12 @@ sub infill_every_layers {
|
||||||
{
|
{
|
||||||
my @new_surfaces = ();
|
my @new_surfaces = ();
|
||||||
push @new_surfaces, grep $_->surface_type ne 'internal', @{$layer->fill_surfaces};
|
push @new_surfaces, grep $_->surface_type ne 'internal', @{$layer->fill_surfaces};
|
||||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon
|
push @new_surfaces, map Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal', depth_layers => $d + 1), @$intersection;
|
(expolygon => $_, surface_type => 'internal', depth_layers => $d + 1), @$intersection;
|
||||||
|
|
||||||
foreach my $depth (reverse $d..$Slic3r::infill_every_layers) {
|
foreach my $depth (reverse $d..$Slic3r::infill_every_layers) {
|
||||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon
|
push @new_surfaces, map Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal', depth_layers => $depth),
|
(expolygon => $_, surface_type => 'internal', depth_layers => $depth),
|
||||||
|
|
||||||
# difference between our internal layers with depth == $depth
|
# difference between our internal layers with depth == $depth
|
||||||
# and the intersection found
|
# and the intersection found
|
||||||
|
@ -413,8 +416,8 @@ sub infill_every_layers {
|
||||||
my @new_surfaces = ();
|
my @new_surfaces = ();
|
||||||
push @new_surfaces, grep $_->surface_type ne 'internal', @{$lower_layer->fill_surfaces};
|
push @new_surfaces, grep $_->surface_type ne 'internal', @{$lower_layer->fill_surfaces};
|
||||||
foreach my $depth (1..$Slic3r::infill_every_layers) {
|
foreach my $depth (1..$Slic3r::infill_every_layers) {
|
||||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon
|
push @new_surfaces, map Slic3r::Surface->new
|
||||||
($_, surface_type => 'internal', depth_layers => $depth),
|
(expolygon => $_, surface_type => 'internal', depth_layers => $depth),
|
||||||
|
|
||||||
# difference between internal layers with depth == $depth
|
# difference between internal layers with depth == $depth
|
||||||
# and the intersection found
|
# and the intersection found
|
||||||
|
|
|
@ -1,17 +1,10 @@
|
||||||
package Slic3r::Surface;
|
package Slic3r::Surface;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
has 'contour' => (
|
has 'expolygon' => (
|
||||||
is => 'ro',
|
is => 'ro',
|
||||||
#isa => 'Slic3r::Polyline::Closed',
|
|
||||||
required => 1,
|
required => 1,
|
||||||
);
|
handles => [qw(encloses_point lines contour holes)],
|
||||||
|
|
||||||
has 'holes' => (
|
|
||||||
traits => ['Array'],
|
|
||||||
is => 'rw',
|
|
||||||
#isa => 'ArrayRef[Slic3r::Polyline::Closed]',
|
|
||||||
default => sub { [] },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
has 'surface_type' => (
|
has 'surface_type' => (
|
||||||
|
@ -24,31 +17,6 @@ has 'depth_layers' => (is => 'ro', default => sub {1});
|
||||||
|
|
||||||
has 'bridge_angle' => (is => 'ro');
|
has 'bridge_angle' => (is => 'ro');
|
||||||
|
|
||||||
sub cast_from_polygon {
|
|
||||||
my $class = shift;
|
|
||||||
my ($polygon, %args) = @_;
|
|
||||||
|
|
||||||
return $class->new(
|
|
||||||
contour => Slic3r::Polyline::Closed->cast($polygon),
|
|
||||||
%args,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cast_from_expolygon {
|
|
||||||
my $class = shift;
|
|
||||||
my ($expolygon, %args) = @_;
|
|
||||||
|
|
||||||
if (ref $expolygon eq 'HASH') {
|
|
||||||
$expolygon = Slic3r::ExPolygon->new($expolygon);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $class->new(
|
|
||||||
contour => $expolygon->contour->closed_polyline,
|
|
||||||
holes => [ map $_->closed_polyline, $expolygon->holes ],
|
|
||||||
%args,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
# static method to group surfaces having same surface_type, bridge_angle and depth_layers
|
# static method to group surfaces having same surface_type, bridge_angle and depth_layers
|
||||||
sub group {
|
sub group {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
|
@ -73,7 +41,7 @@ sub add_hole {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($hole) = @_;
|
my ($hole) = @_;
|
||||||
|
|
||||||
push @{ $self->holes }, $hole;
|
push @$self, $hole;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub id {
|
sub id {
|
||||||
|
@ -81,15 +49,6 @@ sub id {
|
||||||
return $self->contour->id;
|
return $self->contour->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub encloses_point {
|
|
||||||
my $self = shift;
|
|
||||||
my ($point) = @_;
|
|
||||||
|
|
||||||
return 0 if !$self->contour->encloses_point($point);
|
|
||||||
return 0 if grep $_->encloses_point($point), @{ $self->holes };
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub clipper_polygon {
|
sub clipper_polygon {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
@ -102,18 +61,8 @@ sub clipper_polygon {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub p {
|
sub p {
|
||||||
my $self = shift;
|
my $self = shift;use XXX; ZZZ $self->expolygon if !eval { 1 if @{$self->expolygon}; 1 };
|
||||||
return ($self->contour->p, map $_->p, @{$self->holes});
|
return @{$self->expolygon};
|
||||||
}
|
|
||||||
|
|
||||||
sub expolygon {
|
|
||||||
my $self = shift;
|
|
||||||
return Slic3r::ExPolygon->new($self->contour->p, map $_->p, @{$self->holes});
|
|
||||||
}
|
|
||||||
|
|
||||||
sub lines {
|
|
||||||
my $self = shift;
|
|
||||||
return @{ $self->contour->lines }, map @{ $_->lines }, @{ $self->holes };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
13
t/arcs.t
13
t/arcs.t
|
@ -13,13 +13,13 @@ use Slic3r;
|
||||||
use Slic3r::Geometry qw(epsilon);
|
use Slic3r::Geometry qw(epsilon);
|
||||||
|
|
||||||
{
|
{
|
||||||
my $path = Slic3r::ExtrusionPath->cast([
|
my $path = Slic3r::ExtrusionPath->new(polyline => Slic3r::Polyline->new(
|
||||||
[135322.42,26654.96], [187029.11,99546.23], [222515.14,92381.93], [258001.16,99546.23],
|
[135322.42,26654.96], [187029.11,99546.23], [222515.14,92381.93], [258001.16,99546.23],
|
||||||
[286979.42,119083.91], [306517.1,148062.17], [313681.4,183548.2],
|
[286979.42,119083.91], [306517.1,148062.17], [313681.4,183548.2],
|
||||||
[306517.1,219034.23], [286979.42,248012.49], [258001.16,267550.17], [222515.14,274714.47],
|
[306517.1,219034.23], [286979.42,248012.49], [258001.16,267550.17], [222515.14,274714.47],
|
||||||
[187029.11,267550.17], [158050.85,248012.49], [138513.17,219034.23], [131348.87,183548.2],
|
[187029.11,267550.17], [158050.85,248012.49], [138513.17,219034.23], [131348.87,183548.2],
|
||||||
[86948.77,175149.09], [119825.35,100585],
|
[86948.77,175149.09], [119825.35,100585],
|
||||||
], role => 'fill');
|
), role => 'fill');
|
||||||
|
|
||||||
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [$path]);
|
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [$path]);
|
||||||
$collection->detect_arcs(30);
|
$collection->detect_arcs(30);
|
||||||
|
@ -31,14 +31,17 @@ use Slic3r::Geometry qw(epsilon);
|
||||||
#==========================================================
|
#==========================================================
|
||||||
|
|
||||||
{
|
{
|
||||||
my $path1 = Slic3r::ExtrusionPath->cast([
|
my $path1 = Slic3r::ExtrusionPath->new(polyline => Slic3r::Polyline->new(
|
||||||
[10,20], [10.7845909572784,19.9691733373313], [11.5643446504023,19.8768834059514],
|
[10,20], [10.7845909572784,19.9691733373313], [11.5643446504023,19.8768834059514],
|
||||||
[12.3344536385591,19.7236992039768], [13.0901699437495,19.5105651629515],
|
[12.3344536385591,19.7236992039768], [13.0901699437495,19.5105651629515],
|
||||||
[13.8268343236509,19.2387953251129], [14.5399049973955,18.9100652418837],
|
[13.8268343236509,19.2387953251129], [14.5399049973955,18.9100652418837],
|
||||||
[15.2249856471595,18.5264016435409], [15.8778525229247,18.0901699437495],
|
[15.2249856471595,18.5264016435409], [15.8778525229247,18.0901699437495],
|
||||||
[16.4944804833018,17.6040596560003],
|
[16.4944804833018,17.6040596560003],
|
||||||
], role => 'fill');
|
), role => 'fill');
|
||||||
my $path2 = Slic3r::ExtrusionPath->cast([ reverse @{$path1->points} ], role => 'fill');
|
my $path2 = Slic3r::ExtrusionPath->new(
|
||||||
|
polyline => Slic3r::Polyline->new(reverse @{$path1->points}),
|
||||||
|
role => 'fill',
|
||||||
|
);
|
||||||
|
|
||||||
my $collection1 = Slic3r::ExtrusionPath::Collection->new(paths => [$path1]);
|
my $collection1 = Slic3r::ExtrusionPath::Collection->new(paths => [$path1]);
|
||||||
my $collection2 = Slic3r::ExtrusionPath::Collection->new(paths => [$path2]);
|
my $collection2 = Slic3r::ExtrusionPath::Collection->new(paths => [$path2]);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use Test::More;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
plan tests => 4;
|
plan tests => 3;
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
use FindBin;
|
use FindBin;
|
||||||
|
@ -11,14 +11,17 @@ BEGIN {
|
||||||
|
|
||||||
use Slic3r;
|
use Slic3r;
|
||||||
|
|
||||||
my $polyline = Slic3r::Polyline::Closed->cast([
|
{
|
||||||
|
my $polygon = Slic3r::Polygon->new([
|
||||||
[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],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$polyline->merge_continuous_lines;
|
$polygon->merge_continuous_lines;
|
||||||
is scalar(@{$polyline->points}), 3, 'merge_continuous_lines';
|
is scalar(@$polygon), 3, 'merge_continuous_lines';
|
||||||
|
}
|
||||||
|
|
||||||
my $gear = [
|
{
|
||||||
|
my $gear = [
|
||||||
[144.9694,317.1543], [145.4181,301.5633], [146.3466,296.921], [131.8436,294.1643], [131.7467,294.1464],
|
[144.9694,317.1543], [145.4181,301.5633], [146.3466,296.921], [131.8436,294.1643], [131.7467,294.1464],
|
||||||
[121.7238,291.5082], [117.1631,290.2776], [107.9198,308.2068], [100.1735,304.5101], [104.9896,290.3672],
|
[121.7238,291.5082], [117.1631,290.2776], [107.9198,308.2068], [100.1735,304.5101], [104.9896,290.3672],
|
||||||
[106.6511,286.2133], [93.453,279.2327], [81.0065,271.4171], [67.7886,286.5055], [60.7927,280.1127],
|
[106.6511,286.2133], [93.453,279.2327], [81.0065,271.4171], [67.7886,286.5055], [60.7927,280.1127],
|
||||||
|
@ -48,18 +51,23 @@ my $gear = [
|
||||||
[234.9061,298.5798], [227.0321,286.2841], [225.2505,281.8301], [211.5387,287.8187], [202.3025,291.0935],
|
[234.9061,298.5798], [227.0321,286.2841], [225.2505,281.8301], [211.5387,287.8187], [202.3025,291.0935],
|
||||||
[197.307,292.831], [199.808,313.1906], [191.5298,315.0787], [187.3082,299.8172], [186.4201,295.3766],
|
[197.307,292.831], [199.808,313.1906], [191.5298,315.0787], [187.3082,299.8172], [186.4201,295.3766],
|
||||||
[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],
|
||||||
];
|
];
|
||||||
$polyline = Slic3r::Polyline::Closed->cast($gear);
|
my $polygon = Slic3r::Polygon->new($gear);
|
||||||
$polyline->merge_continuous_lines;
|
$polygon->merge_continuous_lines;
|
||||||
note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@{$polyline->points});
|
note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@$polygon);
|
||||||
ok @{$polyline->points} < @$gear, 'gear was simplified using merge_continuous_lines';
|
ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines';
|
||||||
|
|
||||||
my $num_points = scalar @{$polyline->points};
|
# simplify() is not being used, so we don't test it
|
||||||
$polyline->cleanup;
|
if (0) {
|
||||||
note sprintf "original points: %d\nnew points: %d", $num_points, scalar(@{$polyline->points});
|
my $num_points = scalar @$polygon;
|
||||||
ok @{$polyline->points} < $num_points, 'gear was further simplified using Douglas-Peucker';
|
$polygon->simplify;
|
||||||
|
note sprintf "original points: %d\nnew points: %d", $num_points, scalar(@$polygon);
|
||||||
|
ok @$polygon < $num_points, 'gear was further simplified using Douglas-Peucker';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
my $circle = [
|
{
|
||||||
|
my $circle = [
|
||||||
[3744.8,8045.8],[3788.1,8061.4],[3940.6,8116.3],[3984.8,8129.2],[4140.6,8174.4],[4185.5,8184.4],[4343.8,8219.9],
|
[3744.8,8045.8],[3788.1,8061.4],[3940.6,8116.3],[3984.8,8129.2],[4140.6,8174.4],[4185.5,8184.4],[4343.8,8219.9],
|
||||||
[4389.2,8227.1],[4549.4,8252.4],[4595.2,8256.7],[4756.6,8272],[4802.6,8273.4],[4964.7,8278.5],[5010.7,8277.1],
|
[4389.2,8227.1],[4549.4,8252.4],[4595.2,8256.7],[4756.6,8272],[4802.6,8273.4],[4964.7,8278.5],[5010.7,8277.1],
|
||||||
[5172.8,8272],[5218.6,8267.7],[5380,8252.4],[5425.5,8245.2],[5585.6,8219.9],[5630.5,8209.8],[5788.8,8174.4],
|
[5172.8,8272],[5218.6,8267.7],[5380,8252.4],[5425.5,8245.2],[5585.6,8219.9],[5630.5,8209.8],[5788.8,8174.4],
|
||||||
|
@ -89,9 +97,10 @@ my $circle = [
|
||||||
[2283.7,6912.5],[2311.9,6948.8],[2411.4,7077],[2441.8,7111.5],[2549,7233.2],[2581.5,7265.7],[2696.2,7380.4],
|
[2283.7,6912.5],[2311.9,6948.8],[2411.4,7077],[2441.8,7111.5],[2549,7233.2],[2581.5,7265.7],[2696.2,7380.4],
|
||||||
[2730.7,7410.8],[2852.4,7518],[2888.8,7546.2],[3016.9,7645.7],[3055,7671.5],[3189.1,7762.7],[3228.7,7786.1],
|
[2730.7,7410.8],[2852.4,7518],[2888.8,7546.2],[3016.9,7645.7],[3055,7671.5],[3189.1,7762.7],[3228.7,7786.1],
|
||||||
[3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4],
|
[3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4],
|
||||||
];
|
];
|
||||||
|
|
||||||
$polyline = Slic3r::Polyline::Closed->cast($circle);
|
my $polygon = Slic3r::Polygon->new($circle);
|
||||||
$polyline->merge_continuous_lines;
|
$polygon->merge_continuous_lines;
|
||||||
note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@{$polyline->points});
|
note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@$polygon);
|
||||||
ok @{$polyline->points} >= @$gear/3, 'circle was simplified using merge_continuous_lines';
|
ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines';
|
||||||
|
}
|
||||||
|
|
|
@ -103,8 +103,8 @@ is_deeply $intersection, [ [12, 12], [18, 16] ], 'internal lines are preserved';
|
||||||
], 'tangent line is clipped to square with hole';
|
], 'tangent line is clipped to square with hole';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
my $polyline = Slic3r::Polyline->cast([ [5, 18], [25, 18], [25, 15], [15, 15], [15, 12], [12, 12], [12, 5] ]);
|
my $polyline = Slic3r::Polyline->new([ [5, 18], [25, 18], [25, 15], [15, 15], [15, 12], [12, 12], [12, 5] ]);
|
||||||
is_deeply [ map $_->p, $polyline->clip_with_expolygon($expolygon) ], [
|
is_deeply [ map $_, $polyline->clip_with_expolygon($expolygon) ], [
|
||||||
[ [10, 18], [20, 18] ],
|
[ [10, 18], [20, 18] ],
|
||||||
[ [20, 15], [16, 15] ],
|
[ [20, 15], [16, 15] ],
|
||||||
[ [15, 14], [15, 12], [12, 12], [12, 10] ],
|
[ [15, 14], [15, 12], [12, 12], [12, 10] ],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue