geospatials2

S2Polygon contains return true for a Point that not inside the Polygon


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): enter image description here

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!


Solution

  • 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.