Skip to content

Instantly share code, notes, and snippets.

@zhujunsan
Created May 15, 2018 05:44
Show Gist options
  • Save zhujunsan/81d6a2f05d590f618a5ad36f25666fc2 to your computer and use it in GitHub Desktop.
Save zhujunsan/81d6a2f05d590f618a5ad36f25666fc2 to your computer and use it in GitHub Desktop.
winding number algorithm for the inclusion of a point in polygon
<?php
class Point
{
public $x;
public $y;
public function __construct($x, $y)
{
$this->x = $x;
$this->y = $y;
}
}
class wnPoly
{
private static function isLeft(Point $P0, Point $P1, Point $P2)
{
return (($P1->x - $P0->x) * ($P2->y - $P0->y) - ($P2->x - $P0->x) * ($P1->y - $P0->y));
}
// wn_PnPoly(): winding number test for a point in a polygon
// Input: P = a point,
// V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
/**
* @param Point $P
* @param Point[] $V
* @return int
*/
public static function wn_PnPoly(Point $P, array $V)
{
$wn = 0;
$n = count($V);
// loop through all edges of the polygon
for ($i = 0; $i < $n; $i++) { // edge from V[i] to V[i+1]
if ($V[$i]->y <= $P->y) { // start y <= P->y
if ($V[($i + 1) % $n]->y > $P->y) // an upward crossing
if (self::isLeft($V[$i], $V[($i + 1) % $n], $P) > 0) // P left of edge
++$wn; // have a valid up intersect
} else { // start y > P->y (no test needed)
if ($V[($i + 1) % $n]->y <= $P->y) // a downward crossing
if (self::isLeft($V[$i], $V[($i + 1) % $n], $P) < 0) // P right of edge
--$wn; // have a valid down intersect
}
}
return $wn;
}
}
$V = [];
$V [] = new Point(0, 0);
$V [] = new Point(10, 0);
$V [] = new Point(10, 10);
$V [] = new Point(0, 10);
$P = new Point(5, 51);
$r = wnPoly::wn_PnPoly($P, $V);
var_dump($r);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment