diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index e052240a1..9bcebdb9b 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -79,7 +79,6 @@ use constant SCALED_RESOLUTION => RESOLUTION / SCALING_FACTOR; use constant LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER => 0.15; use constant INFILL_OVERLAP_OVER_SPACING => 0.3; use constant EXTERNAL_INFILL_MARGIN => 3; -use constant INSET_OVERLAP_TOLERANCE => 0.4; # keep track of threads we created my @my_threads = (); diff --git a/lib/Slic3r/Layer/PerimeterGenerator.pm b/lib/Slic3r/Layer/PerimeterGenerator.pm index daf2ba8f8..a4b0d4aec 100644 --- a/lib/Slic3r/Layer/PerimeterGenerator.pm +++ b/lib/Slic3r/Layer/PerimeterGenerator.pm @@ -8,6 +8,8 @@ use Slic3r::Geometry::Clipper qw(union_ex diff diff_ex intersection_ex offset of offset_ex offset2_ex intersection_ppl diff_ppl); use Slic3r::Surface ':types'; +use constant INSET_OVERLAP_TOLERANCE => 0.4; + has 'slices' => (is => 'ro', required => 1); # SurfaceCollection has 'lower_slices' => (is => 'ro', required => 0); has 'layer_height' => (is => 'ro', required => 1); @@ -20,7 +22,6 @@ has 'config' => (is => 'ro', default => sub { Slic3r::Config::Pri has 'object_config' => (is => 'ro', default => sub { Slic3r::Config::PrintObject->new }); has 'print_config' => (is => 'ro', default => sub { Slic3r::Config::Print->new }); has '_lower_slices_p' => (is => 'rw', default => sub { [] }); -has '_holes_pt' => (is => 'rw'); has '_ext_mm3_per_mm' => (is => 'rw'); has '_mm3_per_mm' => (is => 'rw'); has '_mm3_per_mm_overhang' => (is => 'rw'); @@ -500,34 +501,4 @@ sub _fill_gaps { } -package Slic3r::Layer::PerimeterGenerator::Loop; -use Moo; - -has 'polygon' => (is => 'ro', required => 1); -has 'is_contour' => (is => 'ro', required => 1); -has 'depth' => (is => 'ro', required => 1); -has 'children' => (is => 'ro', default => sub { [] }); - -use List::Util qw(first); - -sub add_child { - my ($self, $child) = @_; - push @{$self->children}, $child; -} - -sub is_external { - my ($self) = @_; - return $self->depth == 0; -} - -sub is_internal_contour { - my ($self) = @_; - - if ($self->is_contour) { - # an internal contour is a contour containing no other contours - return !defined first { $_->is_contour } @{$self->children}; - } - return 0; -} - 1; diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp new file mode 100644 index 000000000..5c054aa6a --- /dev/null +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -0,0 +1,120 @@ +#include "PerimeterGenerator.hpp" + +namespace Slic3r { + +void +PerimeterGenerator::process() +{ + +} + +ExtrusionEntityCollection +PerimeterGenerator::_traverse_loops(const std::vector &loops, + const Polylines &thin_walls) const +{ + +} + +ExtrusionEntityCollection +PerimeterGenerator::_fill_gaps(double min, double max, double w, + const Polygons &gaps) const +{ + ExtrusionEntityCollection coll; + + min *= (1 - INSET_OVERLAP_TOLERANCE); + + ExPolygon curr = diff( + offset2(gaps, -min/2, +min/2), + offset2(gaps, -max/2, +max/2), + true, + ); + + Polylines polylines; + for (ExPolygons::const_iterator ex = curr.begin(); ex != curr.end(); ++ex) + ex->medial_axis(max, min/2, &polylines); + if (polylines.empty()) + return coll; + + #ifdef SLIC3R_DEBUG + if (!curr.empty()) + printf(" %d gaps filled with extrusion width = %zu\n", curr.size(), w); + #endif + + //my $flow = $layerm->flow(FLOW_ROLE_SOLID_INFILL, 0, $w); + Flow flow( + w, this->layer_height, this->solid_infill_flow.nozzle_diameter + ); + + double mm3_per_mm = flow.mm3_per_mm(); + + /* + my %path_args = ( + role => EXTR_ROLE_GAPFILL, + mm3_per_mm => $flow->mm3_per_mm, + width => $flow->width, + height => $self->layer_height, + ); + */ + + for (Polylines::const_iterator p = polylines.begin(); p != polylines.end(); ++p) { + /* + #if ($polylines[$i]->isa('Slic3r::Polygon')) { + # my $loop = Slic3r::ExtrusionLoop->new; + # $loop->append(Slic3r::ExtrusionPath->new(polyline => $polylines[$i]->split_at_first_point, %path_args)); + # $polylines[$i] = $loop; + */ + if (p->is_valid() && p->first_point().coincides_with(p->last_point())) { + // since medial_axis() now returns only Polyline objects, detect loops here + + + ExtrusionLoop loop; + loop.paths.push_back(); + } else { + + } + } + + foreach my $polyline (@polylines) { + #if ($polylines[$i]->isa('Slic3r::Polygon')) { + # my $loop = Slic3r::ExtrusionLoop->new; + # $loop->append(Slic3r::ExtrusionPath->new(polyline => $polylines[$i]->split_at_first_point, %path_args)); + # $polylines[$i] = $loop; + if ($polyline->is_valid && $polyline->first_point->coincides_with($polyline->last_point)) { + # since medial_axis() now returns only Polyline objects, detect loops here + push @entities, my $loop = Slic3r::ExtrusionLoop->new; + $loop->append(Slic3r::ExtrusionPath->new(polyline => $polyline, %path_args)); + } else { + push @entities, Slic3r::ExtrusionPath->new(polyline => $polyline, %path_args); + } + } + + return coll; +} + +#ifdef SLIC3RXS +REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator"); +#endif + +bool +PerimeterGeneratorLoop::is_external() const +{ + return this->depth == 0; +} + +bool +PerimeterGeneratorLoop::is_internal_contour() const +{ + if (this->is_contour) { + // an internal contour is a contour containing no other contours + for (std::vector::const_iterator loop = this->children.begin(); + loop != this->children.end(); ++loop) { + if (loop->is_contour) { + return false; + } + } + return true; + } + return false; +} + +} diff --git a/xs/src/libslic3r/PerimeterGenerator.hpp b/xs/src/libslic3r/PerimeterGenerator.hpp new file mode 100644 index 000000000..d896cd8da --- /dev/null +++ b/xs/src/libslic3r/PerimeterGenerator.hpp @@ -0,0 +1,64 @@ +#ifndef slic3r_PerimeterGenerator_hpp_ +#define slic3r_PerimeterGenerator_hpp_ + +#include + +namespace Slic3r { + +class PerimeterGeneratorLoop; + +class PerimeterGeneratorLoop { + public: + Polygon polygon; + bool is_contour; + unsigned short depth; + std::vector children; + + PerimeterGeneratorLoop(Polygon polygon, unsigned short depth) + : polygon(polygon), depth(depth) + {}; + bool is_external() const; + bool is_internal_contour() const; +}; + +class PerimeterGenerator { + public: + SurfaceCollection* slices; + SurfaceCollection* lower_slices; + double layer_height; + int layer_id; + Flow perimeter_flow; + Flow ext_perimeter_flow; + Flow overhang_flow; + Flow solid_infill_flow; + PrintRegionConfig* config; + PrintObjectConfig* object_config; + PrintConfig* print_config; + double _ext_mm3_per_mm; + double _mm3_per_mm; + double _mm3_per_mm_overhang; + ExtrusionEntityCollection* loops; + ExtrusionEntityCollection* gap_fill; + SurfaceCollection* fill_surfaces; + + PerimeterGenerator(SurfaceCollection* slices, double layer_height, + ExtrusionEntityCollection* loops, ExtrusionEntityCollection* gap_fill, + SurfaceCollection* fill_surfaces) + : slices(slices), layer_height(layer_height), layer_id(-1), + _ext_mm3_per_mm(-1), _mm3_per_mm(-1), _mm3_per_mm_overhang(-1), + loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces) + {}; + void process(); + + private: + Polygons _lower_slices_p; + + ExtrusionEntityCollection _traverse_loops(const std::vector &loops, + const Polylines &thin_walls) const; + ExtrusionEntityCollection _fill_gaps(double min, double max, double w, + const Polygons &gaps) const; +}; + +} + +#endif diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index fcf90f133..87d98caf1 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -15,6 +15,7 @@ #define PI 3.141592653589793238 #define LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER 0.15 #define SMALL_PERIMETER_LENGTH (6.5 / SCALING_FACTOR) * 2 * PI +#define INSET_OVERLAP_TOLERANCE 0.4 #define scale_(val) (val / SCALING_FACTOR) #define unscale(val) (val * SCALING_FACTOR) #define SCALED_EPSILON scale_(EPSILON)