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/Polygon.pm
|
||||
lib/Slic3r/Polyline.pm
|
||||
lib/Slic3r/Polyline/Closed.pm
|
||||
lib/Slic3r/Print.pm
|
||||
lib/Slic3r/Skein.pm
|
||||
lib/Slic3r/STL.pm
|
||||
|
|
|
@ -25,7 +25,6 @@ use Slic3r::Perimeter;
|
|||
use Slic3r::Point;
|
||||
use Slic3r::Polygon;
|
||||
use Slic3r::Polyline;
|
||||
use Slic3r::Polyline::Closed;
|
||||
use Slic3r::Print;
|
||||
use Slic3r::Skein;
|
||||
use Slic3r::STL;
|
||||
|
|
|
@ -40,6 +40,11 @@ sub holes {
|
|||
return @$self[1..$#$self];
|
||||
}
|
||||
|
||||
sub lines {
|
||||
my $self = shift;
|
||||
return map $_->lines, @$self;
|
||||
}
|
||||
|
||||
sub clipper_expolygon {
|
||||
my $self = shift;
|
||||
return {
|
||||
|
@ -106,7 +111,7 @@ sub bounding_box {
|
|||
sub clip_line {
|
||||
my $self = shift;
|
||||
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 @dir = (
|
||||
|
@ -203,6 +208,8 @@ sub medial_axis {
|
|||
}
|
||||
return undef if !@skeleton_lines;
|
||||
|
||||
return undef if !@skeleton_lines;
|
||||
|
||||
# now build a single polyline
|
||||
my $polyline = [];
|
||||
{
|
||||
|
@ -248,7 +255,7 @@ sub medial_axis {
|
|||
if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) {
|
||||
return Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]);
|
||||
} else {
|
||||
return Slic3r::Polyline->cast($polyline);
|
||||
return Slic3r::Polyline->new($polyline);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,21 @@ use Moo;
|
|||
|
||||
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
|
||||
has 'role' => (is => 'rw', required => 1);
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
bless $self->polygon, 'Slic3r::Polygon';
|
||||
}
|
||||
|
||||
sub split_at {
|
||||
my $self = shift;
|
||||
my ($point) = @_;
|
||||
|
@ -16,8 +26,8 @@ sub split_at {
|
|||
|
||||
# find index of point
|
||||
my $i = -1;
|
||||
for (my $n = 0; $n <= $#{$self->points}; $n++) {
|
||||
if ($point->id eq $self->points->[$n]->id) {
|
||||
for (my $n = 0; $n <= $#{$self->polygon}; $n++) {ZZZ "here" if ref $self->polygon->[$n] eq 'ARRAY';
|
||||
if ($point->id eq $self->polygon->[$n]->id) {
|
||||
$i = $n;
|
||||
last;
|
||||
}
|
||||
|
@ -25,10 +35,13 @@ sub split_at {
|
|||
die "Point not found" if $i == -1;
|
||||
|
||||
my @new_points = ();
|
||||
push @new_points, @{$self->points}[$i .. $#{$self->points}];
|
||||
push @new_points, @{$self->points}[0 .. $i];
|
||||
push @new_points, @{$self->polygon}[$i .. $#{$self->polygon}];
|
||||
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,7 +1,15 @@
|
|||
package Slic3r::ExtrusionPath;
|
||||
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
|
||||
# expressed in layers
|
||||
|
@ -12,8 +20,10 @@ has 'flow_spacing' => (is => 'rw');
|
|||
# perimeter/fill/solid-fill/bridge/skirt
|
||||
has 'role' => (is => 'rw', required => 1);
|
||||
|
||||
use Slic3r::Geometry qw(PI X Y epsilon deg2rad rotate_points);
|
||||
use XXX;
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
bless $self->polyline, 'Slic3r::Polyline';
|
||||
}
|
||||
|
||||
sub clip_end {
|
||||
my $self = shift;
|
||||
|
@ -35,6 +45,11 @@ sub clip_end {
|
|||
}
|
||||
}
|
||||
|
||||
sub points {
|
||||
my $self = shift;
|
||||
return $self->polyline;
|
||||
}
|
||||
|
||||
sub endpoints {
|
||||
my $self = shift;
|
||||
return ($self->points->[0], $self->points->[-1]);
|
||||
|
@ -68,10 +83,10 @@ sub split_at_acute_angles {
|
|||
# if the angle between $p[-2], $p[-1], $p3 is too acute
|
||||
# then consider $p3 only as a starting point of a new
|
||||
# path and stop the current one as it is
|
||||
push @paths, (ref $self)->cast(
|
||||
[@p],
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
push @paths, (ref $self)->new(
|
||||
polyline => Slic3r::Polyline->new(\@p),
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
);
|
||||
@p = ($p3);
|
||||
push @p, grep $_, shift @points or last;
|
||||
|
@ -79,10 +94,10 @@ sub split_at_acute_angles {
|
|||
push @p, $p3;
|
||||
}
|
||||
}
|
||||
push @paths, (ref $self)->cast(
|
||||
[@p],
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
push @paths, (ref $self)->new(
|
||||
polyline => Slic3r::Polyline->new(\@p),
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
) if @p > 1;
|
||||
|
||||
return @paths;
|
||||
|
@ -168,7 +183,7 @@ sub detect_arcs {
|
|||
}
|
||||
|
||||
my $arc = Slic3r::ExtrusionPath::Arc->new(
|
||||
points => [@arc_points],
|
||||
polyline => Slic3r::Polyline->new(\@arc_points),
|
||||
role => $self->role,
|
||||
orientation => $orientation,
|
||||
center => $arc_center,
|
||||
|
@ -177,9 +192,9 @@ sub detect_arcs {
|
|||
|
||||
# points 0..$i form a linear path
|
||||
push @paths, (ref $self)->new(
|
||||
points => [ @points[0..$i] ],
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
polyline => Slic3r::Polyline->new(@points[0..$i]),
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
) if $i > 0;
|
||||
|
||||
# add our arc
|
||||
|
@ -196,9 +211,9 @@ sub detect_arcs {
|
|||
|
||||
# remaining points form a linear path
|
||||
push @paths, (ref $self)->new(
|
||||
points => [@points],
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
polyline => Slic3r::Polyline->new(\@points),
|
||||
role => $self->role,
|
||||
depth_layers => $self->depth_layers,
|
||||
) if @points > 1;
|
||||
|
||||
return @paths;
|
||||
|
|
|
@ -71,7 +71,8 @@ sub make_fill {
|
|||
1,
|
||||
);
|
||||
|
||||
push @surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
push @surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => $group->[0]->surface_type,
|
||||
bridge_angle => $group->[0]->bridge_angle,
|
||||
depth_layers => $group->[0]->depth_layers,
|
||||
|
@ -100,7 +101,8 @@ sub make_fill {
|
|||
[ @offsets ],
|
||||
);
|
||||
|
||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
push @new_surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => $surface->surface_type,
|
||||
bridge_angle => $surface->bridge_angle,
|
||||
depth_layers => $surface->depth_layers,
|
||||
|
@ -111,7 +113,7 @@ sub make_fill {
|
|||
|
||||
# organize infill surfaces using a shortest path search
|
||||
@surfaces = @{shortest_path([
|
||||
map [ $_->contour->points->[0], $_ ], @surfaces,
|
||||
map [ $_->contour->[0], $_ ], @surfaces,
|
||||
])};
|
||||
|
||||
SURFACE: foreach my $surface (@surfaces) {
|
||||
|
@ -145,15 +147,14 @@ sub make_fill {
|
|||
# save into layer
|
||||
push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new(
|
||||
paths => [
|
||||
map Slic3r::ExtrusionPath->cast(
|
||||
[ @$_ ],
|
||||
map Slic3r::ExtrusionPath->new(
|
||||
polyline => Slic3r::Polyline->new(@$_),
|
||||
role => ($is_bridge ? 'bridge' : $is_solid ? 'solid-fill' : 'fill'),
|
||||
depth_layers => $surface->depth_layers,
|
||||
flow_spacing => $params->{flow_spacing},
|
||||
), @paths,
|
||||
],
|
||||
) if @paths;
|
||||
###$layer->fills->[-1]->cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ sub fill_surface {
|
|||
($bounding_box->[X1] + $bounding_box->[X2]) / 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
|
||||
$cur_pos = $loop->nearest_point_to($cur_pos);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ sub fill_surface {
|
|||
my $path = "Math::PlanePath::$1"->new;
|
||||
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,
|
||||
]);
|
||||
return {} if !@{$polyline->points};
|
||||
|
|
|
@ -55,7 +55,7 @@ sub fill_surface {
|
|||
# connect lines
|
||||
{
|
||||
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 = ();
|
||||
|
||||
|
|
|
@ -24,23 +24,15 @@ has 'lines' => (
|
|||
);
|
||||
|
||||
# collection of surfaces generated by slicing the original geometry
|
||||
has 'slices' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
has 'slices' => (is => 'ro', default => sub { [] });
|
||||
|
||||
# collection of polygons or polylines representing thin walls contained
|
||||
# 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
|
||||
has 'fill_boundaries' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
has 'fill_boundaries' => (is => 'ro', default => sub { [] });
|
||||
|
||||
# collection of surfaces generated by clipping the slices to the fill boundaries
|
||||
has 'surfaces' => (
|
||||
|
@ -150,7 +142,7 @@ sub make_surfaces {
|
|||
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
|
||||
|
||||
push @{$self->slices},
|
||||
map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'),
|
||||
map Slic3r::Surface->new(expolygon => $_, surface_type => 'internal'),
|
||||
@$expolygons;
|
||||
}
|
||||
|
||||
|
@ -160,8 +152,8 @@ sub make_surfaces {
|
|||
my @surfaces = @{$self->slices};
|
||||
@{$self->slices} = ();
|
||||
foreach my $surface (@surfaces) {
|
||||
push @{$self->slices}, map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal'),
|
||||
push @{$self->slices}, map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal'),
|
||||
$surface->expolygon->offset_ex(-$distance);
|
||||
}
|
||||
|
||||
|
@ -183,7 +175,7 @@ sub make_surfaces {
|
|||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
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} ],
|
||||
);
|
||||
}
|
||||
|
@ -210,7 +202,7 @@ sub prepare_fill_surfaces {
|
|||
(map $_->p, grep $_->surface_type eq 'top', @surfaces),
|
||||
(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);
|
||||
}
|
||||
|
||||
|
@ -242,7 +234,8 @@ sub remove_small_surfaces {
|
|||
@offsets = map $_->offset_ex($distance), @offsets;
|
||||
@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;
|
||||
}
|
||||
|
||||
|
@ -257,7 +250,8 @@ sub remove_small_surfaces {
|
|||
[ map $_->p, @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;
|
||||
}
|
||||
}
|
||||
|
@ -382,7 +376,8 @@ sub process_bridges {
|
|||
[ $bridge_offset ],
|
||||
);
|
||||
|
||||
push @bridges, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
push @bridges, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => $surface->surface_type,
|
||||
bridge_angle => $bridge_angle,
|
||||
), @$intersection;
|
||||
|
@ -405,7 +400,8 @@ sub process_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,
|
||||
bridge_angle => $surfaces->[0]->bridge_angle,
|
||||
), @$union;
|
||||
|
@ -424,7 +420,8 @@ sub process_bridges {
|
|||
[ $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,
|
||||
bridge_angle => $bridge->bridge_angle,
|
||||
), @$actual_bridge;
|
||||
|
@ -436,7 +433,8 @@ sub process_bridges {
|
|||
[ map $_->p, @$group ],
|
||||
[ 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,6 @@ sub new {
|
|||
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 b { $_[0][1] }
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ sub make_perimeter {
|
|||
|
||||
# organize perimeter surfaces using a shortest path search
|
||||
my @surfaces = @{shortest_path([
|
||||
map [ $_->contour->points->[0], $_ ], @{$layer->slices},
|
||||
map [ $_->contour->[0], $_ ], @{$layer->slices},
|
||||
])};
|
||||
|
||||
foreach my $surface (@surfaces) {
|
||||
|
@ -50,9 +50,7 @@ sub make_perimeter {
|
|||
|
||||
# create one more offset to be used as boundary for fill
|
||||
{
|
||||
my @fill_boundaries = map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => $surface->surface_type),
|
||||
map $_->offset_ex(-$distance), @last_offsets;
|
||||
my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets;
|
||||
|
||||
# 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,
|
||||
|
@ -66,12 +64,12 @@ sub make_perimeter {
|
|||
foreach my $island (@perimeters) {
|
||||
# do holes starting from innermost one
|
||||
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
|
||||
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
|
||||
for (@{ $layer->thin_walls }) {
|
||||
if ($_->isa('Slic3r::Polygon')) {
|
||||
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->cast($_, role => 'perimeter');
|
||||
push @{ $layer->perimeters }, Slic3r::ExtrusionLoop->new(polygon => $_, role => 'perimeter');
|
||||
} 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;
|
||||
|
||||
# a polygon is a closed polyline.
|
||||
# if you're asking why there's a Slic3r::Polygon as well
|
||||
# as a Slic3r::Polyline::Closed you're right. I plan to
|
||||
# ditch the latter and port everything to this class.
|
||||
use parent 'Slic3r::Polyline';
|
||||
|
||||
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);
|
||||
use Slic3r::Geometry::Clipper qw(JT_MITER);
|
||||
|
||||
|
@ -31,12 +30,6 @@ sub clone {
|
|||
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 {
|
||||
my $self = shift;
|
||||
return map Slic3r::Line->new($_), polygon_lines($self);
|
||||
|
@ -44,7 +37,20 @@ sub lines {
|
|||
|
||||
sub cleanup {
|
||||
my $self = shift;
|
||||
$self->merge_continuous_lines;
|
||||
}
|
||||
|
||||
sub merge_continuous_lines {
|
||||
my $self = shift;
|
||||
|
||||
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 {
|
||||
|
@ -106,7 +112,8 @@ sub subdivide {
|
|||
|
||||
# $num_points is the number of points to add between $i-1 and $i
|
||||
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;
|
||||
|
||||
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,38 +1,37 @@
|
|||
package Slic3r::Polyline;
|
||||
use Moo;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Math::Clipper qw();
|
||||
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);
|
||||
use Sub::Quote;
|
||||
move_points same_point);
|
||||
use XXX;
|
||||
|
||||
# arrayref of ordered points
|
||||
has 'points' => (
|
||||
is => 'rw',
|
||||
required => 1,
|
||||
default => sub { [] },
|
||||
isa => quote_sub q{ use Carp; confess "invalid points" if grep ref $_ ne 'Slic3r::Point', @{$_[0]} },
|
||||
);
|
||||
# the constructor accepts an array(ref) of points
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self;
|
||||
if (@_ == 1) {
|
||||
$self = [ @{$_[0]} ];
|
||||
} else {
|
||||
$self = [ @_ ];
|
||||
}
|
||||
|
||||
bless $self, $class;
|
||||
bless $_, 'Slic3r::Point' for @$self;
|
||||
$self;
|
||||
}
|
||||
|
||||
sub id {
|
||||
my $self = shift;
|
||||
return join ' - ', sort map $_->id, @{$self->points};
|
||||
}
|
||||
|
||||
sub cast {
|
||||
my $class = shift;
|
||||
my ($points, %args) = @_;
|
||||
|
||||
$points = [ map Slic3r::Point->cast($_), @$points ];
|
||||
return $class->new(points => $points, %args);
|
||||
return join ' - ', sort map $_->id, @$self;
|
||||
}
|
||||
|
||||
sub lines {
|
||||
my $self = shift;
|
||||
my @lines = ();
|
||||
my $previous_point;
|
||||
foreach my $point (@{ $self->points }) {
|
||||
foreach my $point (@$self) {
|
||||
if ($previous_point) {
|
||||
push @lines, Slic3r::Line->new($previous_point, $point);
|
||||
}
|
||||
|
@ -41,43 +40,25 @@ sub lines {
|
|||
return @lines;
|
||||
}
|
||||
|
||||
sub p {
|
||||
my $self = shift;
|
||||
return [ @{$self->points} ];
|
||||
}
|
||||
|
||||
sub merge_continuous_lines {
|
||||
my $self = shift;
|
||||
my $points = $self->p;
|
||||
if ($self->isa('Slic3r::Polyline::Closed')) {
|
||||
polygon_remove_parallel_continuous_edges($points);
|
||||
} else {
|
||||
polyline_remove_parallel_continuous_edges($points);
|
||||
}
|
||||
@{$self->points} = map Slic3r::Point->new($_), @$points;
|
||||
|
||||
polyline_remove_parallel_continuous_edges($self);
|
||||
bless $_, 'Slic3r::Point' for @$self;
|
||||
}
|
||||
|
||||
sub remove_acute_vertices {
|
||||
my $self = shift;
|
||||
my $points = $self->p;
|
||||
if ($self->isa('Slic3r::Polyline::Closed')) {
|
||||
polygon_remove_acute_vertices($points);
|
||||
} else {
|
||||
polyline_remove_acute_vertices($points);
|
||||
}
|
||||
@{$self->points} = map Slic3r::Point->new($_), @$points;
|
||||
polyline_remove_acute_vertices($self);
|
||||
bless $_, 'Slic3r::Point' for @$self;
|
||||
}
|
||||
|
||||
sub cleanup {
|
||||
sub simplify {
|
||||
my $self = shift;
|
||||
my $tolerance = shift || 10;
|
||||
|
||||
my $points = $self->p;
|
||||
push @$points, $points->[0] if $self->isa('Slic3r::Polyline::Closed');
|
||||
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;
|
||||
@$self = Slic3r::Geometry::Douglas_Peucker($self, $tolerance);
|
||||
bless $_, 'Slic3r::Point' for @$self;
|
||||
}
|
||||
|
||||
sub reverse_points {
|
||||
|
@ -104,7 +85,7 @@ sub nearest_point_to {
|
|||
my $self = shift;
|
||||
my ($point) = @_;
|
||||
|
||||
$point = Slic3r::Geometry::nearest_point($point, $self->p);
|
||||
$point = Slic3r::Geometry::nearest_point($point, $self);
|
||||
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 {
|
||||
|
|
|
@ -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, ],
|
||||
);
|
||||
|
||||
@{$layer->slices} = map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal'),
|
||||
@{$layer->slices} = map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal'),
|
||||
@$diff;
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ sub detect_surfaces_type {
|
|||
1,
|
||||
);
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -223,7 +223,7 @@ sub detect_surfaces_type {
|
|||
@internal = $surface_difference->($layer->slices, [@top, @bottom], 'internal');
|
||||
|
||||
# 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",
|
||||
$layer->id, scalar(@bottom), scalar(@top), scalar(@internal);
|
||||
|
@ -235,10 +235,10 @@ sub detect_surfaces_type {
|
|||
foreach my $surface (@{$layer->slices}) {
|
||||
my $intersection = intersection_ex(
|
||||
[ $surface->p ],
|
||||
[ map $_->p, @{$layer->fill_boundaries} ],
|
||||
[ map @$_, @{$layer->fill_boundaries} ],
|
||||
);
|
||||
push @{$layer->surfaces}, map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => $surface->surface_type),
|
||||
push @{$layer->surfaces}, map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => $surface->surface_type),
|
||||
@$intersection;
|
||||
}
|
||||
}
|
||||
|
@ -298,13 +298,13 @@ sub discover_horizontal_shells {
|
|||
# assign resulting inner surfaces to layer
|
||||
my $neighbor_fill_surfaces = $self->layers->[$n]->fill_surfaces;
|
||||
@$neighbor_fill_surfaces = ();
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal')
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal')
|
||||
for @$internal;
|
||||
|
||||
# assign new internal-solid surfaces to layer
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal-solid')
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal-solid')
|
||||
for @$internal_solid;
|
||||
|
||||
# assign top and bottom surfaces to layer
|
||||
|
@ -313,8 +313,8 @@ sub discover_horizontal_shells {
|
|||
[ map $_->p, @$s ],
|
||||
[ map @$_, @$internal_solid, @$internal ],
|
||||
);
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle)
|
||||
push @$neighbor_fill_surfaces, Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle)
|
||||
for @$solid_surfaces;
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +341,10 @@ sub extrude_skirt {
|
|||
for (my $i = $Slic3r::skirts - 1; $i >= 0; $i--) {
|
||||
my $distance = scale ($Slic3r::skirt_distance + ($Slic3r::flow_spacing * $i));
|
||||
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
|
||||
|
@ -387,12 +390,12 @@ sub infill_every_layers {
|
|||
{
|
||||
my @new_surfaces = ();
|
||||
push @new_surfaces, grep $_->surface_type ne 'internal', @{$layer->fill_surfaces};
|
||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal', depth_layers => $d + 1), @$intersection;
|
||||
push @new_surfaces, map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal', depth_layers => $d + 1), @$intersection;
|
||||
|
||||
foreach my $depth (reverse $d..$Slic3r::infill_every_layers) {
|
||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal', depth_layers => $depth),
|
||||
push @new_surfaces, map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal', depth_layers => $depth),
|
||||
|
||||
# difference between our internal layers with depth == $depth
|
||||
# and the intersection found
|
||||
|
@ -413,8 +416,8 @@ sub infill_every_layers {
|
|||
my @new_surfaces = ();
|
||||
push @new_surfaces, grep $_->surface_type ne 'internal', @{$lower_layer->fill_surfaces};
|
||||
foreach my $depth (1..$Slic3r::infill_every_layers) {
|
||||
push @new_surfaces, map Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal', depth_layers => $depth),
|
||||
push @new_surfaces, map Slic3r::Surface->new
|
||||
(expolygon => $_, surface_type => 'internal', depth_layers => $depth),
|
||||
|
||||
# difference between internal layers with depth == $depth
|
||||
# and the intersection found
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
package Slic3r::Surface;
|
||||
use Moo;
|
||||
|
||||
has 'contour' => (
|
||||
is => 'ro',
|
||||
#isa => 'Slic3r::Polyline::Closed',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has 'holes' => (
|
||||
traits => ['Array'],
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Polyline::Closed]',
|
||||
default => sub { [] },
|
||||
has 'expolygon' => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
handles => [qw(encloses_point lines contour holes)],
|
||||
);
|
||||
|
||||
has 'surface_type' => (
|
||||
|
@ -24,31 +17,6 @@ has 'depth_layers' => (is => 'ro', default => sub {1});
|
|||
|
||||
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
|
||||
sub group {
|
||||
my $class = shift;
|
||||
|
@ -73,7 +41,7 @@ sub add_hole {
|
|||
my $self = shift;
|
||||
my ($hole) = @_;
|
||||
|
||||
push @{ $self->holes }, $hole;
|
||||
push @$self, $hole;
|
||||
}
|
||||
|
||||
sub id {
|
||||
|
@ -81,15 +49,6 @@ sub 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 {
|
||||
my $self = shift;
|
||||
|
||||
|
@ -102,18 +61,8 @@ sub clipper_polygon {
|
|||
}
|
||||
|
||||
sub p {
|
||||
my $self = shift;
|
||||
return ($self->contour->p, map $_->p, @{$self->holes});
|
||||
}
|
||||
|
||||
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 };
|
||||
my $self = shift;use XXX; ZZZ $self->expolygon if !eval { 1 if @{$self->expolygon}; 1 };
|
||||
return @{$self->expolygon};
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
13
t/arcs.t
13
t/arcs.t
|
@ -13,13 +13,13 @@ use Slic3r;
|
|||
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],
|
||||
[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],
|
||||
[187029.11,267550.17], [158050.85,248012.49], [138513.17,219034.23], [131348.87,183548.2],
|
||||
[86948.77,175149.09], [119825.35,100585],
|
||||
], role => 'fill');
|
||||
), role => 'fill');
|
||||
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [$path]);
|
||||
$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],
|
||||
[12.3344536385591,19.7236992039768], [13.0901699437495,19.5105651629515],
|
||||
[13.8268343236509,19.2387953251129], [14.5399049973955,18.9100652418837],
|
||||
[15.2249856471595,18.5264016435409], [15.8778525229247,18.0901699437495],
|
||||
[16.4944804833018,17.6040596560003],
|
||||
], role => 'fill');
|
||||
my $path2 = Slic3r::ExtrusionPath->cast([ reverse @{$path1->points} ], role => 'fill');
|
||||
), 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 $collection2 = Slic3r::ExtrusionPath::Collection->new(paths => [$path2]);
|
||||
|
|
|
@ -2,7 +2,7 @@ use Test::More;
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 4;
|
||||
plan tests => 3;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
|
@ -11,87 +11,96 @@ BEGIN {
|
|||
|
||||
use Slic3r;
|
||||
|
||||
my $polyline = Slic3r::Polyline::Closed->cast([
|
||||
[5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0],
|
||||
]);
|
||||
{
|
||||
my $polygon = Slic3r::Polygon->new([
|
||||
[5,0], [10,0], [15,0], [20,0], [20,10], [20,30], [0,0],
|
||||
]);
|
||||
|
||||
$polyline->merge_continuous_lines;
|
||||
is scalar(@{$polyline->points}), 3, 'merge_continuous_lines';
|
||||
$polygon->merge_continuous_lines;
|
||||
is scalar(@$polygon), 3, 'merge_continuous_lines';
|
||||
}
|
||||
|
||||
my $gear = [
|
||||
[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],
|
||||
[106.6511,286.2133], [93.453,279.2327], [81.0065,271.4171], [67.7886,286.5055], [60.7927,280.1127],
|
||||
[69.3928,268.2566], [72.7271,264.9224], [61.8152,253.9959], [52.2273,242.8494], [47.5799,245.7224],
|
||||
[34.6577,252.6559], [30.3369,245.2236], [42.1712,236.3251], [46.1122,233.9605], [43.2099,228.4876],
|
||||
[35.0862,211.5672], [33.1441,207.0856], [13.3923,212.1895], [10.6572,203.3273], [6.0707,204.8561],
|
||||
[7.2775,204.4259], [29.6713,196.3631], [25.9815,172.1277], [25.4589,167.2745], [19.8337,167.0129],
|
||||
[5.0625,166.3346], [5.0625,156.9425], [5.3701,156.9282], [21.8636,156.1628], [25.3713,156.4613],
|
||||
[25.4243,155.9976], [29.3432,155.8157], [30.3838,149.3549], [26.3596,147.8137], [27.1085,141.2604],
|
||||
[29.8466,126.8337], [24.5841,124.9201], [10.6664,119.8989], [13.4454,110.9264], [33.1886,116.0691],
|
||||
[38.817,103.1819], [45.8311,89.8133], [30.4286,76.81], [35.7686,70.0812], [48.0879,77.6873],
|
||||
[51.564,81.1635], [61.9006,69.1791], [72.3019,58.7916], [60.5509,42.5416], [68.3369,37.1532],
|
||||
[77.9524,48.1338], [80.405,52.2215], [92.5632,44.5992], [93.0123,44.3223], [106.3561,37.2056],
|
||||
[100.8631,17.4679], [108.759,14.3778], [107.3148,11.1283], [117.0002,32.8627], [140.9109,27.3974],
|
||||
[145.7004,26.4994], [145.1346,6.1011], [154.502,5.4063], [156.9398,25.6501], [171.0557,26.2017],
|
||||
[181.3139,27.323], [186.2377,27.8532], [191.6031,8.5474], [200.6724,11.2756], [197.2362,30.2334],
|
||||
[220.0789,39.1906], [224.3261,41.031], [236.3506,24.4291], [243.6897,28.6723], [234.2956,46.7747],
|
||||
[245.6562,55.1643], [257.2523,65.0901], [261.4374,61.5679], [273.1709,52.8031], [278.555,59.5164],
|
||||
[268.4334,69.8001], [264.1615,72.3633], [268.2763,77.9442], [278.8488,93.5305], [281.4596,97.6332],
|
||||
[286.4487,95.5191], [300.2821,90.5903], [303.4456,98.5849], [286.4523,107.7253], [293.7063,131.1779],
|
||||
[294.9748,135.8787], [314.918,133.8172], [315.6941,143.2589], [300.9234,146.1746], [296.6419,147.0309],
|
||||
[297.1839,161.7052], [296.6136,176.3942], [302.1147,177.4857], [316.603,180.3608], [317.1658,176.7341],
|
||||
[315.215,189.6589], [315.1749,189.6548], [294.9411,187.5222], [291.13,201.7233], [286.2615,215.5916],
|
||||
[291.1944,218.2545], [303.9158,225.1271], [299.2384,233.3694], [285.7165,227.6001], [281.7091,225.1956],
|
||||
[273.8981,237.6457], [268.3486,245.2248], [267.4538,246.4414], [264.8496,250.0221], [268.6392,253.896],
|
||||
[278.5017,265.2131], [272.721,271.4403], [257.2776,258.3579], [234.4345,276.5687], [242.6222,294.8315],
|
||||
[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],
|
||||
[180.595,296.0487], [161.7854,297.4248], [156.8058,297.6214], [154.3395,317.8592],
|
||||
];
|
||||
$polyline = Slic3r::Polyline::Closed->cast($gear);
|
||||
$polyline->merge_continuous_lines;
|
||||
note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@{$polyline->points});
|
||||
ok @{$polyline->points} < @$gear, 'gear was simplified using merge_continuous_lines';
|
||||
{
|
||||
my $gear = [
|
||||
[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],
|
||||
[106.6511,286.2133], [93.453,279.2327], [81.0065,271.4171], [67.7886,286.5055], [60.7927,280.1127],
|
||||
[69.3928,268.2566], [72.7271,264.9224], [61.8152,253.9959], [52.2273,242.8494], [47.5799,245.7224],
|
||||
[34.6577,252.6559], [30.3369,245.2236], [42.1712,236.3251], [46.1122,233.9605], [43.2099,228.4876],
|
||||
[35.0862,211.5672], [33.1441,207.0856], [13.3923,212.1895], [10.6572,203.3273], [6.0707,204.8561],
|
||||
[7.2775,204.4259], [29.6713,196.3631], [25.9815,172.1277], [25.4589,167.2745], [19.8337,167.0129],
|
||||
[5.0625,166.3346], [5.0625,156.9425], [5.3701,156.9282], [21.8636,156.1628], [25.3713,156.4613],
|
||||
[25.4243,155.9976], [29.3432,155.8157], [30.3838,149.3549], [26.3596,147.8137], [27.1085,141.2604],
|
||||
[29.8466,126.8337], [24.5841,124.9201], [10.6664,119.8989], [13.4454,110.9264], [33.1886,116.0691],
|
||||
[38.817,103.1819], [45.8311,89.8133], [30.4286,76.81], [35.7686,70.0812], [48.0879,77.6873],
|
||||
[51.564,81.1635], [61.9006,69.1791], [72.3019,58.7916], [60.5509,42.5416], [68.3369,37.1532],
|
||||
[77.9524,48.1338], [80.405,52.2215], [92.5632,44.5992], [93.0123,44.3223], [106.3561,37.2056],
|
||||
[100.8631,17.4679], [108.759,14.3778], [107.3148,11.1283], [117.0002,32.8627], [140.9109,27.3974],
|
||||
[145.7004,26.4994], [145.1346,6.1011], [154.502,5.4063], [156.9398,25.6501], [171.0557,26.2017],
|
||||
[181.3139,27.323], [186.2377,27.8532], [191.6031,8.5474], [200.6724,11.2756], [197.2362,30.2334],
|
||||
[220.0789,39.1906], [224.3261,41.031], [236.3506,24.4291], [243.6897,28.6723], [234.2956,46.7747],
|
||||
[245.6562,55.1643], [257.2523,65.0901], [261.4374,61.5679], [273.1709,52.8031], [278.555,59.5164],
|
||||
[268.4334,69.8001], [264.1615,72.3633], [268.2763,77.9442], [278.8488,93.5305], [281.4596,97.6332],
|
||||
[286.4487,95.5191], [300.2821,90.5903], [303.4456,98.5849], [286.4523,107.7253], [293.7063,131.1779],
|
||||
[294.9748,135.8787], [314.918,133.8172], [315.6941,143.2589], [300.9234,146.1746], [296.6419,147.0309],
|
||||
[297.1839,161.7052], [296.6136,176.3942], [302.1147,177.4857], [316.603,180.3608], [317.1658,176.7341],
|
||||
[315.215,189.6589], [315.1749,189.6548], [294.9411,187.5222], [291.13,201.7233], [286.2615,215.5916],
|
||||
[291.1944,218.2545], [303.9158,225.1271], [299.2384,233.3694], [285.7165,227.6001], [281.7091,225.1956],
|
||||
[273.8981,237.6457], [268.3486,245.2248], [267.4538,246.4414], [264.8496,250.0221], [268.6392,253.896],
|
||||
[278.5017,265.2131], [272.721,271.4403], [257.2776,258.3579], [234.4345,276.5687], [242.6222,294.8315],
|
||||
[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],
|
||||
[180.595,296.0487], [161.7854,297.4248], [156.8058,297.6214], [154.3395,317.8592],
|
||||
];
|
||||
my $polygon = Slic3r::Polygon->new($gear);
|
||||
$polygon->merge_continuous_lines;
|
||||
note sprintf "original points: %d\nnew points: %d", scalar(@$gear), scalar(@$polygon);
|
||||
ok @$polygon < @$gear, 'gear was simplified using merge_continuous_lines';
|
||||
|
||||
my $num_points = scalar @{$polyline->points};
|
||||
$polyline->cleanup;
|
||||
note sprintf "original points: %d\nnew points: %d", $num_points, scalar(@{$polyline->points});
|
||||
ok @{$polyline->points} < $num_points, 'gear was further simplified using Douglas-Peucker';
|
||||
# simplify() is not being used, so we don't test it
|
||||
if (0) {
|
||||
my $num_points = scalar @$polygon;
|
||||
$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 = [
|
||||
[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],
|
||||
[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],
|
||||
[5833,8161.6],[5988.8,8116.3],[6032,8100.7],[6184.6,8045.8],[6226.8,8027.5],[6375.6,7963.2],[6416.6,7942.3],
|
||||
[6561.1,7868.6],[6600.7,7845.2],[6740.3,7762.7],[6778.4,7736.8],[6912.5,7645.7],[6948.8,7617.5],[7077,7518],
|
||||
[7111.5,7487.6],[7233.2,7380.4],[7347.9,7265.7],[7380.4,7233.2],[7410.8,7198.7],[7518,7077],[7546.2,7040.6],
|
||||
[7645.7,6912.5],[7671.5,6874.4],[7762.7,6740.3],[7786.1,6700.7],[7868.6,6561.1],[7889.5,6520.2],[7963.2,6375.6],
|
||||
[7981.4,6333.4],[8045.8,6184.6],[8061.4,6141.3],[8116.3,5988.8],[8129.2,5944.6],[8174.4,5788.8],[8184.4,5743.9],
|
||||
[8219.9,5585.6],[8227.1,5540.2],[8252.4,5380],[8256.7,5334.2],[8272,5172.8],[8273.4,5126.8],[8278.5,4964.7],
|
||||
[8277.1,4918.7],[8272,4756.6],[8267.7,4710.8],[8252.4,4549.4],[8245.2,4503.9],[8219.9,4343.8],[8209.8,4298.9],
|
||||
[8174.4,4140.6],[8161.6,4096.4],[8116.3,3940.6],[8100.7,3897.4],[8045.8,3744.8],[8027.5,3702.6],[7963.2,3553.8],
|
||||
[7942.3,3512.8],[7868.6,3368.3],[7845.2,3328.7],[7762.7,3189.1],[7736.8,3151],[7645.7,3016.9],[7617.5,2980.6],
|
||||
[7518,2852.4],[7487.6,2817.9],[7380.4,2696.2],[7347.9,2663.7],[7233.2,2549],[7198.7,2518.6],[7077,2411.4],
|
||||
[7040.6,2383.2],[6912.5,2283.7],[6874.4,2257.9],[6740.3,2166.7],[6700.7,2143.3],[6561.1,2060.8],[6520.2,2039.9],
|
||||
[6375.6,1966.2],[6333.4,1948],[6184.6,1883.6],[6141.3,1868],[5988.8,1813.1],[5944.6,1800.2],[5788.8,1755],
|
||||
[5743.9,1745],[5585.6,1709.5],[5540.2,1702.3],[5380,1677],[5334.2,1672.7],[5172.8,1657.4],[5126.8,1656],
|
||||
[4964.7,1650.9],[4918.7,1652.3],[4756.6,1657.4],[4710.8,1661.7],[4549.4,1677],[4503.9,1684.2],[4343.8,1709.5],
|
||||
[4298.9,1719.6],[4140.6,1755],[4096.4,1767.8],[3940.6,1813.1],[3897.4,1828.7],[3744.8,1883.6],[3702.6,1901.9],
|
||||
[3553.8,1966.2],[3512.8,1987.1],[3368.3,2060.8],[3328.7,2084.2],[3189.1,2166.7],[3151,2192.6],[3016.9,2283.7],
|
||||
[2980.6,2311.9],[2852.4,2411.4],[2817.9,2441.8],[2696.2,2549],[2581.5,2663.7],[2549,2696.2],[2518.6,2730.7],
|
||||
[2411.4,2852.4],[2383.2,2888.8],[2283.7,3016.9],[2257.9,3055],[2166.7,3189.1],[2143.3,3228.7],[2060.8,3368.3],
|
||||
[2039.9,3409.2],[1966.2,3553.8],[1948,3596],[1883.6,3744.8],[1868,3788.1],[1813.1,3940.6],[1800.2,3984.8],
|
||||
[1755,4140.6],[1745,4185.5],[1709.5,4343.8],[1702.3,4389.2],[1677,4549.4],[1672.7,4595.2],[1657.4,4756.6],
|
||||
[1656,4802.6],[1650.9,4964.7],[1652.3,5010.7],[1657.4,5172.8],[1661.7,5218.6],[1677,5380],[1684.2,5425.5],
|
||||
[1709.5,5585.6],[1719.6,5630.5],[1755,5788.8],[1767.8,5833],[1813.1,5988.8],[1828.7,6032],[1883.6,6184.6],
|
||||
[1901.9,6226.8],[1966.2,6375.6],[1987.1,6416.6],[2060.8,6561.1],[2084.2,6600.7],[2166.7,6740.3],[2192.6,6778.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],
|
||||
[3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4],
|
||||
];
|
||||
{
|
||||
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],
|
||||
[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],
|
||||
[5833,8161.6],[5988.8,8116.3],[6032,8100.7],[6184.6,8045.8],[6226.8,8027.5],[6375.6,7963.2],[6416.6,7942.3],
|
||||
[6561.1,7868.6],[6600.7,7845.2],[6740.3,7762.7],[6778.4,7736.8],[6912.5,7645.7],[6948.8,7617.5],[7077,7518],
|
||||
[7111.5,7487.6],[7233.2,7380.4],[7347.9,7265.7],[7380.4,7233.2],[7410.8,7198.7],[7518,7077],[7546.2,7040.6],
|
||||
[7645.7,6912.5],[7671.5,6874.4],[7762.7,6740.3],[7786.1,6700.7],[7868.6,6561.1],[7889.5,6520.2],[7963.2,6375.6],
|
||||
[7981.4,6333.4],[8045.8,6184.6],[8061.4,6141.3],[8116.3,5988.8],[8129.2,5944.6],[8174.4,5788.8],[8184.4,5743.9],
|
||||
[8219.9,5585.6],[8227.1,5540.2],[8252.4,5380],[8256.7,5334.2],[8272,5172.8],[8273.4,5126.8],[8278.5,4964.7],
|
||||
[8277.1,4918.7],[8272,4756.6],[8267.7,4710.8],[8252.4,4549.4],[8245.2,4503.9],[8219.9,4343.8],[8209.8,4298.9],
|
||||
[8174.4,4140.6],[8161.6,4096.4],[8116.3,3940.6],[8100.7,3897.4],[8045.8,3744.8],[8027.5,3702.6],[7963.2,3553.8],
|
||||
[7942.3,3512.8],[7868.6,3368.3],[7845.2,3328.7],[7762.7,3189.1],[7736.8,3151],[7645.7,3016.9],[7617.5,2980.6],
|
||||
[7518,2852.4],[7487.6,2817.9],[7380.4,2696.2],[7347.9,2663.7],[7233.2,2549],[7198.7,2518.6],[7077,2411.4],
|
||||
[7040.6,2383.2],[6912.5,2283.7],[6874.4,2257.9],[6740.3,2166.7],[6700.7,2143.3],[6561.1,2060.8],[6520.2,2039.9],
|
||||
[6375.6,1966.2],[6333.4,1948],[6184.6,1883.6],[6141.3,1868],[5988.8,1813.1],[5944.6,1800.2],[5788.8,1755],
|
||||
[5743.9,1745],[5585.6,1709.5],[5540.2,1702.3],[5380,1677],[5334.2,1672.7],[5172.8,1657.4],[5126.8,1656],
|
||||
[4964.7,1650.9],[4918.7,1652.3],[4756.6,1657.4],[4710.8,1661.7],[4549.4,1677],[4503.9,1684.2],[4343.8,1709.5],
|
||||
[4298.9,1719.6],[4140.6,1755],[4096.4,1767.8],[3940.6,1813.1],[3897.4,1828.7],[3744.8,1883.6],[3702.6,1901.9],
|
||||
[3553.8,1966.2],[3512.8,1987.1],[3368.3,2060.8],[3328.7,2084.2],[3189.1,2166.7],[3151,2192.6],[3016.9,2283.7],
|
||||
[2980.6,2311.9],[2852.4,2411.4],[2817.9,2441.8],[2696.2,2549],[2581.5,2663.7],[2549,2696.2],[2518.6,2730.7],
|
||||
[2411.4,2852.4],[2383.2,2888.8],[2283.7,3016.9],[2257.9,3055],[2166.7,3189.1],[2143.3,3228.7],[2060.8,3368.3],
|
||||
[2039.9,3409.2],[1966.2,3553.8],[1948,3596],[1883.6,3744.8],[1868,3788.1],[1813.1,3940.6],[1800.2,3984.8],
|
||||
[1755,4140.6],[1745,4185.5],[1709.5,4343.8],[1702.3,4389.2],[1677,4549.4],[1672.7,4595.2],[1657.4,4756.6],
|
||||
[1656,4802.6],[1650.9,4964.7],[1652.3,5010.7],[1657.4,5172.8],[1661.7,5218.6],[1677,5380],[1684.2,5425.5],
|
||||
[1709.5,5585.6],[1719.6,5630.5],[1755,5788.8],[1767.8,5833],[1813.1,5988.8],[1828.7,6032],[1883.6,6184.6],
|
||||
[1901.9,6226.8],[1966.2,6375.6],[1987.1,6416.6],[2060.8,6561.1],[2084.2,6600.7],[2166.7,6740.3],[2192.6,6778.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],
|
||||
[3368.3,7868.6],[3409.2,7889.5],[3553.8,7963.2],[3596,7981.4],
|
||||
];
|
||||
|
||||
$polyline = Slic3r::Polyline::Closed->cast($circle);
|
||||
$polyline->merge_continuous_lines;
|
||||
note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@{$polyline->points});
|
||||
ok @{$polyline->points} >= @$gear/3, 'circle was simplified using merge_continuous_lines';
|
||||
my $polygon = Slic3r::Polygon->new($circle);
|
||||
$polygon->merge_continuous_lines;
|
||||
note sprintf "original points: %d\nnew points: %d", scalar(@$circle), scalar(@$polygon);
|
||||
ok @$polygon >= @$circle/3, 'circle was simplified using merge_continuous_lines';
|
||||
}
|
||||
|
|
|
@ -103,8 +103,8 @@ is_deeply $intersection, [ [12, 12], [18, 16] ], 'internal lines are preserved';
|
|||
], '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] ]);
|
||||
is_deeply [ map $_->p, $polyline->clip_with_expolygon($expolygon) ], [
|
||||
my $polyline = Slic3r::Polyline->new([ [5, 18], [25, 18], [25, 15], [15, 15], [15, 12], [12, 12], [12, 5] ]);
|
||||
is_deeply [ map $_, $polyline->clip_with_expolygon($expolygon) ], [
|
||||
[ [10, 18], [20, 18] ],
|
||||
[ [20, 15], [16, 15] ],
|
||||
[ [15, 14], [15, 12], [12, 12], [12, 10] ],
|
||||
|
|
Loading…
Reference in a new issue