mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-14 10:17:55 -06:00
New seal_position option that replaces randomize_start, start_perimeters_at_concave_points and start_perimeters_at_non_overhang. The two latter options are now always on by default. A new "Aligned" seal position value has been added, that forces starting points to be aligned when not randomized. #1741 #925
This commit is contained in:
parent
c63bd8165d
commit
a3bd1b5302
17 changed files with 153 additions and 112 deletions
|
@ -8,7 +8,8 @@ use List::Util qw(first max);
|
|||
# cemetery of old config settings
|
||||
our @Ignore = qw(duplicate_x duplicate_y multiply_x multiply_y support_material_tool acceleration
|
||||
adjust_overhang_flow standby_temperature scale rotate duplicate duplicate_grid
|
||||
rotate scale duplicate_grid);
|
||||
rotate scale duplicate_grid start_perimeters_at_concave_points start_perimeters_at_non_overhang
|
||||
randomize_start);
|
||||
|
||||
our $Options = print_config_def();
|
||||
|
||||
|
@ -140,6 +141,10 @@ sub _handle_legacy {
|
|||
$value *= 100;
|
||||
$value = "$value"; # force update of the PV value, workaround for bug https://rt.cpan.org/Ticket/Display.html?id=94110
|
||||
}
|
||||
if ($opt_key eq 'randomize_start' && $value) {
|
||||
$opt_key = 'seal_position';
|
||||
$value = 'random';
|
||||
}
|
||||
|
||||
# For historical reasons, the world's full of configs having these very low values;
|
||||
# to avoid unexpected behavior we need to ignore them. Banning these two hard-coded
|
||||
|
|
|
@ -19,6 +19,7 @@ has '_layer_index' => (is => 'rw', default => sub {-1}); # just a counter
|
|||
has 'layer' => (is => 'rw');
|
||||
has '_layer_islands' => (is => 'rw');
|
||||
has '_upper_layer_islands' => (is => 'rw');
|
||||
has '_seal_position' => (is => 'ro', default => sub { {} }); # $object => pos
|
||||
has 'shift_x' => (is => 'rw', default => sub {0} );
|
||||
has 'shift_y' => (is => 'rw', default => sub {0} );
|
||||
has 'z' => (is => 'rw');
|
||||
|
@ -150,45 +151,37 @@ sub extrude_loop {
|
|||
# extrude all loops ccw
|
||||
my $was_clockwise = $loop->make_counter_clockwise;
|
||||
|
||||
# find candidate starting points
|
||||
# start looking for concave vertices not being overhangs
|
||||
my $polygon = $loop->polygon;
|
||||
my @concave = ();
|
||||
if ($self->config->start_perimeters_at_concave_points) {
|
||||
@concave = $polygon->concave_points;
|
||||
}
|
||||
my @candidates = ();
|
||||
if ($self->config->start_perimeters_at_non_overhang) {
|
||||
@candidates = grep !$loop->has_overhang_point($_), @concave;
|
||||
}
|
||||
if (!@candidates) {
|
||||
# if none, look for any concave vertex
|
||||
@candidates = @concave;
|
||||
if (!@candidates) {
|
||||
# if none, look for any non-overhang vertex
|
||||
if ($self->config->start_perimeters_at_non_overhang) {
|
||||
@candidates = grep !$loop->has_overhang_point($_), @$polygon;
|
||||
}
|
||||
if (!@candidates) {
|
||||
# if none, all points are valid candidates
|
||||
@candidates = @$polygon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# find the point of the loop that is closest to the current extruder position
|
||||
# or randomize if requested
|
||||
my $last_pos = $self->last_pos;
|
||||
if ($self->config->randomize_start && $loop->role == EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER) {
|
||||
$last_pos = Slic3r::Point->new(scale $self->config->print_center->[X], scale $self->config->bed_size->[Y]);
|
||||
$last_pos->rotate(rand(2*PI), $self->config->print_center);
|
||||
}
|
||||
|
||||
# split the loop at the starting point
|
||||
if ($self->config->spiral_vase) {
|
||||
$loop->split_at($last_pos);
|
||||
} else {
|
||||
$loop->split_at_vertex($last_pos->nearest_point(\@candidates));
|
||||
} elsif ($self->config->seal_position eq 'nearest' || $self->config->seal_position eq 'aligned') {
|
||||
my $polygon = $loop->polygon;
|
||||
my @candidates = @{$polygon->concave_points(PI*4/3)};
|
||||
@candidates = @{$polygon->convex_points(PI*2/3)} if !@candidates;
|
||||
@candidates = @{$polygon} if !@candidates;
|
||||
|
||||
my @non_overhang = grep !$loop->has_overhang_point($_), @candidates;
|
||||
@candidates = @non_overhang if @non_overhang;
|
||||
|
||||
if ($self->config->seal_position eq 'nearest') {
|
||||
$loop->split_at_vertex($last_pos->nearest_point(\@candidates));
|
||||
} elsif ($self->config->seal_position eq 'aligned') {
|
||||
if (defined $self->layer && defined $self->_seal_position->{$self->layer->object}) {
|
||||
$last_pos = $self->_seal_position->{$self->layer->object};
|
||||
}
|
||||
my $point = $self->_seal_position->{$self->layer->object} = $last_pos->nearest_point(\@candidates);
|
||||
$loop->split_at_vertex($point);
|
||||
}
|
||||
} elsif ($self->config->seal_position eq 'random') {
|
||||
if ($loop->role == EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER) {
|
||||
my $polygon = $loop->polygon;
|
||||
my $centroid = $polygon->centroid;
|
||||
$last_pos = Slic3r::Point->new($polygon->bounding_box->x_max, $centroid->y); #))
|
||||
$last_pos->rotate(rand(2*PI), $centroid);
|
||||
}
|
||||
$loop->split_at($last_pos);
|
||||
}
|
||||
|
||||
# clip the path to avoid the extruder to get exactly on the first point of the loop;
|
||||
|
|
|
@ -417,21 +417,17 @@ sub build {
|
|||
},
|
||||
{
|
||||
title => 'Quality (slower slicing)',
|
||||
options => [qw(extra_perimeters avoid_crossing_perimeters start_perimeters_at_concave_points start_perimeters_at_non_overhang thin_walls overhangs)],
|
||||
options => [qw(extra_perimeters avoid_crossing_perimeters thin_walls overhangs)],
|
||||
lines => [
|
||||
Slic3r::GUI::OptionsGroup->single_option_line('extra_perimeters'),
|
||||
Slic3r::GUI::OptionsGroup->single_option_line('avoid_crossing_perimeters'),
|
||||
{
|
||||
label => 'Start perimeters at',
|
||||
options => [qw(start_perimeters_at_concave_points start_perimeters_at_non_overhang)],
|
||||
},
|
||||
Slic3r::GUI::OptionsGroup->single_option_line('thin_walls'),
|
||||
Slic3r::GUI::OptionsGroup->single_option_line('overhangs'),
|
||||
],
|
||||
},
|
||||
{
|
||||
title => 'Advanced',
|
||||
options => [qw(randomize_start external_perimeters_first)],
|
||||
options => [qw(seal_position external_perimeters_first)],
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
@ -260,12 +260,19 @@ sub make_perimeters {
|
|||
|
||||
my $role = EXTR_ROLE_PERIMETER;
|
||||
my $loop_role = EXTRL_ROLE_DEFAULT;
|
||||
if ($is_contour ? $depth == 0 : !@{ $polynode->{children} }) {
|
||||
|
||||
my $root_level = $depth == 0;
|
||||
my $no_children = !@{ $polynode->{children} };
|
||||
my $is_external = $is_contour ? $root_level : $no_children;
|
||||
my $is_internal = $is_contour ? $no_children : $root_level;
|
||||
if ($is_external) {
|
||||
# external perimeters are root level in case of contours
|
||||
# and items with no children in case of holes
|
||||
$role = EXTR_ROLE_EXTERNAL_PERIMETER;
|
||||
$loop_role = EXTRL_ROLE_EXTERNAL_PERIMETER;
|
||||
} elsif ($depth == 1 && $is_contour) {
|
||||
} elsif ($is_contour && $is_internal) {
|
||||
# internal perimeters are root level in case of holes
|
||||
# and items with no children in case of contours
|
||||
$loop_role = EXTRL_ROLE_CONTOUR_INTERNAL_PERIMETER;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,15 +40,34 @@ sub subdivide {
|
|||
return Slic3r::Polygon->new(@new_points);
|
||||
}
|
||||
|
||||
# for cw polygons this will return convex points!
|
||||
# angle is checked on the internal side of the polygon
|
||||
sub concave_points {
|
||||
my $self = shift;
|
||||
my ($self, $angle) = @_;
|
||||
|
||||
$angle //= PI;
|
||||
|
||||
my @points = @$self;
|
||||
my @points_pp = @{$self->pp};
|
||||
return map $points[$_],
|
||||
grep Slic3r::Geometry::angle3points(@points_pp[$_, $_-1, $_+1]) < PI - epsilon,
|
||||
-1 .. ($#points-1);
|
||||
return [
|
||||
map $points[$_],
|
||||
grep Slic3r::Geometry::angle3points(@points_pp[$_, $_-1, $_+1]) < $angle,
|
||||
-1 .. ($#points-1)
|
||||
];
|
||||
}
|
||||
|
||||
# angle is checked on the internal side of the polygon
|
||||
sub convex_points {
|
||||
my ($self, $angle) = @_;
|
||||
|
||||
$angle //= PI;
|
||||
|
||||
my @points = @$self;
|
||||
my @points_pp = @{$self->pp};
|
||||
return [
|
||||
map $points[$_],
|
||||
grep Slic3r::Geometry::angle3points(@points_pp[$_, $_-1, $_+1]) > $angle,
|
||||
-1 .. ($#points-1)
|
||||
];
|
||||
}
|
||||
|
||||
1;
|
|
@ -3,7 +3,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use List::Util qw(first);
|
||||
use Slic3r::Geometry qw(X Y epsilon);
|
||||
use Slic3r::Geometry qw(X Y PI epsilon);
|
||||
use Slic3r::Geometry::Clipper qw(JT_SQUARE);
|
||||
|
||||
sub new_scale {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue