Browse Source

Bugfix: make_perimeters() was not truly idempotent because prepare_infill() split ->slices into typed surfaces

Alessandro Ranellucci 10 years ago
parent
commit
d9f5fdae72
6 changed files with 38 additions and 3 deletions
  1. 5 0
      lib/Slic3r/Layer.pm
  2. 11 0
      lib/Slic3r/Layer/Region.pm
  3. 10 1
      lib/Slic3r/Print/Object.pm
  4. 2 1
      xs/src/Print.cpp
  5. 4 0
      xs/src/Print.hpp
  6. 6 1
      xs/xsp/Print.xsp

+ 5 - 0
lib/Slic3r/Layer.pm

@@ -57,6 +57,11 @@ sub make_slices {
     $self->slices->append(@$slices);
 }
 
+sub merge_slices {
+    my ($self) = @_;
+    $_->merge_slices for @{$self->regions};
+}
+
 sub make_perimeters {
     my $self = shift;
     Slic3r::debugf "Making perimeters for layer %d\n", $self->id;

+ 11 - 0
lib/Slic3r/Layer/Region.pm

@@ -40,6 +40,17 @@ sub flow {
     );
 }
 
+sub merge_slices {
+    my ($self) = @_;
+    
+    my $expolygons = union_ex([ map $_->p, @{$self->slices} ]);
+    $self->slices->clear;
+    $self->slices->append(Slic3r::Surface->new(
+        expolygon    => $_,
+        surface_type => S_TYPE_INTERNAL,
+    )) for @$expolygons;
+}
+
 sub make_perimeters {
     my ($self, $slices, $fill_surfaces) = @_;
     

+ 10 - 1
lib/Slic3r/Print/Object.pm

@@ -366,6 +366,7 @@ sub slice {
     die "No layers were detected. You might want to repair your STL file(s) or check their size and retry.\n"
         if !@{$self->layers};
     
+    $self->set_typed_slices(0);
     $self->set_step_done(STEP_SLICE);
 }
 
@@ -412,6 +413,13 @@ sub make_perimeters {
     $self->set_step_started(STEP_PERIMETERS);
     $self->print->status_cb->(20, "Generating perimeters");
     
+    # merge slices if they were split into types
+    if ($self->typed_slices) {
+        $_->merge_slices for @{$self->layers};
+        $self->set_typed_slices(0);
+        $self->invalidate_step(STEP_PREPARE_INFILL);
+    }
+    
     # compare each layer to the one below, and mark those slices needing
     # one additional inner perimeter, like the top of domed objects-
     
@@ -509,7 +517,8 @@ sub prepare_infill {
     # and transform $layerm->fill_surfaces from expolygon 
     # to typed top/bottom/internal surfaces;
     $self->detect_surfaces_type;
-
+    $self->set_typed_slices(1);
+    
     # decide what surfaces are to be filled
     $_->prepare_fill_surfaces for map @{$_->regions}, @{$self->layers};
 

+ 2 - 1
xs/src/Print.cpp

@@ -66,7 +66,8 @@ REGISTER_CLASS(PrintRegion, "Print::Region");
 
 PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox)
 :   _print(print),
-    _model_object(model_object)
+    _model_object(model_object),
+    typed_slices(false)
 {
     region_volumes.resize(this->_print->regions.size());
 

+ 4 - 0
xs/src/Print.hpp

@@ -70,6 +70,10 @@ class PrintObject
     Points copies;      // Slic3r::Point objects in scaled G-code coordinates
     PrintObjectConfig config;
     t_layer_height_ranges layer_height_ranges;
+    
+    // this is set to true when LayerRegion->slices is split in top/internal/bottom
+    // so that next call to make_perimeters() performs a union() before computing loops
+    bool typed_slices;
 
     Point3 size;           // XYZ in scaled coordinates
 

+ 6 - 1
xs/xsp/Print.xsp

@@ -61,7 +61,12 @@ _constant()
         %code%{ RETVAL = &THIS->size; %};
     Ref<Point> _copies_shift()
         %code%{ RETVAL = &THIS->_copies_shift; %};
-
+    
+    bool typed_slices()
+        %code%{ RETVAL = THIS->typed_slices; %};
+    void set_typed_slices(bool value)
+        %code%{ THIS->typed_slices = value; %};
+    
     Points _shifted_copies()
         %code%{ RETVAL = THIS->_shifted_copies; %};
     void set_shifted_copies(Points value)