diff options
author | Alessandro Ranellucci <aar@cpan.org> | 2011-11-23 15:29:27 +0400 |
---|---|---|
committer | Alessandro Ranellucci <aar@cpan.org> | 2011-11-23 15:29:27 +0400 |
commit | 8598b66b0a9dfa19c49598e52d603657d3113fd7 (patch) | |
tree | 24401d84ac45c04c61da7f735bbf0455b600908f /lib/Slic3r/Layer.pm | |
parent | 13ef24b5ebd633a5286ee536b8f782c5a7e56d80 (diff) |
Large refactoring. Cleaner logic, smaller memory footprint.
Diffstat (limited to 'lib/Slic3r/Layer.pm')
-rw-r--r-- | lib/Slic3r/Layer.pm | 104 |
1 files changed, 29 insertions, 75 deletions
diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 5ae594ea1..a4ad47382 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -29,20 +29,6 @@ has 'surfaces' => ( default => sub { [] }, ); -# collection of surfaces representing bridges -has 'bridges' => ( - is => 'rw', - #isa => 'ArrayRef[Slic3r::Surface]', - default => sub { [] }, -); - -# collection of surfaces to make perimeters for -has 'perimeter_surfaces' => ( - is => 'rw', - #isa => 'ArrayRef[Slic3r::Surface]', - default => sub { [] }, -); - # ordered collection of extrusion paths to build all perimeters has 'perimeters' => ( is => 'rw', @@ -58,10 +44,10 @@ has 'skirts' => ( ); # collection of surfaces generated by offsetting the innermost perimeter(s) -# they represent boundaries of areas to fill (grouped by original objects) -has 'fill_surfaces' => ( +# they represent boundaries of areas to fill +has 'fill_boundaries' => ( is => 'rw', - #isa => 'ArrayRef[ArrayRef[Slic3r::Surface]]', + #isa => 'ArrayRef[Slic3r::Surface]', default => sub { [] }, ); @@ -352,6 +338,8 @@ sub remove_small_perimeters { sub process_bridges { my $self = shift; + my @bridges = (); + # a bottom surface on a layer > 0 is either a bridge or a overhang # or a combination of both; any top surface is a candidate for # reverse bridge processing @@ -426,8 +414,8 @@ sub process_bridges { # now, extend our bridge by taking a portion of supporting surfaces { - # offset the bridge by the specified amount of mm - my $bridge_overlap = 2 * $Slic3r::perimeters * $Slic3r::flow_width / $Slic3r::resolution; + # offset the bridge by the specified amount of mm (minimum 3) + my $bridge_overlap = 3 / $Slic3r::resolution; my ($bridge_offset) = $expolygon->contour->offset($bridge_overlap, $Slic3r::resolution * 100, JT_MITER, 2); # calculate the new bridge @@ -436,7 +424,7 @@ sub process_bridges { [ $bridge_offset ], ); - push @{$self->bridges}, map Slic3r::Surface->cast_from_expolygon($_, + push @bridges, map Slic3r::Surface->cast_from_expolygon($_, surface_type => $surface->surface_type, bridge_angle => $bridge_angle, ), @$intersection; @@ -446,86 +434,52 @@ sub process_bridges { # now we need to merge bridges to avoid overlapping { # build a list of unique bridge types - my @surface_groups = Slic3r::Surface->group(@{$self->bridges}); + my @surface_groups = Slic3r::Surface->group(@bridges); # merge bridges of the same type, removing any of the bridges already merged; # the order of @surface_groups determines the priority between bridges having # different surface_type or bridge_angle - @{$self->bridges} = (); + @bridges = (); foreach my $surfaces (@surface_groups) { my $union = union_ex([ map $_->p, @$surfaces ]); my $diff = diff_ex( [ map @$_, @$union ], - [ map $_->p, @{$self->bridges} ], + [ map $_->p, @bridges ], ); - push @{$self->bridges}, map Slic3r::Surface->cast_from_expolygon($_, + push @bridges, map Slic3r::Surface->cast_from_expolygon($_, surface_type => $surfaces->[0]->surface_type, bridge_angle => $surfaces->[0]->bridge_angle, ), @$union; } } -} - -# generates a set of surfaces that will be used to make perimeters -# thus, we need to merge internal surfaces and bridges -sub detect_perimeter_surfaces { - my $self = shift; - - # little optimization: skip the Clipper UNION if we have no bridges - if (!@{$self->bridges}) { - push @{$self->perimeter_surfaces}, @{$self->surfaces}; - } else { - my $union = union_ex([ - (map $_->p, grep $_->surface_type =~ /internal/, @{$self->surfaces}), - (map $_->p, @{$self->bridges}), - ]); - - # schedule perimeters for internal surfaces merged with bridges - push @{$self->perimeter_surfaces}, - map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'), - @$union; - - # schedule perimeters for the remaining surfaces - foreach my $type (qw(top bottom)) { - my $diff = diff_ex( - [ map $_->p, grep $_->surface_type eq $type, @{$self->surfaces} ], - [ map @$_, @$union ], - ); - push @{$self->perimeter_surfaces}, - map Slic3r::Surface->cast_from_expolygon($_, surface_type => $type), - @$diff; - } - } -} - -# splits fill_surfaces in internal and bridge surfaces -sub split_bridges_fills { - my $self = shift; - foreach my $surfaces (@{$self->fill_surfaces}) { - my @surfaces = @$surfaces; - @$surfaces = (); + # apply bridges to layer + { + my @surfaces = @{$self->surfaces}; + @{$self->surfaces} = (); - # intersect fill_surfaces with bridges to get actual bridges - foreach my $bridge (@{$self->bridges}) { - my $intersection = intersection_ex( + # intersect layer surfaces with bridges to get actual bridges + foreach my $bridge (@bridges) { + my $actual_bridge = intersection_ex( [ map $_->p, @surfaces ], [ $bridge->p ], ); - push @$surfaces, map Slic3r::Surface->cast_from_expolygon($_, + push @{$self->surfaces}, map Slic3r::Surface->cast_from_expolygon($_, surface_type => $bridge->surface_type, bridge_angle => $bridge->bridge_angle, - ), @$intersection; + ), @$actual_bridge; } - # difference between fill_surfaces and bridges are the other surfaces - foreach my $type (qw(top bottom internal internal-solid)) { - my @my_surfaces = grep $_->surface_type eq $type, @surfaces; - my $difference = diff_ex([ map $_->p, @my_surfaces ], [ map $_->p, @{$self->bridges} ]); - push @$surfaces, map Slic3r::Surface->cast_from_expolygon($_, - surface_type => $type), @$difference; + # difference between layer surfaces and bridges are the other surfaces + foreach my $group (Slic3r::Surface->group(@surfaces)) { + my $difference = diff_ex( + [ map $_->p, @$group ], + [ map $_->p, @bridges ], + ); + push @{$self->surfaces}, map Slic3r::Surface->cast_from_expolygon($_, + surface_type => $group->[0]->surface_type), @$difference; } } } |