aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2020-11-19 22:09:54 -0800
committerAnton Tananaev <anton.tananaev@gmail.com>2020-11-19 22:09:54 -0800
commit6d9708e7e8688727fbb6e1db04cf667854addba7 (patch)
tree4c3e90fd2e8f51d3233fd8813d3400a86d5ccd87
parent6ea7e5229f8a9269cbcee639a0bd6ede3c7ceb88 (diff)
downloadtraccar-server-6d9708e7e8688727fbb6e1db04cf667854addba7.tar.gz
traccar-server-6d9708e7e8688727fbb6e1db04cf667854addba7.tar.bz2
traccar-server-6d9708e7e8688727fbb6e1db04cf667854addba7.zip
Fix polygon area calculation
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/org/traccar/geofence/GeofencePolygon.java40
-rw-r--r--src/test/java/org/traccar/geofence/GeofencePolygonTest.java13
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));
}