#! perl -slw use strict; use constant X => 0; use constant Y => 1; use constant PI => atan2(0,-1); use constant TWOPI => 2*PI; sub mapAdjPairs (&@) { my $code = shift; map { local ($a, $b) = (shift, $_[0]); $code->() } 0 .. @_-2; } sub Angle{ my ($x1, $y1, $x2, $y2) = @_; my $dtheta = atan2($y1, $x1) - atan2($y2, $x2); $dtheta -= TWOPI while $dtheta > PI; $dtheta += TWOPI while $dtheta < - PI; return $dtheta; } sub PtInPoly{ my ($poly, $pt) = @_; my $angle=0; mapAdjPairs{ $angle += Angle( $a->[X] - $pt->[X], $a->[Y] - $pt->[Y], $b->[X] - $pt->[X], $b->[Y] - $pt->[Y] ) } @$poly, $poly->[0]; return !(abs($angle) < PI); } my @pts = ( [-1,1], [1,1], [1,-1], [-1,-1] ); print '[0,0] should be in the polygon:', PtInPoly( \@pts, [0,0]) ? 'It is' : 'It is not'; print '[2,0] should be out of polygon:', PtInPoly( \@pts, [2,0]) ? 'It is not' : 'It is'; my @diamond = ( [0,1], [1,2], [2,1], [1,0] ); print "[$_->[0],$_->[1]] is " , PtInPoly(\@diamond, $_) ? 'inside' : 'outside' for [0.49999999999,0.49999999999], [0.5,0.5], [0.50000000001,0.50000000001]; my @concave = ( [0,3],[3,0],[5,2],[4,3],[3,2],[2,3],[3,4],[2,5] ); print '[2,2] is ', PtInPoly(\@concave, [2,2]) ? 'inside' : 'outside'; print '[3,3] is ', PtInPoly(\@concave, [3,3]) ? 'inside' : 'outside'; print '[2,4] is ', PtInPoly(\@concave, [2,4]) ? 'inside' : 'outside'; print '[4,2] is ', PtInPoly(\@concave, [4,2]) ? 'inside' : 'outside'; __END__ C:\test>temp [0,0] should be in the polygon:It is [2,0] should be out of polygon:It is [0.49999999999,0.49999999999] is outside [0.5,0.5] is outside [0.50000000001,0.50000000001] is inside [2,2] is inside [3,3] is outside [2,4] is inside [4,2] is inside