From 6ea7e5229f8a9269cbcee639a0bd6ede3c7ceb88 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 18 Nov 2020 22:29:36 -0800 Subject: Add geofence area calculation --- .../java/org/traccar/geofence/GeofenceCircle.java | 9 ++++- .../org/traccar/geofence/GeofenceGeometry.java | 4 +- .../java/org/traccar/geofence/GeofencePolygon.java | 44 +++++++++++++++++++--- .../org/traccar/geofence/GeofencePolyline.java | 7 +++- 4 files changed, 55 insertions(+), 9 deletions(-) (limited to 'src/main/java/org/traccar') diff --git a/src/main/java/org/traccar/geofence/GeofenceCircle.java b/src/main/java/org/traccar/geofence/GeofenceCircle.java index eda63832d..5d566f84e 100644 --- a/src/main/java/org/traccar/geofence/GeofenceCircle.java +++ b/src/main/java/org/traccar/geofence/GeofenceCircle.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +48,11 @@ public class GeofenceCircle extends GeofenceGeometry { return distanceFromCenter(latitude, longitude) <= radius; } + @Override + public double calculateArea() { + return Math.PI * radius * radius; + } + @Override public String toWkt() { String wkt; @@ -68,7 +73,7 @@ public class GeofenceCircle extends GeofenceGeometry { throw new ParseException("Mismatch geometry type", 0); } String content = wkt.substring(wkt.indexOf("(") + 1, wkt.indexOf(")")); - if (content == null || content.equals("")) { + if (content.equals("")) { throw new ParseException("No content", 0); } String[] commaTokens = content.split(","); diff --git a/src/main/java/org/traccar/geofence/GeofenceGeometry.java b/src/main/java/org/traccar/geofence/GeofenceGeometry.java index 857ba3414..2c45c22af 100644 --- a/src/main/java/org/traccar/geofence/GeofenceGeometry.java +++ b/src/main/java/org/traccar/geofence/GeofenceGeometry.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,8 @@ public abstract class GeofenceGeometry { public abstract boolean containsPoint(double latitude, double longitude); + public abstract double calculateArea(); + public abstract String toWkt(); public abstract void fromWkt(String wkt) throws ParseException; diff --git a/src/main/java/org/traccar/geofence/GeofencePolygon.java b/src/main/java/org/traccar/geofence/GeofencePolygon.java index 2048ba26d..c03a71225 100644 --- a/src/main/java/org/traccar/geofence/GeofencePolygon.java +++ b/src/main/java/org/traccar/geofence/GeofencePolygon.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ public class GeofencePolygon extends GeofenceGeometry { private boolean needNormalize = false; - private void precalc() { + private void preCalculate() { if (coordinates == null) { return; } @@ -107,14 +107,47 @@ 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; + } + + double earthRadius = 6371009; + return total * (earthRadius * earthRadius); + } + @Override public String toWkt() { StringBuilder buf = new StringBuilder(); buf.append("POLYGON (("); for (Coordinate coordinate : coordinates) { - buf.append(String.valueOf(coordinate.getLat())); + buf.append(coordinate.getLat()); buf.append(" "); - buf.append(String.valueOf(coordinate.getLon())); + buf.append(coordinate.getLon()); buf.append(", "); } return buf.substring(0, buf.length() - 2) + "))"; @@ -158,7 +191,8 @@ public class GeofencePolygon extends GeofenceGeometry { } coordinates.add(coordinate); } - precalc(); + + preCalculate(); } } diff --git a/src/main/java/org/traccar/geofence/GeofencePolyline.java b/src/main/java/org/traccar/geofence/GeofencePolyline.java index d84f512e3..370bf99bb 100644 --- a/src/main/java/org/traccar/geofence/GeofencePolyline.java +++ b/src/main/java/org/traccar/geofence/GeofencePolyline.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2020 Anton Tananaev (anton@traccar.org) * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,6 +46,11 @@ public class GeofencePolyline extends GeofenceGeometry { return false; } + @Override + public double calculateArea() { + return 0; + } + @Override public String toWkt() { StringBuilder buf = new StringBuilder(); -- cgit v1.2.3