Rewrite honeycomb infill so that it only generates the pattern for the bounding box of the region instead of the full print, so reduce complexity of the clipping routine

This commit is contained in:
Alessandro Ranellucci 2013-06-16 13:13:52 +02:00
parent ac4a0bcdd8
commit 961586fe8f

View File

@ -14,69 +14,67 @@ sub fill_surface {
my $self = shift; my $self = shift;
my ($surface, %params) = @_; 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); my $rotate_vector = $self->infill_direction($surface);
# infill math # cache hexagons math
my $min_spacing = scale $params{flow_spacing}; my $cache_id = sprintf "d%s_s%s", $params{density}, $params{flow_spacing};
my $distance = $min_spacing / $params{density}; my $m;
if (!($m = $self->cache->{$cache_id})) {
$m = $self->cache->{$cache_id} = {};
my $min_spacing = scale $params{flow_spacing};
$m->{distance} = $min_spacing / $params{density};
$m->{hex_side} = $m->{distance} / (sqrt(3)/2);
$m->{hex_width} = $m->{distance} * 2; # $m->{hex_width} == $m->{hex_side} * sqrt(3);
my $hex_height = $m->{hex_side} * 2;
$m->{pattern_height} = $hex_height + $m->{hex_side};
$m->{y_short} = $m->{distance} * sqrt(3)/3;
$m->{x_offset} = $min_spacing / 2;
$m->{y_offset} = $m->{x_offset} * sqrt(3)/3;
$m->{hex_center} = Slic3r::Point->new($m->{hex_width}/2, $m->{hex_side});
}
my $cache_id = sprintf "d%s_s%s_a%s", my @polygons = ();
$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 # adjust actual bounding box to the nearest multiple of our hex pattern
# and align it so that it matches across layers # and align it so that it matches across layers
my $bounding_box = $self->bounding_box->clone; my $bounding_box = $surface->expolygon->bounding_box;
$bounding_box->extents->[$_][MIN] = 0 for X, Y;
{ {
# rotate bounding box according to infill direction
my $bb_polygon = $bounding_box->polygon; my $bb_polygon = $bounding_box->polygon;
$bb_polygon->scale(sqrt 2); $bb_polygon->rotate($rotate_vector->[0][0], $m->{hex_center});
$bb_polygon->rotate($rotate_vector->[0][0], $hex_center);
$bounding_box = $bb_polygon->bounding_box; $bounding_box = $bb_polygon->bounding_box;
# $bounding_box->y_min and $bounding_box->y_max represent the displacement between new bounding box offset and old one
$bounding_box->extents->[X][MIN] -= $bounding_box->x_min % $hex_width; # extend bounding box so that our pattern will be aligned with other layers
$bounding_box->extents->[Y][MAX] -= $bounding_box->y_min % $pattern_height; # $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
$bounding_box->extents->[X][MIN] -= $bounding_box->x_min % $m->{hex_width};
$bounding_box->extents->[Y][MIN] -= $bounding_box->y_min % $m->{pattern_height};
} }
my @polygons = ();
my $x = $bounding_box->x_min; my $x = $bounding_box->x_min;
while ($x <= $bounding_box->x_max) { while ($x <= $bounding_box->x_max) {
my $p = []; my $p = [];
my @x = ($x + $x_offset, $x + $distance - $x_offset); my @x = ($x + $m->{x_offset}, $x + $m->{distance} - $m->{x_offset});
for (1..2) { for (1..2) {
@$p = reverse @$p; # turn first half upside down @$p = reverse @$p; # turn first half upside down
my @p = (); my @p = ();
for (my $y = $bounding_box->x_min; $y <= $bounding_box->y_max; $y += $y_short + $hex_side + $y_short + $hex_side) { for (my $y = $bounding_box->y_min; $y <= $bounding_box->y_max; $y += $m->{y_short} + $m->{hex_side} + $m->{y_short} + $m->{hex_side}) {
push @$p, push @$p,
[ $x[1], $y + $y_offset ], [ $x[1], $y + $m->{y_offset} ],
[ $x[0], $y + $y_short - $y_offset ], [ $x[0], $y + $m->{y_short} - $m->{y_offset} ],
[ $x[0], $y + $y_short + $hex_side + $y_offset ], [ $x[0], $y + $m->{y_short} + $m->{hex_side} + $m->{y_offset} ],
[ $x[1], $y + $y_short + $hex_side + $y_short - $y_offset ], [ $x[1], $y + $m->{y_short} + $m->{hex_side} + $m->{y_short} - $m->{y_offset} ],
[ $x[1], $y + $y_short + $hex_side + $y_short + $hex_side + $y_offset ]; [ $x[1], $y + $m->{y_short} + $m->{hex_side} + $m->{y_short} + $m->{hex_side} + $m->{y_offset} ];
} }
@x = map $_ + $distance, reverse @x; # draw symmetrical pattern @x = map $_ + $m->{distance}, reverse @x; # draw symmetrical pattern
$x += $distance; $x += $m->{distance};
} }
push @polygons, Slic3r::Polygon->new($p); push @polygons, Slic3r::Polygon->new($p);
} }
$_->rotate(-$rotate_vector->[0][0], $hex_center) for @polygons; $_->rotate(-$rotate_vector->[0][0], $m->{hex_center}) for @polygons;
$self->cache->{$cache_id} = [@polygons];
} }
# consider polygons as polylines without re-appending the initial point: # consider polygons as polylines without re-appending the initial point:
@ -84,8 +82,8 @@ sub fill_surface {
# path is more straight # path is more straight
my @paths = map Slic3r::Polyline->new($_), my @paths = map Slic3r::Polyline->new($_),
@{ Boost::Geometry::Utils::polygon_multi_linestring_intersection( @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
$expolygon, $surface->expolygon,
$self->cache->{$cache_id}, \@polygons,
) }; ) };
return { flow_spacing => $params{flow_spacing} }, return { flow_spacing => $params{flow_spacing} },