Honeycomb infill. #300
This commit is contained in:
parent
0faebad4da
commit
cb182b8bc2
1
MANIFEST
1
MANIFEST
@ -13,6 +13,7 @@ lib/Slic3r/Fill/Base.pm
|
||||
lib/Slic3r/Fill/Concentric.pm
|
||||
lib/Slic3r/Fill/Flowsnake.pm
|
||||
lib/Slic3r/Fill/HilbertCurve.pm
|
||||
lib/Slic3r/Fill/Honeycomb.pm
|
||||
lib/Slic3r/Fill/Line.pm
|
||||
lib/Slic3r/Fill/OctagramSpiral.pm
|
||||
lib/Slic3r/Fill/PlanePath.pm
|
||||
|
@ -220,8 +220,8 @@ our $Options = {
|
||||
label => 'Fill pattern',
|
||||
cli => 'fill-pattern=s',
|
||||
type => 'select',
|
||||
values => [qw(rectilinear line concentric hilbertcurve archimedeanchords octagramspiral)],
|
||||
labels => [qw(rectilinear line concentric), 'hilbertcurve (slow)', 'archimedeanchords (slow)', 'octagramspiral (slow)'],
|
||||
values => [qw(rectilinear line concentric honeycomb hilbertcurve archimedeanchords octagramspiral)],
|
||||
labels => [qw(rectilinear line concentric honeycomb), 'hilbertcurve (slow)', 'archimedeanchords (slow)', 'octagramspiral (slow)'],
|
||||
},
|
||||
'solid_fill_pattern' => {
|
||||
label => 'Solid fill pattern',
|
||||
|
@ -6,6 +6,7 @@ use Slic3r::Fill::Base;
|
||||
use Slic3r::Fill::Concentric;
|
||||
use Slic3r::Fill::Flowsnake;
|
||||
use Slic3r::Fill::HilbertCurve;
|
||||
use Slic3r::Fill::Honeycomb;
|
||||
use Slic3r::Fill::Line;
|
||||
use Slic3r::Fill::OctagramSpiral;
|
||||
use Slic3r::Fill::PlanePath;
|
||||
@ -28,6 +29,7 @@ our %FillTypes = (
|
||||
hilbertcurve => 'Slic3r::Fill::HilbertCurve',
|
||||
line => 'Slic3r::Fill::Line',
|
||||
concentric => 'Slic3r::Fill::Concentric',
|
||||
honeycomb => 'Slic3r::Fill::Honeycomb',
|
||||
);
|
||||
|
||||
sub BUILD {
|
||||
|
@ -3,11 +3,14 @@ use Moo;
|
||||
|
||||
use XXX;
|
||||
|
||||
has 'print' => (is => 'rw');
|
||||
has 'layer' => (is => 'rw');
|
||||
has 'max_print_dimension' => (is => 'rw');
|
||||
|
||||
use constant PI => 4 * atan2(1, 1);
|
||||
|
||||
sub angles () { [0, PI/2] }
|
||||
|
||||
sub infill_direction {
|
||||
my $self = shift;
|
||||
my ($surface) = @_;
|
||||
@ -20,9 +23,9 @@ sub infill_direction {
|
||||
|
||||
if ($self->layer) {
|
||||
# alternate fill direction
|
||||
if (($self->layer->id / $surface->depth_layers) % 2) {
|
||||
$rotate[0] = Slic3r::Geometry::deg2rad($Slic3r::fill_angle) + PI/2;
|
||||
}
|
||||
my $layer_num = $self->layer->id / $surface->depth_layers;
|
||||
my $angle = $self->angles->[$layer_num % @{$self->angles}];
|
||||
$rotate[0] = Slic3r::Geometry::deg2rad($Slic3r::fill_angle) + $angle if $angle;
|
||||
}
|
||||
|
||||
# use bridge angle
|
||||
|
95
lib/Slic3r/Fill/Honeycomb.pm
Normal file
95
lib/Slic3r/Fill/Honeycomb.pm
Normal file
@ -0,0 +1,95 @@
|
||||
package Slic3r::Fill::Honeycomb;
|
||||
use Moo;
|
||||
|
||||
extends 'Slic3r::Fill::Base';
|
||||
|
||||
has 'cache' => (is => 'rw', default => sub {{}});
|
||||
|
||||
use Slic3r::Geometry qw(PI X1 Y1 X2 Y2 X Y scale);
|
||||
use Slic3r::Geometry::Clipper qw(intersection_ex);
|
||||
use XXX;
|
||||
|
||||
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};
|
||||
my $overlap_distance = scale $Slic3r::flow_width * 0.4;
|
||||
|
||||
my $cache_id = sprintf "d%s_s%s_a%s",
|
||||
$params{density}, $params{flow_spacing}, $rotate_vector->[0][0];
|
||||
if (!$self->cache->{$cache_id}) {
|
||||
|
||||
# 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
|
||||
my $bounding_box = [ 0, 0, $self->print->x_length, $self->print->y_length ];
|
||||
{
|
||||
my $bb_polygon = Slic3r::Polygon->new([
|
||||
[ $bounding_box->[X1], $bounding_box->[Y1] ],
|
||||
[ $bounding_box->[X2], $bounding_box->[Y1] ],
|
||||
[ $bounding_box->[X2], $bounding_box->[Y2] ],
|
||||
[ $bounding_box->[X1], $bounding_box->[Y2] ],
|
||||
]);
|
||||
$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];
|
||||
}
|
||||
|
||||
my $loops = intersection_ex(
|
||||
$self->cache->{$cache_id},
|
||||
[ map @$_, $expolygon->offset_ex($overlap_distance) ],
|
||||
);
|
||||
my @paths = map [ @$_, $_->[0] ], map @$_, @$loops;
|
||||
|
||||
return {}, @paths;
|
||||
}
|
||||
|
||||
1;
|
@ -54,6 +54,18 @@ sub distance_to {
|
||||
return Slic3r::Geometry::distance_between_points($self, $point);
|
||||
}
|
||||
|
||||
sub rotate {
|
||||
my $self = shift;
|
||||
my ($angle, $center) = @_;
|
||||
@$self = @{ +(Slic3r::Geometry::rotate_points($angle, $center, $self))[0] };
|
||||
}
|
||||
|
||||
sub translate {
|
||||
my $self = shift;
|
||||
my ($x, $y) = @_;
|
||||
@$self = @{ +(Slic3r::Geometry::move_points([$x, $y], $self))[0] };
|
||||
}
|
||||
|
||||
sub x { $_[0]->[0] }
|
||||
sub y { $_[0]->[1] }
|
||||
|
||||
|
@ -6,8 +6,7 @@ use warnings;
|
||||
use parent 'Slic3r::Polyline';
|
||||
|
||||
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
|
||||
scale polygon_remove_acute_vertices
|
||||
polygon_segment_having_point point_in_polygon move_points rotate_points);
|
||||
scale polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon);
|
||||
use Slic3r::Geometry::Clipper qw(JT_MITER);
|
||||
|
||||
# the constructor accepts an array(ref) of points
|
||||
@ -83,18 +82,6 @@ sub encloses_point {
|
||||
return point_in_polygon($point, $self);
|
||||
}
|
||||
|
||||
sub translate {
|
||||
my $self = shift;
|
||||
my ($x, $y) = @_;
|
||||
@$self = move_points([$x, $y], @$self);
|
||||
}
|
||||
|
||||
sub rotate {
|
||||
my $self = shift;
|
||||
my ($angle, $center) = @_;
|
||||
@$self = rotate_points($angle, $center, @$self);
|
||||
}
|
||||
|
||||
sub area {
|
||||
my $self = shift;
|
||||
return Slic3r::Geometry::Clipper::area($self);
|
||||
|
@ -114,10 +114,16 @@ sub bounding_box {
|
||||
return Slic3r::Geometry::bounding_box($self);
|
||||
}
|
||||
|
||||
sub rotate {
|
||||
my $self = shift;
|
||||
my ($angle, $center) = @_;
|
||||
@$self = Slic3r::Geometry::rotate_points($angle, $center, @$self);
|
||||
}
|
||||
|
||||
sub translate {
|
||||
my $self = shift;
|
||||
my ($x, $y) = @_;
|
||||
@$self = move_points([$x, $y], @$self);
|
||||
@$self = Slic3r::Geometry::move_points([$x, $y], @$self);
|
||||
}
|
||||
|
||||
1;
|
||||
|
Loading…
Reference in New Issue
Block a user