diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 919bb10e83..897268fe0a 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -11,6 +11,8 @@ use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union use Slic3r::Print::State ':steps'; use Slic3r::Surface ':types'; +# If enabled, phases of prepare_infill will be written into SVG files to an "out" directory. +our $SLIC3R_DEBUG_SLICE_PROCESSING = 0; # TODO: lazy sub fill_maker { @@ -492,19 +494,76 @@ sub prepare_infill { # and transform $layerm->fill_surfaces from expolygon # to typed top/bottom/internal surfaces; $self->detect_surfaces_type; + # Mark the object to have the slices classified (typed, which also means they are split based on whether they are supported, bridging, top layers etc.) $self->set_typed_slices(1); - # decide what surfaces are to be filled + # Decide what surfaces are to be filled. + # Here the S_TYPE_TOP / S_TYPE_BOTTOMBRIDGE / S_TYPE_BOTTOM infill is turned to just S_TYPE_INTERNAL if zero top / bottom infill layers are configured. + # Also tiny S_TYPE_INTERNAL surfaces are turned to S_TYPE_INTERNAL_SOLID. $_->prepare_fill_surfaces for map @{$_->regions}, @{$self->layers}; # this will detect bridges and reverse bridges # and rearrange top/bottom/internal surfaces + # It produces enlarged overlapping bridging areas. + # + # 1) S_TYPE_BOTTOMBRIDGE / S_TYPE_BOTTOM infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap. + # 2) S_TYPE_TOP is grown by 3mm and clipped by the grown bottom areas. The areas may overlap. + # 3) Clip the internal surfaces by the grown top/bottom surfaces. + # 4) Merge surfaces with the same style. This will mostly get rid of the overlaps. + #FIXME This does not likely merge surfaces, which are supported by a material with different colors, but same properties. $self->process_external_surfaces; - # detect which fill surfaces are near external layers - # they will be split in internal and internal-solid surfaces + # Add solid fills to ensure the shell vertical thickness. + $self->discover_vertical_shells; + + # Debugging output. + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + for my $region_id (0 .. ($self->print->region_count-1)) { + for (my $i = 0; $i < $self->layer_count; $i++) { + my $layerm = $self->get_layer($i)->regions->[$region_id]; + $layerm->export_region_slices_to_svg_debug("6_discover_vertical_shells-final"); + $layerm->export_region_fill_surfaces_to_svg_debug("6_discover_vertical_shells-final"); + } # for each layer + } # for each region + } + + # Detect, which fill surfaces are near external layers. + # They will be split in internal and internal-solid surfaces. + # The purpose is to add a configurable number of solid layers to support the TOP surfaces + # and to add a configurable number of solid layers above the BOTTOM / BOTTOMBRIDGE surfaces + # to close these surfaces reliably. + #FIXME Vojtech: Is this a good place to add supporting infills below sloping perimeters? $self->discover_horizontal_shells; + + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + # Debugging output. + for my $region_id (0 .. ($self->print->region_count-1)) { + for (my $i = 0; $i < $self->layer_count; $i++) { + my $layerm = $self->get_layer($i)->regions->[$region_id]; + $layerm->export_region_slices_to_svg_debug("7_discover_horizontal_shells-final"); + $layerm->export_region_fill_surfaces_to_svg_debug("7_discover_horizontal_shells-final"); + } # for each layer + } # for each region + } + + # Only active if config->infill_only_where_needed. This step trims the sparse infill, + # so it acts as an internal support. It maintains all other infill types intact. + # Here the internal surfaces and perimeters have to be supported by the sparse infill. + #FIXME The surfaces are supported by a sparse infill, but the sparse infill is only as large as the area to support. + # Likely the sparse infill will not be anchored correctly, so it will not work as intended. + # Also one wishes the perimeters to be supported by a full infill. $self->clip_fill_surfaces; + + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + # Debugging output. + for my $region_id (0 .. ($self->print->region_count-1)) { + for (my $i = 0; $i < $self->layer_count; $i++) { + my $layerm = $self->get_layer($i)->regions->[$region_id]; + $layerm->export_region_slices_to_svg_debug("8_clip_surfaces-final"); + $layerm->export_region_fill_surfaces_to_svg_debug("8_clip_surfaces-final"); + } # for each layer + } # for each region + } # the following step needs to be done before combination because it may need # to remove only half of the combined infill @@ -513,6 +572,22 @@ sub prepare_infill { # combine fill surfaces to honor the "infill every N layers" option $self->combine_infill; + # Debugging output. + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + for my $region_id (0 .. ($self->print->region_count-1)) { + for (my $i = 0; $i < $self->layer_count; $i++) { + my $layerm = $self->get_layer($i)->regions->[$region_id]; + $layerm->export_region_slices_to_svg_debug("9_prepare_infill-final"); + $layerm->export_region_fill_surfaces_to_svg_debug("9_prepare_infill-final"); + } # for each layer + } # for each region + for (my $i = 0; $i < $self->layer_count; $i++) { + my $layer = $self->get_layer($i); + $layer->export_region_slices_to_svg_debug("9_prepare_infill-final"); + $layer->export_region_fill_surfaces_to_svg_debug("9_prepare_infill-final"); + } # for each layer + } + $self->set_step_done(STEP_PREPARE_INFILL); } @@ -591,6 +666,15 @@ sub _support_material { ); } +# This function analyzes slices of a region (SurfaceCollection slices). +# Each slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface. +# Initially all slices are of type S_TYPE_INTERNAL. +# Slices are compared against the top / bottom slices and regions and classified to the following groups: +# S_TYPE_TOP - Part of a region, which is not covered by any upper layer. This surface will be filled with a top solid infill. +# S_TYPE_BOTTOMBRIDGE - Part of a region, which is not fully supported, but it hangs in the air, or it hangs losely on a support or a raft. +# S_TYPE_BOTTOM - Part of a region, which is not supported by the same region, but it is supported either by another region, or by a soluble interface layer. +# S_TYPE_INTERNAL - Part of a region, which is supported by the same region type. +# If a part of a region is of S_TYPE_BOTTOM and S_TYPE_TOP, the S_TYPE_BOTTOM wins. sub detect_surfaces_type { my $self = shift; Slic3r::debugf "Detecting solid surfaces...\n"; @@ -623,6 +707,8 @@ sub detect_surfaces_type { # of current layer and upper one) my @top = (); if ($upper_layer) { + # Config value $self->config->interface_shells is true, if a support is separated from the object + # by a soluble material (for example a PVA plastic). my $upper_slices = $self->config->interface_shells ? [ map $_->expolygon, @{$upper_layer->regions->[$region_id]->slices} ] : $upper_layer->slices; @@ -643,14 +729,15 @@ sub detect_surfaces_type { # of current layer and lower one) my @bottom = (); if ($lower_layer) { - # any surface lying on the void is a true bottom bridge + # Any surface lying on the void is a true bottom bridge (an overhang) push @bottom, $difference->( [ map $_->expolygon, @{$layerm->slices} ], $lower_layer->slices, S_TYPE_BOTTOMBRIDGE, ); - # if we have soluble support material, don't bridge + # If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating + # the support from the print. if ($self->config->support_material && $self->config->support_material_contact_distance == 0) { $_->surface_type(S_TYPE_BOTTOM) for @bottom; } @@ -707,7 +794,11 @@ sub detect_surfaces_type { Slic3r::debugf " layer %d has %d bottom, %d top and %d internal surfaces\n", $layerm->layer->id, scalar(@bottom), scalar(@top), scalar(@internal) if $Slic3r::debug; - } + + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + $layerm->export_region_slices_to_svg_debug("detect_surfaces_type-final"); + } + } # for each layer of a region # clip surfaces to the fill boundaries foreach my $layer (@{$self->layers}) { @@ -728,8 +819,12 @@ sub detect_surfaces_type { for map Slic3r::Surface->new(expolygon => $_, surface_type => $surface->surface_type), @$intersection; } - } - } + + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + $layerm->export_region_fill_surfaces_to_svg_debug("1_detect_surfaces_type-final"); + } + } # for each layer of a region + } # for each $self->print->region_count } # Idempotence of this method is guaranteed by the fact that we don't remove things from @@ -771,6 +866,8 @@ sub clip_fill_surfaces { ); # only consider perimeter areas that are at least one extrusion width thick + #FIXME Offset2 eats out from both sides, while the perimeters are create outside in. + #Should the $pw not be half of the current value? my $pw = min(map $_->flow(FLOW_ROLE_PERIMETER)->scaled_width, @{$layer->regions}); $perimeters = offset2($perimeters, -$pw, +$pw); @@ -829,6 +926,10 @@ sub clip_fill_surfaces { $layerm->fill_surfaces->clear; $layerm->fill_surfaces->append($_) for (@new, @other); + + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + $layerm->export_region_fill_surfaces_to_svg_debug("6_clip_fill_surfaces"); + } } } } @@ -844,6 +945,8 @@ sub discover_horizontal_shells { if ($layerm->region->config->solid_infill_every_layers && $layerm->region->config->fill_density > 0 && ($i % $layerm->region->config->solid_infill_every_layers) == 0) { + # This is the layer to put the sparse infill in. Mark S_TYPE_INTERNAL surfaces as S_TYPE_INTERNALSOLID or S_TYPE_INTERNALBRIDGE. + # If the sparse infill is not active, the internal surfaces are of type S_TYPE_INTERNAL. my $type = $layerm->region->config->fill_density == 100 ? S_TYPE_INTERNALSOLID : S_TYPE_INTERNALBRIDGE; $_->surface_type($type) for @{$layerm->fill_surfaces->filter_by_type(S_TYPE_INTERNAL)}; } @@ -869,15 +972,18 @@ sub discover_horizontal_shells { ? $layerm->region->config->top_solid_layers : $layerm->region->config->bottom_solid_layers; NEIGHBOR: for (my $n = ($type == S_TYPE_TOP) ? $i-1 : $i+1; - abs($n - $i) <= $solid_layers-1; - ($type == S_TYPE_TOP) ? $n-- : $n++) { + abs($n - $i) < $solid_layers; + ($type == S_TYPE_TOP) ? $n-- : $n++) { next if $n < 0 || $n >= $self->layer_count; Slic3r::debugf " looking for neighbors on layer %d...\n", $n; + # Reference to the lower layer of a TOP surface, or an upper layer of a BOTTOM surface. my $neighbor_layerm = $self->get_layer($n)->regions->[$region_id]; + # Reference to the neighbour fill surfaces. my $neighbor_fill_surfaces = $neighbor_layerm->fill_surfaces; - my @neighbor_fill_surfaces = map $_->clone, @$neighbor_fill_surfaces; # clone because we will use these surfaces even after clearing the collection + # Clone because we will use these surfaces even after clearing the collection. + my @neighbor_fill_surfaces = map $_->clone, @$neighbor_fill_surfaces; # find intersection between neighbor and current layer's surfaces # intersections have contours and holes @@ -888,6 +994,7 @@ sub discover_horizontal_shells { # shells to be generated in the base but not in the walls (where there are many # narrow bottom surfaces): reassigning $solid will consider the 'shadow' of the # upper perimeter as an obstacle and shell will not be propagated to more upper layers + #FIXME How does it work for S_TYPE_INTERNALBRIDGE? This is set for sparse infill. Likely this does not work. my $new_internal_solid = $solid = intersection( $solid, [ map $_->p, grep { ($_->surface_type == S_TYPE_INTERNAL) || ($_->surface_type == S_TYPE_INTERNALSOLID) } @neighbor_fill_surfaces ], @@ -914,7 +1021,7 @@ sub discover_horizontal_shells { # make sure the new internal solid is wide enough, as it might get collapsed # when spacing is added in Fill.pm - { + if (0) { my $margin = 3 * $layerm->flow(FLOW_ROLE_SOLID_INFILL)->scaled_width; # require at least this size # we use a higher miterLimit here to handle areas with acute angles # in those cases, the default miterLimit would cut the corner and we'd @@ -984,12 +1091,23 @@ sub discover_horizontal_shells { for map $s->[0]->clone(expolygon => $_), @$solid_surfaces; } } - } - } + } # foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_BOTTOMBRIDGE) + } # for each layer + } # for each region + + # Debugging output. + if ($SLIC3R_DEBUG_SLICE_PROCESSING) { + for my $region_id (0 .. ($self->print->region_count-1)) { + for (my $i = 0; $i < $self->layer_count; $i++) { + my $layerm = $self->get_layer($i)->regions->[$region_id]; + $layerm->export_region_slices_to_svg_debug("5_discover_horizontal_shells"); + $layerm->export_region_fill_surfaces_to_svg_debug("5_discover_horizontal_shells"); + } # for each layer + } # for each region } } -# combine fill surfaces across layers +# combine fill surfaces across layers to honor the "infill every N layers" option # Idempotence of this method is guaranteed by the fact that we don't remove things from # fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries. sub combine_infill { diff --git a/xs/src/libslic3r/ExPolygon.hpp b/xs/src/libslic3r/ExPolygon.hpp index 4bb8cf8e4b..ada37cecc1 100644 --- a/xs/src/libslic3r/ExPolygon.hpp +++ b/xs/src/libslic3r/ExPolygon.hpp @@ -134,7 +134,7 @@ namespace boost { namespace polygon { return t.holes.end(); } static inline unsigned int size_holes(const ExPolygon& t) { - return t.holes.size(); + return (int)t.holes.size(); } }; diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index a2a5ba7b4c..311d0b8a53 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -138,6 +138,7 @@ class PrintObject bool has_support_material() const; void process_external_surfaces(); + void discover_vertical_shells(); void bridge_over_infill(); private: diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 016403059f..4f9c04d035 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -2,6 +2,7 @@ #include "BoundingBox.hpp" #include "ClipperUtils.hpp" #include "Geometry.hpp" +#include "SVG.hpp" namespace Slic3r { @@ -358,6 +359,167 @@ PrintObject::process_external_surfaces() } } +void +PrintObject::discover_vertical_shells() +{ + for (size_t idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region) { + for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++ idx_layer) { + Layer* layer = this->layers[idx_layer]; + LayerRegion* layerm = layer->get_region(idx_region); + // Find a union of perimeters below / above this surface to guarantee a minimum shell thickness. + Polygons shell; + ExPolygons shell_ex; + if (1) + { +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static size_t idx = 0; + char path_cummulative[2048]; + sprintf(path_cummulative, "out\\discover_vertical_shells-perimeters-before-union-run%d.svg", idx); + SVG svg_cummulative(path_cummulative, this->bounding_box()); + for (int n = (int)idx_layer - layerm->region()->config.bottom_solid_layers + 1; n < (int)idx_layer + layerm->region()->config.top_solid_layers; ++ n) { + if (n < 0 || n >= (int)this->layers.size()) + continue; + ExPolygons &expolys = this->layers[n]->perimeter_expolygons; + for (size_t i = 0; i < expolys.size(); ++ i) { + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-perimeters-before-union-run%d-layer%d-expoly%d.svg", idx, n, i); + SVG svg(path, get_extents(expolys[i])); + svg.draw(expolys[i]); + svg.draw_outline(expolys[i].contour, "black", scale_(0.05)); + svg.draw_outline(expolys[i].holes, "blue", scale_(0.05)); + svg.Close(); + + svg_cummulative.draw(expolys[i]); + svg_cummulative.draw_outline(expolys[i].contour, "black", scale_(0.05)); + svg_cummulative.draw_outline(expolys[i].holes, "blue", scale_(0.05)); + } + } + ++ idx; + } +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + for (int n = (int)idx_layer - layerm->region()->config.bottom_solid_layers + 1; n < (int)idx_layer + layerm->region()->config.top_solid_layers; ++ n) { + if (n < 0 || n >= (int)this->layers.size()) + continue; + ExPolygons &expolys = this->layers[n]->perimeter_expolygons; + for (size_t i = 0; i < expolys.size(); ++ i) { + shell.push_back(expolys[i].contour); + shell.insert(shell.end(), expolys[i].holes.begin(), expolys[i].holes.end()); + } + } +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static size_t idx = 0; + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-perimeters-before-union-%d.svg", idx ++); + SVG svg(path, get_extents(shell)); + svg.draw(shell); + svg.draw_outline(shell, "black", scale_(0.05)); + svg.Close(); + } +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + shell = union_(shell, true); +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + shell_ex = union_ex(shell, true); +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + } + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static size_t idx = 0; + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-perimeters-after-union-%d.svg", idx ++); + SVG svg(path, get_extents(shell)); + svg.draw(shell_ex); + svg.draw_outline(shell_ex, "black", "blue", scale_(0.05)); + svg.Close(); + } +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static size_t idx = 0; + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-internal-wshell-%d.svg", idx ++); + SVG svg(path, get_extents(shell)); + svg.draw(layerm->fill_surfaces.filter_by_type(stInternal), "yellow", 0.5); + svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternal), "black", "blue", scale_(0.05)); + svg.draw(shell_ex, "blue", 0.5); + svg.draw_outline(shell_ex, "black", "blue", scale_(0.05)); + svg.Close(); + } + { + static size_t idx = 0; + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-internalvoid-wshell-%d.svg", idx ++); + SVG svg(path, get_extents(shell)); + svg.draw(layerm->fill_surfaces.filter_by_type(stInternalVoid), "yellow", 0.5); + svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternalVoid), "black", "blue", scale_(0.05)); + svg.draw(shell_ex, "blue", 0.5); + svg.draw_outline(shell_ex, "black", "blue", scale_(0.05)); + svg.Close(); + } + { + static size_t idx = 0; + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-internalvoid-wshell-%d.svg", idx ++); + SVG svg(path, get_extents(shell)); + svg.draw(layerm->fill_surfaces.filter_by_type(stInternalVoid), "yellow", 0.5); + svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternalVoid), "black", "blue", scale_(0.05)); + svg.draw(shell_ex, "blue", 0.5); + svg.draw_outline(shell_ex, "black", "blue", scale_(0.05)); + svg.Close(); + } +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + + // Trim the internal & internalvoid by the $shell. + Slic3r::ExPolygons new_internal = diff_ex( + to_polygons(layerm->fill_surfaces.filter_by_type(stInternal)), + shell, + false + ); + Slic3r::ExPolygons new_internal_void = diff_ex( + to_polygons(layerm->fill_surfaces.filter_by_type(stInternalVoid)), + shell, + false + ); + // Add shells tstInternalVoido internal & internalvoid. + const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid }; + Slic3r::ExPolygons new_internal_solid = intersection_ex( + to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 2)), + shell, + true + ); + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + { + static size_t idx = 0; + char path[2048]; + sprintf(path, "out\\discover_vertical_shells-new_internal-%d.svg", idx); + SVG::export_expolygons(path, get_extents(shell), new_internal, "black", "blue", scale_(0.05)); + sprintf(path, "out\\discover_vertical_shells-new_internal_void-%d.svg", idx); + SVG::export_expolygons(path, get_extents(shell), new_internal_void, "black", "blue", scale_(0.05)); + sprintf(path, "out\\discover_vertical_shells-new_internal_solid-%d.svg", idx); + SVG::export_expolygons(path, get_extents(shell), new_internal_solid, "black", "blue", scale_(0.05)); + ++ idx; + } +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + + // Assign resulting internal surfaces to layer. + const SurfaceType surfaceTypesKeep[] = { stTop, stBottom, stBottomBridge, stInternalSolid }; + layerm->fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType)); + layerm->fill_surfaces.append(stInternal , new_internal); + layerm->fill_surfaces.append(stInternalVoid , new_internal_void); + layerm->fill_surfaces.append(stInternalSolid, new_internal_solid); + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells"); + layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells"); +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ + } // for each layer + } // for each region +} + /* This method applies bridge flow to the first internal solid layer above sparse infill */ void @@ -415,6 +577,9 @@ PrintObject::bridge_over_infill() } // there's no point in bridging too thin/short regions + //FIXME Vojtech: The offset2 function is not a geometric offset, + // therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour. + // The gaps will be filled by a separate region, which makes the infill less stable and it takes longer. { double min_width = bridge_flow.scaled_width() * 3; to_bridge_pp = offset2(to_bridge_pp, -min_width, +min_width); @@ -432,22 +597,17 @@ PrintObject::bridge_over_infill() // compute the remaning internal solid surfaces as difference ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true); + to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true); // build the new collection of fill_surfaces { - Surfaces new_surfaces; - for (Surfaces::const_iterator surface = layerm->fill_surfaces.surfaces.begin(); surface != layerm->fill_surfaces.surfaces.end(); ++surface) { - if (surface->surface_type != stInternalSolid) - new_surfaces.push_back(*surface); - } - + layerm->fill_surfaces.remove_type(stInternalSolid); + for (ExPolygons::const_iterator ex = to_bridge.begin(); ex != to_bridge.end(); ++ex) - new_surfaces.push_back(Surface(stInternalBridge, *ex)); + layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, *ex)); for (ExPolygons::const_iterator ex = not_to_bridge.begin(); ex != not_to_bridge.end(); ++ex) - new_surfaces.push_back(Surface(stInternalSolid, *ex)); - - layerm->fill_surfaces.surfaces = new_surfaces; + layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, *ex)); } /* @@ -483,6 +643,11 @@ PrintObject::bridge_over_infill() } } */ + +#ifdef SLIC3R_DEBUG_SLICE_PROCESSING + layerm->export_region_slices_to_svg_debug("7_bridge_over_infill"); + layerm->export_region_fill_surfaces_to_svg_debug("7_bridge_over_infill"); +#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ } } } diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 00e4ef90dd..431b6fb459 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -62,4 +62,7 @@ void confess_at(const char *file, int line, const char *func, const char *pat, . #define SLIC3R_CPPVER 0 #endif +// Write slices as SVG images into out directory during the 2D processing of the slices. +#define SLIC3R_DEBUG_SLICE_PROCESSING + #endif diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 27d970a5b4..db64ef7499 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -108,6 +108,7 @@ _constant() %code%{ THIS->state.set_started(step); %}; void process_external_surfaces(); + void discover_vertical_shells(); void bridge_over_infill(); int ptr()