From 6adce9f66b4a935036f88f86f4b2647a5144adba Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 17 Sep 2013 23:14:49 +0200 Subject: [PATCH] Update support material code to use shared memory --- lib/Slic3r.pm | 6 +++ lib/Slic3r/Layer.pm | 6 +-- lib/Slic3r/Print/Object.pm | 81 +++++++++++++------------------------- 3 files changed, 36 insertions(+), 57 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 620e872b5..22727a369 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -97,6 +97,7 @@ sub parallelize { Slic3r::thread_cleanup(); return $result; }; + $params{collect_cb} ||= sub {}; @_ = (); foreach my $th (map threads->create($thread_cb), 1..$Config->threads) { @@ -113,6 +114,11 @@ sub parallelize { # inherited at the thread creation (thus shared) and those # that we are returning: destruction will be handled by the # main thread in both cases. +# reminder: do not destroy inherited objects in other threads, +# as the main thread will still try to destroy them when they +# go out of scope; in other words, if you're undef()'ing an +# object in a thread, make sure the main thread still holds a +# reference so that it won't be destroyed in thread. sub thread_cleanup { # prevent destruction of shared objects no warnings 'redefine'; diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index ebf3280b1..49d48216b 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -69,9 +69,9 @@ use Moo; extends 'Slic3r::Layer'; # ordered collection of extrusion paths to fill surfaces for support material -has 'support_islands' => (is => 'rw', default => sub { [] }); -has 'support_fills' => (is => 'rw'); -has 'support_interface_fills' => (is => 'rw'); +has 'support_islands' => (is => 'rw', default => sub { Slic3r::ExPolygon::Collection->new }); +has 'support_fills' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new }); +has 'support_interface_fills' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new }); sub islands { my $self = shift; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index fe4a52121..0befe2e2e 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -1024,32 +1024,27 @@ sub generate_support_material { my $process_layer = sub { my ($layer_id) = @_; + my $layer = $self->support_layers->[$layer_id]; - $contact{$support_layers[$layer_id]} ||= []; - $interface{$layer_id} ||= []; - $support{$layer_id} ||= []; + my $overhang = $overhang{$support_layers[$layer_id]} || []; + my $contact = $contact{$support_layers[$layer_id]} || []; + my $interface = $interface{$layer_id} || []; + my $support = $support{$layer_id} || []; if (0) { require "Slic3r/SVG.pm"; Slic3r::SVG::output("layer_" . $support_layers[$layer_id] . ".svg", - red_expolygons => union_ex($contact{$support_layers[$layer_id]}), - green_expolygons => union_ex($interface{$layer_id}), + red_expolygons => union_ex($contact), + green_expolygons => union_ex($interface), ); } # islands - my $result = { contact => [], interface => [], support => [] }; - $result->{islands} = union_ex([ - map @$_, - $interface{$layer_id}, - $support{$layer_id}, - $contact{$support_layers[$layer_id]}, - ]); + $layer->support_islands->append(@{union_ex([ @$interface, @$support, @$contact ])}); # contact my $contact_infill = []; - if ((my $contact = $contact{$support_layers[$layer_id]}) && $contact_loops > 0) { - my $overhang = $overhang{$support_layers[$layer_id]}; + if ($contact && $contact_loops > 0) { $contact = [ grep $_->is_counter_clockwise, @$contact ]; # generate the outermost loop @@ -1090,26 +1085,26 @@ sub generate_support_material { flow_spacing => $flow->spacing, ), @loops; - $result->{contact} = [ @loops ]; + $layer->support_interface_fills->append(@loops); } # interface and contact infill - if (@{$interface{$layer_id}} || @$contact_infill) { + if (@$interface || @$contact_infill) { $fillers{interface}->angle($interface_angle); # steal some space from support - $interface{$layer_id} = intersection( - offset([ map @$_, $interface{$layer_id}, $contact_infill ], scale 3), - [ map @$_, $interface{$layer_id}, $support{$layer_id}, $contact_infill ], + $interface = intersection( + offset([ @$interface, @$contact_infill ], scale 3), + [ @$interface, @$support, @$contact_infill ], 1, ); $support{$layer_id} = diff( - $support{$layer_id}, - $interface{$layer_id}, + $support, + $interface, ); my @paths = (); - foreach my $expolygon (@{union_ex($interface{$layer_id})}) { + foreach my $expolygon (@{union_ex($interface)}) { my @p = $fillers{interface}->fill_surface( Slic3r::Surface->new(expolygon => $expolygon, surface_type => S_TYPE_INTERNAL), density => $interface_density, @@ -1125,18 +1120,18 @@ sub generate_support_material { flow_spacing => $params->{flow_spacing}, ), @p; } - $result->{interface} = [ @paths ]; + $layer->support_interface_fills->append(@paths); } # support or flange - if (@{$support{$layer_id}}) { + if (@$support) { my $filler = $fillers{support}; $filler->angle($angles[ ($layer_id) % @angles ]); my $density = $support_density; my $flow_spacing = $flow->spacing; # TODO: use offset2_ex() - my $to_infill = union_ex($support{$layer_id}, 1); + my $to_infill = union_ex($support, 1); my @paths = (); # base flange @@ -1176,52 +1171,30 @@ sub generate_support_material { ), @p; } - push @{$result->{support}}, @paths; + $layer->support_fills->append(@paths); } if (0) { require "Slic3r/SVG.pm"; Slic3r::SVG::output("islands_" . $support_layers[$layer_id] . ".svg", - red_expolygons => union_ex($contact{$support_layers[$layer_id]} || []), - green_expolygons => union_ex($interface{$layer_id} || []), - red_polylines => [ map $_->unpack->polyline, @{$result->{contact}} ], - green_polylines => [ map $_->unpack->polyline, @{$result->{interface}} ], - polylines => [ map $_->unpack->polyline, @{$result->{support}} ], + red_expolygons => union_ex($contact), + green_expolygons => union_ex($interface), + green_polylines => [ map $_->unpack->polyline, @{$layer->support_contact_fills} ], + polylines => [ map $_->unpack->polyline, @{$layer->support_fills} ], ); } - - return $result; }; - my $apply = sub { - my ($layer_id, $result) = @_; - my $layer = $self->support_layers->[$layer_id]; - - my $interface_collection = Slic3r::ExtrusionPath::Collection->new(@{$result->{contact}}, @{$result->{interface}}); - $layer->support_interface_fills($interface_collection) if @$interface_collection > 0; - - my $support_collection = Slic3r::ExtrusionPath::Collection->new(@{$result->{support}}); - $layer->support_fills($support_collection) if @$support_collection > 0; - - # TODO: use a Slic3r::ExPolygon::Collection - $layer->support_islands($result->{islands}); - }; Slic3r::parallelize( items => [ 0 .. $#{$self->support_layers} ], thread_cb => sub { my $q = shift; - my $result = {}; while (defined (my $layer_id = $q->dequeue)) { - $result->{$layer_id} = $process_layer->($layer_id); + $process_layer->($layer_id); } - return $result; - }, - collect_cb => sub { - my $result = shift; - $apply->($_, $result->{$_}) for keys %$result; }, no_threads_cb => sub { - $apply->($_, $process_layer->($_)) for 0 .. $#{$self->support_layers}; + $process_layer->($_) for 0 .. $#{$self->support_layers}; }, ); }