Math-Geometry-Planar

 view release on metacpan or  search on metacpan

Planar.pm  view on Meta::CPAN

  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 )