New algorithm for clipping lines to complex polygons
This commit is contained in:
parent
5812804d6b
commit
e2d2574b8b
@ -90,9 +90,7 @@ sub point_in_polygon {
|
||||
|
||||
# if point is not in polygon, let's check whether it belongs to the contour
|
||||
if (!$side && 0) {
|
||||
foreach my $line (polygon_lines($polygon)) {
|
||||
return 1 if point_in_segment($point, $line);
|
||||
}
|
||||
return 1 if polygon_segment_having_point($polygon, $point);
|
||||
}
|
||||
|
||||
return $side;
|
||||
@ -458,5 +456,22 @@ sub bounding_box_intersect {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub clip_segment_complex_polygon {
|
||||
my ($line, $polygons) = @_;
|
||||
|
||||
my @intersections = grep $_, map line_intersection($line, $_, 1),
|
||||
map polygon_lines($_), @$polygons;
|
||||
|
||||
@intersections = sort { "$a->[X],$a->[Y]" cmp "$b->[X],$b->[Y]" } @intersections;
|
||||
|
||||
shift(@intersections) if !grep(point_in_polygon($intersections[0], $_), @$polygons)
|
||||
&& !grep(polygon_segment_having_point($_, $intersections[0]), @$polygons);
|
||||
|
||||
my @lines = ();
|
||||
while (@intersections) {
|
||||
push @lines, [ shift(@intersections), shift(@intersections) ];
|
||||
}
|
||||
return [@lines];
|
||||
}
|
||||
|
||||
1;
|
||||
|
12
t/geometry.t
12
t/geometry.t
@ -2,7 +2,7 @@ use Test::More;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 4;
|
||||
plan tests => 5;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
@ -13,8 +13,14 @@ use Slic3r;
|
||||
|
||||
#==========================================================
|
||||
|
||||
my $line1 = [ [73.6310778185108/0.0000001, 371.74239268924/0.0000001], [73.6310778185108/0.0000001, 501.74239268924/0.0000001] ];
|
||||
my $line2 = [ [75/0.0000001, 437.9853/0.0000001], [62.7484/0.0000001, 440.4223/0.0000001] ];
|
||||
my $line1 = [ [5, 15], [30, 15] ];
|
||||
my $line2 = [ [10, 20], [10, 10] ];
|
||||
is_deeply Slic3r::Geometry::line_intersection($line1, $line2, 1), [10, 15], 'line_intersection';
|
||||
|
||||
#==========================================================
|
||||
|
||||
$line1 = [ [73.6310778185108/0.0000001, 371.74239268924/0.0000001], [73.6310778185108/0.0000001, 501.74239268924/0.0000001] ];
|
||||
$line2 = [ [75/0.0000001, 437.9853/0.0000001], [62.7484/0.0000001, 440.4223/0.0000001] ];
|
||||
isnt Slic3r::Geometry::line_intersection($line1, $line2, 1), undef, 'line_intersection';
|
||||
|
||||
#==========================================================
|
||||
|
28
t/polyclip.t
28
t/polyclip.t
@ -1,6 +1,6 @@
|
||||
use Test::More;
|
||||
|
||||
plan tests => 9;
|
||||
plan tests => 10;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
@ -9,7 +9,7 @@ BEGIN {
|
||||
|
||||
use Slic3r;
|
||||
|
||||
my $square = [
|
||||
my $square = [ # ccw
|
||||
[10, 10],
|
||||
[20, 10],
|
||||
[20, 20],
|
||||
@ -21,18 +21,42 @@ my $line = [ [5, 15], [30, 15] ];
|
||||
my $intersection = Slic3r::Geometry::clip_segment_polygon($line, $square);
|
||||
is_deeply $intersection, [ [10, 15], [20, 15] ], 'line is clipped to square';
|
||||
|
||||
#==========================================================
|
||||
|
||||
$intersection = Slic3r::Geometry::clip_segment_polygon([ [0, 15], [8, 15] ], $square);
|
||||
is $intersection, undef, 'external lines are ignored 1';
|
||||
|
||||
#==========================================================
|
||||
|
||||
$intersection = Slic3r::Geometry::clip_segment_polygon([ [30, 15], [40, 15] ], $square);
|
||||
is $intersection, undef, 'external lines are ignored 2';
|
||||
|
||||
#==========================================================
|
||||
|
||||
$intersection = Slic3r::Geometry::clip_segment_polygon([ [12, 12], [18, 16] ], $square);
|
||||
is_deeply $intersection, [ [12, 12], [18, 16] ], 'internal lines are preserved';
|
||||
|
||||
#==========================================================
|
||||
|
||||
my $hole_in_square = [ # cw
|
||||
[14, 14],
|
||||
[14, 16],
|
||||
[16, 16],
|
||||
[16, 14],
|
||||
];
|
||||
my $intersections = Slic3r::Geometry::clip_segment_complex_polygon($line, [ $square, $hole_in_square ]);
|
||||
is_deeply $intersections, [
|
||||
[ [10, 15], [14, 15] ],
|
||||
[ [16, 15], [20, 15] ],
|
||||
], 'line is clipped to square with hole';
|
||||
|
||||
#==========================================================
|
||||
|
||||
is Slic3r::Geometry::point_in_segment([10, 10], [ [5, 10], [20, 10] ]), 1, 'point in horizontal segment';
|
||||
is Slic3r::Geometry::point_in_segment([30, 10], [ [5, 10], [20, 10] ]), 0, 'point not in horizontal segment';
|
||||
is Slic3r::Geometry::point_in_segment([10, 10], [ [10, 5], [10, 20] ]), 1, 'point in vertical segment';
|
||||
is Slic3r::Geometry::point_in_segment([10, 30], [ [10, 5], [10, 20] ]), 0, 'point not in vertical segment';
|
||||
is Slic3r::Geometry::point_in_segment([15, 15], [ [10, 10], [20, 20] ]), 1, 'point in diagonal segment';
|
||||
is Slic3r::Geometry::point_in_segment([20, 15], [ [10, 10], [20, 20] ]), 0, 'point not in diagonal segment';
|
||||
|
||||
#==========================================================
|
||||
|
Loading…
Reference in New Issue
Block a user