Align rectilinear and line infill across layers (new implementation). #712

This commit is contained in:
Alessandro Ranellucci 2013-04-18 17:34:21 +02:00
parent c723c07f8c
commit 430c825918
7 changed files with 57 additions and 51 deletions

View file

@ -5,6 +5,7 @@ use Slic3r::Geometry qw(PI);
has 'layer_id' => (is => 'rw');
has 'angle' => (is => 'rw', default => sub { $Slic3r::Config->fill_angle });
has 'bounding_box' => (is => 'ro', required => 1);
sub angles () { [0, PI/2] }
@ -15,7 +16,7 @@ sub infill_direction {
# set infill angle
my (@rotate, @shift);
$rotate[0] = Slic3r::Geometry::deg2rad($self->angle);
$rotate[1] = $surface->expolygon->bounding_box_center;
$rotate[1] = Slic3r::Geometry::bounding_box_center($self->bounding_box);
@shift = @{$rotate[1]};
if (defined $self->layer_id) {
@ -41,11 +42,9 @@ sub rotate_points {
my @rotate = @{$rotate_vector->[0]};
my @shift = @{$rotate_vector->[1]};
# rotate points as needed
if ($rotate[0]) {
$expolygon->rotate(@rotate);
$expolygon->translate(@shift);
}
# rotate points
$expolygon->rotate(@rotate);
$expolygon->translate(@shift);
}
sub rotate_points_back {
@ -54,10 +53,8 @@ sub rotate_points_back {
my @rotate = @{$rotate_vector->[0]};
my @shift = @{$rotate_vector->[1]};
if ($rotate[0]) {
@$paths = map [ Slic3r::Geometry::rotate_points(-$rotate[0], $rotate[1], @$_) ],
map [ Slic3r::Geometry::move_points([map -$_, @shift], @$_) ], @$paths;
}
@$paths = map [ Slic3r::Geometry::rotate_points(-$rotate[0], $rotate[1], @$_) ],
map [ Slic3r::Geometry::move_points([map -$_, @shift], @$_) ], @$paths;
}
sub adjust_solid_spacing {

View file

@ -3,7 +3,6 @@ use Moo;
extends 'Slic3r::Fill::Base';
has 'bounding_box' => (is => 'rw');
has 'cache' => (is => 'rw', default => sub {{}});
use Slic3r::Geometry qw(PI X1 Y1 X2 Y2 X Y scale);
@ -25,7 +24,7 @@ sub fill_surface {
my $cache_id = sprintf "d%s_s%s_a%s",
$params{density}, $params{flow_spacing}, $rotate_vector->[0][0];
if (!$self->cache->{$cache_id} || !defined $self->bounding_box) {
if (!$self->cache->{$cache_id}) {
# hexagons math
my $hex_side = $distance / (sqrt(3)/2);
@ -39,7 +38,7 @@ sub fill_surface {
# adjust actual bounding box to the nearest multiple of our hex pattern
# and align it so that it matches across layers
my $bounding_box = [ $self->bounding_box ? @{$self->bounding_box} : $expolygon->bounding_box ];
my $bounding_box = [ @{$self->bounding_box} ]; # clone
$bounding_box->[$_] = 0 for X1, Y1;
{
my $bb_polygon = Slic3r::Polygon->new_from_bounding_box($bounding_box);

View file

@ -3,6 +3,8 @@ use Moo;
extends 'Slic3r::Fill::Base';
has 'cache' => (is => 'rw', default => sub {{}});
use Slic3r::Geometry qw(X1 Y1 X2 Y2 A B X Y scale unscale scaled_epsilon);
sub fill_surface {
@ -16,39 +18,55 @@ sub fill_surface {
my ($expolygon_off) = $expolygon->offset_ex(scale $params{flow_spacing}/2);
return {} if !$expolygon_off; # skip some very small polygons (which shouldn't arrive here)
my $bounding_box = [ $expolygon->bounding_box ];
my $flow_spacing = $params{flow_spacing};
my $min_spacing = scale $params{flow_spacing};
my $distance_between_lines = $min_spacing / $params{density};
my $line_oscillation = $distance_between_lines - $min_spacing;
my $flow_spacing = $params{flow_spacing};
if ($params{density} == 1 && !$params{dont_adjust}) {
$distance_between_lines = $self->adjust_solid_spacing(
width => $bounding_box->[X2] - $bounding_box->[X1],
distance => $distance_between_lines,
);
$flow_spacing = unscale $distance_between_lines;
}
my $x = $bounding_box->[X1];
my $is_line_pattern = $self->isa('Slic3r::Fill::Line');
my @vertical_lines = ();
for (my $i = 0; $x <= $bounding_box->[X2] + scaled_epsilon; $i++) {
my $vertical_line = Slic3r::Line->new([$x, $bounding_box->[Y2]], [$x, $bounding_box->[Y1]]);
if ($is_line_pattern && $i % 2) {
$vertical_line->[A][X] += $line_oscillation;
$vertical_line->[B][X] -= $line_oscillation;
my $cache_id = sprintf "d%s_s%s_a%s",
$params{density}, $params{flow_spacing}, $rotate_vector->[0][0];
if (!$self->cache->{$cache_id}) {
# compute bounding box
my $bounding_box = $self->bounding_box;
{
my $bb_expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new_from_bounding_box($bounding_box));
$self->rotate_points($bb_expolygon, $rotate_vector);
$bounding_box = [ $bb_expolygon->bounding_box ];
}
push @vertical_lines, $vertical_line;
$x += $distance_between_lines;
# define flow spacing according to requested density
if ($params{density} == 1 && !$params{dont_adjust}) {
$distance_between_lines = $self->adjust_solid_spacing(
width => $bounding_box->[X2] - $bounding_box->[X1],
distance => $distance_between_lines,
);
$flow_spacing = unscale $distance_between_lines;
}
# generate the basic pattern
my $x = $bounding_box->[X1];
my @vertical_lines = ();
for (my $i = 0; $x <= $bounding_box->[X2] + scaled_epsilon; $i++) {
my $vertical_line = Slic3r::Line->new([$x, $bounding_box->[Y2]], [$x, $bounding_box->[Y1]]);
if ($is_line_pattern && $i % 2) {
$vertical_line->[A][X] += $line_oscillation;
$vertical_line->[B][X] -= $line_oscillation;
}
push @vertical_lines, $vertical_line;
$x += $distance_between_lines;
}
$self->cache->{$cache_id} = [@vertical_lines];
}
# clip paths against a slightly offsetted expolygon, so that the first and last paths
# are kept even if the expolygon has vertical sides
my @paths = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
+($expolygon->offset_ex(scaled_epsilon))[0], # TODO: we should use all the resulting expolygons and clip the linestrings to a multipolygon object
[ @vertical_lines ],
[ @{ $self->cache->{$cache_id} } ],
) };
# connect lines