diff --git a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java index 4e14397..fbc416a 100644 --- a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java +++ b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java @@ -22,13 +22,51 @@ public class PolygonGeofence implements Geofence { */ @Override public boolean containsLocation(Location location) { - int numberOfCorners = polygonPoints.size(); - - //adding the first corner at the end so that we can count the edge between last and first corners too - List corners = new ArrayList(polygonPoints); - corners.add(polygonPoints.get(0)); - - return false; + return pointIsInRegion(location); } + private boolean pointIsInRegion(Location aTestLocation) { + boolean inside = false; + + int count = polygonPoints.size(); + for (int i = 0; i < count; i++) { + Location beginOfLineLocation = polygonPoints.get(i); + Location endOfLineLocation = polygonPoints.get((i + 1) % count); + if (rayCrossesSegment(aTestLocation, beginOfLineLocation, endOfLineLocation)) { + inside = !inside; + } + } + + return inside; + } + + private boolean rayCrossesSegment(Location point, Location beginOfLine, Location endOfLine) { + double pointX = point.getLongitude(); + double pointY = point.getLatitude(); + double beginOfLineX = beginOfLine.getLongitude(); + double beginOfLineY = beginOfLine.getLatitude(); + double endOfLineX = endOfLine.getLongitude(); + double endOfLineY = endOfLine.getLatitude(); + + if (beginOfLineY > endOfLineY) { + return rayCrossesSegment(point, endOfLine, beginOfLine); + } + + if (pointY == beginOfLineY || pointY == endOfLineY) { + pointY += 0.00000001; + } + + if ( (pointY > endOfLineY || pointY < beginOfLineY) || (pointX > Math.max(beginOfLineX, endOfLineX)) ) { + return false; + } + + if (pointX < Math.min(beginOfLineX, endOfLineX)) { + return true; + } + + double red = (pointY - beginOfLineY) / (double) (pointX - beginOfLineX); + double blue = (endOfLineY - beginOfLineY) / (double) (endOfLineX - beginOfLineX); + + return (blue >= red); + } } diff --git a/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java index c76753e..71a400f 100644 --- a/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java +++ b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java @@ -19,23 +19,31 @@ import static com.esrlabs.geofence.Utils.location; @Config(constants = BuildConfig.class, emulateSdk = 17) public class PolygonGeofenceTest extends TestCase { // Test polygon defined physically like: - // 48.119033, 11.601664 48.119051, 11.601766 + // 48.119033, 11.601664 48.119051, 11.603766 + // + // 48.118051, 11.600766 -> This doesn't work - the test was defect + // // 48.117726, 11.602404 48.117758, 11.602543 - public static final Location testPolygonTopRightCorner = location(NETWORK_PROVIDER, 48.119033, 11.601664); - public static final Location testPolygonTopLeftCorner = location(NETWORK_PROVIDER, 48.119051, 11.601966); - public static final Location testPolygonBottomRightCorner = location(NETWORK_PROVIDER, 48.116726, 11.602404); - public static final Location testPolygonBottomLeftCorner = location(NETWORK_PROVIDER, 48.116758, 11.602743); + public static final Location testPolygonTopLeftCorner = location(NETWORK_PROVIDER, 48.119033, 11.601664); + public static final Location testPolygonTopRightCorner = location(NETWORK_PROVIDER, 48.119051, 11.603766); + public static final Location testPolygonBottomRightCorner = location(NETWORK_PROVIDER, 48.117758, 11.602543); + public static final Location testPolygonBottomLeftCorner = location(NETWORK_PROVIDER, 48.117726, 11.602404); public static final PolygonGeofence testGeofence = new PolygonGeofence(testPolygonTopRightCorner, testPolygonTopLeftCorner, testPolygonBottomRightCorner, testPolygonBottomLeftCorner); @Test public void testContainsLocation() throws Exception { assertTrue(testGeofence.containsLocation(someLocationInside())); + assertTrue(testGeofence.containsLocation(anotherLocationInside())); assertFalse(testGeofence.containsLocation(someLocationOutside())); } private Location someLocationInside() { - return location(NETWORK_PROVIDER, testPolygonTopRightCorner.getLatitude() - 0.001, testPolygonTopRightCorner.getLongitude() - 0.001); + return location(NETWORK_PROVIDER, testPolygonTopRightCorner.getLatitude() - 0.0001, testPolygonTopRightCorner.getLongitude() - 0.0001); + } + + private Location anotherLocationInside() { + return location(NETWORK_PROVIDER, 48.118, 11.60245); } private Location someLocationOutside() {