Fixes, improvements and refactoring for bridges and solid surfaces.
This commit is contained in:
parent
d13a0e2503
commit
13ef24b5eb
7 changed files with 61 additions and 51 deletions
|
@ -31,7 +31,6 @@ use Slic3r::Print;
|
|||
use Slic3r::Skein;
|
||||
use Slic3r::STL;
|
||||
use Slic3r::Surface;
|
||||
use Slic3r::Surface::Bridge;
|
||||
|
||||
# printer options
|
||||
our $nozzle_diameter = 0.5;
|
||||
|
|
|
@ -64,8 +64,7 @@ sub make_fill {
|
|||
|
||||
# force 100% density and rectilinear fill for external surfaces
|
||||
if ($surface->surface_type ne 'internal') {
|
||||
my $is_bridge = $surface->isa('Slic3r::Surface::Bridge')
|
||||
&& $surface->surface_type eq 'bottom';
|
||||
my $is_bridge = $layer->id > 0 && $surface->surface_type eq 'bottom';
|
||||
$density = 1;
|
||||
$filler = $is_bridge ? 'rectilinear' : $Slic3r::solid_fill_pattern;
|
||||
$flow_width = $Slic3r::nozzle_diameter if $is_bridge;
|
||||
|
|
|
@ -24,7 +24,7 @@ sub infill_direction {
|
|||
}
|
||||
|
||||
# use bridge angle
|
||||
if ($surface->isa('Slic3r::Surface::Bridge') && defined $surface->bridge_angle) {
|
||||
if ($surface->surface_type eq 'bottom' && $self->layer->id > 0 && defined $surface->bridge_angle) {
|
||||
Slic3r::debugf "Filling bridge with angle %d\n", $surface->bridge_angle;
|
||||
$rotate[0] = Slic3r::Geometry::deg2rad($surface->bridge_angle);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ has 'surfaces' => (
|
|||
# collection of surfaces representing bridges
|
||||
has 'bridges' => (
|
||||
is => 'rw',
|
||||
#isa => 'ArrayRef[Slic3r::Surface::Bridge]',
|
||||
#isa => 'ArrayRef[Slic3r::Surface]',
|
||||
default => sub { [] },
|
||||
);
|
||||
|
||||
|
@ -436,7 +436,7 @@ sub process_bridges {
|
|||
[ $bridge_offset ],
|
||||
);
|
||||
|
||||
push @{$self->bridges}, map Slic3r::Surface::Bridge->cast_from_expolygon($_,
|
||||
push @{$self->bridges}, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $surface->surface_type,
|
||||
bridge_angle => $bridge_angle,
|
||||
), @$intersection;
|
||||
|
@ -446,32 +446,24 @@ sub process_bridges {
|
|||
# now we need to merge bridges to avoid overlapping
|
||||
{
|
||||
# build a list of unique bridge types
|
||||
my $unique_type = sub { $_[0]->surface_type . "_" . ($_[0]->bridge_angle || '') };
|
||||
my @unique_types = ();
|
||||
foreach my $bridge (@{$self->bridges}) {
|
||||
my $type = $unique_type->($bridge);
|
||||
push @unique_types, $type unless grep $_ eq $type, @unique_types;
|
||||
}
|
||||
my @surface_groups = Slic3r::Surface->group(@{$self->bridges});
|
||||
|
||||
# merge bridges of the same type, removing any of the bridges already merged;
|
||||
# the order of @unique_types determines the priority between bridges having
|
||||
# the order of @surface_groups determines the priority between bridges having
|
||||
# different surface_type or bridge_angle
|
||||
my @bridges = ();
|
||||
foreach my $type (@unique_types) {
|
||||
my @surfaces = grep { $unique_type->($_) eq $type } @{$self->bridges};
|
||||
my $union = union_ex([ map $_->p, @surfaces ]);
|
||||
@{$self->bridges} = ();
|
||||
foreach my $surfaces (@surface_groups) {
|
||||
my $union = union_ex([ map $_->p, @$surfaces ]);
|
||||
my $diff = diff_ex(
|
||||
[ map @$_, @$union ],
|
||||
[ map $_->p, @bridges ],
|
||||
[ map $_->p, @{$self->bridges} ],
|
||||
);
|
||||
|
||||
push @bridges, map Slic3r::Surface::Bridge->cast_from_expolygon($_,
|
||||
surface_type => $surfaces[0]->surface_type,
|
||||
bridge_angle => $surfaces[0]->bridge_angle,
|
||||
push @{$self->bridges}, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $surfaces->[0]->surface_type,
|
||||
bridge_angle => $surfaces->[0]->bridge_angle,
|
||||
), @$union;
|
||||
}
|
||||
|
||||
@{$self->bridges} = @bridges;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,17 +514,18 @@ sub split_bridges_fills {
|
|||
[ $bridge->p ],
|
||||
);
|
||||
|
||||
push @$surfaces, map Slic3r::Surface::Bridge->cast_from_expolygon($_,
|
||||
push @$surfaces, map Slic3r::Surface->cast_from_expolygon($_,
|
||||
surface_type => $bridge->surface_type,
|
||||
bridge_angle => $bridge->bridge_angle,
|
||||
), @$intersection;
|
||||
}
|
||||
|
||||
# difference between fill_surfaces and bridges are the other surfaces
|
||||
foreach my $surface (@surfaces) {
|
||||
my $difference = diff_ex([ $surface->p ], [ map $_->p, @{$self->bridges} ]);
|
||||
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 => $surface->surface_type), @$difference;
|
||||
surface_type => $type), @$difference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use Moo;
|
|||
use Math::ConvexHull 1.0.4 qw(convex_hull);
|
||||
use Slic3r::Geometry qw(X Y PI);
|
||||
use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex
|
||||
offset JT_ROUND JT_MITER);
|
||||
union_ex offset JT_ROUND JT_MITER);
|
||||
use XXX;
|
||||
|
||||
has 'x_length' => (
|
||||
|
@ -220,27 +220,32 @@ sub discover_horizontal_shells {
|
|||
|
||||
foreach my $surfaces (@{$self->layers->[$n]->fill_surfaces}) {
|
||||
my @neighbor = @$surfaces;
|
||||
my $neighbor_p = [ map $_->p, @neighbor ];
|
||||
|
||||
# find intersection between @surfaces and current layer's surfaces
|
||||
# intersections have contours and holes
|
||||
my $intersections = intersection_ex($surfaces_p, $neighbor_p);
|
||||
my $new_internal_solid = intersection_ex(
|
||||
$surfaces_p,
|
||||
[ map $_->p, grep $_->surface_type =~ /internal/, @neighbor ],
|
||||
);
|
||||
next if !@$new_internal_solid;
|
||||
|
||||
next if @$intersections == 0;
|
||||
# internal-solid are the union of the existing internal-solid surfaces
|
||||
# and new ones
|
||||
my $internal_solid = union_ex([
|
||||
( map $_->p, grep $_->surface_type eq 'internal-solid', @neighbor ),
|
||||
( map @$_, @$new_internal_solid ),
|
||||
]);
|
||||
|
||||
# subtract intersections from layer surfaces to get resulting inner surfaces
|
||||
my $internal = diff_ex(
|
||||
$neighbor_p,
|
||||
[
|
||||
(map @$_, @$intersections),
|
||||
(map $_->p, grep $_->surface_type !~ /internal/, @neighbor),
|
||||
],
|
||||
[ map $_->p, grep $_->surface_type eq 'internal', @neighbor ],
|
||||
[ map @$_, @$internal_solid ],
|
||||
);
|
||||
Slic3r::debugf " %d internal-solid and %d internal surfaces found\n",
|
||||
scalar(@$intersections), scalar(@$internal);
|
||||
scalar(@$internal_solid), scalar(@$internal);
|
||||
|
||||
# Note: due to floating point math we're going to get some very small
|
||||
# polygons as $internal_polygons; they will be removed by removed_small_features()
|
||||
# polygons as $internal; they will be removed by removed_small_features()
|
||||
|
||||
# assign resulting inner surfaces to layer
|
||||
@$surfaces = ();
|
||||
|
@ -251,15 +256,16 @@ sub discover_horizontal_shells {
|
|||
# assign new internal-solid surfaces to layer
|
||||
push @$surfaces, Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => 'internal-solid')
|
||||
for @$intersections;
|
||||
for @$internal_solid;
|
||||
|
||||
for my $neigh_type (qw(top bottom)) {
|
||||
# assign top and bottom surfaces to layer
|
||||
foreach my $s (Slic3r::Surface->group(grep $_->surface_type =~ /top|bottom/, @neighbor)) {
|
||||
my $solid_surfaces = diff_ex(
|
||||
[ map $_->p, grep $_->surface_type eq $neigh_type, @neighbor ],
|
||||
[ map @$_, @$intersections, @$internal ],
|
||||
[ map $_->p, @$s ],
|
||||
[ map @$_, @$internal_solid, @$internal ],
|
||||
);
|
||||
push @$surfaces, Slic3r::Surface->cast_from_expolygon
|
||||
($_, surface_type => $neigh_type)
|
||||
($_, surface_type => $s->[0]->surface_type, bridge_angle => $s->[0]->bridge_angle)
|
||||
for @$solid_surfaces;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ has 'surface_type' => (
|
|||
# this integer represents the thickness of the surface expressed in layers
|
||||
has 'depth_layers' => (is => 'ro', default => sub {1});
|
||||
|
||||
has 'bridge_angle' => (is => 'ro');
|
||||
|
||||
sub cast_from_polygon {
|
||||
my $class = shift;
|
||||
my ($polygon, %args) = @_;
|
||||
|
@ -47,6 +49,25 @@ sub cast_from_expolygon {
|
|||
);
|
||||
}
|
||||
|
||||
# static method to group surfaces having same surface_type and bridge_angle
|
||||
sub group {
|
||||
my $class = shift;
|
||||
my (@surfaces) = @_;
|
||||
|
||||
my $unique_type = sub { $_[0]->surface_type . "_" . ($_[0]->bridge_angle || '') };
|
||||
my @unique_types = ();
|
||||
foreach my $surface (@surfaces) {
|
||||
my $type = $unique_type->($surface);
|
||||
push @unique_types, $type unless grep $_ eq $type, @unique_types;
|
||||
}
|
||||
|
||||
my @groups = ();
|
||||
foreach my $type (@unique_types) {
|
||||
push @groups, [ grep { $unique_type->($_) eq $type } @surfaces ];
|
||||
}
|
||||
return @groups;
|
||||
}
|
||||
|
||||
sub add_hole {
|
||||
my $self = shift;
|
||||
my ($hole) = @_;
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package Slic3r::Surface::Bridge;
|
||||
use Moo;
|
||||
|
||||
extends "Slic3r::Surface";
|
||||
|
||||
has 'bridge_angle' => (is => 'ro');
|
||||
|
||||
1;
|
Loading…
Reference in a new issue