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 point is not in polygon, let's check whether it belongs to the contour
|
||||||
if (!$side && 0) {
|
if (!$side && 0) {
|
||||||
foreach my $line (polygon_lines($polygon)) {
|
return 1 if polygon_segment_having_point($polygon, $point);
|
||||||
return 1 if point_in_segment($point, $line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $side;
|
return $side;
|
||||||
@ -458,5 +456,22 @@ sub bounding_box_intersect {
|
|||||||
return 1;
|
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;
|
1;
|
||||||
|
12
t/geometry.t
12
t/geometry.t
@ -2,7 +2,7 @@ use Test::More;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
plan tests => 4;
|
plan tests => 5;
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
use FindBin;
|
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 $line1 = [ [5, 15], [30, 15] ];
|
||||||
my $line2 = [ [75/0.0000001, 437.9853/0.0000001], [62.7484/0.0000001, 440.4223/0.0000001] ];
|
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';
|
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;
|
use Test::More;
|
||||||
|
|
||||||
plan tests => 9;
|
plan tests => 10;
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
use FindBin;
|
use FindBin;
|
||||||
@ -9,7 +9,7 @@ BEGIN {
|
|||||||
|
|
||||||
use Slic3r;
|
use Slic3r;
|
||||||
|
|
||||||
my $square = [
|
my $square = [ # ccw
|
||||||
[10, 10],
|
[10, 10],
|
||||||
[20, 10],
|
[20, 10],
|
||||||
[20, 20],
|
[20, 20],
|
||||||
@ -21,18 +21,42 @@ my $line = [ [5, 15], [30, 15] ];
|
|||||||
my $intersection = Slic3r::Geometry::clip_segment_polygon($line, $square);
|
my $intersection = Slic3r::Geometry::clip_segment_polygon($line, $square);
|
||||||
is_deeply $intersection, [ [10, 15], [20, 15] ], 'line is clipped to square';
|
is_deeply $intersection, [ [10, 15], [20, 15] ], 'line is clipped to square';
|
||||||
|
|
||||||
|
#==========================================================
|
||||||
|
|
||||||
$intersection = Slic3r::Geometry::clip_segment_polygon([ [0, 15], [8, 15] ], $square);
|
$intersection = Slic3r::Geometry::clip_segment_polygon([ [0, 15], [8, 15] ], $square);
|
||||||
is $intersection, undef, 'external lines are ignored 1';
|
is $intersection, undef, 'external lines are ignored 1';
|
||||||
|
|
||||||
|
#==========================================================
|
||||||
|
|
||||||
$intersection = Slic3r::Geometry::clip_segment_polygon([ [30, 15], [40, 15] ], $square);
|
$intersection = Slic3r::Geometry::clip_segment_polygon([ [30, 15], [40, 15] ], $square);
|
||||||
is $intersection, undef, 'external lines are ignored 2';
|
is $intersection, undef, 'external lines are ignored 2';
|
||||||
|
|
||||||
|
#==========================================================
|
||||||
|
|
||||||
$intersection = Slic3r::Geometry::clip_segment_polygon([ [12, 12], [18, 16] ], $square);
|
$intersection = Slic3r::Geometry::clip_segment_polygon([ [12, 12], [18, 16] ], $square);
|
||||||
is_deeply $intersection, [ [12, 12], [18, 16] ], 'internal lines are preserved';
|
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([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([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, 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([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([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';
|
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