From 90d10b24a8b9844ec878f9af846fc67360bd9c56 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 12 Jan 2012 22:05:35 +0100 Subject: [PATCH] Fill gaps using medial axis detection --- README.markdown | 4 ++-- lib/Slic3r/ExtrusionLoop.pm | 2 +- lib/Slic3r/Fill.pm | 11 +++++++++++ lib/Slic3r/Layer.pm | 4 ++++ lib/Slic3r/Perimeter.pm | 16 ++++++++++++---- lib/Slic3r/Point.pm | 2 -- lib/Slic3r/Surface.pm | 2 +- 7 files changed, 31 insertions(+), 10 deletions(-) diff --git a/README.markdown b/README.markdown index 094ece767..236c4fcd5 100644 --- a/README.markdown +++ b/README.markdown @@ -49,14 +49,14 @@ Roadmap includes the following goals: * support material for internal perimeters; * new and better GUI; * cool; -* other fill patterns. +* more fill patterns. ## Is it usable already? Any known limitation? Sure, it's very usable. Remember that: * it doesn't generate support material; -* it only works well with manifold models (check them with Meshlab or Netfabb or http://cloud.netfabb.com/). +* it only works well with manifold and clean models (check them with Meshlab or Netfabb or http://cloud.netfabb.com/). ## How to install? diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index caee31ede..ed91651b4 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -26,7 +26,7 @@ sub split_at { # find index of point my $i = -1; - for (my $n = 0; $n <= $#{$self->polygon}; $n++) {ZZZ "here" if ref $self->polygon->[$n] eq 'ARRAY'; + for (my $n = 0; $n <= $#{$self->polygon}; $n++) { if ($point->id eq $self->polygon->[$n]->id) { $i = $n; last; diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index eab0633dd..98aa2a6ef 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -161,6 +161,17 @@ sub make_fill { ], ) if @paths; } + + # add thin fill regions + push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new( + paths => [ + map { + $_->isa('Slic3r::Polygon') + ? Slic3r::ExtrusionLoop->new(polygon => $_, role => 'solid-fill')->split_at($_->[0]) + : Slic3r::ExtrusionPath->new(polyline => $_, role => 'solid-fill') + } @{$layer->thin_fills}, + ], + ) if @{$layer->thin_fills}; } 1; diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 4f2701105..5d36d0591 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -34,6 +34,10 @@ has 'thin_walls' => (is => 'ro', default => sub { [] }); # they represent boundaries of areas to fill has 'fill_boundaries' => (is => 'ro', default => sub { [] }); +# collection of polygons or polylines representing thin infill regions that +# need to be filled with a medial axis +has 'thin_fills' => (is => 'ro', default => sub { [] }); + # collection of surfaces generated by clipping the slices to the fill boundaries has 'surfaces' => ( is => 'rw', diff --git a/lib/Slic3r/Perimeter.pm b/lib/Slic3r/Perimeter.pm index ed9f7df0a..2b64f83a8 100644 --- a/lib/Slic3r/Perimeter.pm +++ b/lib/Slic3r/Perimeter.pm @@ -3,6 +3,7 @@ use Moo; use Math::Clipper ':all'; use Slic3r::Geometry qw(X Y shortest_path scale); +use Slic3r::Geometry::Clipper qw(diff_ex); use XXX; sub make_perimeter { @@ -42,6 +43,7 @@ sub make_perimeter { for (my $loop = 0; $loop < $Slic3r::perimeters; $loop++) { # offsetting a polygon can result in one or many offset polygons @last_offsets = map $_->offset_ex(-$distance), @last_offsets if $distance; + last if !@last_offsets; push @{ $perimeters[-1] }, [@last_offsets]; # offset distance for inner loops @@ -51,12 +53,18 @@ sub make_perimeter { # create one more offset to be used as boundary for fill { my @fill_boundaries = map $_->offset_ex(-$distance), @last_offsets; + push @{ $layer->fill_boundaries }, @fill_boundaries; - # TODO: diff(offset(@last_offsets, -$distance/2), offset(@fill_boundaries, +$distance/2)) - # this represents the small gaps that we need to treat like thin polygons, + # detect the small gaps that we need to treat like thin polygons, # thus generating the skeleton and using it to fill them - - push @{ $layer->fill_boundaries }, @fill_boundaries if @fill_boundaries; + my $small_gaps = diff_ex( + [ map @$_, map $_->offset_ex(-$distance/2), map @$_, @{$perimeters[-1]} ], + [ map @$_, map $_->offset_ex(+$distance/2), @fill_boundaries ], + ); + push @{ $layer->thin_fills }, + grep $_, + map $_->medial_axis(scale $Slic3r::flow_width), + @$small_gaps; } } diff --git a/lib/Slic3r/Point.pm b/lib/Slic3r/Point.pm index f8d3af071..5d471e3b3 100644 --- a/lib/Slic3r/Point.pm +++ b/lib/Slic3r/Point.pm @@ -12,8 +12,6 @@ sub new { } elsif ($_[0]->isa(__PACKAGE__)) { return $_[0]; } else { - use XXX; - ZZZ \@_; die "Invalid arguments for ${class}->new"; } bless $self, $class; diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm index 8605f7b81..1b7b37888 100644 --- a/lib/Slic3r/Surface.pm +++ b/lib/Slic3r/Surface.pm @@ -61,7 +61,7 @@ sub clipper_polygon { } sub p { - my $self = shift;use XXX; ZZZ $self->expolygon if !eval { 1 if @{$self->expolygon}; 1 }; + my $self = shift; return @{$self->expolygon}; }