I have a S2Polygon and need to check whether a point is inside the Polygon or outside. I expect this testcase to pass:
@Test
void testPolygonContainsPoint() {
// create a list of (latitude, longitude) points
List<S2Point> points = new ArrayList<>();
//last point is same as first point to complete the loop
points.add(S2LatLng.fromDegrees(40.7711, -73.9345).toPoint());
points.add(S2LatLng.fromDegrees(40.7710, -73.9342).toPoint());
points.add(S2LatLng.fromDegrees(40.7704, -73.9344).toPoint());
points.add(S2LatLng.fromDegrees(40.7702, -73.9345).toPoint());
points.add(S2LatLng.fromDegrees(40.7711, -73.9345).toPoint());
// create S2Loop from S2Points
S2Loop loop = new S2Loop(points);
// create S2Polygon from S2Loop
S2Polygon polygon = new S2Polygon(loop);
// create a latitude and longitude point to check
S2LatLng pointToCheck = S2LatLng.fromDegrees(40.7705, -73.9394);
boolean isContained = polygon.contains(pointToCheck.toPoint());
//I expect isContained to be 'false' but its 'true'
Assertions.assertEquals(false, isContained);
}
The point is not inside the polygon (as seen in GeoViz below):
I already checked this (doesn't seem to be applicable in my case). Any ideas on where am I going wrong will be very helpful, thanks!
Try calling loop.Normalize()
before passing it to S2Polygon
. Otherwise it might describe complimentary polygon (i.e. all points on globe except what you want - it has the same boundary, but different loop orientation).
From Normalize description:
// Invert the loop if necessary so that the area enclosed by the loop is at
// most 2*Pi.
BigQuery's ST_GeogFromText
does it by default, so it shows normalized polygon. This can be changed by passing argument oriented => TRUE
if you might encounter polygons larger than hemisphere.