Duplication is now performed on generated toolpaths instead of mesh (speed boost). #179
This commit is contained in:
parent
90c6ed3b20
commit
e0e2023a5a
@ -4,8 +4,8 @@ use Moo;
|
|||||||
use Slic3r::Geometry qw(scale);
|
use Slic3r::Geometry qw(scale);
|
||||||
|
|
||||||
has 'layer' => (is => 'rw');
|
has 'layer' => (is => 'rw');
|
||||||
has 'shift_x' => (is => 'ro', default => sub {0} );
|
has 'shift_x' => (is => 'rw', default => sub {0} );
|
||||||
has 'shift_y' => (is => 'ro', default => sub {0} );
|
has 'shift_y' => (is => 'rw', default => sub {0} );
|
||||||
has 'z' => (is => 'rw', default => sub {0} );
|
has 'z' => (is => 'rw', default => sub {0} );
|
||||||
has 'print_feed_rate' => (is => 'rw');
|
has 'print_feed_rate' => (is => 'rw');
|
||||||
|
|
||||||
|
@ -25,21 +25,23 @@ sub shortest_path {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($start_near) = @_;
|
my ($start_near) = @_;
|
||||||
|
|
||||||
|
my @my_paths = @{$self->paths};
|
||||||
my @paths = ();
|
my @paths = ();
|
||||||
my $start_at;
|
my $start_at;
|
||||||
CYCLE: while (@{$self->paths}) {
|
CYCLE: while (@my_paths) {
|
||||||
# find nearest point
|
# find nearest point
|
||||||
|
my $endpoints = [ map $_->endpoints, @my_paths ];
|
||||||
$start_at = $start_near
|
$start_at = $start_near
|
||||||
? Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, $self->endpoints))
|
? Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, $endpoints))
|
||||||
: $self->endpoints->[0];
|
: $self->endpoints->[0];
|
||||||
|
|
||||||
# loop through paths to find the one that starts or ends at the point found
|
# loop through paths to find the one that starts or ends at the point found
|
||||||
PATH: for (my $i = 0; $i <= $#{$self->paths}; $i++) {
|
PATH: for (my $i = 0; $i <= $#my_paths; $i++) {
|
||||||
if ($start_at->id eq $self->paths->[$i]->points->[0]->id) {
|
if ($start_at->id eq $my_paths[$i]->points->[0]->id) {
|
||||||
push @paths, splice @{$self->paths}, $i, 1;
|
push @paths, splice @my_paths, $i, 1;
|
||||||
} elsif ($start_at->id eq $self->paths->[$i]->points->[-1]->id) {
|
} elsif ($start_at->id eq $my_paths[$i]->points->[-1]->id) {
|
||||||
$self->paths->[$i]->reverse;
|
$my_paths[$i]->reverse;
|
||||||
push @paths, splice @{$self->paths}, $i, 1;
|
push @paths, splice @my_paths, $i, 1;
|
||||||
} else {
|
} else {
|
||||||
next PATH;
|
next PATH;
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,16 @@ package Slic3r::Print;
|
|||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
use Math::ConvexHull 1.0.4 qw(convex_hull);
|
use Math::ConvexHull 1.0.4 qw(convex_hull);
|
||||||
use Slic3r::Geometry qw(X Y Z PI MIN MAX scale);
|
use Slic3r::Geometry qw(X Y Z PI MIN MAX scale unscale move_points);
|
||||||
use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex
|
use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex
|
||||||
union_ex offset JT_ROUND JT_MITER);
|
union_ex offset JT_ROUND JT_MITER);
|
||||||
use XXX;
|
use XXX;
|
||||||
|
|
||||||
has 'x_length' => (
|
has 'x_length' => (is => 'ro', required => 1);
|
||||||
is => 'ro',
|
has 'y_length' => (is => 'ro', required => 1);
|
||||||
required => 1,
|
has 'total_x_length' => (is => 'rw'); # including duplicates
|
||||||
);
|
has 'total_y_length' => (is => 'rw'); # including duplicates
|
||||||
|
has 'copies' => (is => 'rw', default => sub {[]});
|
||||||
has 'y_length' => (
|
|
||||||
is => 'ro',
|
|
||||||
required => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'layers' => (
|
has 'layers' => (
|
||||||
traits => ['Array'],
|
traits => ['Array'],
|
||||||
@ -41,14 +37,6 @@ sub new_from_mesh {
|
|||||||
$mesh->move(@shift);
|
$mesh->move(@shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
# duplicate object
|
|
||||||
{
|
|
||||||
my @size = $mesh->size;
|
|
||||||
my @duplicate_offset = map +($size[$_] + scale $Slic3r::duplicate_distance), (X,Y);
|
|
||||||
$mesh->duplicate(map [$duplicate_offset[X] * ($_-1), 0], 2..$Slic3r::duplicate_x);
|
|
||||||
$mesh->duplicate(map [0, $duplicate_offset[Y] * ($_-1)], 2..$Slic3r::duplicate_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
# initialize print job
|
# initialize print job
|
||||||
my @size = $mesh->size;
|
my @size = $mesh->size;
|
||||||
my $print = $class->new(
|
my $print = $class->new(
|
||||||
@ -138,6 +126,24 @@ sub new_from_mesh {
|
|||||||
return $print;
|
return $print;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub BUILD {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $dist = scale $Slic3r::duplicate_distance;
|
||||||
|
$self->total_x_length($self->x_length * $Slic3r::duplicate_x + $dist * ($Slic3r::duplicate_x - 1));
|
||||||
|
$self->total_y_length($self->y_length * $Slic3r::duplicate_y + $dist * ($Slic3r::duplicate_y - 1));
|
||||||
|
|
||||||
|
# generate offsets for copies
|
||||||
|
for my $x_copy (1..$Slic3r::duplicate_x) {
|
||||||
|
for my $y_copy (1..$Slic3r::duplicate_y) {
|
||||||
|
push @{$self->copies}, [
|
||||||
|
($self->x_length + scale $Slic3r::duplicate_distance) * ($x_copy-1),
|
||||||
|
($self->y_length + scale $Slic3r::duplicate_distance) * ($y_copy-1),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub layer_count {
|
sub layer_count {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return scalar @{ $self->layers };
|
return scalar @{ $self->layers };
|
||||||
@ -339,6 +345,9 @@ sub extrude_skirt {
|
|||||||
);
|
);
|
||||||
return if !@points;
|
return if !@points;
|
||||||
|
|
||||||
|
# duplicate points to take copies into account
|
||||||
|
push @points, map move_points($_, @points), @{$self->copies};
|
||||||
|
|
||||||
# find out convex hull
|
# find out convex hull
|
||||||
my $convex_hull = convex_hull(\@points);
|
my $convex_hull = convex_hull(\@points);
|
||||||
|
|
||||||
@ -480,30 +489,39 @@ sub export_gcode {
|
|||||||
print $fh "M82 ; use absolute distances for extrusion\n";
|
print $fh "M82 ; use absolute distances for extrusion\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
# set up our extruder object
|
# calculate X,Y shift to center print around specified origin
|
||||||
my $extruder = Slic3r::Extruder->new(
|
my @shift = (
|
||||||
# calculate X,Y shift to center print around specified origin
|
$Slic3r::print_center->[X] - (unscale $self->total_x_length / 2),
|
||||||
shift_x => $Slic3r::print_center->[X] - ($self->x_length * $Slic3r::resolution / 2),
|
$Slic3r::print_center->[Y] - (unscale $self->total_y_length / 2),
|
||||||
shift_y => $Slic3r::print_center->[Y] - ($self->y_length * $Slic3r::resolution / 2),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# set up our extruder object
|
||||||
|
my $extruder = Slic3r::Extruder->new;
|
||||||
|
|
||||||
# write gcode commands layer by layer
|
# write gcode commands layer by layer
|
||||||
foreach my $layer (@{ $self->layers }) {
|
foreach my $layer (@{ $self->layers }) {
|
||||||
# go to layer
|
# go to layer
|
||||||
print $fh $extruder->change_layer($layer);
|
print $fh $extruder->change_layer($layer);
|
||||||
|
|
||||||
# extrude skirts
|
# extrude skirts
|
||||||
|
$extruder->shift_x($shift[X]);
|
||||||
|
$extruder->shift_y($shift[Y]);
|
||||||
print $fh $extruder->set_acceleration($Slic3r::perimeter_acceleration);
|
print $fh $extruder->set_acceleration($Slic3r::perimeter_acceleration);
|
||||||
print $fh $extruder->extrude_loop($_, 'skirt') for @{ $layer->skirts };
|
print $fh $extruder->extrude_loop($_, 'skirt') for @{ $layer->skirts };
|
||||||
|
|
||||||
# extrude perimeters
|
foreach my $copy (@{$self->copies}) {
|
||||||
print $fh $extruder->extrude($_, 'perimeter') for @{ $layer->perimeters };
|
$extruder->shift_x($shift[X] + unscale $copy->[X]);
|
||||||
|
$extruder->shift_y($shift[Y] + unscale $copy->[Y]);
|
||||||
# extrude fills
|
|
||||||
print $fh $extruder->set_acceleration($Slic3r::infill_acceleration);
|
# extrude perimeters
|
||||||
for my $fill (@{ $layer->fills }) {
|
print $fh $extruder->extrude($_, 'perimeter') for @{ $layer->perimeters };
|
||||||
print $fh $extruder->extrude_path($_, 'fill')
|
|
||||||
for $fill->shortest_path($extruder->last_pos);
|
# extrude fills
|
||||||
|
print $fh $extruder->set_acceleration($Slic3r::infill_acceleration);
|
||||||
|
for my $fill (@{ $layer->fills }) {
|
||||||
|
print $fh $extruder->extrude_path($_, 'fill')
|
||||||
|
for $fill->shortest_path($extruder->last_pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ has 'edges_facets' => (is => 'ro', default => sub { [] }); # id => [ $f1_id, $f
|
|||||||
use constant MIN => 0;
|
use constant MIN => 0;
|
||||||
use constant MAX => 1;
|
use constant MAX => 1;
|
||||||
|
|
||||||
|
# always make sure BUILD is idempotent
|
||||||
sub BUILD {
|
sub BUILD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
@ -303,6 +304,7 @@ sub duplicate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
push @{$self->facets}, @new_facets;
|
push @{$self->facets}, @new_facets;
|
||||||
|
$self->BUILD;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub bounding_box {
|
sub bounding_box {
|
||||||
|
Loading…
Reference in New Issue
Block a user