Port offset_ex() and offset2_ex() to XS

This commit is contained in:
Alessandro Ranellucci 2013-07-16 20:09:53 +02:00
parent 9458c7db97
commit 898007fc36
20 changed files with 4349 additions and 52 deletions

View file

@ -51,12 +51,12 @@ sub offset {
sub offset_ex {
my $self = shift;
return Slic3r::Geometry::Clipper::offset_ex($self, @_);
return Slic3r::Geometry::Clipper::offset_ex(\@$self, @_);
}
sub safety_offset {
my $self = shift;
return Slic3r::Geometry::Clipper::safety_offset_ex($self, @_);
return Slic3r::Geometry::Clipper::safety_offset_ex(\@$self, @_);
}
sub noncollapsing_offset_ex {
@ -69,7 +69,7 @@ sub noncollapsing_offset_ex {
sub encloses_point {
my $self = shift;
my ($point) = @_;
return Boost::Geometry::Utils::point_covered_by_polygon($point->arrayref, $self->pp);
return Boost::Geometry::Utils::point_covered_by_polygon($point->pp, $self->pp);
}
# A version of encloses_point for use when hole borders do not matter.
@ -78,7 +78,7 @@ sub encloses_point {
sub encloses_point_quick {
my $self = shift;
my ($point) = @_;
return Boost::Geometry::Utils::point_within_polygon($point->arrayref, $self->arrayref);
return Boost::Geometry::Utils::point_within_polygon($point->pp, $self->pp);
}
sub encloses_line {

View file

@ -115,7 +115,7 @@ sub fill_surface {
# clip paths again to prevent connection segments from crossing the expolygon boundaries
@paths = map Slic3r::Polyline->new(@$_),
@{ Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection(
[ map $_->pp, $surface->expolygon->offset_ex(scaled_epsilon) ],
[ map $_->pp, @{$surface->expolygon->offset_ex(scaled_epsilon)} ],
[ map $_->pp, @paths ],
) } if @paths; # this temporary check is a workaround for the multilinestring bug in B::G::U
}

View file

@ -16,7 +16,7 @@ sub fill_surface {
my $rotate_vector = $self->infill_direction($surface);
$self->rotate_points($expolygon, $rotate_vector);
my ($expolygon_off) = $expolygon->offset_ex(scale $params{flow_spacing}/2);
my $expolygon_off = $expolygon->offset_ex(scale $params{flow_spacing}/2)->[0];
return {} if !defined $expolygon_off; # skip some very small polygons (which shouldn't arrive here)
my $flow_spacing = $params{flow_spacing};
@ -67,7 +67,7 @@ sub fill_surface {
# are kept even if the expolygon has vertical sides
my @polylines = map Slic3r::Polyline->new(@$_),
@{ Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection(
[ map $_->pp, $expolygon->offset_ex(scaled_epsilon) ],
[ map $_->pp, @{ $expolygon->offset_ex(scaled_epsilon) } ],
[ map $_->pp, @{ $self->cache->{$cache_id} } ],
) };

View file

@ -49,7 +49,7 @@ sub BUILD {
# so that no motion along external perimeters happens
$self->_inner->[$i] = $self->no_internal
? []
: [ $self->islands->[$i]->offset_ex(-$self->_inner_margin) ];
: $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) ];

View file

@ -45,26 +45,6 @@ sub offset2 {
return @$offsets;
}
sub offset_ex {
my ($polygons, $distance, $scale, $joinType, $miterLimit) = @_;
$scale ||= 100000;
$joinType //= JT_MITER;
$miterLimit //= 3;
my $offsets = Math::Clipper::ex_int_offset(_convert($polygons), $distance, $scale, $joinType, $miterLimit);
return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @$offsets;
}
sub offset2_ex {
my ($polygons, $delta1, $delta2, $scale, $joinType, $miterLimit) = @_;
$scale ||= 100000;
$joinType //= JT_MITER;
$miterLimit //= 3;
my $offsets = Math::Clipper::ex_int_offset2(_convert($polygons), $delta1, $delta2, $scale, $joinType, $miterLimit);
return map Slic3r::ExPolygon->new($_->{outer}, @{$_->{holes}}), @$offsets;
}
sub diff_ex {
my ($subject, $clip, $safety_offset) = @_;
@ -147,7 +127,7 @@ sub xor_ex {
sub collapse_ex {
my ($polygons, $width) = @_;
return [ offset2_ex($polygons, -$width/2, +$width/2) ];
return offset2_ex($polygons, -$width/2, +$width/2);
}
sub simplify_polygon {

View file

@ -5,7 +5,7 @@ use List::Util qw(sum first);
use Slic3r::ExtrusionPath ':roles';
use Slic3r::Geometry qw(PI A B scale chained_path_items points_coincide);
use Slic3r::Geometry::Clipper qw(safety_offset union_ex diff_ex intersection_ex
offset offset2 offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection);
offset offset2 offset_ex offset2_ex PFT_EVENODD union_pt traverse_pt diff intersection);
use Slic3r::Surface ':types';
has 'layer' => (
@ -141,7 +141,7 @@ sub _merge_loops {
$expolygons = diff_ex([ map @$_, @$expolygons ], [$loop]);
}
}
$expolygons = [ map $_->offset_ex(-$safety_offset), @$expolygons ];
$expolygons = offset_ex([ map @$_, @$expolygons ], -$safety_offset);
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
@ -180,7 +180,7 @@ sub make_perimeters {
? $perimeter_spacing / 2
: $perimeter_spacing;
my @offsets = offset2_ex(\@last, -1.5*$spacing, +0.5*$spacing);
my @offsets = @{offset2_ex(\@last, -1.5*$spacing, +0.5*$spacing)};
my @contours_offsets = map $_->contour, @offsets;
my @holes_offsets = map $_->holes, @offsets;
@offsets = (@contours_offsets, @holes_offsets); # turn @offsets from ExPolygons to Polygons
@ -209,11 +209,11 @@ sub make_perimeters {
# non-collapsing regions
# use a bogus surface_type
$self->fill_surfaces->append(
map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_TOP), offset2_ex(
map Slic3r::Surface->new(expolygon => $_, surface_type => S_TYPE_TOP), @{offset2_ex(
[ map $_->simplify(&Slic3r::SCALED_RESOLUTION), @last ],
-($perimeter_spacing/2 + $infill_spacing),
+$infill_spacing,
)
)}
);
}
@ -322,8 +322,8 @@ sub _fill_gaps {
my $flow = $self->perimeter_flow->clone(width => $width);
# extract the gaps having this width
my @this_width = map $_->offset_ex(+0.5*$flow->scaled_width),
map $_->noncollapsing_offset_ex(-0.5*$flow->scaled_width),
my @this_width = map @{$_->offset_ex(+0.5*$flow->scaled_width)},
map @{$_->noncollapsing_offset_ex(-0.5*$flow->scaled_width)},
@$gaps;
if (0) { # remember to re-enable t/dynamic.t
@ -346,7 +346,7 @@ sub _fill_gaps {
# fill gaps using zigzag infill
# since this is infill, we have to offset by half-extrusion width inwards
my @infill = map $_->offset_ex(-0.5*$flow->scaled_width), @this_width;
my @infill = map @{$_->offset_ex(-0.5*$flow->scaled_width)}, @this_width;
foreach my $expolygon (@infill) {
my @paths = $filler->fill_surface(
@ -520,7 +520,7 @@ sub _detect_bridges {
}
} elsif (@edges) {
# inset the bridge expolygon; we'll use this one to clip our test lines
my $inset = [ $surface->expolygon->offset_ex($self->infill_flow->scaled_width) ];
my $inset = $surface->expolygon->offset_ex($self->infill_flow->scaled_width);
# detect anchors as intersection between our bridge expolygon and the lower slices
my $anchors = intersection_ex(

View file

@ -766,9 +766,9 @@ sub write_gcode {
]);
# discard layers only containing thin walls (offset would fail on an empty polygon)
if (@$convex_hull) {
my @island = Slic3r::ExPolygon->new($convex_hull)
->translate(scale $shift[X], scale $shift[Y])
->offset_ex(scale $distance_from_objects, 1, JT_SQUARE);
my $expolygon = Slic3r::ExPolygon->new($convex_hull);
$expolygon->translate(scale $shift[X], scale $shift[Y]);
my @island = @{$expolygon->offset_ex(scale $distance_from_objects, 1, JT_SQUARE)};
foreach my $copy (@{ $self->objects->[$obj_idx]->copies }) {
push @islands, map $_->clone->translate(@$copy), @island;
}

View file

@ -488,9 +488,9 @@ sub clip_fill_surfaces {
my $overhang_width = $layerm->overhang_width;
# we want to support any solid surface, not just tops
# (internal solids might have been generated)
push @overhangs, map $_->offset_ex($additional_margin), @{intersection_ex(
push @overhangs, map @{$_->offset_ex($additional_margin)}, @{intersection_ex(
[ map @{$_->expolygon}, grep $_->surface_type != S_TYPE_INTERNAL, @{$layerm->fill_surfaces} ],
[ map @$_, map $_->offset_ex(-$overhang_width), @{$lower_layer->slices} ],
[ map @$_, map @{$_->offset_ex(-$overhang_width)}, @{$lower_layer->slices} ],
)};
}
}
@ -825,7 +825,7 @@ sub generate_support_material {
my $layer = $self->layers->[$i];
my $lower_layer = $i > 0 ? $self->layers->[$i-1] : undef;
my @current_layer_offsetted_slices = map $_->offset_ex($distance_from_object), @{$layer->slices};
my @current_layer_offsetted_slices = map @{$_->offset_ex($distance_from_object)}, @{$layer->slices};
# $upper_layers_overhangs[-1] contains the overhangs of the upper layer, regardless of any interface layers
# $upper_layers_overhangs[0] contains the overhangs of the first upper layer above the interface layers
@ -884,7 +884,7 @@ sub generate_support_material {
? scale $lower_layer->height * ((cos $threshold_rad) / (sin $threshold_rad))
: $self->layers->[1]->regions->[0]->overhang_width;
@overhangs = map $_->offset_ex(+$distance), @{diff_ex(
@overhangs = map @{$_->offset_ex(+$distance)}, @{diff_ex(
[ map @$_, @{$layer->slices} ],
[ map @$_, @{$lower_layer->slices} ],
1,
@ -906,7 +906,7 @@ sub generate_support_material {
my $support_interface_patterns = [];
{
# 0.5 ensures the paths don't get clipped externally when applying them to layers
my @areas = map $_->offset_ex(- 0.5 * $flow->scaled_width),
my @areas = map @{$_->offset_ex(- 0.5 * $flow->scaled_width)},
@{union_ex([ map $_->contour, map @$_, values %layers, values %layers_interfaces, values %layers_contact_areas ])};
my $pattern = $Slic3r::Config->support_material_pattern;

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 {