Naming (signature): polyCheck is not a clear name. And the arguments's names could help explain the function's semantic as well.
public bool IsPointInPolygon(Vector2 point, Vector2[] polygon)
Packing / golfing: not using the {}
for the for
loop doesn't help for anything (including speed), neither does packing all the computation in one line : it just makes the code impossible to read which seems of little use. In the same manner, make the operator precedence obvious by using ()
and using several lines.
Performance:
- What is striking at first glance is the redundancy of
p[i]
and p[j]
: do cache those vectors inside some vars. 8 array indirection per polygon point can be avoided. And even better : cache the polygon point's coordinates instead of caching the polygon points to save 6 property indirection per polygon point.
- point.x and point.y won't change: cache them.
- after reading more closely, since
i
always follows j
, you could load p[j]
from p[i]
, or rather those points' coordinates, to reduce by a factor of 2 the array/property access.
- Maybe you are doing this test before, but computing a bounding box for your polygons and using it as a first test could -depending on many factors of course- tremendously speed up things.
Naming (variables): c, p, ... think about someone else reading this code... or you in 3 months !!!
I'd be curious to know if this code is faster, and by which amount, since compilers are very smart. Let me know if you happen to test it!
public bool IsPointInPolygon(Vector2 point, Vector2[] polygon) {
int polygonLength = polygon.Length, i=0;
bool inside = false;
// x, y for tested point.
float pointX = point.x, pointY = point.y;
// start / end point for the current polygon segment.
float startX, startY, endX, endY;
Vector2 endPoint = polygon[polygonLength-1];
endX = endPoint.x;
endY = endPoint.y;
while (i<polygonLength) {
startX = endX; startY = endY;
endPoint = polygon[i++];
endX = endPoint.x; endY = endPoint.y;
//
inside ^= ( endY > pointY ^ startY > pointY ) /* ? pointY inside [startY;endY] segment ? */
&& /* if so, test if it is under the segment */
( (pointX - endX) < (pointY - endY) * (startX - endX) / (startY - endY) ) ;
}
return inside;
}