Better implementation of the external motion planner
This commit is contained in:
parent
27090f83bd
commit
c98e9515ed
4 changed files with 46 additions and 28 deletions
lib/Slic3r
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
|
|
||||||
use Boost::Geometry::Utils;
|
use Boost::Geometry::Utils;
|
||||||
use Math::Geometry::Voronoi;
|
use Math::Geometry::Voronoi;
|
||||||
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line scale epsilon);
|
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line line_length scale epsilon);
|
||||||
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
|
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER);
|
||||||
|
|
||||||
# the constructor accepts an array of polygons
|
# the constructor accepts an array of polygons
|
||||||
|
@ -110,10 +110,14 @@ sub encloses_point_quick {
|
||||||
|
|
||||||
sub encloses_line {
|
sub encloses_line {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($line) = @_;
|
my ($line, $tolerance) = @_;
|
||||||
|
|
||||||
my $clip = $self->clip_line($line);
|
my $clip = $self->clip_line($line);
|
||||||
return @$clip == 1 && abs($line->length - Slic3r::Geometry::line_length($clip->[0])) < scale epsilon;
|
if (!defined $tolerance) {
|
||||||
|
# optimization
|
||||||
|
return @$clip == 1 && same_line($clip->[0], $line);
|
||||||
|
} else {
|
||||||
|
return @$clip == 1 && abs(line_length($clip->[0]) - $line->length) < $tolerance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub point_on_segment {
|
sub point_on_segment {
|
||||||
|
|
|
@ -11,8 +11,10 @@ has 'shift_y' => (is => 'rw', default => sub {0} );
|
||||||
has 'z' => (is => 'rw', default => sub {0} );
|
has 'z' => (is => 'rw', default => sub {0} );
|
||||||
has 'speed' => (is => 'rw');
|
has 'speed' => (is => 'rw');
|
||||||
|
|
||||||
has 'motionplanner' => (is => 'rw');
|
has 'external_mp' => (is => 'rw');
|
||||||
has 'straight_once' => (is => 'rw');
|
has 'layer_mp' => (is => 'rw');
|
||||||
|
has 'new_object' => (is => 'rw', default => sub {0});
|
||||||
|
has 'straight_once' => (is => 'rw', default => sub {1});
|
||||||
has 'extruder_idx' => (is => 'rw');
|
has 'extruder_idx' => (is => 'rw');
|
||||||
has 'extrusion_distance' => (is => 'rw', default => sub {0} );
|
has 'extrusion_distance' => (is => 'rw', default => sub {0} );
|
||||||
has 'elapsed_time' => (is => 'rw', default => sub {0} ); # seconds
|
has 'elapsed_time' => (is => 'rw', default => sub {0} ); # seconds
|
||||||
|
@ -76,7 +78,7 @@ sub change_layer {
|
||||||
|
|
||||||
$self->layer($layer);
|
$self->layer($layer);
|
||||||
if ($Slic3r::Config->avoid_crossing_perimeters) {
|
if ($Slic3r::Config->avoid_crossing_perimeters) {
|
||||||
$self->motionplanner(Slic3r::GCode::MotionPlanner->new(
|
$self->layer_mp(Slic3r::GCode::MotionPlanner->new(
|
||||||
islands => union_ex([ map @{$_->expolygon}, @{$layer->slices} ], undef, 1),
|
islands => union_ex([ map @{$_->expolygon}, @{$layer->slices} ], undef, 1),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -216,13 +218,32 @@ sub travel_to {
|
||||||
my ($point, $comment) = @_;
|
my ($point, $comment) = @_;
|
||||||
|
|
||||||
return "" if points_coincide($self->last_pos, $point);
|
return "" if points_coincide($self->last_pos, $point);
|
||||||
|
|
||||||
|
my $gcode = "";
|
||||||
if ($Slic3r::Config->avoid_crossing_perimeters && $self->last_pos->distance_to($point) > scale 5 && !$self->straight_once) {
|
if ($Slic3r::Config->avoid_crossing_perimeters && $self->last_pos->distance_to($point) > scale 5 && !$self->straight_once) {
|
||||||
return join '', map $self->G0($_->b, undef, 0, $comment || ""),
|
my $plan = sub {
|
||||||
$self->motionplanner->shortest_path($self->last_pos, $point)->lines;
|
my $mp = shift;
|
||||||
|
return join '',
|
||||||
|
map $self->G0($_->b, undef, 0, $comment || ""),
|
||||||
|
$mp->shortest_path($self->last_pos, $point)->lines;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($self->new_object) {
|
||||||
|
my @shift = ($self->shift_x, $self->shift_y);
|
||||||
|
$self->set_shift(0,0);
|
||||||
|
$point->translate(map scale $_, @shift);
|
||||||
|
$gcode .= $plan->($self->external_mp);
|
||||||
|
$self->new_object(0);
|
||||||
|
$self->set_shift(@shift);
|
||||||
|
} else {
|
||||||
|
$gcode .= $plan->($self->layer_mp);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$self->straight_once(0);
|
$self->straight_once(0);
|
||||||
return $self->G0($point, undef, 0, $comment || "");
|
$gcode .= $self->G0($point, undef, 0, $comment || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub retract {
|
sub retract {
|
||||||
|
|
|
@ -45,7 +45,7 @@ sub BUILD {
|
||||||
for my $i (0 .. $#points) {
|
for my $i (0 .. $#points) {
|
||||||
for my $j (($i+1) .. $#points) {
|
for my $j (($i+1) .. $#points) {
|
||||||
my $line = Slic3r::Line->new($points[$i], $points[$j]);
|
my $line = Slic3r::Line->new($points[$i], $points[$j]);
|
||||||
if ($expolygon->encloses_line($line, scale Slic3r::Geometry::epsilon)) {
|
if ($expolygon->encloses_line($line, $tolerance)) {
|
||||||
my $dist = $line->length * ($crosses_perimeter ? CROSSING_FACTOR : 1);
|
my $dist = $line->length * ($crosses_perimeter ? CROSSING_FACTOR : 1);
|
||||||
$edges->{$points[$i]}{$points[$j]} = $dist;
|
$edges->{$points[$i]}{$points[$j]} = $dist;
|
||||||
$edges->{$points[$j]}{$points[$i]} = $dist;
|
$edges->{$points[$j]}{$points[$i]} = $dist;
|
||||||
|
|
|
@ -614,7 +614,6 @@ sub write_gcode {
|
||||||
);
|
);
|
||||||
|
|
||||||
# initialize a motion planner for object-to-object travel moves
|
# initialize a motion planner for object-to-object travel moves
|
||||||
my $external_motionplanner;
|
|
||||||
if ($Slic3r::Config->avoid_crossing_perimeters) {
|
if ($Slic3r::Config->avoid_crossing_perimeters) {
|
||||||
my $distance_from_objects = 1;
|
my $distance_from_objects = 1;
|
||||||
# compute the offsetted convex hull for each object and repeat it for each copy.
|
# compute the offsetted convex hull for each object and repeat it for each copy.
|
||||||
|
@ -622,15 +621,15 @@ sub write_gcode {
|
||||||
foreach my $obj_idx (0 .. $#{$self->objects}) {
|
foreach my $obj_idx (0 .. $#{$self->objects}) {
|
||||||
my @island = Slic3r::ExPolygon->new(convex_hull([
|
my @island = Slic3r::ExPolygon->new(convex_hull([
|
||||||
map @{$_->expolygon->contour}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers},
|
map @{$_->expolygon->contour}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers},
|
||||||
]))->translate(map -$_, @shift)->offset_ex(scale $distance_from_objects);
|
]))->translate(scale $shift[X], scale $shift[Y])->offset_ex(scale $distance_from_objects, 1, JT_SQUARE);
|
||||||
foreach my $copy (@{$self->copies->[$obj_idx]}) {
|
foreach my $copy (@{$self->copies->[$obj_idx]}) {
|
||||||
push @islands, map $_->clone->translate(@$copy), @island;
|
push @islands, map $_->clone->translate(@$copy), @island;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$external_motionplanner = Slic3r::GCode::MotionPlanner->new(
|
$gcodegen->external_mp(Slic3r::GCode::MotionPlanner->new(
|
||||||
islands => union_ex([ map @$_, @islands ]),
|
islands => union_ex([ map @$_, @islands ]),
|
||||||
no_internal => 1,
|
no_internal => 1,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
# prepare the logic to print one layer
|
# prepare the logic to print one layer
|
||||||
|
@ -663,6 +662,7 @@ sub write_gcode {
|
||||||
$gcode .= $gcodegen->extrude_loop($_, 'skirt') for @{$self->skirt};
|
$gcode .= $gcodegen->extrude_loop($_, 'skirt') for @{$self->skirt};
|
||||||
}
|
}
|
||||||
$skirt_done++;
|
$skirt_done++;
|
||||||
|
$gcodegen->straight_once(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
# extrude brim
|
# extrude brim
|
||||||
|
@ -670,27 +670,18 @@ sub write_gcode {
|
||||||
$gcodegen->set_shift(@shift);
|
$gcodegen->set_shift(@shift);
|
||||||
$gcode .= $gcodegen->extrude_loop($_, 'brim') for @{$self->brim};
|
$gcode .= $gcodegen->extrude_loop($_, 'brim') for @{$self->brim};
|
||||||
$brim_done = 1;
|
$brim_done = 1;
|
||||||
|
$gcodegen->straight_once(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for my $obj_copy (@$object_copies) {
|
for my $obj_copy (@$object_copies) {
|
||||||
my ($obj_idx, $copy) = @$obj_copy;
|
my ($obj_idx, $copy) = @$obj_copy;
|
||||||
|
$gcodegen->new_object(1) if $last_obj_copy && $last_obj_copy ne "${obj_idx}_${copy}";
|
||||||
my $layer = $self->objects->[$obj_idx]->layers->[$layer_id];
|
my $layer = $self->objects->[$obj_idx]->layers->[$layer_id];
|
||||||
|
|
||||||
# retract explicitely because changing the shift_[xy] properties below
|
# retract explicitely because changing the shift_[xy] properties below
|
||||||
# won't always trigger the automatic retraction
|
# won't always trigger the automatic retraction
|
||||||
$gcode .= $gcodegen->retract;
|
$gcode .= $gcodegen->retract;
|
||||||
|
|
||||||
# travel to the first perimeter point using the external motion planner
|
|
||||||
if ($external_motionplanner && @{ $layer->perimeters } && !$gcodegen->straight_once && $last_obj_copy ne "${obj_idx}_${copy}") {
|
|
||||||
$gcodegen->set_shift(@shift);
|
|
||||||
my $layer_mp = $gcodegen->motionplanner;
|
|
||||||
$gcodegen->motionplanner($external_motionplanner);
|
|
||||||
my $first_perimeter = $layer->perimeters->[0]->unpack;
|
|
||||||
my $target = $first_perimeter->polygon->[0]->clone->translate(@$copy);
|
|
||||||
$gcode .= $gcodegen->travel_to($target, "move to first perimeter point");
|
|
||||||
$gcodegen->motionplanner($layer_mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
$gcodegen->set_shift(
|
$gcodegen->set_shift(
|
||||||
$shift[X] + unscale $copy->[X],
|
$shift[X] + unscale $copy->[X],
|
||||||
$shift[Y] + unscale $copy->[Y],
|
$shift[Y] + unscale $copy->[Y],
|
||||||
|
@ -773,8 +764,10 @@ sub write_gcode {
|
||||||
# this happens before Z goes down to layer 0 again, so that
|
# this happens before Z goes down to layer 0 again, so that
|
||||||
# no collision happens hopefully.
|
# no collision happens hopefully.
|
||||||
if ($finished_objects > 0) {
|
if ($finished_objects > 0) {
|
||||||
$gcodegen->shift_x($shift[X] + unscale $copy->[X]);
|
$gcodegen->set_shift(
|
||||||
$gcodegen->shift_y($shift[Y] + unscale $copy->[Y]);
|
$shift[X] + unscale $copy->[X],
|
||||||
|
$shift[Y] + unscale $copy->[Y],
|
||||||
|
);
|
||||||
print $fh $gcodegen->retract;
|
print $fh $gcodegen->retract;
|
||||||
print $fh $gcodegen->G0(Slic3r::Point->new(0,0), undef, 0, 'move to origin position for next object');
|
print $fh $gcodegen->G0(Slic3r::Point->new(0,0), undef, 0, 'move to origin position for next object');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue