Math-Geometry-Planar
view release on metacpan or search on metacpan
my $wn; # thw winding number counter
for (my $i = 0 ; $i < @points ; $i++) {
my $cp = CrossProduct([$points[$i-1],$points[$i],$pointref]);
# if colinear and in between the 2 points of the polygon
# segment, it's on the perimeter and considered inside
if ($cp == 0) {
if (
((($points[$i-1][0] <= $point[0] &&
$point[0] <= $points[$i][0])) ||
(($points[$i-1][0] >= $point[0] &&
$point[0] >= $points[$i][0])))
&&
((($points[$i-1][1] <= $$pointref[1] &&
$point[1] <= $points[$i][1])) ||
(($points[$i-1][1] >= $point[1] &&
$point[1] >= $points[$i][1])))
) {
return 1;
}
}
if ($points[$i-1][1] <= $point[1]) { # start y <= P.y
if ($points[$i][1] > $point[1]) { # // an upward crossing
if ($cp > 0) {
# point left of edge
$wn++; # have a valid up intersect
}
}
} else { # start y > P.y (no test needed)
if ($points[$i][1] <= $point[1]) { # a downward crossing
if ($cp < 0) {
# point right of edge
$wn--; # have a valid down intersect
}
}
}
}
return $wn;
}
################################################################################
#
# Check if polygon inside polygon or contour
# (for a contour, a point is inside when it's within the outer shape and
# not within one of the inner shapes (holes) )
sub isinside {
my ($self,$pointref) = @_;
my $pointsref = $self->points;
if ($pointsref) {
return IsInsidePolygon($pointsref,$pointref);
} else {
my @polygonrefs = $self->get_polygons;
return 0 if (! IsInsidePolygon($polygonrefs[0],$pointref));
my @result;
for (my $i = 1; $i <@polygonrefs; $i++) {
return 0 if (IsInsidePolygon($polygonrefs[$i],$pointref));
}
return 1;
}
}
################################################################################
#
# a counter clockwise rotation over an angle a is given by the formula
#
# / x2 \ / cos(a) -sin(a) \ / x1 \
# | | = | | | |
# \ y2 / \ sin(a) cos(a) / \ y1 /
#
# args: reference to polygon object
# angle (in radians)
# reference to center point (use origin if no center point entered)
#
sub RotatePolygon {
my ($pointsref,$angle,$center) = @_;
my $xc = 0;
my $yc = 0;
if ($center) {
my @point = @$center;
$xc = $point[0];
$yc = $point[1];
}
if ($pointsref) {
my @points = @$pointsref;
my @result;
for (my $i = 0 ; $i < @points ; $i++) {
my $x = $xc + cos($angle)*($points[$i][0] - $xc) - sin($angle)*($points[$i][1] - $yc);
my $y = $yc + sin($angle)*($points[$i][0] - $xc) + cos($angle)*($points[$i][1] - $yc);
$result[$i][0] = $x;
$result[$i][1] = $y;
}
return [@result];
}
}
################################################################################
#
# rotate jpolygon or contour
#
sub rotate {
my ($self,$angle,$center) = @_;
my $rotate = Math::Geometry::Planar->new;
my $pointsref = $self->points;
if ($pointsref) {
$rotate->points(RotatePolygon($pointsref,$angle,$center));
} else {
my @polygonrefs = $self->get_polygons;
my @result;
foreach (@polygonrefs) {
$rotate->add_polygons(RotatePolygon($_,$angle,$center));
}
}
return $rotate;
}
################################################################################
#
# move a polygon over a distance in x and y direction
#
# args: reference to polygon object
# X offset
# y offset
#
sub MovePolygon {
my ($pointsref,$dx,$dy) = @_;
if ($pointsref) {
( run in 0.362 second using v1.01-cache-2.11-cpan-e1769b4cff6 )