Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2016-11-02 12:47:00 +0300
committerbubnikv <bubnikv@gmail.com>2016-11-02 12:47:00 +0300
commit95ede7c4b8cc40fe0fcf1960f25dfa9c66843b29 (patch)
tree609d320018e09d27f4b945915572d0fdf6e8c906 /lib
parent3a31d37d3574093565ed4fc8baa7f90428d9324e (diff)
Rewrote Fill2.pm to C++, deleted Perl infills for good.
Removed dependency on Perl Math::PlanePath module. Fixed compilation with Visual Studio and SLIC3R_DEBUG: Visual Studio older than 2015 does not support the prinf type specifier %zu. Use %Iu instead. C++11 move semantics enabled.
Diffstat (limited to 'lib')
-rw-r--r--lib/Slic3r.pm4
-rw-r--r--lib/Slic3r/Fill.pm308
-rw-r--r--lib/Slic3r/Fill/3DHoneycomb.pm230
-rw-r--r--lib/Slic3r/Fill/Base.pm101
-rw-r--r--lib/Slic3r/Fill/Concentric.pm57
-rw-r--r--lib/Slic3r/Fill/Honeycomb.pm129
-rw-r--r--lib/Slic3r/Fill/PlanePath.pm118
-rw-r--r--lib/Slic3r/Fill/Rectilinear.pm172
-rw-r--r--lib/Slic3r/Fill2.pm294
-rw-r--r--lib/Slic3r/Layer.pm11
-rw-r--r--lib/Slic3r/Print/GCode.pm4
-rw-r--r--lib/Slic3r/Print/Object.pm26
-rw-r--r--lib/Slic3r/Print/SupportMaterial.pm9
13 files changed, 12 insertions, 1451 deletions
diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm
index b7c265c41..a4e1d07d8 100644
--- a/lib/Slic3r.pm
+++ b/lib/Slic3r.pm
@@ -56,8 +56,6 @@ use Slic3r::Config;
use Slic3r::ExPolygon;
use Slic3r::ExtrusionLoop;
use Slic3r::ExtrusionPath;
-use Slic3r::Fill;
-use Slic3r::Fill2;
use Slic3r::Flow;
use Slic3r::Format::AMF;
use Slic3r::Format::OBJ;
@@ -139,7 +137,7 @@ sub spawn_thread {
# Otherwise run the task on the current thread.
# Used for
# Slic3r::Print::Object->layers->make_perimeters : This is a pure C++ function.
-# Slic3r::Print::Object->layers->make_fill : This requires a rewrite of Fill.pm to C++.
+# Slic3r::Print::Object->layers->make_fill : This is a pure C++ function.
# Slic3r::Print::SupportMaterial::generate_toolpaths
sub parallelize {
my %params = @_;
diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm
deleted file mode 100644
index 4e500d275..000000000
--- a/lib/Slic3r/Fill.pm
+++ /dev/null
@@ -1,308 +0,0 @@
-package Slic3r::Fill;
-use Moo;
-
-use List::Util qw(max);
-use Slic3r::ExtrusionPath ':roles';
-use Slic3r::Fill::3DHoneycomb;
-use Slic3r::Fill::Base;
-use Slic3r::Fill::Concentric;
-use Slic3r::Fill::Honeycomb;
-use Slic3r::Fill::PlanePath;
-use Slic3r::Fill::Rectilinear;
-use Slic3r::Flow ':roles';
-use Slic3r::Geometry qw(X Y PI scale chained_path deg2rad);
-use Slic3r::Geometry::Clipper qw(union union_ex diff diff_ex intersection_ex offset offset2);
-use Slic3r::Surface ':types';
-
-
-has 'bounding_box' => (is => 'ro', required => 0);
-has 'fillers' => (is => 'rw', default => sub { {} });
-
-our %FillTypes = (
- archimedeanchords => 'Slic3r::Fill::ArchimedeanChords',
- rectilinear => 'Slic3r::Fill::Rectilinear',
- grid => 'Slic3r::Fill::Grid',
- flowsnake => 'Slic3r::Fill::Flowsnake',
- octagramspiral => 'Slic3r::Fill::OctagramSpiral',
- hilbertcurve => 'Slic3r::Fill::HilbertCurve',
- line => 'Slic3r::Fill::Line',
- concentric => 'Slic3r::Fill::Concentric',
- honeycomb => 'Slic3r::Fill::Honeycomb',
- '3dhoneycomb' => 'Slic3r::Fill::3DHoneycomb',
-);
-
-sub filler {
- my $self = shift;
- my ($filler) = @_;
-
- if (!ref $self) {
- return $FillTypes{$filler}->new;
- }
-
- $self->fillers->{$filler} ||= $FillTypes{$filler}->new(
- bounding_box => $self->bounding_box,
- );
- return $self->fillers->{$filler};
-}
-
-sub make_fill {
- my $self = shift;
- my ($layerm) = @_;
-
- Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
-
- my $fill_density = $layerm->region->config->fill_density;
- my $infill_flow = $layerm->flow(FLOW_ROLE_INFILL);
- my $solid_infill_flow = $layerm->flow(FLOW_ROLE_SOLID_INFILL);
- my $top_solid_infill_flow = $layerm->flow(FLOW_ROLE_TOP_SOLID_INFILL);
-
- my @surfaces = ();
-
- # merge adjacent surfaces
- # in case of bridge surfaces, the ones with defined angle will be attached to the ones
- # without any angle (shouldn't this logic be moved to process_external_surfaces()?)
- {
- my @surfaces_with_bridge_angle = grep { $_->bridge_angle >= 0 } @{$layerm->fill_surfaces};
-
- # group surfaces by distinct properties
- my @groups = @{$layerm->fill_surfaces->group};
-
- # merge compatible groups (we can generate continuous infill for them)
- {
- # cache flow widths and patterns used for all solid groups
- # (we'll use them for comparing compatible groups)
- my @is_solid = my @fw = my @pattern = ();
- for (my $i = 0; $i <= $#groups; $i++) {
- # we can only merge solid non-bridge surfaces, so discard
- # non-solid surfaces
- if ($groups[$i][0]->is_solid && (!$groups[$i][0]->is_bridge || $layerm->layer->id == 0)) {
- $is_solid[$i] = 1;
- $fw[$i] = ($groups[$i][0]->surface_type == S_TYPE_TOP)
- ? $top_solid_infill_flow->width
- : $solid_infill_flow->width;
- $pattern[$i] = $groups[$i][0]->is_external
- ? $layerm->region->config->external_fill_pattern
- : 'rectilinear';
- } else {
- $is_solid[$i] = 0;
- $fw[$i] = 0;
- $pattern[$i] = 'none';
- }
- }
-
- # loop through solid groups
- for (my $i = 0; $i <= $#groups; $i++) {
- next if !$is_solid[$i];
-
- # find compatible groups and append them to this one
- for (my $j = $i+1; $j <= $#groups; $j++) {
- next if !$is_solid[$j];
-
- if ($fw[$i] == $fw[$j] && $pattern[$i] eq $pattern[$j]) {
- # groups are compatible, merge them
- push @{$groups[$i]}, @{$groups[$j]};
- splice @groups, $j, 1;
- splice @is_solid, $j, 1;
- splice @fw, $j, 1;
- splice @pattern, $j, 1;
- }
- }
- }
- }
-
- # give priority to bridges
- @groups = sort { ($a->[0]->bridge_angle >= 0) ? -1 : 0 } @groups;
-
- foreach my $group (@groups) {
- my $union_p = union([ map $_->p, @$group ], 1);
-
- # subtract surfaces having a defined bridge_angle from any other
- if (@surfaces_with_bridge_angle && $group->[0]->bridge_angle < 0) {
- $union_p = diff(
- $union_p,
- [ map $_->p, @surfaces_with_bridge_angle ],
- 1,
- );
- }
-
- # subtract any other surface already processed
- my $union = diff_ex(
- $union_p,
- [ map $_->p, @surfaces ],
- 1,
- );
-
- push @surfaces, map $group->[0]->clone(expolygon => $_), @$union;
- }
- }
-
- # we need to detect any narrow surfaces that might collapse
- # when adding spacing below
- # such narrow surfaces are often generated in sloping walls
- # by bridge_over_infill() and combine_infill() as a result of the
- # subtraction of the combinable area from the layer infill area,
- # which leaves small areas near the perimeters
- # we are going to grow such regions by overlapping them with the void (if any)
- # TODO: detect and investigate whether there could be narrow regions without
- # any void neighbors
- {
- my $distance_between_surfaces = max(
- $infill_flow->scaled_spacing,
- $solid_infill_flow->scaled_spacing,
- $top_solid_infill_flow->scaled_spacing,
- );
- my $collapsed = diff(
- [ map @{$_->expolygon}, @surfaces ],
- offset2([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2, +$distance_between_surfaces/2),
- 1,
- );
- push @surfaces, map Slic3r::Surface->new(
- expolygon => $_,
- surface_type => S_TYPE_INTERNALSOLID,
- ), @{intersection_ex(
- offset($collapsed, $distance_between_surfaces),
- [
- (map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNALVOID, @surfaces),
- (@$collapsed),
- ],
- 1,
- )};
- }
-
- if (0) {
- require "Slic3r/SVG.pm";
- Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
- expolygons => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
- red_expolygons => [ map $_->expolygon, grep $_->is_solid, @surfaces ],
- );
- }
-
- my @fills = ();
- SURFACE: foreach my $surface (@surfaces) {
- next if $surface->surface_type == S_TYPE_INTERNALVOID;
- my $filler = $layerm->region->config->fill_pattern;
- my $density = $fill_density;
- my $role = ($surface->surface_type == S_TYPE_TOP) ? FLOW_ROLE_TOP_SOLID_INFILL
- : $surface->is_solid ? FLOW_ROLE_SOLID_INFILL
- : FLOW_ROLE_INFILL;
- my $is_bridge = $layerm->layer->id > 0 && $surface->is_bridge;
- my $is_solid = $surface->is_solid;
-
- if ($surface->is_solid) {
- $density = 100;
- $filler = 'rectilinear';
- if ($surface->is_external && !$is_bridge) {
- $filler = $layerm->region->config->external_fill_pattern;
- }
- } else {
- next SURFACE unless $density > 0;
- }
-
- # get filler object
- my $f = $self->filler($filler);
-
- # calculate the actual flow we'll be using for this infill
- my $h = $surface->thickness == -1 ? $layerm->layer->height : $surface->thickness;
- my $flow = $layerm->region->flow(
- $role,
- $h,
- $is_bridge || $f->use_bridge_flow,
- $layerm->layer->id == 0,
- -1,
- $layerm->layer->object,
- );
-
- # calculate flow spacing for infill pattern generation
- my $using_internal_flow = 0;
- if (!$is_solid && !$is_bridge) {
- # it's internal infill, so we can calculate a generic flow spacing
- # for all layers, for avoiding the ugly effect of
- # misaligned infill on first layer because of different extrusion width and
- # layer height
- my $internal_flow = $layerm->region->flow(
- FLOW_ROLE_INFILL,
- $layerm->layer->object->config->layer_height, # TODO: handle infill_every_layers?
- 0, # no bridge
- 0, # no first layer
- -1, # auto width
- $layerm->layer->object,
- );
- $f->spacing($internal_flow->spacing);
- $using_internal_flow = 1;
-# } elsif ($surface->surface_type == S_TYPE_INTERNALBRIDGE) {
-# # The internal bridging layer will be sparse.
-# $f->spacing($flow->spacing * 2.);
- } else {
- $f->spacing($flow->spacing);
- }
-
- my $old_spacing = $f->spacing;
-
- $f->layer_id($layerm->layer->id);
- $f->z($layerm->layer->print_z);
- $f->angle(deg2rad($layerm->region->config->fill_angle));
- $f->loop_clipping(scale($flow->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
-
- # apply half spacing using this flow's own spacing and generate infill
- my @polylines = map $f->fill_surface(
- $_,
- density => $density/100,
- layer_height => $h,
-#FIXME Vojtech disabled the automatic extrusion width adjustment as this feature quite often
-# generated extrusions with excessive widths.
-# The goal of the automatic line width adjustment was to fill in a region without a gap, but because
-# the filled regions are mostly not aligned with the fill direction, very likely
-# the extrusion width adjustment causes more harm than good.
- dont_adjust => 1,
- ), @{ $surface->offset(-scale($f->spacing)/2) };
-
- next unless @polylines;
-
- # calculate actual flow from spacing (which might have been adjusted by the infill
- # pattern generator)
- if ($using_internal_flow) {
- # if we used the internal flow we're not doing a solid infill
- # so we can safely ignore the slight variation that might have
- # been applied to $f->flow_spacing
- } else {
- if (abs($old_spacing - $f->spacing) > 0.3 * $old_spacing) {
- print "Infill: Extreme spacing adjustment, from: ", $old_spacing, " to: ", $f->spacing, "\n";
- }
- $flow = Slic3r::Flow->new_from_spacing(
- spacing => $f->spacing,
- nozzle_diameter => $flow->nozzle_diameter,
- layer_height => $h,
- bridge => $is_bridge || $f->use_bridge_flow,
- );
- }
- my $mm3_per_mm = $flow->mm3_per_mm;
-
- # save into layer
- {
- my $role = $is_bridge ? EXTR_ROLE_BRIDGE
- : $is_solid ? (($surface->surface_type == S_TYPE_TOP) ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL)
- : EXTR_ROLE_FILL;
-
- push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new;
- $collection->no_sort($f->no_sort);
- $collection->append(
- map Slic3r::ExtrusionPath->new(
- polyline => $_,
- role => $role,
- mm3_per_mm => $mm3_per_mm,
- width => $flow->width,
- height => $flow->height,
- ), @polylines,
- );
- }
- }
-
- # add thin fill regions
- foreach my $thin_fill (@{$layerm->thin_fills}) {
- push @fills, Slic3r::ExtrusionPath::Collection->new($thin_fill);
- }
-
- return @fills;
-}
-
-1;
diff --git a/lib/Slic3r/Fill/3DHoneycomb.pm b/lib/Slic3r/Fill/3DHoneycomb.pm
deleted file mode 100644
index 3bf7e547f..000000000
--- a/lib/Slic3r/Fill/3DHoneycomb.pm
+++ /dev/null
@@ -1,230 +0,0 @@
-package Slic3r::Fill::3DHoneycomb;
-use Moo;
-
-extends 'Slic3r::Fill::Base';
-
-use POSIX qw(ceil fmod);
-use Slic3r::Geometry qw(scale scaled_epsilon);
-use Slic3r::Geometry::Clipper qw(intersection_pl);
-
-# require bridge flow since most of this pattern hangs in air
-sub use_bridge_flow { 1 }
-
-sub fill_surface {
- my ($self, $surface, %params) = @_;
-
- my $expolygon = $surface->expolygon;
- my $bb = $expolygon->bounding_box;
- my $size = $bb->size;
-
- my $distance = scale($self->spacing) / $params{density};
-
- # align bounding box to a multiple of our honeycomb grid module
- # (a module is 2*$distance since one $distance half-module is
- # growing while the other $distance half-module is shrinking)
- {
- my $min = $bb->min_point;
- $min->translate(
- -($bb->x_min % (2*$distance)),
- -($bb->y_min % (2*$distance)),
- );
- $bb->merge_point($min);
- }
-
- # generate pattern
- my @polylines = map Slic3r::Polyline->new(@$_),
- makeGrid(
- scale($self->z),
- $distance,
- ceil($size->x / $distance) + 1,
- ceil($size->y / $distance) + 1, #//
- (($self->layer_id / $surface->thickness_layers) % 2) + 1,
- );
-
- # move pattern in place
- $_->translate($bb->x_min, $bb->y_min) for @polylines;
-
- # clip pattern to boundaries
- @polylines = @{intersection_pl(\@polylines, \@$expolygon)};
-
- # connect lines
- unless ($params{dont_connect} || !@polylines) { # prevent calling leftmost_point() on empty collections
- my ($expolygon_off) = @{$expolygon->offset_ex(scaled_epsilon)};
- my $collection = Slic3r::Polyline::Collection->new(@polylines);
- @polylines = ();
- foreach my $polyline (@{$collection->chained_path_from($collection->leftmost_point, 0)}) {
- # try to append this polyline to previous one if any
- if (@polylines) {
- my $line = Slic3r::Line->new($polylines[-1]->last_point, $polyline->first_point);
- if ($line->length <= 1.5*$distance && $expolygon_off->contains_line($line)) {
- $polylines[-1]->append_polyline($polyline);
- next;
- }
- }
-
- # make a clone before $collection goes out of scope
- push @polylines, $polyline->clone;
- }
- }
-
- # TODO: return ExtrusionLoop objects to get better chained paths
- return @polylines;
-}
-
-
-=head1 DESCRIPTION
-
-Creates a contiguous sequence of points at a specified height that make
-up a horizontal slice of the edges of a space filling truncated
-octahedron tesselation. The octahedrons are oriented so that the
-square faces are in the horizontal plane with edges parallel to the X
-and Y axes.
-
-Credits: David Eccles (gringer).
-
-=head2 makeGrid(z, gridSize, gridWidth, gridHeight, curveType)
-
-Generate a set of curves (array of array of 2d points) that describe a
-horizontal slice of a truncated regular octahedron with a specified
-grid square size.
-
-=cut
-
-sub makeGrid {
- my ($z, $gridSize, $gridWidth, $gridHeight, $curveType) = @_;
- my $scaleFactor = $gridSize;
- my $normalisedZ = $z / $scaleFactor;
- my @points = makeNormalisedGrid($normalisedZ, $gridWidth, $gridHeight, $curveType);
- foreach my $lineRef (@points) {
- foreach my $pointRef (@$lineRef) {
- $pointRef->[0] *= $scaleFactor;
- $pointRef->[1] *= $scaleFactor;
- }
- }
- return @points;
-}
-
-=head1 FUNCTIONS
-=cut
-
-=head2 colinearPoints(offset, gridLength)
-
-Generate an array of points that are in the same direction as the
-basic printing line (i.e. Y points for columns, X points for rows)
-
-Note: a negative offset only causes a change in the perpendicular
-direction
-
-=cut
-
-sub colinearPoints {
- my ($offset, $baseLocation, $gridLength) = @_;
-
- my @points = ();
- push @points, $baseLocation - abs($offset/2);
- for (my $i = 0; $i < $gridLength; $i++) {
- push @points, $baseLocation + $i + abs($offset/2);
- push @points, $baseLocation + ($i+1) - abs($offset/2);
- }
- push @points, $baseLocation + $gridLength + abs($offset/2);
- return @points;
-}
-
-=head2 colinearPoints(offset, baseLocation, gridLength)
-
-Generate an array of points for the dimension that is perpendicular to
-the basic printing line (i.e. X points for columns, Y points for rows)
-
-=cut
-
-sub perpendPoints {
- my ($offset, $baseLocation, $gridLength) = @_;
-
- my @points = ();
- my $side = 2*(($baseLocation) % 2) - 1;
- push @points, $baseLocation - $offset/2 * $side;
- for (my $i = 0; $i < $gridLength; $i++) {
- $side = 2*(($i+$baseLocation) % 2) - 1;
- push @points, $baseLocation + $offset/2 * $side;
- push @points, $baseLocation + $offset/2 * $side;
- }
- push @points, $baseLocation - $offset/2 * $side;
-
- return @points;
-}
-
-=head2 trim(pointArrayRef, minX, minY, maxX, maxY)
-
-Trims an array of points to specified rectangular limits. Point
-components that are outside these limits are set to the limits.
-
-=cut
-
-sub trim {
- my ($pointArrayRef, $minX, $minY, $maxX, $maxY) = @_;
-
- foreach (@$pointArrayRef) {
- $_->[0] = ($_->[0] < $minX) ? $minX : (($_->[0] > $maxX) ? $maxX : $_->[0]);
- $_->[1] = ($_->[1] < $minY) ? $minY : (($_->[1] > $maxY) ? $maxY : $_->[1]);
- }
-}
-
-=head2 makeNormalisedGrid(z, gridWidth, gridHeight, curveType)
-
-Generate a set of curves (array of array of 2d points) that describe a
-horizontal slice of a truncated regular octahedron with edge length 1.
-
-curveType specifies which lines to print, 1 for vertical lines
-(columns), 2 for horizontal lines (rows), and 3 for both.
-
-=cut
-
-sub makeNormalisedGrid {
- my ($z, $gridWidth, $gridHeight, $curveType) = @_;
-
- ## offset required to create a regular octagram
- my $octagramGap = 0.5;
-
- # sawtooth wave function for range f($z) = [-$octagramGap .. $octagramGap]
- my $a = sqrt(2); # period
- my $wave = abs(fmod($z, $a) - $a/2)/$a*4 - 1;
- my $offset = $wave * $octagramGap;
-
- my @points = ();
- if (($curveType & 1) != 0) {
- for (my $x = 0; $x <= $gridWidth; $x++) {
- my @xPoints = perpendPoints($offset, $x, $gridHeight);
- my @yPoints = colinearPoints($offset, 0, $gridHeight);
- # This is essentially @newPoints = zip(@xPoints, @yPoints)
- my @newPoints = map [ $xPoints[$_], $yPoints[$_] ], 0..$#xPoints;
-
- # trim points to grid edges
- #trim(\@newPoints, 0, 0, $gridWidth, $gridHeight);
-
- if ($x % 2 == 0){
- push @points, [ @newPoints ];
- } else {
- push @points, [ reverse @newPoints ];
- }
- }
- }
- if (($curveType & 2) != 0) {
- for (my $y = 0; $y <= $gridHeight; $y++) {
- my @xPoints = colinearPoints($offset, 0, $gridWidth);
- my @yPoints = perpendPoints($offset, $y, $gridWidth);
- my @newPoints = map [ $xPoints[$_], $yPoints[$_] ], 0..$#xPoints;
-
- # trim points to grid edges
- #trim(\@newPoints, 0, 0, $gridWidth, $gridHeight);
-
- if ($y % 2 == 0) {
- push @points, [ @newPoints ];
- } else {
- push @points, [ reverse @newPoints ];
- }
- }
- }
- return @points;
-}
-
-1;
diff --git a/lib/Slic3r/Fill/Base.pm b/lib/Slic3r/Fill/Base.pm
deleted file mode 100644
index 482594a31..000000000
--- a/lib/Slic3r/Fill/Base.pm
+++ /dev/null
@@ -1,101 +0,0 @@
-package Slic3r::Fill::Base;
-use Moo;
-
-has 'layer_id' => (is => 'rw');
-has 'z' => (is => 'rw'); # in unscaled coordinates
-has 'angle' => (is => 'rw'); # in radians, ccw, 0 = East
-has 'spacing' => (is => 'rw'); # in unscaled coordinates
-has 'loop_clipping' => (is => 'rw', default => sub { 0 }); # in scaled coordinates
-has 'bounding_box' => (is => 'ro', required => 0); # Slic3r::Geometry::BoundingBox object
-
-sub set_spacing {
- my ($self, $spacing) = @_;
- $self->spacing($spacing);
-}
-
-sub set_angle {
- my ($self, $angle) = @_;
- $self->angle($angle);
-}
-
-sub adjust_solid_spacing {
- my $self = shift;
- my %params = @_;
-
- my $number_of_lines = int($params{width} / $params{distance}) + 1;
- return $params{distance} if $number_of_lines <= 1;
-
- my $extra_space = $params{width} % $params{distance};
- return $params{distance} + $extra_space / ($number_of_lines - 1);
-}
-
-sub no_sort { 0 }
-sub use_bridge_flow { 0 }
-
-
-package Slic3r::Fill::WithDirection;
-use Moo::Role;
-
-use Slic3r::Geometry qw(PI rad2deg);
-
-sub angles () { [0, PI/2] }
-
-sub infill_direction {
- my $self = shift;
- my ($surface) = @_;
-
- if (!defined $self->angle) {
- warn "Using undefined infill angle";
- $self->angle(0);
- }
-
- # set infill angle
- my (@rotate);
- $rotate[0] = $self->angle;
- $rotate[1] = $self->bounding_box
- ? $self->bounding_box->center
- : $surface->expolygon->bounding_box->center;
- my $shift = $rotate[1]->clone;
-
- if (defined $self->layer_id) {
- # alternate fill direction
- my $layer_num = $self->layer_id / $surface->thickness_layers;
- my $angle = $self->angles->[$layer_num % @{$self->angles}];
- $rotate[0] = $self->angle + $angle if $angle;
- }
-
- # use bridge angle
- if ($surface->bridge_angle >= 0) {
- Slic3r::debugf "Filling bridge with angle %d\n", rad2deg($surface->bridge_angle);
- $rotate[0] = $surface->bridge_angle;
- }
-
- $rotate[0] += PI/2;
- $shift->rotate(@rotate);
- return [\@rotate, $shift];
-}
-
-# this method accepts any object that implements rotate() and translate()
-sub rotate_points {
- my $self = shift;
- my ($expolygon, $rotate_vector) = @_;
-
- # rotate points
- my ($rotate, $shift) = @$rotate_vector;
- $rotate = [ -$rotate->[0], $rotate->[1] ];
- $expolygon->rotate(@$rotate);
- $expolygon->translate(@$shift);
-}
-
-sub rotate_points_back {
- my $self = shift;
- my ($paths, $rotate_vector) = @_;
-
- my ($rotate, $shift) = @$rotate_vector;
- $shift = [ map -$_, @$shift ];
-
- $_->translate(@$shift) for @$paths;
- $_->rotate(@$rotate) for @$paths;
-}
-
-1;
diff --git a/lib/Slic3r/Fill/Concentric.pm b/lib/Slic3r/Fill/Concentric.pm
deleted file mode 100644
index ca1837c4e..000000000
--- a/lib/Slic3r/Fill/Concentric.pm
+++ /dev/null
@@ -1,57 +0,0 @@
-package Slic3r::Fill::Concentric;
-use Moo;
-
-extends 'Slic3r::Fill::Base';
-
-use Slic3r::Geometry qw(scale unscale X);
-use Slic3r::Geometry::Clipper qw(offset offset2 union_pt_chained);
-
-sub no_sort { 1 }
-
-sub fill_surface {
- my $self = shift;
- my ($surface, %params) = @_;
-
- # no rotation is supported for this infill pattern
-
- my $expolygon = $surface->expolygon;
- my $bounding_box = $expolygon->bounding_box;
-
- my $min_spacing = scale($self->spacing);
- my $distance = $min_spacing / $params{density};
-
- if ($params{density} == 1 && !$params{dont_adjust}) {
- $distance = $self->adjust_solid_spacing(
- width => $bounding_box->size->[X],
- distance => $distance,
- );
- $self->spacing(unscale $distance);
- }
-
- my @loops = my @last = map $_->clone, @$expolygon;
- while (@last) {
- push @loops, @last = @{offset2(\@last, -($distance + 0.5*$min_spacing), +0.5*$min_spacing)};
- }
-
- # generate paths from the outermost to the innermost, to avoid
- # adhesion problems of the first central tiny loops
- @loops = map Slic3r::Polygon->new(@$_),
- reverse @{union_pt_chained(\@loops)};
-
- # split paths using a nearest neighbor search
- my @paths = ();
- my $last_pos = Slic3r::Point->new(0,0);
- foreach my $loop (@loops) {
- push @paths, $loop->split_at_index($last_pos->nearest_point_index(\@$loop));
- $last_pos = $paths[-1]->last_point;
- }
-
- # clip the paths to prevent the extruder from getting exactly on the first point of the loop
- $_->clip_end($self->loop_clipping) for @paths;
- @paths = grep $_->is_valid, @paths; # remove empty paths (too short, thus eaten by clipping)
-
- # TODO: return ExtrusionLoop objects to get better chained paths
- return @paths;
-}
-
-1;
diff --git a/lib/Slic3r/Fill/Honeycomb.pm b/lib/Slic3r/Fill/Honeycomb.pm
deleted file mode 100644
index b0fbd65ff..000000000
--- a/lib/Slic3r/Fill/Honeycomb.pm
+++ /dev/null
@@ -1,129 +0,0 @@
-package Slic3r::Fill::Honeycomb;
-use Moo;
-
-extends 'Slic3r::Fill::Base';
-with qw(Slic3r::Fill::WithDirection);
-
-has 'cache' => (is => 'rw', default => sub {{}});
-
-use Slic3r::Geometry qw(PI X Y MIN MAX scale scaled_epsilon);
-use Slic3r::Geometry::Clipper qw(intersection intersection_pl);
-
-sub angles () { [0, PI/3, PI/3*2] }
-
-sub fill_surface {
- my $self = shift;
- my ($surface, %params) = @_;
-
- my $rotate_vector = $self->infill_direction($surface);
-
- # cache hexagons math
- my $cache_id = sprintf "d%s_s%s", $params{density}, $self->spacing;
- my $m;
- if (!($m = $self->cache->{$cache_id})) {
- $m = $self->cache->{$cache_id} = {};
- my $min_spacing = scale($self->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 @polygons = ();
- {
- # adjust actual bounding box to the nearest multiple of our hex pattern
- # and align it so that it matches across layers
-
- my $bounding_box = $surface->expolygon->bounding_box;
- {
- # rotate bounding box according to infill direction
- my $bb_polygon = $bounding_box->polygon;
- $bb_polygon->rotate($rotate_vector->[0][0], $m->{hex_center});
- $bounding_box = $bb_polygon->bounding_box;
-
- # extend bounding box so that our pattern will be aligned with other layers
- # $bounding_box->[X1] and [Y1] represent the displacement between new bounding box offset and old one
- $bounding_box->merge_point(Slic3r::Point->new(
- $bounding_box->x_min - ($bounding_box->x_min % $m->{hex_width}),
- $bounding_box->y_min - ($bounding_box->y_min % $m->{pattern_height}),
- ));
- }
-
- my $x = $bounding_box->x_min;
- while ($x <= $bounding_box->x_max) {
- my $p = [];
-
- my @x = ($x + $m->{x_offset}, $x + $m->{distance} - $m->{x_offset});
- for (1..2) {
- @$p = reverse @$p; # turn first half upside down
- my @p = ();
- 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,
- [ $x[1], $y + $m->{y_offset} ],
- [ $x[0], $y + $m->{y_short} - $m->{y_offset} ],
- [ $x[0], $y + $m->{y_short} + $m->{hex_side} + $m->{y_offset} ],
- [ $x[1], $y + $m->{y_short} + $m->{hex_side} + $m->{y_short} - $m->{y_offset} ],
- [ $x[1], $y + $m->{y_short} + $m->{hex_side} + $m->{y_short} + $m->{hex_side} + $m->{y_offset} ];
- }
- @x = map $_ + $m->{distance}, reverse @x; # draw symmetrical pattern
- $x += $m->{distance};
- }
-
- push @polygons, Slic3r::Polygon->new(@$p);
- }
-
- $_->rotate(-$rotate_vector->[0][0], $m->{hex_center}) for @polygons;
- }
-
- my @paths;
- if ($params{complete} || 1) {
- # we were requested to complete each loop;
- # in this case we don't try to make more continuous paths
- @paths = map $_->split_at_first_point,
- @{intersection([ $surface->p ], \@polygons)};
-
- } else {
- # consider polygons as polylines without re-appending the initial point:
- # this cuts the last segment on purpose, so that the jump to the next
- # path is more straight
- @paths = @{intersection_pl(
- [ map Slic3r::Polyline->new(@$_), @polygons ],
- [ @{$surface->expolygon} ],
- )};
-
- # connect paths
- if (@paths) { # prevent calling leftmost_point() on empty collections
- my $collection = Slic3r::Polyline::Collection->new(@paths);
- @paths = ();
- foreach my $path (@{$collection->chained_path_from($collection->leftmost_point, 0)}) {
- if (@paths) {
- # distance between first point of this path and last point of last path
- my $distance = $paths[-1]->last_point->distance_to($path->first_point);
-
- if ($distance <= $m->{hex_width}) {
- $paths[-1]->append_polyline($path);
- next;
- }
- }
-
- # make a clone before $collection goes out of scope
- push @paths, $path->clone;
- }
- }
-
- # clip paths again to prevent connection segments from crossing the expolygon boundaries
- @paths = @{intersection_pl(
- \@paths,
- [ map @$_, @{$surface->expolygon->offset_ex(scaled_epsilon)} ],
- )};
- }
-
- return @paths;
-}
-
-1;
diff --git a/lib/Slic3r/Fill/PlanePath.pm b/lib/Slic3r/Fill/PlanePath.pm
deleted file mode 100644
index 556835ec4..000000000
--- a/lib/Slic3r/Fill/PlanePath.pm
+++ /dev/null
@@ -1,118 +0,0 @@
-package Slic3r::Fill::PlanePath;
-use Moo;
-
-extends 'Slic3r::Fill::Base';
-with qw(Slic3r::Fill::WithDirection);
-
-use Slic3r::Geometry qw(scale X1 Y1 X2 Y2);
-use Slic3r::Geometry::Clipper qw(intersection_pl);
-
-sub angles () { [0] }
-sub multiplier () { 1 }
-
-sub process_polyline {}
-
-sub fill_surface {
- my $self = shift;
- my ($surface, %params) = @_;
-
- # rotate polygons
- my $expolygon = $surface->expolygon->clone;
- my $rotate_vector = $self->infill_direction($surface);
- $self->rotate_points($expolygon, $rotate_vector);
-
- my $distance_between_lines = scale($self->spacing) / $params{density} * $self->multiplier;
-
- # align infill across layers using the object's bounding box
- my $bb_polygon = $self->bounding_box->polygon;
- $self->rotate_points($bb_polygon, $rotate_vector);
- my $bounding_box = $bb_polygon->bounding_box;
-
- (ref $self) =~ /::([^:]+)$/;
- my $path = "Math::PlanePath::$1"->new;
-
- my $translate = Slic3r::Point->new(0,0); # vector
- if ($path->x_negative || $path->y_negative) {
- # if the curve extends on both positive and negative coordinate space,
- # center our expolygon around origin
- $translate = $bounding_box->center->negative;
- } else {
- # if the curve does not extend in negative coordinate space,
- # move expolygon entirely in positive coordinate space
- $translate = $bounding_box->min_point->negative;
- }
- $expolygon->translate(@$translate);
- $bounding_box->translate(@$translate);
-
- my ($n_lo, $n_hi) = $path->rect_to_n_range(
- map { $_ / $distance_between_lines }
- @{$bounding_box->min_point},
- @{$bounding_box->max_point},
- );
-
- my $polyline = Slic3r::Polyline->new(
- map [ map { $_ * $distance_between_lines } $path->n_to_xy($_) ], ($n_lo..$n_hi)
- );
- return {} if @$polyline <= 1;
-
- $self->process_polyline($polyline, $bounding_box);
-
- my @paths = @{intersection_pl([$polyline], \@$expolygon)};
-
- if (0) {
- require "Slic3r/SVG.pm";
- Slic3r::SVG::output("fill.svg",
- no_arrows => 1,
- polygons => \@$expolygon,
- green_polygons => [ $bounding_box->polygon ],
- polylines => [ $polyline ],
- red_polylines => \@paths,
- );
- }
-
- # paths must be repositioned and rotated back
- $_->translate(@{$translate->negative}) for @paths;
- $self->rotate_points_back(\@paths, $rotate_vector);
-
- return @paths;
-}
-
-
-package Slic3r::Fill::ArchimedeanChords;
-use Moo;
-extends 'Slic3r::Fill::PlanePath';
-use Math::PlanePath::ArchimedeanChords;
-
-
-package Slic3r::Fill::Flowsnake;
-use Moo;
-extends 'Slic3r::Fill::PlanePath';
-use Math::PlanePath::Flowsnake;
-use Slic3r::Geometry qw(X);
-
-# Sorry, this fill is currently broken.
-
-sub process_polyline {
- my $self = shift;
- my ($polyline, $bounding_box) = @_;
-
- $_->[X] += $bounding_box->center->[X] for @$polyline;
-}
-
-
-package Slic3r::Fill::HilbertCurve;
-use Moo;
-extends 'Slic3r::Fill::PlanePath';
-use Math::PlanePath::HilbertCurve;
-
-
-package Slic3r::Fill::OctagramSpiral;
-use Moo;
-extends 'Slic3r::Fill::PlanePath';
-use Math::PlanePath::OctagramSpiral;
-
-sub multiplier () { sqrt(2) }
-
-
-
-1;
diff --git a/lib/Slic3r/Fill/Rectilinear.pm b/lib/Slic3r/Fill/Rectilinear.pm
deleted file mode 100644
index 780b76291..000000000
--- a/lib/Slic3r/Fill/Rectilinear.pm
+++ /dev/null
@@ -1,172 +0,0 @@
-package Slic3r::Fill::Rectilinear;
-use Moo;
-
-extends 'Slic3r::Fill::Base';
-with qw(Slic3r::Fill::WithDirection);
-
-has '_min_spacing' => (is => 'rw');
-has '_line_spacing' => (is => 'rw');
-has '_diagonal_distance' => (is => 'rw');
-has '_line_oscillation' => (is => 'rw');
-
-use Slic3r::Geometry qw(scale unscale scaled_epsilon);
-use Slic3r::Geometry::Clipper qw(intersection_pl);
-
-sub horizontal_lines { 0 }
-
-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);
- $self->rotate_points($expolygon, $rotate_vector);
-
- $self->_min_spacing(scale $self->spacing);
- $self->_line_spacing($self->_min_spacing / $params{density});
- $self->_diagonal_distance($self->_line_spacing * 2);
- $self->_line_oscillation($self->_line_spacing - $self->_min_spacing); # only for Line infill
- my $bounding_box = $expolygon->bounding_box;
-
- # define flow spacing according to requested density
- if ($params{density} == 1 && !$params{dont_adjust}) {
- my $old_spacing = $self->spacing;
- $self->_line_spacing($self->adjust_solid_spacing(
- width => $bounding_box->size->x,
- distance => $self->_line_spacing,
- ));
- $self->spacing(unscale $self->_line_spacing);
- if (abs($old_spacing - $self->spacing) > 0.3 * $old_spacing) {
- print "Infill2: Extreme spacing adjustment, from: ", $old_spacing, " to: ", $self->spacing, "\n";
- }
- } else {
- # extend bounding box so that our pattern will be aligned with other layers
- $bounding_box->merge_point(Slic3r::Point->new(
- $bounding_box->x_min - ($bounding_box->x_min % $self->_line_spacing),
- $bounding_box->y_min - ($bounding_box->y_min % $self->_line_spacing),
- ));
- }
-
- # generate the basic pattern
- my $x_max = $bounding_box->x_max + scaled_epsilon;
- my @lines = ();
- for (my $x = $bounding_box->x_min; $x <= $x_max; $x += $self->_line_spacing) {
- push @lines, $self->_line($#lines, $x, $bounding_box->y_min, $bounding_box->y_max);
- }
- if ($self->horizontal_lines) {
- my $y_max = $bounding_box->y_max + scaled_epsilon;
- for (my $y = $bounding_box->y_min; $y <= $y_max; $y += $self->_line_spacing) {
- push @lines, Slic3r::Polyline->new(
- [$bounding_box->x_min, $y],
- [$bounding_box->x_max, $y],
- );
- }
- }
-
- # clip paths against a slightly larger expolygon, so that the first and last paths
- # are kept even if the expolygon has vertical sides
- # the minimum offset for preventing edge lines from being clipped is scaled_epsilon;
- # however we use a larger offset to support expolygons with slightly skewed sides and
- # not perfectly straight
- my @polylines = @{intersection_pl(\@lines, $expolygon->offset(+scale 0.02))};
-
- my $extra = $self->_min_spacing * &Slic3r::INFILL_OVERLAP_OVER_SPACING;
- foreach my $polyline (@polylines) {
- my ($first_point, $last_point) = @$polyline[0,-1];
- if ($first_point->y > $last_point->y) { #>
- ($first_point, $last_point) = ($last_point, $first_point);
- }
- $first_point->set_y($first_point->y - $extra); #--
- $last_point->set_y($last_point->y + $extra); #++
- }
-
- # connect lines
- unless ($params{dont_connect} || !@polylines) { # prevent calling leftmost_point() on empty collections
- # offset the expolygon by max(min_spacing/2, extra)
- my ($expolygon_off) = @{$expolygon->offset_ex($self->_min_spacing/2)};
- my $collection = Slic3r::Polyline::Collection->new(@polylines);
- @polylines = ();
-
- foreach my $polyline (@{$collection->chained_path_from($collection->leftmost_point, 0)}) {
- if (@polylines) {
- my $first_point = $polyline->first_point;
- my $last_point = $polylines[-1]->last_point;
- my @distance = map abs($first_point->$_ - $last_point->$_), qw(x y);
-
- # TODO: we should also check that both points are on a fill_boundary to avoid
- # connecting paths on the boundaries of internal regions
- if ($self->_can_connect(@distance) && $expolygon_off->contains_line(Slic3r::Line->new($last_point, $first_point))) {
- $polylines[-1]->append_polyline($polyline);
- next;
- }
- }
-
- # make a clone before $collection goes out of scope
- push @polylines, $polyline->clone;
- }
- }
-
- # paths must be rotated back
- $self->rotate_points_back(\@polylines, $rotate_vector);
-
- return @polylines;
-}
-
-sub _line {
- my ($self, $i, $x, $y_min, $y_max) = @_;
-
- return Slic3r::Polyline->new(
- [$x, $y_min],
- [$x, $y_max],
- );
-}
-
-sub _can_connect {
- my ($self, $dist_X, $dist_Y) = @_;
-
- return $dist_X <= $self->_diagonal_distance
- && $dist_Y <= $self->_diagonal_distance;
-}
-
-
-package Slic3r::Fill::Line;
-use Moo;
-extends 'Slic3r::Fill::Rectilinear';
-
-use Slic3r::Geometry qw(scaled_epsilon);
-
-sub _line {
- my ($self, $i, $x, $y_min, $y_max) = @_;
-
- if ($i % 2) {
- return Slic3r::Polyline->new(
- [$x - $self->_line_oscillation, $y_min],
- [$x + $self->_line_oscillation, $y_max],
- );
- } else {
- return Slic3r::Polyline->new(
- [$x, $y_min],
- [$x, $y_max],
- );
- }
-}
-
-sub _can_connect {
- my ($self, $dist_X, $dist_Y) = @_;
-
- my $TOLERANCE = 10 * scaled_epsilon;
- return ($dist_X >= ($self->_line_spacing - $self->_line_oscillation) - $TOLERANCE)
- && ($dist_X <= ($self->_line_spacing + $self->_line_oscillation) + $TOLERANCE)
- && $dist_Y <= $self->_diagonal_distance;
-}
-
-
-package Slic3r::Fill::Grid;
-use Moo;
-extends 'Slic3r::Fill::Rectilinear';
-
-sub angles () { [0] }
-sub horizontal_lines { 1 }
-
-1;
diff --git a/lib/Slic3r/Fill2.pm b/lib/Slic3r/Fill2.pm
deleted file mode 100644
index 940e47b06..000000000
--- a/lib/Slic3r/Fill2.pm
+++ /dev/null
@@ -1,294 +0,0 @@
-# This is derived from Fill.pm
-# and it uses the C++ fillers.
-package Slic3r::Fill2;
-use Moo;
-
-use List::Util qw(max);
-use Slic3r::ExtrusionPath ':roles';
-
-use Slic3r::Flow ':roles';
-use Slic3r::Geometry qw(X Y PI scale chained_path deg2rad);
-use Slic3r::Geometry::Clipper qw(union union_ex diff diff_ex intersection_ex offset offset2);
-use Slic3r::Surface ':types';
-
-has 'bounding_box' => (is => 'ro', required => 0);
-has 'fillers' => (is => 'rw', default => sub { {} });
-
-sub filler {
- my $self = shift;
- my ($filler) = @_;
-
- if (!ref $self) {
- return Slic3r::Filler->new_from_type($filler);
- }
-
- #print "Filler: ", $filler, "\n";
- $self->fillers->{$filler} ||= Slic3r::Filler->new_from_type($filler);
- $self->fillers->{$filler}->set_bounding_box($self->bounding_box);
- return $self->fillers->{$filler};
-}
-
-
-# Generate infills for Slic3r::Layer::Region.
-# The Slic3r::Layer::Region at this point of time may contain
-# surfaces of various types (internal/bridge/top/bottom/solid).
-# The infills are generated on the groups of surfaces with a compatible type.
-# Returns an array of Slic3r::ExtrusionPath::Collection objects containing the infills generaed now
-# and the thin fills generated by generate_perimeters().
-sub make_fill {
- my $self = shift;
- # of type - C++: LayerRegion, Perl: Slic3r::Layer::Region
- my ($layerm) = @_;
-
- Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
-
- my $fill_density = $layerm->region->config->fill_density;
- my $infill_flow = $layerm->flow(FLOW_ROLE_INFILL);
- my $solid_infill_flow = $layerm->flow(FLOW_ROLE_SOLID_INFILL);
- my $top_solid_infill_flow = $layerm->flow(FLOW_ROLE_TOP_SOLID_INFILL);
-
- # Surfaces are of the type Slic3r::Surface
- my @surfaces = ();
-
- # merge adjacent surfaces
- # in case of bridge surfaces, the ones with defined angle will be attached to the ones
- # without any angle (shouldn't this logic be moved to process_external_surfaces()?)
- {
- my @surfaces_with_bridge_angle = grep { $_->bridge_angle >= 0 } @{$layerm->fill_surfaces};
-
- # group surfaces by distinct properties
- # group is of type Slic3r::SurfaceCollection
- my @groups = @{$layerm->fill_surfaces->group};
-
- # merge compatible groups (we can generate continuous infill for them)
- {
- # cache flow widths and patterns used for all solid groups
- # (we'll use them for comparing compatible groups)
- my @is_solid = my @fw = my @pattern = ();
- for (my $i = 0; $i <= $#groups; $i++) {
- # we can only merge solid non-bridge surfaces, so discard
- # non-solid surfaces
- if ($groups[$i][0]->is_solid && (!$groups[$i][0]->is_bridge || $layerm->layer->id == 0)) {
- $is_solid[$i] = 1;
- $fw[$i] = ($groups[$i][0]->surface_type == S_TYPE_TOP)
- ? $top_solid_infill_flow->width
- : $solid_infill_flow->width;
- $pattern[$i] = $groups[$i][0]->is_external
- ? $layerm->region->config->external_fill_pattern
- : 'rectilinear';
- } else {
- $is_solid[$i] = 0;
- $fw[$i] = 0;
- $pattern[$i] = 'none';
- }
- }
-
- # loop through solid groups
- for (my $i = 0; $i <= $#groups; $i++) {
- next if !$is_solid[$i];
-
- # find compatible groups and append them to this one
- for (my $j = $i+1; $j <= $#groups; $j++) {
- next if !$is_solid[$j];
-
- if ($fw[$i] == $fw[$j] && $pattern[$i] eq $pattern[$j]) {
- # groups are compatible, merge them
- push @{$groups[$i]}, @{$groups[$j]};
- splice @groups, $j, 1;
- splice @is_solid, $j, 1;
- splice @fw, $j, 1;
- splice @pattern, $j, 1;
- }
- }
- }
- }
-
- # give priority to bridges
- @groups = sort { ($a->[0]->bridge_angle >= 0) ? -1 : 0 } @groups;
-
- foreach my $group (@groups) {
- # Make a union of polygons defining the infiill regions of a group, use a safety offset.
- my $union_p = union([ map $_->p, @$group ], 1);
-
- # Subtract surfaces having a defined bridge_angle from any other, use a safety offset.
- if (@surfaces_with_bridge_angle && $group->[0]->bridge_angle < 0) {
- $union_p = diff(
- $union_p,
- [ map $_->p, @surfaces_with_bridge_angle ],
- 1,
- );
- }
-
- # subtract any other surface already processed
- #FIXME Vojtech: Because the bridge surfaces came first, they are subtracted twice!
- my $union = diff_ex(
- $union_p,
- [ map $_->p, @surfaces ],
- 1,
- );
-
- push @surfaces, map $group->[0]->clone(expolygon => $_), @$union;
- }
- }
-
- # we need to detect any narrow surfaces that might collapse
- # when adding spacing below
- # such narrow surfaces are often generated in sloping walls
- # by bridge_over_infill() and combine_infill() as a result of the
- # subtraction of the combinable area from the layer infill area,
- # which leaves small areas near the perimeters
- # we are going to grow such regions by overlapping them with the void (if any)
- # TODO: detect and investigate whether there could be narrow regions without
- # any void neighbors
- {
- my $distance_between_surfaces = max(
- $infill_flow->scaled_spacing,
- $solid_infill_flow->scaled_spacing,
- $top_solid_infill_flow->scaled_spacing,
- );
- my $collapsed = diff(
- [ map @{$_->expolygon}, @surfaces ],
- offset2([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2, +$distance_between_surfaces/2),
- 1,
- );
- push @surfaces, map Slic3r::Surface->new(
- expolygon => $_,
- surface_type => S_TYPE_INTERNALSOLID,
- ), @{intersection_ex(
- offset($collapsed, $distance_between_surfaces),
- [
- (map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNALVOID, @surfaces),
- (@$collapsed),
- ],
- 1,
- )};
- }
-
- if (0) {
- require "Slic3r/SVG.pm";
- Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
- expolygons => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
- red_expolygons => [ map $_->expolygon, grep $_->is_solid, @surfaces ],
- );
- }
-
- # Fills are of perl type Slic3r::ExtrusionPath::Collection, c++ type ExtrusionEntityCollection
- my @fills = ();
- SURFACE: foreach my $surface (@surfaces) {
- next if $surface->surface_type == S_TYPE_INTERNALVOID;
- my $filler = $layerm->region->config->fill_pattern;
- my $density = $fill_density;
- my $role = ($surface->surface_type == S_TYPE_TOP) ? FLOW_ROLE_TOP_SOLID_INFILL
- : $surface->is_solid ? FLOW_ROLE_SOLID_INFILL
- : FLOW_ROLE_INFILL;
- my $is_bridge = $layerm->layer->id > 0 && $surface->is_bridge;
- my $is_solid = $surface->is_solid;
-
- if ($surface->is_solid) {
- $density = 100;
- $filler = 'rectilinear';
- if ($surface->is_external && !$is_bridge) {
- $filler = $layerm->region->config->external_fill_pattern;
- }
- } else {
- next SURFACE unless $density > 0;
- }
-
- # get filler object
- my $f = $self->filler($filler);
-
- # calculate the actual flow we'll be using for this infill
- my $h = $surface->thickness == -1 ? $layerm->layer->height : $surface->thickness;
- my $flow = $layerm->region->flow(
- $role,
- $h,
- $is_bridge || $f->use_bridge_flow,
- $layerm->layer->id == 0,
- -1,
- $layerm->layer->object,
- );
-
- # calculate flow spacing for infill pattern generation
- my $using_internal_flow = 0;
- if (!$is_solid && !$is_bridge) {
- # it's internal infill, so we can calculate a generic flow spacing
- # for all layers, for avoiding the ugly effect of
- # misaligned infill on first layer because of different extrusion width and
- # layer height
- my $internal_flow = $layerm->region->flow(
- FLOW_ROLE_INFILL,
- $layerm->layer->object->config->layer_height, # TODO: handle infill_every_layers?
- 0, # no bridge
- 0, # no first layer
- -1, # auto width
- $layerm->layer->object,
- );
- $f->set_spacing($internal_flow->spacing);
- $using_internal_flow = 1;
- } else {
- $f->set_spacing($flow->spacing);
- }
-
- $f->set_layer_id($layerm->layer->id);
- $f->set_z($layerm->layer->print_z);
- $f->set_angle(deg2rad($layerm->region->config->fill_angle));
- $f->set_loop_clipping(scale($flow->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
-
- # apply half spacing using this flow's own spacing and generate infill
- my @polylines = $f->fill_surface(
- $surface,
- density => $density/100,
- layer_height => $h,
- );
- next unless @polylines;
-
-
- # calculate actual flow from spacing (which might have been adjusted by the infill
- # pattern generator)
- if ($using_internal_flow) {
- # if we used the internal flow we're not doing a solid infill
- # so we can safely ignore the slight variation that might have
- # been applied to $f->flow_spacing
- } else {
- $flow = Slic3r::Flow->new_from_spacing(
- spacing => $f->spacing,
- nozzle_diameter => $flow->nozzle_diameter,
- layer_height => $h,
- bridge => $is_bridge || $f->use_bridge_flow,
- );
- }
-
- # save into layer
- {
- my $role = $is_bridge ? EXTR_ROLE_BRIDGE
- : $is_solid ? (($surface->surface_type == S_TYPE_TOP) ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL)
- : EXTR_ROLE_FILL;
-
- push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new;
- # Only concentric fills are not sorted.
- $collection->no_sort($f->no_sort);
- $collection->append(
- map Slic3r::ExtrusionPath->new(
- polyline => $_,
- role => $role,
- mm3_per_mm => $flow->mm3_per_mm,
- width => $flow->width,
- height => $flow->height,
- ), map @$_, @polylines,
- );
- }
- }
-
- # add thin fill regions
- # thin_fills are of C++ Slic3r::ExtrusionEntityCollection, perl type Slic3r::ExtrusionPath::Collection
- # Unpacks the collection, creates multiple collections per path.
- # The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
- # Why the paths are unpacked?
- foreach my $thin_fill (@{$layerm->thin_fills}) {
- push @fills, Slic3r::ExtrusionPath::Collection->new($thin_fill);
- }
-
- return @fills;
-}
-
-1;
diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm
index f1a3d7a57..4bff9b61f 100644
--- a/lib/Slic3r/Layer.pm
+++ b/lib/Slic3r/Layer.pm
@@ -31,17 +31,6 @@ sub regions {
return [ map $self->get_region($_), 0..($self->region_count-1) ];
}
-sub make_fill {
- my ($self) = @_;
-
- foreach my $layerm (@{$self->regions}) {
- $layerm->fills->clear;
- # Fearlessly enable the C++ fillers.
- $layerm->fills->append($_) for $self->object->fill_maker2->make_fill($layerm);
-# $layerm->fills->append($_) for $self->object->fill_maker->make_fill($layerm);
- }
-}
-
package Slic3r::Layer::Support;
our @ISA = qw(Slic3r::Layer);
diff --git a/lib/Slic3r/Print/GCode.pm b/lib/Slic3r/Print/GCode.pm
index d837a4637..d1b0009ad 100644
--- a/lib/Slic3r/Print/GCode.pm
+++ b/lib/Slic3r/Print/GCode.pm
@@ -544,8 +544,8 @@ sub process_layer {
}
# process infill
- # $layerm->fills is a collection of ExtrusionPath::Collection objects, each one containing
- # the ExtrusionPath objects of a certain infill "group" (also called "surface"
+ # $layerm->fills is a collection of Slic3r::ExtrusionPath::Collection objects (C++ class ExtrusionEntityCollection),
+ # each one containing the ExtrusionPath objects of a certain infill "group" (also called "surface"
# throughout the code). We can redefine the order of such Collections but we have to
# do each one completely at once.
foreach my $fill (@{$layerm->fills}) {
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index 5ca29789c..791731543 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -14,19 +14,6 @@ use Slic3r::Surface ':types';
# If enabled, phases of prepare_infill will be written into SVG files to an "out" directory.
our $SLIC3R_DEBUG_SLICE_PROCESSING = 0;
-# TODO: lazy
-sub fill_maker {
- my $self = shift;
- return Slic3r::Fill->new(bounding_box => $self->bounding_box);
-}
-
-# Vojtech's implementation: Create the C++ filler.
-# TODO: lazy
-sub fill_maker2 {
- my $self = shift;
- return Slic3r::Fill2->new(bounding_box => $self->bounding_box);
-}
-
sub region_volumes {
my $self = shift;
return [ map $self->get_region_volumes($_), 0..($self->region_count - 1) ];
@@ -617,12 +604,12 @@ sub infill {
thread_cb => sub {
my $q = shift;
while (defined (my $i = $q->dequeue)) {
- $self->get_layer($i)->make_fill;
+ $self->get_layer($i)->make_fills;
}
},
no_threads_cb => sub {
foreach my $layer (@{$self->layers}) {
- $layer->make_fill;
+ $layer->make_fills;
}
},
);
@@ -678,14 +665,7 @@ sub _support_material {
);
} else {
# New supports, C++ implementation.
- return Slic3r::Print::SupportMaterial2->new(
- print_config => $self->print->config,
- object_config => $self->config,
- first_layer_flow => $first_layer_flow,
- flow => $self->support_material_flow,
- interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
- soluble_interface => ($self->config->support_material_contact_distance == 0),
- );
+ return Slic3r::Print::SupportMaterial2->new($self);
}
}
diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm
index 875c5af1d..9dbfe4003 100644
--- a/lib/Slic3r/Print/SupportMaterial.pm
+++ b/lib/Slic3r/Print/SupportMaterial.pm
@@ -761,10 +761,13 @@ sub generate_toolpaths {
# Allocate the fillers exclusively in the worker threads! Don't allocate them at the main thread,
# as Perl copies the C++ pointers by default, so then the C++ objects are shared between threads!
my %fillers = (
- interface => $object->fill_maker2->filler('rectilinear'),
- support => $object->fill_maker2->filler($pattern),
+ interface => Slic3r::Filler->new_from_type('rectilinear'),
+ support => Slic3r::Filler->new_from_type($pattern),
);
-
+ my $bounding_box = $object->bounding_box;
+ $fillers{interface}->set_bounding_box($object->bounding_box);
+ $fillers{support}->set_bounding_box($object->bounding_box);
+
# interface and contact infill
if (@$interface || @$contact_infill) {
$fillers{interface}->set_angle($interface_angle);