Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2016-11-10 21:23:01 +0300
committerbubnikv <bubnikv@gmail.com>2016-11-10 21:23:01 +0300
commit4460b5ce50c7160cd922972a190c27bf4381ffbd (patch)
treec9030404b1edebaf3501f107960697cc84f76e02 /lib
parent317e9131e89782c98201849a21c0e2e91c8fc142 (diff)
re-wrote PrintObject::detect_surfaces_type() to C++,
Fixed some cracks in the fill surfaces created by rounding all surfaces inside detect_surface_type(). Fixed https://github.com/prusa3d/Slic3r/issues/12 Bridging-Angle not optimal Extended the "Ensure veritcal wall thickness" mode (merged with the original discover_horizontal_shells function), but this a work in progress. Already Slic3r with "ensure vertical wall thickness" produces less spurious infills inside solids.
Diffstat (limited to 'lib')
-rw-r--r--lib/Slic3r/Print/Object.pm164
1 files changed, 3 insertions, 161 deletions
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index 438c4b1ef..ab390fd3a 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -669,167 +669,6 @@ 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";
-
- for my $region_id (0 .. ($self->print->region_count-1)) {
- for my $i (0 .. ($self->layer_count - 1)) {
- my $layerm = $self->get_layer($i)->regions->[$region_id];
-
- # prepare a reusable subroutine to make surface differences
- my $difference = sub {
- my ($subject, $clip, $result_type) = @_;
- my $diff = diff(
- [ map @$_, @$subject ],
- [ map @$_, @$clip ],
- 1,
- );
-
- # collapse very narrow parts (using the safety offset in the diff is not enough)
- my $offset = $layerm->flow(FLOW_ROLE_EXTERNAL_PERIMETER)->scaled_width / 10;
- return map Slic3r::Surface->new(expolygon => $_, surface_type => $result_type),
- @{ offset2_ex($diff, -$offset, +$offset) };
- };
-
- # comparison happens against the *full* slices (considering all regions)
- # unless internal shells are requested
- my $upper_layer = $i < $self->layer_count - 1 ? $self->get_layer($i+1) : undef;
- my $lower_layer = $i > 0 ? $self->get_layer($i-1) : undef;
-
- # find top surfaces (difference between current surfaces
- # 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;
-
- @top = $difference->(
- [ map $_->expolygon, @{$layerm->slices} ],
- $upper_slices,
- S_TYPE_TOP,
- );
- } else {
- # if no upper layer, all surfaces of this one are solid
- # we clone surfaces because we're going to clear the slices collection
- @top = map $_->clone, @{$layerm->slices};
- $_->surface_type(S_TYPE_TOP) for @top;
- }
-
- # find bottom surfaces (difference between current surfaces
- # of current layer and lower one)
- my @bottom = ();
- if ($lower_layer) {
- # 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. 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;
- }
-
- # if user requested internal shells, we need to identify surfaces
- # lying on other slices not belonging to this region
- if ($self->config->interface_shells) {
- # non-bridging bottom surfaces: any part of this layer lying
- # on something else, excluding those lying on our own region
- my $supported = intersection_ex(
- [ map @{$_->expolygon}, @{$layerm->slices} ],
- [ map @$_, @{$lower_layer->slices} ],
- );
- push @bottom, $difference->(
- $supported,
- [ map $_->expolygon, @{$lower_layer->regions->[$region_id]->slices} ],
- S_TYPE_BOTTOM,
- );
- }
- } else {
- # if no lower layer, all surfaces of this one are solid
- # we clone surfaces because we're going to clear the slices collection
- @bottom = map $_->clone, @{$layerm->slices};
-
- # if we have raft layers, consider bottom layer as a bridge
- # just like any other bottom surface lying on the void
- if ($self->config->raft_layers > 0 && $self->config->support_material_contact_distance > 0) {
- $_->surface_type(S_TYPE_BOTTOMBRIDGE) for @bottom;
- } else {
- $_->surface_type(S_TYPE_BOTTOM) for @bottom;
- }
- }
-
- # now, if the object contained a thin membrane, we could have overlapping bottom
- # and top surfaces; let's do an intersection to discover them and consider them
- # as bottom surfaces (to allow for bridge detection)
- if (@top && @bottom) {
- my $overlapping = intersection_ex([ map $_->p, @top ], [ map $_->p, @bottom ]);
- Slic3r::debugf " layer %d contains %d membrane(s)\n", $layerm->layer->id, scalar(@$overlapping)
- if $Slic3r::debug;
- @top = $difference->([map $_->expolygon, @top], $overlapping, S_TYPE_TOP);
- }
-
- # find internal surfaces (difference between top/bottom surfaces and others)
- my @internal = $difference->(
- [ map $_->expolygon, @{$layerm->slices} ],
- [ map $_->expolygon, @top, @bottom ],
- S_TYPE_INTERNAL,
- );
-
- # save surfaces to layer
- $layerm->slices->clear;
- $layerm->slices->append($_) for (@bottom, @top, @internal);
-
- 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}) {
- my $layerm = $layer->regions->[$region_id];
-
- # Note: this method should be idempotent, but fill_surfaces gets modified
- # in place. However we're now only using its boundaries (which are invariant)
- # so we're safe. This guarantees idempotence of prepare_infill() also in case
- # that combine_infill() turns some fill_surface into VOID surfaces.
- my $fill_boundaries = [ map $_->clone->p, @{$layerm->fill_surfaces} ];
- $layerm->fill_surfaces->clear;
- foreach my $surface (@{$layerm->slices}) {
- my $intersection = intersection_ex(
- [ $surface->p ],
- $fill_boundaries,
- );
- $layerm->fill_surfaces->append($_)
- 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
# fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
sub clip_fill_surfaces {
@@ -953,6 +792,9 @@ sub discover_horizontal_shells {
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)};
}
+
+ # If ensure_vertical_shell_thickness, then the rest has already been performed by discover_vertical_shells().
+ next if ($layerm->region->config->ensure_vertical_shell_thickness);
EXTERNAL: foreach my $type (S_TYPE_TOP, S_TYPE_BOTTOM, S_TYPE_BOTTOMBRIDGE) {
# find slices of current type for current layer