2012-04-16 09:55:14 +00:00
|
|
|
package Slic3r::Fill::Honeycomb;
|
|
|
|
use Moo;
|
|
|
|
|
|
|
|
extends 'Slic3r::Fill::Base';
|
|
|
|
|
2012-10-30 13:34:41 +00:00
|
|
|
has 'bounding_box' => (is => 'rw');
|
|
|
|
has 'cache' => (is => 'rw', default => sub {{}});
|
2012-04-16 09:55:14 +00:00
|
|
|
|
|
|
|
use Slic3r::Geometry qw(PI X1 Y1 X2 Y2 X Y scale);
|
|
|
|
use Slic3r::Geometry::Clipper qw(intersection_ex);
|
|
|
|
|
|
|
|
sub angles () { [0, PI/3, PI/3*2] }
|
|
|
|
|
|
|
|
sub fill_surface {
|
|
|
|
my $self = shift;
|
|
|
|
my ($surface, %params) = @_;
|
|
|
|
|
|
|
|
# rotate polygons so that we can work with vertical lines here
|
|
|
|
my $expolygon = $surface->expolygon->clone;
|
|
|
|
my $rotate_vector = $self->infill_direction($surface);
|
|
|
|
|
|
|
|
# infill math
|
|
|
|
my $min_spacing = scale $params{flow_spacing};
|
|
|
|
my $distance = $min_spacing / $params{density};
|
2012-10-30 13:21:59 +00:00
|
|
|
my $overlap_distance = scale $params{flow_spacing} * &Slic3r::PERIMETER_INFILL_OVERLAP_OVER_SPACING;
|
2012-04-16 09:55:14 +00:00
|
|
|
|
|
|
|
my $cache_id = sprintf "d%s_s%s_a%s",
|
|
|
|
$params{density}, $params{flow_spacing}, $rotate_vector->[0][0];
|
2013-03-16 20:10:12 +00:00
|
|
|
if (!$self->cache->{$cache_id} || !defined $self->bounding_box) {
|
2012-04-16 09:55:14 +00:00
|
|
|
|
|
|
|
# hexagons math
|
|
|
|
my $hex_side = $distance / (sqrt(3)/2);
|
|
|
|
my $hex_width = $distance * 2; # $hex_width == $hex_side * sqrt(3);
|
|
|
|
my $hex_height = $hex_side * 2;
|
|
|
|
my $pattern_height = $hex_height + $hex_side;
|
|
|
|
my $y_short = $distance * sqrt(3)/3;
|
|
|
|
my $x_offset = $min_spacing / 2;
|
|
|
|
my $y_offset = $x_offset * sqrt(3)/3;
|
|
|
|
my $hex_center = Slic3r::Point->new($hex_width/2, $hex_side);
|
|
|
|
|
|
|
|
# adjust actual bounding box to the nearest multiple of our hex pattern
|
|
|
|
# and align it so that it matches across layers
|
2013-03-16 20:10:12 +00:00
|
|
|
my $bounding_box = [ $self->bounding_box ? @{$self->bounding_box} : $expolygon->bounding_box ];
|
|
|
|
$bounding_box->[$_] = 0 for X1, Y1;
|
2012-04-16 09:55:14 +00:00
|
|
|
{
|
2013-03-16 20:10:12 +00:00
|
|
|
my $bb_polygon = Slic3r::Polygon->new_from_bounding_box($bounding_box);
|
2012-04-16 09:55:14 +00:00
|
|
|
$bb_polygon->rotate($rotate_vector->[0][0], $hex_center);
|
|
|
|
$bounding_box = [ Slic3r::Geometry::bounding_box($bb_polygon) ];
|
|
|
|
# $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
|
|
|
|
$bounding_box->[X1] -= $bounding_box->[X1] % $hex_width;
|
|
|
|
$bounding_box->[Y1] -= $bounding_box->[Y1] % $pattern_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
my @polygons = ();
|
|
|
|
my $x = $bounding_box->[X1];
|
|
|
|
while ($x <= $bounding_box->[X2]) {
|
|
|
|
my $p = [];
|
|
|
|
|
|
|
|
my @x = ($x + $x_offset, $x + $distance - $x_offset);
|
|
|
|
for (1..2) {
|
|
|
|
@$p = reverse @$p; # turn first half upside down
|
|
|
|
my @p = ();
|
|
|
|
for (my $y = $bounding_box->[Y1]; $y <= $bounding_box->[Y2]; $y += $y_short + $hex_side + $y_short + $hex_side) {
|
|
|
|
push @$p,
|
|
|
|
[ $x[1], $y + $y_offset ],
|
|
|
|
[ $x[0], $y + $y_short - $y_offset ],
|
|
|
|
[ $x[0], $y + $y_short + $hex_side + $y_offset ],
|
|
|
|
[ $x[1], $y + $y_short + $hex_side + $y_short - $y_offset ],
|
|
|
|
[ $x[1], $y + $y_short + $hex_side + $y_short + $hex_side + $y_offset ];
|
|
|
|
}
|
|
|
|
@x = map $_ + $distance, reverse @x; # draw symmetrical pattern
|
|
|
|
$x += $distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
push @polygons, Slic3r::Polygon->new($p);
|
|
|
|
}
|
|
|
|
|
|
|
|
$_->rotate(-$rotate_vector->[0][0], $hex_center) for @polygons;
|
|
|
|
$self->cache->{$cache_id} = [@polygons];
|
|
|
|
}
|
|
|
|
|
2012-08-24 17:19:45 +00:00
|
|
|
# build polylines from polygons without re-appending the initial point:
|
|
|
|
# this cuts the last segment on purpose, so that the jump to the next
|
|
|
|
# path is more straight
|
|
|
|
my @paths = map Slic3r::Polyline->new(@$_), map @$_, @{intersection_ex(
|
2012-04-16 09:55:14 +00:00
|
|
|
$self->cache->{$cache_id},
|
|
|
|
[ map @$_, $expolygon->offset_ex($overlap_distance) ],
|
2012-06-24 14:09:24 +00:00
|
|
|
)};
|
2012-04-16 09:55:14 +00:00
|
|
|
|
2012-09-12 10:13:43 +00:00
|
|
|
return { flow_spacing => $params{flow_spacing} },
|
2013-02-05 16:27:45 +00:00
|
|
|
Slic3r::Polyline::Collection->new(polylines => \@paths)->chained_path;
|
2012-04-16 09:55:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
1;
|