Ported encloses_point() to XS and renamed to contains_point()

svg-paths
Alessandro Ranellucci 2013-11-21 16:21:42 +01:00
parent a225a8b2ef
commit 5f81292f3f
22 changed files with 81 additions and 76 deletions

View File

@ -39,36 +39,11 @@ sub noncollapsing_offset_ex {
return $self->offset_ex($distance + 1, @params); return $self->offset_ex($distance + 1, @params);
} }
sub encloses_point {
my $self = shift;
my ($point) = @_;
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.
# Useful because point_on_segment is probably slower (this was true
# before the switch to Boost.Geometry, not sure about now)
sub encloses_point_quick {
my $self = shift;
my ($point) = @_;
return Boost::Geometry::Utils::point_within_polygon($point->pp, $self->pp);
}
sub bounding_box { sub bounding_box {
my $self = shift; my $self = shift;
return $self->contour->bounding_box; return $self->contour->bounding_box;
} }
sub clip_line {
my $self = shift;
my ($line) = @_; # line must be a Slic3r::Line object
return [
map Slic3r::Line->new(@$_),
@{Slic3r::Geometry::Clipper::intersection_pl([ $line->as_polyline ], \@$self)}
];
}
sub simplify_as_polygons { sub simplify_as_polygons {
my $self = shift; my $self = shift;
my ($tolerance) = @_; my ($tolerance) = @_;
@ -192,8 +167,13 @@ sub _medial_axis_voronoi {
# ignore lines going to infinite # ignore lines going to infinite
next if $edge->[1] == -1 || $edge->[2] == -1; next if $edge->[1] == -1 || $edge->[2] == -1;
next if !$self->encloses_point_quick(Slic3r::Point->new(@{$vertices->[$edge->[1]]})) my $line = Slic3r::Line->new($vertices->[$edge->[1]], $vertices->[$edge->[2]]);
|| !$self->encloses_point_quick(Slic3r::Point->new(@{$vertices->[$edge->[2]]})); next if !$self->contains_line($line);
# contains_point() could be faster, but we need an implementation that
# reliably considers points on boundary
#next if !$self->contains_point(Slic3r::Point->new(@{$vertices->[$edge->[1]]}))
# || !$self->contains_point(Slic3r::Point->new(@{$vertices->[$edge->[2]]}));
push @skeleton_lines, [$edge->[1], $edge->[2]]; push @skeleton_lines, [$edge->[1], $edge->[2]];
} }

View File

@ -94,7 +94,7 @@ sub fill_surface {
)}; )};
# connect paths # connect paths
{ if (@paths) { # prevent calling leftmost_point() on empty collections
my $collection = Slic3r::Polyline::Collection->new(@paths); my $collection = Slic3r::Polyline::Collection->new(@paths);
@paths = (); @paths = ();
foreach my $path (@{$collection->chained_path_from($collection->leftmost_point, 0)}) { foreach my $path (@{$collection->chained_path_from($collection->leftmost_point, 0)}) {

View File

@ -61,7 +61,7 @@ sub fill_surface {
my @polylines = @{intersection_pl(\@vertical_lines, $expolygon->offset($line_spacing*0.05))}; my @polylines = @{intersection_pl(\@vertical_lines, $expolygon->offset($line_spacing*0.05))};
# connect lines # connect lines
unless ($params{dont_connect}) { unless ($params{dont_connect} || !@polylines) { # prevent calling leftmost_point() on empty collections
my ($expolygon_off) = @{$expolygon->offset_ex(scale $params{flow_spacing}/2)}; my ($expolygon_off) = @{$expolygon->offset_ex(scale $params{flow_spacing}/2)};
my $collection = Slic3r::Polyline::Collection->new(@polylines); my $collection = Slic3r::Polyline::Collection->new(@polylines);
@polylines = (); @polylines = ();

View File

@ -139,7 +139,7 @@ sub process_layer {
for 1 .. (@{$layer->slices} || 1); # make sure we have at least one island hash to avoid failure of the -1 subscript below for 1 .. (@{$layer->slices} || 1); # make sure we have at least one island hash to avoid failure of the -1 subscript below
PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) { PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) {
for my $i (0 .. $#{$layer->slices}-1) { for my $i (0 .. $#{$layer->slices}-1) {
if ($layer->slices->[$i]->contour->encloses_point($perimeter->first_point)) { if ($layer->slices->[$i]->contour->contains_point($perimeter->first_point)) {
push @{ $islands[$i]{perimeters} }, $perimeter; push @{ $islands[$i]{perimeters} }, $perimeter;
next PERIMETER; next PERIMETER;
} }
@ -148,7 +148,7 @@ sub process_layer {
} }
FILL: foreach my $fill (@{$layerm->fills}) { FILL: foreach my $fill (@{$layerm->fills}) {
for my $i (0 .. $#{$layer->slices}-1) { for my $i (0 .. $#{$layer->slices}-1) {
if ($layer->slices->[$i]->contour->encloses_point($fill->first_point)) { if ($layer->slices->[$i]->contour->contains_point($fill->first_point)) {
push @{ $islands[$i]{fills} }, $fill; push @{ $islands[$i]{fills} }, $fill;
next FILL; next FILL;
} }

View File

@ -192,13 +192,13 @@ sub find_node {
# if we're inside a hole, move to a point on hole; # if we're inside a hole, move to a point on hole;
{ {
my $polygon = first { $_->encloses_point($point) } (map @{$_->holes}, map @$_, @{$self->_inner}); my $polygon = first { $_->contains_point($point) } (map @{$_->holes}, map @$_, @{$self->_inner});
return $point->nearest_point([ @$polygon ]) if $polygon; return $point->nearest_point([ @$polygon ]) if $polygon;
} }
# if we're inside an expolygon move to a point on contour or holes # if we're inside an expolygon move to a point on contour or holes
{ {
my $expolygon = first { $_->encloses_point_quick($point) } (map @$_, @{$self->_inner}); my $expolygon = first { $_->contains_point($point) } (map @$_, @{$self->_inner});
return $point->nearest_point([ map @$_, @$expolygon ]) if $expolygon; return $point->nearest_point([ map @$_, @$expolygon ]) if $expolygon;
} }
@ -206,11 +206,11 @@ sub find_node {
my $outer_polygon_idx; my $outer_polygon_idx;
if (!$self->no_internal) { if (!$self->no_internal) {
# look for an outer expolygon whose contour contains our point # look for an outer expolygon whose contour contains our point
$outer_polygon_idx = first { first { $_->contour->encloses_point($point) } @{$self->_contours_ex->[$_]} } $outer_polygon_idx = first { first { $_->contour->contains_point($point) } @{$self->_contours_ex->[$_]} }
0 .. $#{ $self->_contours_ex }; 0 .. $#{ $self->_contours_ex };
} else { } else {
# # look for an outer expolygon containing our point # # look for an outer expolygon containing our point
$outer_polygon_idx = first { first { $_->encloses_point($point) } @{$self->_outer->[$_]} } $outer_polygon_idx = first { first { $_->contains_point($point) } @{$self->_outer->[$_]} }
0 .. $#{ $self->_outer }; 0 .. $#{ $self->_outer };
} }
my $candidates = defined $outer_polygon_idx my $candidates = defined $outer_polygon_idx

View File

@ -1024,7 +1024,7 @@ sub mouse_event {
$parent->selection_changed(0); $parent->selection_changed(0);
for my $preview (@{$parent->{object_previews}}) { for my $preview (@{$parent->{object_previews}}) {
my ($obj_idx, $instance_idx, $thumbnail) = @$preview; my ($obj_idx, $instance_idx, $thumbnail) = @$preview;
if (defined first { $_->contour->encloses_point($pos) } @$thumbnail) { if (defined first { $_->contour->contains_point($pos) } @$thumbnail) {
$parent->{selected_objects} = [ [$obj_idx, $instance_idx] ]; $parent->{selected_objects} = [ [$obj_idx, $instance_idx] ];
$parent->{list}->Select($obj_idx, 1); $parent->{list}->Select($obj_idx, 1);
$parent->selection_changed(1); $parent->selection_changed(1);
@ -1053,7 +1053,7 @@ sub mouse_event {
} elsif ($event->Moving) { } elsif ($event->Moving) {
my $cursor = wxSTANDARD_CURSOR; my $cursor = wxSTANDARD_CURSOR;
for my $preview (@{$parent->{object_previews}}) { for my $preview (@{$parent->{object_previews}}) {
if (defined first { $_->contour->encloses_point($pos) } @{ $preview->[2] }) { if (defined first { $_->contour->contains_point($pos) } @{ $preview->[2] }) {
$cursor = Wx::Cursor->new(wxCURSOR_HAND); $cursor = Wx::Cursor->new(wxCURSOR_HAND);
last; last;
} }

View File

@ -114,7 +114,7 @@ sub _merge_loops {
# supply everything to offset_ex() instead of performing several union/diff calls. # supply everything to offset_ex() instead of performing several union/diff calls.
# we sort by area assuming that the outermost loops have larger area; # we sort by area assuming that the outermost loops have larger area;
# the previous sorting method, based on $b->encloses_point($a->[0]), failed to nest # the previous sorting method, based on $b->contains_point($a->[0]), failed to nest
# loops correctly in some edge cases when original model had overlapping facets # loops correctly in some edge cases when original model had overlapping facets
my @abs_area = map abs($_), my @area = map $_->area, @$loops; my @abs_area = map abs($_), my @area = map $_->area, @$loops;
my @sorted = sort { $abs_area[$b] <=> $abs_area[$a] } 0..$#$loops; # outer first my @sorted = sort { $abs_area[$b] <=> $abs_area[$a] } 0..$#$loops; # outer first
@ -568,10 +568,12 @@ sub _detect_bridge_direction {
my @clipped_lines = map Slic3r::Line->new(@$_), @{ intersection_pl(\@lines, [ map @$_, @$inset ]) }; my @clipped_lines = map Slic3r::Line->new(@$_), @{ intersection_pl(\@lines, [ map @$_, @$inset ]) };
# remove any line not having both endpoints within anchors # remove any line not having both endpoints within anchors
# NOTE: these calls to contains_point() probably need to check whether the point
# is on the anchor boundaries too
@clipped_lines = grep { @clipped_lines = grep {
my $line = $_; my $line = $_;
!(first { $_->encloses_point_quick($line->a) } @$anchors) !(first { $_->contains_point($line->a) } @$anchors)
&& !(first { $_->encloses_point_quick($line->b) } @$anchors); && !(first { $_->contains_point($line->b) } @$anchors);
} @clipped_lines; } @clipped_lines;
# sum length of bridged lines # sum length of bridged lines

View File

@ -27,12 +27,6 @@ sub remove_acute_vertices {
polygon_remove_acute_vertices($self); polygon_remove_acute_vertices($self);
} }
sub encloses_point {
my $self = shift;
my ($point) = @_;
return Boost::Geometry::Utils::point_covered_by_polygon($point->pp, [$self->pp]);
}
sub grow { sub grow {
my $self = shift; my $self = shift;
return $self->split_at_first_point->grow(@_); return $self->split_at_first_point->grow(@_);

View File

@ -527,7 +527,7 @@ EOF
my $layer = $self->objects->[$obj_idx]->layers->[$layer_id] or next; my $layer = $self->objects->[$obj_idx]->layers->[$layer_id] or next;
# sort slices so that the outermost ones come first # sort slices so that the outermost ones come first
my @slices = sort { $a->contour->encloses_point($b->contour->[0]) ? 0 : 1 } @{$layer->slices}; my @slices = sort { $a->contour->contains_point($b->contour->first_point) ? 0 : 1 } @{$layer->slices};
foreach my $copy (@{$self->objects->[$obj_idx]->copies}) { foreach my $copy (@{$self->objects->[$obj_idx]->copies}) {
foreach my $slice (@slices) { foreach my $slice (@slices) {
my $expolygon = $slice->clone; my $expolygon = $slice->clone;

View File

@ -8,7 +8,7 @@ our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_INTERNALSO
our %EXPORT_TAGS = (types => \@EXPORT_OK); our %EXPORT_TAGS = (types => \@EXPORT_OK);
# delegate handles # delegate handles
sub encloses_point { $_[0]->expolygon->encloses_point } sub contains_point { $_[0]->expolygon->contains_point }
sub lines { $_[0]->expolygon->lines } sub lines { $_[0]->expolygon->lines }
sub contour { $_[0]->expolygon->contour } sub contour { $_[0]->expolygon->contour }
sub holes { $_[0]->expolygon->holes } sub holes { $_[0]->expolygon->holes }

View File

@ -2,7 +2,7 @@ use Test::More;
use strict; use strict;
use warnings; use warnings;
plan tests => 26; plan tests => 25;
BEGIN { BEGIN {
use FindBin; use FindBin;
@ -85,13 +85,6 @@ my $polygons = [
), ),
]; ];
my $points = [
Slic3r::Point->new(73631077, 371742392),
Slic3r::Point->new(73631077, 501742392),
];
is Slic3r::Geometry::can_connect_points(@$points, $polygons), 0, 'can_connect_points';
#========================================================== #==========================================================
{ {

View File

@ -55,7 +55,7 @@ use Slic3r::Test;
} }
}); });
my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map $_->pp, @extrusion_points ])}); my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map $_->pp, @extrusion_points ])});
ok !(first { $convex_hull->encloses_point($_) } @toolchange_points), 'all toolchanges happen outside skirt'; ok !(first { $convex_hull->contains_point($_) } @toolchange_points), 'all toolchanges happen outside skirt';
} }
__END__ __END__

View File

@ -60,7 +60,7 @@ use Slic3r::Test;
my $move_dest = Slic3r::Point->new_scale(@$info{qw(new_X new_Y)}); my $move_dest = Slic3r::Point->new_scale(@$info{qw(new_X new_Y)});
$external_loops{$self->Z}++; $external_loops{$self->Z}++;
$has_outwards_move = 1 $has_outwards_move = 1
if !Slic3r::Polygon->new_scale(@$cur_loop)->encloses_point($move_dest) if !Slic3r::Polygon->new_scale(@$cur_loop)->contains_point($move_dest)
? ($external_loops{$self->Z} == 2) # contour should include destination ? ($external_loops{$self->Z} == 2) # contour should include destination
: ($external_loops{$self->Z} == 1); # hole should not : ($external_loops{$self->Z} == 1); # hole should not
} }

View File

@ -2,7 +2,7 @@ use Test::More;
use strict; use strict;
use warnings; use warnings;
plan tests => 23; plan tests => 19;
BEGIN { BEGIN {
use FindBin; use FindBin;
@ -10,6 +10,7 @@ BEGIN {
} }
use Slic3r; use Slic3r;
use Slic3r::Geometry::Clipper qw(intersection_pl);
#========================================================== #==========================================================
@ -29,8 +30,6 @@ my $square = Slic3r::Polygon->new( # ccw
[100, 200], [100, 200],
); );
my $line = Slic3r::Line->new([50, 150], [300, 150]);
#========================================================== #==========================================================
{ {
@ -41,41 +40,41 @@ my $line = Slic3r::Line->new([50, 150], [300, 150]);
[160, 140], [160, 140],
]; ];
my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square); my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
is $expolygon->encloses_point(Slic3r::Point->new(100, 100)), 1, 'corner point is recognized'; #is $expolygon->contains_point(Slic3r::Point->new(100, 100)), 1, 'corner point is recognized';
is $expolygon->encloses_point(Slic3r::Point->new(100, 180)), 1, 'point on contour is recognized'; #is $expolygon->contains_point(Slic3r::Point->new(100, 180)), 1, 'point on contour is recognized';
is $expolygon->encloses_point(Slic3r::Point->new(140, 150)), 1, 'point on hole contour is recognized'; #is $expolygon->contains_point(Slic3r::Point->new(140, 150)), 1, 'point on hole contour is recognized';
is $expolygon->encloses_point(Slic3r::Point->new(140, 140)), 1, 'point on hole corner is recognized'; #is $expolygon->contains_point(Slic3r::Point->new(140, 140)), 1, 'point on hole corner is recognized';
{ {
my $intersection = $expolygon->clip_line(Slic3r::Line->new([150,180], [150,150])); my $intersection = intersection_pl([Slic3r::Polyline->new([150,180], [150,150])], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([150, 180], [150, 160])->length, is $intersection->[0]->length, Slic3r::Line->new([150, 180], [150, 160])->length,
'line is clipped to square with hole'; 'line is clipped to square with hole';
} }
{ {
my $intersection = $expolygon->clip_line(Slic3r::Line->new([150,150], [150,120])); my $intersection = intersection_pl([Slic3r::Polyline->new([150,150], [150,120])], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([150, 140], [150, 120])->length, is $intersection->[0]->length, Slic3r::Line->new([150, 140], [150, 120])->length,
'line is clipped to square with hole'; 'line is clipped to square with hole';
} }
{ {
my $intersection = $expolygon->clip_line(Slic3r::Line->new([120,180], [180,180])); my $intersection = intersection_pl([Slic3r::Polyline->new([120,180], [180,180])], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([120,180], [180,180])->length, is $intersection->[0]->length, Slic3r::Line->new([120,180], [180,180])->length,
'line is clipped to square with hole'; 'line is clipped to square with hole';
} }
{ {
my $intersection = $expolygon->clip_line($line); my $intersection = intersection_pl([Slic3r::Polyline->new([50, 150], [300, 150])], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([100, 150], [140, 150])->length, is $intersection->[0]->length, Slic3r::Line->new([100, 150], [140, 150])->length,
'line is clipped to square with hole'; 'line is clipped to square with hole';
is $intersection->[1]->length, Slic3r::Line->new([160, 150], [200, 150])->length, is $intersection->[1]->length, Slic3r::Line->new([160, 150], [200, 150])->length,
'line is clipped to square with hole'; 'line is clipped to square with hole';
} }
{ {
my $intersection = $expolygon->clip_line(Slic3r::Line->new(reverse @$line)); my $intersection = intersection_pl([Slic3r::Polyline->new([300, 150], [50, 150])], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([200, 150], [160, 150])->length, is $intersection->[0]->length, Slic3r::Line->new([200, 150], [160, 150])->length,
'reverse line is clipped to square with hole'; 'reverse line is clipped to square with hole';
is $intersection->[1]->length, Slic3r::Line->new([140, 150], [100, 150])->length, is $intersection->[1]->length, Slic3r::Line->new([140, 150], [100, 150])->length,
'reverse line is clipped to square with hole'; 'reverse line is clipped to square with hole';
} }
{ {
my $intersection = $expolygon->clip_line(Slic3r::Line->new([100,180], [200,180])); my $intersection = intersection_pl([Slic3r::Polyline->new([100,180], [200,180])], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([100,180], [200,180])->length, is $intersection->[0]->length, Slic3r::Line->new([100,180], [200,180])->length,
'tangent line is clipped to square with hole'; 'tangent line is clipped to square with hole';
} }
@ -117,9 +116,9 @@ my $line = Slic3r::Line->new([50, 150], [300, 150]);
ok $small_circle->is_clockwise, "hole is clockwise"; ok $small_circle->is_clockwise, "hole is clockwise";
my $expolygon = Slic3r::ExPolygon->new($large_circle, $small_circle); my $expolygon = Slic3r::ExPolygon->new($large_circle, $small_circle);
$line = Slic3r::Line->new_scale([152.742,288.086671142818], [152.742,34.166466971035]); my $line = Slic3r::Polyline->new_scale([152.742,288.086671142818], [152.742,34.166466971035]);
my $intersection = $expolygon->clip_line($line); my $intersection = intersection_pl([$line], \@$expolygon);
is $intersection->[0]->length, Slic3r::Line->new([152742000, 288086661], [152742000, 215178843])->length, is $intersection->[0]->length, Slic3r::Line->new([152742000, 288086661], [152742000, 215178843])->length,
'line is clipped to square with hole'; 'line is clipped to square with hole';
is $intersection->[1]->length, Slic3r::Line->new([152742000, 108087507], [152742000, 35166477])->length, is $intersection->[1]->length, Slic3r::Line->new([152742000, 108087507], [152742000, 35166477])->length,

View File

@ -62,7 +62,7 @@ ExPolygon::is_valid() const
} }
bool bool
ExPolygon::contains_line(Line* line) const ExPolygon::contains_line(const Line* line) const
{ {
Polylines pl(1); Polylines pl(1);
pl.push_back(*line); pl.push_back(*line);
@ -72,6 +72,16 @@ ExPolygon::contains_line(Line* line) const
return pl_out.empty(); return pl_out.empty();
} }
bool
ExPolygon::contains_point(const Point* point) const
{
if (!this->contour.contains_point(point)) return false;
for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) {
if (it->contains_point(point)) return false;
}
return true;
}
#ifdef SLIC3RXS #ifdef SLIC3RXS
SV* SV*
ExPolygon::to_AV() { ExPolygon::to_AV() {

View File

@ -17,7 +17,8 @@ class ExPolygon
void rotate(double angle, Point* center); void rotate(double angle, Point* center);
double area() const; double area() const;
bool is_valid() const; bool is_valid() const;
bool contains_line(Line* line) const; bool contains_line(const Line* line) const;
bool contains_point(const Point* point) const;
#ifdef SLIC3RXS #ifdef SLIC3RXS
void from_SV(SV* poly_sv); void from_SV(SV* poly_sv);

View File

@ -110,6 +110,21 @@ Polygon::is_valid() const
return this->points.size() >= 3; return this->points.size() >= 3;
} }
bool
Polygon::contains_point(const Point* point) const
{
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
bool result;
Points::const_iterator i = this->points.begin();
Points::const_iterator j = this->points.end() - 1;
for (; i != this->points.end(); j = i++) {
if ( ((i->y > point->y) != (j->y > point->y))
&& (point->x < (j->x - i->x) * (point->y - i->y) / (j->y - i->y) + i->x) )
result = !result;
}
return result;
}
#ifdef SLIC3RXS #ifdef SLIC3RXS
SV* SV*
Polygon::to_SV_ref() { Polygon::to_SV_ref() {

View File

@ -23,6 +23,7 @@ class Polygon : public MultiPoint {
bool make_counter_clockwise(); bool make_counter_clockwise();
bool make_clockwise(); bool make_clockwise();
bool is_valid() const; bool is_valid() const;
bool contains_point(const Point* point) const;
#ifdef SLIC3RXS #ifdef SLIC3RXS
SV* to_SV_ref(); SV* to_SV_ref();

View File

@ -49,6 +49,7 @@ PolylineCollection::leftmost_point() const
if (p == NULL || it->points.front().x < p->x) if (p == NULL || it->points.front().x < p->x)
p = &(it->points.front()); p = &(it->points.front());
} }
if (p == NULL) return NULL;
return new Point (*p); return new Point (*p);
} }

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 14; use Test::More tests => 17;
my $square = [ # ccw my $square = [ # ccw
[100, 100], [100, 100],
@ -14,6 +14,9 @@ my $square = [ # ccw
]; ];
my $polygon = Slic3r::Polygon->new(@$square); my $polygon = Slic3r::Polygon->new(@$square);
my $cw_polygon = $polygon->clone;
$cw_polygon->reverse;
ok $polygon->is_valid, 'is_valid'; ok $polygon->is_valid, 'is_valid';
is_deeply $polygon->pp, $square, 'polygon roundtrip'; is_deeply $polygon->pp, $square, 'polygon roundtrip';
@ -34,6 +37,7 @@ is_deeply $polygon->split_at(Slic3r::Point->new(@{$square->[2]}))->pp, [ @$squar
is $polygon->area, 100*100, 'area'; is $polygon->area, 100*100, 'area';
ok $polygon->is_counter_clockwise, 'is_counter_clockwise'; ok $polygon->is_counter_clockwise, 'is_counter_clockwise';
ok !$cw_polygon->is_counter_clockwise, 'is_counter_clockwise';
{ {
my $clone = $polygon->clone; my $clone = $polygon->clone;
$clone->reverse; $clone->reverse;
@ -46,6 +50,9 @@ ok $polygon->is_counter_clockwise, 'is_counter_clockwise';
ok ref($polygon->first_point) eq 'Slic3r::Point', 'first_point'; ok ref($polygon->first_point) eq 'Slic3r::Point', 'first_point';
ok $polygon->contains_point(Slic3r::Point->new(150,150)), 'ccw contains_point';
ok $cw_polygon->contains_point(Slic3r::Point->new(150,150)), 'cw contains_point';
# this is not a test: this just demonstrates bad usage, where $polygon->clone gets # this is not a test: this just demonstrates bad usage, where $polygon->clone gets
# DESTROY'ed before the derived object ($point), causing bad memory access # DESTROY'ed before the derived object ($point), causing bad memory access
if (0) { if (0) {

View File

@ -22,6 +22,7 @@
double area(); double area();
bool is_valid(); bool is_valid();
bool contains_line(Line* line); bool contains_line(Line* line);
bool contains_point(Point* point);
%{ %{
ExPolygon* ExPolygon*

View File

@ -33,6 +33,7 @@
bool is_valid(); bool is_valid();
Point* first_point() Point* first_point()
%code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->first_point(); %}; %code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->first_point(); %};
bool contains_point(Point* point);
%{ %{
Polygon* Polygon*