/** * Static method to be used with jexl * Checks if Point is inside any of the given polygonal geofences based on the winding number algorithm. * * @param latitude latitude of the location to verify * @param longitude longitude of the location to verify * @param geofences GeoJson representation of the fence area * @return true if location is inside any of the given geofences, else false */ public static Boolean inFence(double latitude, double longitude, String geofences) { Coordinates location = Coordinates.of(longitude, latitude); Boolean inzone = false; FeatureCollection featureCollection; try { featureCollection = GSON.fromJson(geofences, FeatureCollection.class); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(String.format("String %s is not a valid geoJson representation of fence", geofences), e); } catch (JsonSyntaxException e) { throw new IllegalArgumentException(String.format("String %s is not a valid Json string", geofences), e); } for (Feature feature : featureCollection.features()) { inzone = inzone || isPointInside(feature, location); } return inzone; }
private static Boolean isPointInside(Feature feature, Coordinates location) { Polygon polygon = (Polygon) feature.geometry(); List<SinglePosition> positions = Lists.newArrayList(polygon.perimeter().positions().children()); if ((positions == null) || (location == null)) { return false; } int wn = 0; for (int i = 0; i < positions.size() - 1; i++) { if (positions.get(i).coordinates().getLat() <= location.getLat()) { if (positions.get(i + 1).coordinates().getLat() > location.getLat()) { if (isLeft(positions.get(i).coordinates(), positions.get(i + 1).coordinates(), location) > 0.0) { ++wn; } } } else { if (positions.get(i + 1).coordinates().getLat() <= location.getLat()) { if (isLeft(positions.get(i).coordinates(), positions.get(i + 1).coordinates(), location) < 0.0) { --wn; } } } } return (wn != 0); }