diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 267424f39..64b60b9cc 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -4,6 +4,7 @@ use Moo; use Math::Clipper ':all'; use Math::ConvexHull qw(convex_hull); use Slic3r::Geometry qw(polygon_lines points_coincide angle3points polyline_lines); +use Slic3r::Geometry::Clipper qw(union_ex); use XXX; use constant PI => 4 * atan2(1, 1); @@ -77,7 +78,7 @@ has 'fills' => ( sub z { my $self = shift; - return $self->id * $Slic3r::layer_height / $Slic3r::resolution; + return ($self->id * $Slic3r::layer_height + $Slic3r::layer_height/2) / $Slic3r::resolution; } sub add_surface { @@ -209,21 +210,25 @@ sub make_surfaces { push @polylines, [@points]; } + #use Slic3r::SVG; #Slic3r::SVG::output(undef, "polylines.svg", # polylines => [ @polylines ], #); - - #@polylines = map Slic3r::Polyline::Closed->cast($_), @polylines; + #exit if $self->id == 30; { - my $clipper = Math::Clipper->new; - $clipper->add_subject_polygons([ @polylines ]); - my $expolygons = $clipper->ex_execute(CT_UNION, PFT_NONZERO, PFT_NONZERO); + my $expolygons = union_ex([ @polylines ]); Slic3r::debugf " %d surface(s) detected from %d polylines\n", scalar(@$expolygons), scalar(@polylines); push @{$self->surfaces}, map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'), @$expolygons; } + + #use Slic3r::SVG; + #Slic3r::SVG::output(undef, "surfaces.svg", + # polygons => [ map $_->contour->p, @{$self->surfaces} ], + # red_polygons => [ map $_->p, map @{$_->holes}, @{$self->surfaces} ], + #); } sub remove_small_surfaces { diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 8cff162da..7de587c73 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -2,6 +2,7 @@ package Slic3r::Print; use Moo; use Math::Clipper ':all'; +use Slic3r::Geometry::Clipper qw(diff_ex union_ex); use XXX; use constant X => 0; @@ -83,10 +84,10 @@ sub detect_surfaces_type { # prepare a reusable subroutine to make surface differences my $surface_difference = sub { my ($subject_surfaces, $clip_surfaces, $result_type) = @_; - $clipper->clear; - $clipper->add_subject_polygons([ map $_->p, @$subject_surfaces ]); - $clipper->add_clip_polygons([ map { ref $_ eq 'ARRAY' ? $_ : $_->p } @$clip_surfaces ]); - my $expolygons = $clipper->ex_execute(CT_DIFFERENCE, PFT_NONZERO, PFT_NONZERO); + my $expolygons = diff_ex( + [ map { ref $_ eq 'ARRAY' ? $_ : $_->p } @$subject_surfaces ], + [ map { ref $_ eq 'ARRAY' ? $_ : $_->p } @$clip_surfaces ], + ); return grep $_->contour->is_printable, map Slic3r::Surface->cast_from_expolygon($_, surface_type => $result_type), @$expolygons; @@ -94,6 +95,7 @@ sub detect_surfaces_type { for (my $i = 0; $i < $self->layer_count; $i++) { my $layer = $self->layers->[$i]; + Slic3r::debugf "Detecting solid surfaces for layer %d\n", $layer->id; my $upper_layer = $self->layers->[$i+1]; my $lower_layer = $i > 0 ? $self->layers->[$i-1] : undef; @@ -103,13 +105,24 @@ sub detect_surfaces_type { # of current layer and upper one) if ($upper_layer) { # offset upper layer surfaces by extrusion_width * perimeters - my $upper_surfaces = offset( - [ map $_->p, @{$upper_layer->surfaces} ], - ($Slic3r::flow_width / $Slic3r::resolution * $Slic3r::perimeter_offsets), - $Slic3r::resolution * 100, - JT_MITER, 2, - ); - @top = $surface_difference->($layer->surfaces, $upper_surfaces, 'top'); + @top = $surface_difference->($layer->surfaces, $upper_layer->surfaces, 'top'); + + # now check whether each resulting top surfaces is large enough to have its + # own perimeters or whether it may be sufficient to use the lower layer's + # perimeters + + # offset upper layer's surfaces + my $upper_surfaces_offsetted; + { + my $distance = $Slic3r::flow_width * ($Slic3r::perimeter_offsets + 1) / $Slic3r::resolution; + $upper_surfaces_offsetted = offset([ map $_->p, @{$upper_layer->surfaces} ], $distance, 100, JT_MITER, 2); + } + + @top = grep { + my $surface = $_; + my $diff = diff_ex([ map $_->p, $surface ], $upper_surfaces_offsetted); + @$diff; + } @top; } else { # if no upper layer, all surfaces of this one are solid @top = @{$layer->surfaces}; @@ -120,6 +133,7 @@ sub detect_surfaces_type { # of current layer and lower one) if ($lower_layer) { @bottom = $surface_difference->($layer->surfaces, $lower_layer->surfaces, 'bottom'); + for (@bottom) { $_->contour->merge_continuous_lines; $_->contour->remove_acute_vertices; @@ -135,6 +149,18 @@ sub detect_surfaces_type { # red_polygons => [ map $_->p, @{$lower_layer->surfaces} ], #); + # offset lower layer's surfaces + my $lower_surfaces_offsetted; + { + my $distance = $Slic3r::flow_width * ($Slic3r::perimeter_offsets + 1) / $Slic3r::resolution; + $lower_surfaces_offsetted = offset([ map $_->p, @{$lower_layer->surfaces} ], $distance, 100, JT_MITER, 2); + } + + @bottom = grep { + my $surface = $_; + my $diff = diff_ex([ map $_->p, $surface ], $lower_surfaces_offsetted); + @$diff; + } @bottom; } else { # if no lower layer, all surfaces of this one are solid diff --git a/lib/Slic3r/SVG.pm b/lib/Slic3r/SVG.pm index 68b0321b2..1843cb259 100644 --- a/lib/Slic3r/SVG.pm +++ b/lib/Slic3r/SVG.pm @@ -46,7 +46,7 @@ sub output { my $g = $svg->group( style => { 'stroke-width' => 2, - 'stroke' => $colour || 'black', + 'stroke' => 'black' || $colour || 'black', 'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')), }, ); @@ -58,6 +58,7 @@ sub output { ); $g->$method( %$path, + 'marker-end' => "url(#endArrow)", ); } }