diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2020-11-19 22:09:54 -0800 |
---|---|---|
committer | Anton Tananaev <anton.tananaev@gmail.com> | 2020-11-19 22:09:54 -0800 |
commit | 6d9708e7e8688727fbb6e1db04cf667854addba7 (patch) | |
tree | 4c3e90fd2e8f51d3233fd8813d3400a86d5ccd87 | |
parent | 6ea7e5229f8a9269cbcee639a0bd6ede3c7ceb88 (diff) | |
download | traccar-server-6d9708e7e8688727fbb6e1db04cf667854addba7.tar.gz traccar-server-6d9708e7e8688727fbb6e1db04cf667854addba7.tar.bz2 traccar-server-6d9708e7e8688727fbb6e1db04cf667854addba7.zip |
Fix polygon area calculation
-rw-r--r-- | build.gradle | 2 | ||||
-rw-r--r-- | src/main/java/org/traccar/geofence/GeofencePolygon.java | 40 | ||||
-rw-r--r-- | src/test/java/org/traccar/geofence/GeofencePolygonTest.java | 13 |
3 files changed, 24 insertions, 31 deletions
diff --git a/build.gradle b/build.gradle index 7207328f2..fb3eceaa6 100644 --- a/build.gradle +++ b/build.gradle @@ -68,6 +68,8 @@ dependencies { implementation "org.apache.velocity:velocity-tools:2.0" implementation "org.apache.commons:commons-collections4:4.4" implementation "org.mnode.ical4j:ical4j:2.0.5" // needs upgrade + implementation "org.locationtech.spatial4j:spatial4j:0.7" + implementation "org.locationtech.jts:jts-core:1.17.1" implementation "com.fizzed:ch-smpp:6.0.0-netty4-beta-3" implementation "net.java.dev.jna:jna-platform:5.6.0" implementation "com.github.jnr:jnr-posix:3.1.2" diff --git a/src/main/java/org/traccar/geofence/GeofencePolygon.java b/src/main/java/org/traccar/geofence/GeofencePolygon.java index c03a71225..cd2cbf16a 100644 --- a/src/main/java/org/traccar/geofence/GeofencePolygon.java +++ b/src/main/java/org/traccar/geofence/GeofencePolygon.java @@ -15,9 +15,16 @@ */ package org.traccar.geofence; +import org.locationtech.spatial4j.context.SpatialContext; +import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory; +import org.locationtech.spatial4j.shape.ShapeFactory; +import org.locationtech.spatial4j.shape.jts.JtsShapeFactory; + import java.text.ParseException; import java.util.ArrayList; +import static org.locationtech.spatial4j.distance.DistanceUtils.DEG_TO_KM; + public class GeofencePolygon extends GeofenceGeometry { public GeofencePolygon() { @@ -107,37 +114,14 @@ public class GeofencePolygon extends GeofenceGeometry { return oddNodes; } - private double toRadians(double input) { - return input / 180.0 * Math.PI; - } - - private double polarTriangleArea(double tan1, double lng1, double tan2, double lng2) { - double deltaLng = lng1 - lng2; - double t = tan1 * tan2; - return 2 * Math.atan2(t * Math.sin(deltaLng), 1 + t * Math.sin(deltaLng)); - } - @Override public double calculateArea() { - if (coordinates.size() < 3) { - return 0; - } - - double total = 0; - Coordinate prev = coordinates.get(coordinates.size() - 1); - double prevTanLat = Math.tan((Math.PI / 2 - toRadians(prev.getLat())) / 2); - double prevLng = toRadians(prev.getLon()); - - for (Coordinate point : coordinates) { - double tanLat = Math.tan((Math.PI / 2 - toRadians(point.getLat())) / 2); - double lng = toRadians(point.getLon()); - total += polarTriangleArea(tanLat, lng, prevTanLat, prevLng); - prevTanLat = tanLat; - prevLng = lng; + JtsShapeFactory jtsShapeFactory = new JtsSpatialContextFactory().newSpatialContext().getShapeFactory(); + ShapeFactory.PolygonBuilder polygonBuilder = jtsShapeFactory.polygon(); + for (Coordinate coordinate : coordinates) { + polygonBuilder.pointXY(coordinate.getLon(), coordinate.getLat()); } - - double earthRadius = 6371009; - return total * (earthRadius * earthRadius); + return polygonBuilder.build().getArea(SpatialContext.GEO) * DEG_TO_KM * DEG_TO_KM; } @Override diff --git a/src/test/java/org/traccar/geofence/GeofencePolygonTest.java b/src/test/java/org/traccar/geofence/GeofencePolygonTest.java index 94b73af3a..cc9c46c94 100644 --- a/src/test/java/org/traccar/geofence/GeofencePolygonTest.java +++ b/src/test/java/org/traccar/geofence/GeofencePolygonTest.java @@ -5,11 +5,18 @@ import java.text.ParseException; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class GeofencePolygonTest { @Test + public void testCalculateArea() throws ParseException { + String test = "POLYGON((-23.559204099194772 148.8653145299711, -23.6000443437826 148.85956016213583, -23.600411843430095 148.89462111436828, -23.5626384786532 148.90278297873897, -23.5574863232753 148.88137329347367, -23.559204099194772 148.8653145299711))"; + assertEquals(17, new GeofencePolygon(test).calculateArea(), 1); + } + + @Test public void testPolygonWkt() throws ParseException { String test = "POLYGON ((55.75474 37.61823, 55.75513 37.61888, 55.7535 37.6222, 55.75315 37.62165))"; GeofenceGeometry geofenceGeometry = new GeofencePolygon(); @@ -23,7 +30,7 @@ public class GeofencePolygonTest { GeofenceGeometry geofenceGeometry = new GeofencePolygon(); geofenceGeometry.fromWkt(test); assertTrue(geofenceGeometry.containsPoint(55.75476, 37.61915)); - assertTrue(!geofenceGeometry.containsPoint(55.75545, 37.61921)); + assertFalse(geofenceGeometry.containsPoint(55.75545, 37.61921)); } @@ -34,7 +41,7 @@ public class GeofencePolygonTest { geofenceGeometry.fromWkt(test); assertTrue(geofenceGeometry.containsPoint(66.9015, -180.0096)); assertTrue(geofenceGeometry.containsPoint(66.9015, 179.991)); - assertTrue(!geofenceGeometry.containsPoint(66.8368, -179.8792)); + assertFalse(geofenceGeometry.containsPoint(66.8368, -179.8792)); } @@ -45,7 +52,7 @@ public class GeofencePolygonTest { geofenceGeometry.fromWkt(test); assertTrue(geofenceGeometry.containsPoint(51.0466, -0.0165)); assertTrue(geofenceGeometry.containsPoint(51.0466, 0.018)); - assertTrue(!geofenceGeometry.containsPoint(50.9477, 0.5836)); + assertFalse(geofenceGeometry.containsPoint(50.9477, 0.5836)); } |