in src/h3lib/include/polygonAlgos.h [67:126]
bool GENERIC_LOOP_ALGO(pointInside)(const TYPE* loop, const BBox* bbox,
const GeoCoord* coord) {
// fail fast if we're outside the bounding box
if (!bboxContains(bbox, coord)) {
return false;
}
bool isTransmeridian = bboxIsTransmeridian(bbox);
bool contains = false;
double lat = coord->lat;
double lng = NORMALIZE_LON(coord->lon, isTransmeridian);
GeoCoord a;
GeoCoord b;
INIT_ITERATION;
while (true) {
ITERATE(loop, a, b);
// Ray casting algo requires the second point to always be higher
// than the first, so swap if needed
if (a.lat > b.lat) {
GeoCoord tmp = a;
a = b;
b = tmp;
}
// If we're totally above or below the latitude ranges, the test
// ray cannot intersect the line segment, so let's move on
if (lat < a.lat || lat > b.lat) {
continue;
}
double aLng = NORMALIZE_LON(a.lon, isTransmeridian);
double bLng = NORMALIZE_LON(b.lon, isTransmeridian);
// Rays are cast in the longitudinal direction, in case a point
// exactly matches, to decide tiebreakers, bias westerly
if (aLng == lng || bLng == lng) {
lng -= DBL_EPSILON;
}
// For the latitude of the point, compute the longitude of the
// point that lies on the line segment defined by a and b
// This is done by computing the percent above a the lat is,
// and traversing the same percent in the longitudinal direction
// of a to b
double ratio = (lat - a.lat) / (b.lat - a.lat);
double testLng =
NORMALIZE_LON(aLng + (bLng - aLng) * ratio, isTransmeridian);
// Intersection of the ray
if (testLng > lng) {
contains = !contains;
}
}
return contains;
}