Ported offset() and offset2()

This commit is contained in:
Alessandro Ranellucci 2013-07-17 00:48:29 +02:00
parent bf8c799685
commit c7b6818ccf
15 changed files with 152 additions and 81 deletions

View file

@ -35,7 +35,7 @@ sub is_printable {
# try to get an inwards offset
# for a distance equal to half of the extrusion width;
# if no offset is possible, then expolygon is not printable.
return Slic3r::Geometry::Clipper::offset($self, -$width / 2) ? 1 : 0;
return @{Slic3r::Geometry::Clipper::offset($self, -$width / 2)} ? 1 : 0;
}
sub wkt {
@ -46,7 +46,7 @@ sub wkt {
sub offset {
my $self = shift;
return Slic3r::Geometry::Clipper::offset($self, @_);
return Slic3r::Geometry::Clipper::offset(\@$self, @_);
}
sub offset_ex {

View file

@ -105,17 +105,17 @@ sub make_fill {
{
my $collapsed = diff(
[ map @{$_->expolygon}, @surfaces ],
[ offset(
[ offset([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2) ],
offset(
offset([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2),
+$distance_between_surfaces/2
) ],
),
1,
);
push @surfaces, map Slic3r::Surface->new(
expolygon => $_,
surface_type => S_TYPE_INTERNALSOLID,
), @{intersection_ex(
[ offset($collapsed, $distance_between_surfaces) ],
offset($collapsed, $distance_between_surfaces),
[
(map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNALVOID, @surfaces),
(@$collapsed),
@ -125,7 +125,7 @@ sub make_fill {
}
# add spacing between surfaces
@surfaces = map $_->offset(-$distance_between_surfaces / 2 * &Slic3r::INFILL_OVERLAP_OVER_SPACING), @surfaces;
@surfaces = map @{$_->offset(-$distance_between_surfaces / 2 * &Slic3r::INFILL_OVERLAP_OVER_SPACING)}, @surfaces;
my @fills = ();
my @fills_ordering_points = ();

View file

@ -29,9 +29,9 @@ sub fill_surface {
# compensate the overlap which is good for rectilinear but harmful for concentric
# where the perimeter/infill spacing should be equal to any other loop spacing
my @loops = my @last = offset($expolygon, -&Slic3r::INFILL_OVERLAP_OVER_SPACING * $min_spacing / 2);
my @loops = my @last = @{offset($expolygon, -&Slic3r::INFILL_OVERLAP_OVER_SPACING * $min_spacing / 2)};
while (@last) {
push @loops, @last = offset2(\@last, -1.5*$distance, +0.5*$distance);
push @loops, @last = @{offset2(\@last, -1.5*$distance, +0.5*$distance)};
}
# generate paths from the outermost to the innermost, to avoid

View file

@ -52,7 +52,7 @@ sub BUILD {
: $self->islands->[$i]->offset_ex(-$self->_inner_margin);
# offset the island outwards to make the boundaries for external movements
$self->_outer->[$i] = [ offset([ $self->islands->[$i]->contour], $self->_outer_margin) ];
$self->_outer->[$i] = offset([ $self->islands->[$i]->contour], $self->_outer_margin);
# if internal motion is enabled, build a set of utility expolygons representing
# the outer boundaries (as contours) and the inner boundaries (as holes). whenever

View file

@ -25,26 +25,6 @@ sub safety_offset_ex {
@{Math::Clipper::ex_int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)};
}
sub offset {
my ($polygons, $distance, $scale, $joinType, $miterLimit) = @_;
$scale ||= 100000;
$joinType //= JT_MITER;
$miterLimit //= 3;
my $offsets = Math::Clipper::int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit);
return @$offsets;
}
sub offset2 {
my ($polygons, $distance1, $distance2, $scale, $joinType, $miterLimit) = @_;
$scale ||= 100000;
$joinType //= JT_MITER;
$miterLimit //= 3;
my $offsets = Math::Clipper::int_offset2(_convert($polygons), $distance1, $distance2, $scale, $joinType, $miterLimit);
return @$offsets;
}
sub diff {
my ($subject, $clip, $safety_offset) = @_;

View file

@ -96,7 +96,7 @@ sub make_surfaces {
my $width = $self->perimeter_flow->scaled_width;
my $diff = diff_ex(
[ map $_->p, @{$self->slices} ],
[ offset2([ map @$_, map $_->expolygon, @{$self->slices} ], -$width, +$width) ],
offset2([ map @$_, map $_->expolygon, @{$self->slices} ], -$width, +$width),
1,
);
@ -189,10 +189,10 @@ sub make_perimeters {
# and we can extract the gap for later processing
if ($Slic3r::Config->gap_fill_speed > 0 && $Slic3r::Config->fill_density > 0) {
my $diff = diff_ex(
[ offset(\@last, -0.5*$spacing) ],
offset(\@last, -0.5*$spacing),
# +2 on the offset here makes sure that Clipper float truncation
# won't shrink the clip polygon to be smaller than intended.
[ offset(\@offsets, +0.5*$spacing + 2) ],
offset(\@offsets, +0.5*$spacing + 2),
);
push @gaps, grep $_->area >= $gap_area_threshold, @$diff;
}
@ -416,12 +416,12 @@ sub process_external_surfaces {
# offset them and intersect the results with the actual fill boundaries
my $margin = scale 3; # TODO: ensure this is greater than the total thickness of the perimeters
@top = @{intersection_ex(
[ Slic3r::Geometry::Clipper::offset([ map $_->p, @top ], +$margin) ],
Slic3r::Geometry::Clipper::offset([ map $_->p, @top ], +$margin),
[ map $_->p, @fill_boundaries ],
1, # to ensure adjacent expolygons are unified
)};
@bottom = @{intersection_ex(
[ Slic3r::Geometry::Clipper::offset([ map $_->p, @bottom ], +$margin) ],
Slic3r::Geometry::Clipper::offset([ map $_->p, @bottom ], +$margin),
[ map $_->p, @fill_boundaries ],
1, # to ensure adjacent expolygons are unified
)};

View file

@ -86,7 +86,7 @@ sub is_printable {
# detect them and we would be discarding them.
my $p = $self->clone;
$p->make_counter_clockwise;
return Slic3r::Geometry::Clipper::offset([$p], -$width / 2) ? 1 : 0;
return @{Slic3r::Geometry::Clipper::offset([$p], -$width / 2)} ? 1 : 0;
}
sub is_valid {

View file

@ -47,10 +47,10 @@ sub grow {
my @points = @$self;
return map Slic3r::Polygon->new(@$_),
Slic3r::Geometry::Clipper::offset(
@{Slic3r::Geometry::Clipper::offset(
[ Slic3r::Polygon->new(@points, CORE::reverse @points[1..($#points-1)]) ],
$distance, $scale, $joinType, $miterLimit,
);
)};
}
sub nearest_point_to {

View file

@ -172,8 +172,8 @@ sub validate {
my @points = map [ @$_[X,Y] ], map @{$_->vertices}, @{$self->objects->[$obj_idx]->meshes};
my $convex_hull = Slic3r::Polygon->new(@{convex_hull(\@points)});
($clearance) = map Slic3r::Polygon->new(@$_),
Slic3r::Geometry::Clipper::offset(
[$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND);
@{Slic3r::Geometry::Clipper::offset(
[$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND)};
}
for my $copy (@{$self->objects->[$obj_idx]->copies}) {
my $copy_clearance = $clearance->clone;
@ -610,7 +610,7 @@ sub make_skirt {
my $distance = scale $Slic3r::Config->skirt_distance;
for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) {
$distance += scale $spacing;
my ($loop) = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND);
my $loop = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND)->[0];
push @{$self->skirt}, Slic3r::ExtrusionLoop->new(
polygon => Slic3r::Polygon->new(@$loop),
role => EXTR_ROLE_SKIRT,
@ -666,7 +666,7 @@ sub make_brim {
# JT_SQUARE ensures no vertex is outside the given offset distance
# -0.5 because islands are not represented by their centerlines
# TODO: we need the offset inwards/offset outwards logic to avoid overlapping extrusions
push @loops, offset2(\@islands, ($i - 1.5) * $flow->scaled_spacing, +1.0 * $flow->scaled_spacing, undef, JT_SQUARE);
push @loops, @{offset2(\@islands, ($i - 1.5) * $flow->scaled_spacing, +1.0 * $flow->scaled_spacing, undef, JT_SQUARE)};
}
@{$self->brim} = map Slic3r::ExtrusionLoop->new(

View file

@ -274,15 +274,15 @@ sub make_perimeters {
my $overlap = $perimeter_spacing; # one perimeter
my $diff = diff(
[ offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($Slic3r::Config->perimeters * $perimeter_spacing)) ],
[ offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap) ],
offset([ map @{$_->expolygon}, @{$layerm->slices} ], -($Slic3r::Config->perimeters * $perimeter_spacing)),
offset([ map @{$_->expolygon}, @{$upper_layerm->slices} ], -$overlap),
);
next if !@$diff;
# if we need more perimeters, $diff should contain a narrow region that we can collapse
$diff = diff(
$diff,
[ offset2($diff, -$perimeter_spacing, +$perimeter_spacing) ],
offset2($diff, -$perimeter_spacing, +$perimeter_spacing),
1,
);
next if !@$diff;
@ -295,8 +295,8 @@ sub make_perimeters {
# of our slice
$extra_perimeters++;
my $hypothetical_perimeter = diff(
[ offset($slice->expolygon->arrayref, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters-1))) ],
[ offset($slice->expolygon->arrayref, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters))) ],
offset($slice->expolygon->arrayref, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters-1))),
offset($slice->expolygon->arrayref, -($perimeter_spacing * ($Slic3r::Config->perimeters + $extra_perimeters))),
);
last CYCLE if !@$hypothetical_perimeter; # no extra perimeter is possible
@ -620,7 +620,7 @@ sub discover_horizontal_shells {
my $margin = 3 * $layerm->solid_infill_flow->scaled_width; # require at least this size
my $too_narrow = diff_ex(
[ map @$_, @$new_internal_solid ],
[ offset([ offset([ map @$_, @$new_internal_solid ], -$margin) ], +$margin) ],
offset(offset([ map @$_, @$new_internal_solid ], -$margin), +$margin),
1,
);
@ -634,7 +634,7 @@ sub discover_horizontal_shells {
# make sure our grown surfaces don't exceed the fill area
my @grown = map @$_, @{intersection_ex(
[ offset([ map @$_, @$too_narrow ], +$margin) ],
offset([ map @$_, @$too_narrow ], +$margin),
[ map $_->p, @fill_boundaries ],
)};
$new_internal_solid = union_ex([ @grown, (map @$_, @$new_internal_solid) ]);
@ -745,7 +745,7 @@ sub combine_infill {
# $intersection now contains the regions that can be combined across the full amount of layers
# so let's remove those areas from all layers
my @intersection_with_clearance = map $_->offset(
my @intersection_with_clearance = map @{$_->offset(
$layerms[-1]->solid_infill_flow->scaled_width / 2
+ $layerms[-1]->perimeter_flow->scaled_width / 2
# Because fill areas for rectilinear and honeycomb are grown
@ -753,7 +753,7 @@ sub combine_infill {
+ (($type == S_TYPE_INTERNALSOLID || $Slic3r::Config->fill_pattern =~ /(rectilinear|honeycomb)/)
? $layerms[-1]->solid_infill_flow->scaled_width * &Slic3r::INFILL_OVERLAP_OVER_SPACING
: 0)
), @$intersection;
)}, @$intersection;
foreach my $layerm (@layerms) {

View file

@ -35,7 +35,7 @@ sub group {
sub offset {
my $self = shift;
return map $self->clone(expolygon => $_), @{$self->expolygon->offset_ex(@_)};
return [ map $self->clone(expolygon => $_), @{$self->expolygon->offset_ex(@_)} ];
}
sub simplify {

View file

@ -550,7 +550,7 @@ sub horizontal_projection {
my $scale_vector = Math::Clipper::integerize_coordinate_sets({ bits => 32 }, @f);
$_->make_counter_clockwise for @f; # do this after scaling, as winding order might change while doing that
my $union = union_ex([ Slic3r::Geometry::Clipper::offset(\@f, 10000) ]);
my $union = union_ex(Slic3r::Geometry::Clipper::offset(\@f, 10000));
$union = [ map $_->arrayref, @$union ];
Math::Clipper::unscale_coordinate_sets($scale_vector, $_) for @$union;
return $union;