As stated in the title, the goal is to have a way for detecting whether a given GPS coordinate falls inside a polygon or not.
The polygon itself can be either convex
I thought similarly as shab first (his proposal is called Ray-Casting Algorithm), but had second thoughts like Spacedman:
...but all the geometry will have to be redone in spherical coordinates...
I implemented and tested the mathematically correct way of doing that, e.i. intersecting great circles and determining whether one of the two intersecting points is on both arcs. (Note: I followed the steps described here, but I found several errors: The sign function is missing at the end of step 6 (just before arcsin), and the final test is numerical garbage (as subtraction is badly conditioned); use rather L_1T >= max(L_1a, L_1b) to test whether S1 is on the first arc etc.)
That also is extremely slow and a numerical nightmare (evaluates ~100 trigonometric functions, among other things); it proved not to be usable in our embedded systems.
There's a trick, though: If the area you are considering is small enough, just do a standard cartographic projection, e.g. spherical Mercator projection, of each point:
// latitude, longitude in radians
x = longitude;
y = log(tan(pi/4 + latitude/2));
Then, you can apply ray-casting, where the intersection of arcs is checked by this function:
public bool ArcsIntersecting(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4)
{
double vx1 = x2 - x1;
double vy1 = y2 - y1;
double vx2 = x4 - x3;
double vy2 = y4 - y3;
double denom = vx1 * vy2 - vx2 * vy1;
if (denom == 0) { return false; } // edges are parallel
double t1 = (vx2 * (y1 - y3) - vy2 * (x1 - x3)) / denom;
double t2;
if (vx2 != 0) { t2 = (x1 - x3 + t1 * vx1) / vx2; }
else if (vy2 != 0) { t2 = (y1 - y3 + t1 * vy1) / vy2; }
else { return false; } // edges are matching
return min(t1, t2) >= 0 && max(t1, t2) <= 1;
}