This method works on the basis that the sum of the angles between lines drawn from the point under test, to each of the vertices of the polygon, will add up to 360 degrees, if the point is inside the polygon and be less than 360 if it is outside.

This is easy to visualise for convex polygons,less so for concave ones. The tests below seem to indicate that this also works for them too, but my math isn't strong enough to give a rigorous proof of this.

You'll see from the second group of results that points that lie exactly on an edge of the polygon--to the limits of perls floats to represent them accurately--are treated as being outside of it.

#! 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.500 +00000001]; 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

Examine what is said, not who speaks.

The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.


In reply to Re: OT: point inside polyhedron test by BrowserUk
in thread OT: point inside polyhedron test by stu96art

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.