From 15c4b6b21a31c63bc0f7e624e26d032d531c459d Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 16 Jun 2022 18:48:08 -0700 Subject: Refactor geofence classes --- src/main/java/org/traccar/MainModule.java | 1 - .../java/org/traccar/geofence/GeofenceCircle.java | 4 +- .../org/traccar/geofence/GeofenceGeometry.java | 5 ++- .../java/org/traccar/geofence/GeofencePolygon.java | 4 +- .../org/traccar/geofence/GeofencePolyline.java | 23 +++++------ .../handler/events/GeofenceEventHandler.java | 7 +++- .../org/traccar/helper/model/GeofenceUtil.java | 6 ++- src/main/java/org/traccar/model/Geofence.java | 22 ++++------- .../org/traccar/session/cache/CacheManager.java | 7 +++- .../org/traccar/geofence/GeofenceCircleTest.java | 13 +++--- .../org/traccar/geofence/GeofencePolygonTest.java | 37 +++++++---------- .../org/traccar/geofence/GeofencePolylineTest.java | 46 ++++++++++++++-------- 12 files changed, 93 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/main/java/org/traccar/MainModule.java b/src/main/java/org/traccar/MainModule.java index a29c2c910..a9337a3a2 100644 --- a/src/main/java/org/traccar/MainModule.java +++ b/src/main/java/org/traccar/MainModule.java @@ -75,7 +75,6 @@ import org.traccar.web.WebServer; import javax.annotation.Nullable; import javax.inject.Singleton; -import javax.sql.DataSource; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.ext.ContextResolver; diff --git a/src/main/java/org/traccar/geofence/GeofenceCircle.java b/src/main/java/org/traccar/geofence/GeofenceCircle.java index 5d566f84e..59feb1730 100644 --- a/src/main/java/org/traccar/geofence/GeofenceCircle.java +++ b/src/main/java/org/traccar/geofence/GeofenceCircle.java @@ -18,7 +18,9 @@ package org.traccar.geofence; import java.text.DecimalFormat; import java.text.ParseException; +import org.traccar.config.Config; import org.traccar.helper.DistanceCalculator; +import org.traccar.model.Geofence; public class GeofenceCircle extends GeofenceGeometry { @@ -44,7 +46,7 @@ public class GeofenceCircle extends GeofenceGeometry { } @Override - public boolean containsPoint(double latitude, double longitude) { + public boolean containsPoint(Config config, Geofence geofence, double latitude, double longitude) { return distanceFromCenter(latitude, longitude) <= radius; } diff --git a/src/main/java/org/traccar/geofence/GeofenceGeometry.java b/src/main/java/org/traccar/geofence/GeofenceGeometry.java index 2c45c22af..fadabab1c 100644 --- a/src/main/java/org/traccar/geofence/GeofenceGeometry.java +++ b/src/main/java/org/traccar/geofence/GeofenceGeometry.java @@ -15,11 +15,14 @@ */ package org.traccar.geofence; +import org.traccar.config.Config; +import org.traccar.model.Geofence; + import java.text.ParseException; public abstract class GeofenceGeometry { - public abstract boolean containsPoint(double latitude, double longitude); + public abstract boolean containsPoint(Config config, Geofence geofence, double latitude, double longitude); public abstract double calculateArea(); diff --git a/src/main/java/org/traccar/geofence/GeofencePolygon.java b/src/main/java/org/traccar/geofence/GeofencePolygon.java index cd2cbf16a..13f6658ef 100644 --- a/src/main/java/org/traccar/geofence/GeofencePolygon.java +++ b/src/main/java/org/traccar/geofence/GeofencePolygon.java @@ -19,6 +19,8 @@ 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 org.traccar.config.Config; +import org.traccar.model.Geofence; import java.text.ParseException; import java.util.ArrayList; @@ -95,7 +97,7 @@ public class GeofencePolygon extends GeofenceGeometry { } @Override - public boolean containsPoint(double latitude, double longitude) { + public boolean containsPoint(Config config, Geofence geofence, double latitude, double longitude) { int polyCorners = coordinates.size(); int i; diff --git a/src/main/java/org/traccar/geofence/GeofencePolyline.java b/src/main/java/org/traccar/geofence/GeofencePolyline.java index 370bf99bb..d9c280ae4 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 - 2020 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 Anton Tananaev (anton@traccar.org) * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,23 +19,28 @@ package org.traccar.geofence; import java.text.ParseException; import java.util.ArrayList; +import org.traccar.config.Config; +import org.traccar.config.Keys; import org.traccar.helper.DistanceCalculator; +import org.traccar.model.Geofence; public class GeofencePolyline extends GeofenceGeometry { private ArrayList coordinates; - private double distance; public GeofencePolyline() { } - public GeofencePolyline(String wkt, double distance) throws ParseException { + public GeofencePolyline(String wkt) throws ParseException { fromWkt(wkt); - this.distance = distance; } @Override - public boolean containsPoint(double latitude, double longitude) { + public boolean containsPoint(Config config, Geofence geofence, double latitude, double longitude) { + double distance = geofence.getDouble("polylineDistance"); + if (distance == 0) { + distance = config.getDouble(Keys.GEOFENCE_POLYLINE_DISTANCE); + } for (int i = 1; i < coordinates.size(); i++) { if (DistanceCalculator.distanceToLine( latitude, longitude, coordinates.get(i - 1).getLat(), coordinates.get(i - 1).getLon(), @@ -56,9 +61,9 @@ public class GeofencePolyline extends GeofenceGeometry { StringBuilder buf = new StringBuilder(); buf.append("LINESTRING ("); 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) + ")"; @@ -105,8 +110,4 @@ public class GeofencePolyline extends GeofenceGeometry { } - public void setDistance(double distance) { - this.distance = distance; - } - } diff --git a/src/main/java/org/traccar/handler/events/GeofenceEventHandler.java b/src/main/java/org/traccar/handler/events/GeofenceEventHandler.java index 724f8f0d0..0a924cfc3 100644 --- a/src/main/java/org/traccar/handler/events/GeofenceEventHandler.java +++ b/src/main/java/org/traccar/handler/events/GeofenceEventHandler.java @@ -16,6 +16,7 @@ package org.traccar.handler.events; import io.netty.channel.ChannelHandler; +import org.traccar.config.Config; import org.traccar.helper.model.GeofenceUtil; import org.traccar.helper.model.PositionUtil; import org.traccar.model.Calendar; @@ -35,11 +36,13 @@ import java.util.Map; @ChannelHandler.Sharable public class GeofenceEventHandler extends BaseEventHandler { + private final Config config; private final CacheManager cacheManager; private final ConnectionManager connectionManager; @Inject - public GeofenceEventHandler(CacheManager cacheManager, ConnectionManager connectionManager) { + public GeofenceEventHandler(Config config, CacheManager cacheManager, ConnectionManager connectionManager) { + this.config = config; this.cacheManager = cacheManager; this.connectionManager = connectionManager; } @@ -54,7 +57,7 @@ public class GeofenceEventHandler extends BaseEventHandler { return null; } - List currentGeofences = GeofenceUtil.getCurrentGeofences(cacheManager, position); + List currentGeofences = GeofenceUtil.getCurrentGeofences(config, cacheManager, position); List oldGeofences = new ArrayList<>(); if (device.getGeofenceIds() != null) { oldGeofences.addAll(device.getGeofenceIds()); diff --git a/src/main/java/org/traccar/helper/model/GeofenceUtil.java b/src/main/java/org/traccar/helper/model/GeofenceUtil.java index f56bf4224..9f063a8b4 100644 --- a/src/main/java/org/traccar/helper/model/GeofenceUtil.java +++ b/src/main/java/org/traccar/helper/model/GeofenceUtil.java @@ -15,6 +15,7 @@ */ package org.traccar.helper.model; +import org.traccar.config.Config; import org.traccar.model.Geofence; import org.traccar.model.Position; import org.traccar.session.cache.CacheManager; @@ -27,10 +28,11 @@ public final class GeofenceUtil { private GeofenceUtil() { } - public static List getCurrentGeofences(CacheManager cacheManager, Position position) { + public static List getCurrentGeofences(Config config, CacheManager cacheManager, Position position) { List result = new ArrayList<>(); for (Geofence geofence : cacheManager.getDeviceObjects(position.getDeviceId(), Geofence.class)) { - if (geofence.getGeometry().containsPoint(position.getLatitude(), position.getLongitude())) { + if (geofence.getGeometry().containsPoint( + config, geofence, position.getLatitude(), position.getLongitude())) { result.add(geofence.getId()); } } diff --git a/src/main/java/org/traccar/model/Geofence.java b/src/main/java/org/traccar/model/Geofence.java index 5b857580d..9259028fb 100644 --- a/src/main/java/org/traccar/model/Geofence.java +++ b/src/main/java/org/traccar/model/Geofence.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2022 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. @@ -15,26 +15,19 @@ */ package org.traccar.model; -import java.text.ParseException; - -import org.traccar.Context; -import org.traccar.config.Keys; -import org.traccar.storage.QueryIgnore; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.traccar.geofence.GeofenceCircle; import org.traccar.geofence.GeofenceGeometry; import org.traccar.geofence.GeofencePolygon; import org.traccar.geofence.GeofencePolyline; - -import com.fasterxml.jackson.annotation.JsonIgnore; +import org.traccar.storage.QueryIgnore; import org.traccar.storage.StorageName; +import java.text.ParseException; + @StorageName("tc_geofences") public class Geofence extends ScheduledModel { - public static final String TYPE_GEOFENCE_CILCLE = "geofenceCircle"; - public static final String TYPE_GEOFENCE_POLYGON = "geofencePolygon"; - public static final String TYPE_GEOFENCE_POLYLINE = "geofencePolyline"; - private String name; public String getName() { @@ -68,9 +61,7 @@ public class Geofence extends ScheduledModel { } else if (area.startsWith("POLYGON")) { geometry = new GeofencePolygon(area); } else if (area.startsWith("LINESTRING")) { - final double distance = getDouble("polylineDistance"); - geometry = new GeofencePolyline(area, distance > 0 ? distance - : Context.getConfig().getDouble(Keys.GEOFENCE_POLYLINE_DISTANCE)); + geometry = new GeofencePolyline(area); } else { throw new ParseException("Unknown geometry type", 0); } @@ -92,4 +83,5 @@ public class Geofence extends ScheduledModel { area = geometry.toWkt(); this.geometry = geometry; } + } diff --git a/src/main/java/org/traccar/session/cache/CacheManager.java b/src/main/java/org/traccar/session/cache/CacheManager.java index 18daeae15..14034f3d6 100644 --- a/src/main/java/org/traccar/session/cache/CacheManager.java +++ b/src/main/java/org/traccar/session/cache/CacheManager.java @@ -15,6 +15,7 @@ */ package org.traccar.session.cache; +import org.traccar.config.Config; import org.traccar.helper.model.GeofenceUtil; import org.traccar.model.Attribute; import org.traccar.model.BaseModel; @@ -53,6 +54,7 @@ public class CacheManager { private static final Collection> CLASSES = Arrays.asList( Attribute.class, Driver.class, Geofence.class, Maintenance.class, Notification.class); + private final Config config; private final Storage storage; private final ReadWriteLock lock = new ReentrantReadWriteLock(); @@ -65,7 +67,8 @@ public class CacheManager { private final Map> notificationUsers = new HashMap<>(); @Inject - public CacheManager(Storage storage) throws StorageException { + public CacheManager(Config config, Storage storage) throws StorageException { + this.config = config; this.storage = storage; invalidateServer(); invalidateUsers(); @@ -315,7 +318,7 @@ public class CacheManager { private void invalidateDeviceGeofences(Device device) { Position position = getPosition(device.getId()); if (position != null) { - device.setGeofenceIds(GeofenceUtil.getCurrentGeofences(this, position)); + device.setGeofenceIds(GeofenceUtil.getCurrentGeofences(config, this, position)); } } diff --git a/src/test/java/org/traccar/geofence/GeofenceCircleTest.java b/src/test/java/org/traccar/geofence/GeofenceCircleTest.java index 038e4b6d6..9a02cec76 100644 --- a/src/test/java/org/traccar/geofence/GeofenceCircleTest.java +++ b/src/test/java/org/traccar/geofence/GeofenceCircleTest.java @@ -5,6 +5,7 @@ import org.junit.Test; import java.text.ParseException; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class GeofenceCircleTest { @@ -12,17 +13,15 @@ public class GeofenceCircleTest { @Test public void testCircleWkt() throws ParseException { String test = "CIRCLE (55.75414 37.6204, 100)"; - GeofenceGeometry geofenceGeometry = new GeofenceCircle(); - geofenceGeometry.fromWkt(test); + GeofenceGeometry geofenceGeometry = new GeofenceCircle(test); assertEquals(geofenceGeometry.toWkt(), test); } @Test public void testContainsCircle() throws ParseException { - String test = "CIRCLE (55.75414 37.6204, 100)"; - GeofenceGeometry geofenceGeometry = new GeofenceCircle(); - geofenceGeometry.fromWkt(test); - assertTrue(geofenceGeometry.containsPoint(55.75477, 37.62025)); - assertTrue(!geofenceGeometry.containsPoint(55.75545, 37.61921)); + GeofenceGeometry geofenceGeometry = new GeofenceCircle("CIRCLE (55.75414 37.6204, 100)"); + assertTrue(geofenceGeometry.containsPoint(null, null, 55.75477, 37.62025)); + assertFalse(geofenceGeometry.containsPoint(null, null, 55.75545, 37.61921)); } + } diff --git a/src/test/java/org/traccar/geofence/GeofencePolygonTest.java b/src/test/java/org/traccar/geofence/GeofencePolygonTest.java index 1b8de68ad..5baecd771 100644 --- a/src/test/java/org/traccar/geofence/GeofencePolygonTest.java +++ b/src/test/java/org/traccar/geofence/GeofencePolygonTest.java @@ -19,41 +19,34 @@ public class GeofencePolygonTest { @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(); - geofenceGeometry.fromWkt(test); + GeofenceGeometry geofenceGeometry = new GeofencePolygon(test); assertEquals(geofenceGeometry.toWkt(), test); } @Test public void testContainsPolygon() 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(); - geofenceGeometry.fromWkt(test); - assertTrue(geofenceGeometry.containsPoint(55.75476, 37.61915)); - assertFalse(geofenceGeometry.containsPoint(55.75545, 37.61921)); - + GeofenceGeometry geofenceGeometry = new GeofencePolygon( + "POLYGON ((55.75474 37.61823, 55.75513 37.61888, 55.7535 37.6222, 55.75315 37.62165))"); + assertTrue(geofenceGeometry.containsPoint(null, null, 55.75476, 37.61915)); + assertFalse(geofenceGeometry.containsPoint(null, null, 55.75545, 37.61921)); } @Test public void testContainsPolygon180() throws ParseException { - String test = "POLYGON ((66.9494 179.838, 66.9508 -179.8496, 66.8406 -180.0014))"; - GeofenceGeometry geofenceGeometry = new GeofencePolygon(); - geofenceGeometry.fromWkt(test); - assertTrue(geofenceGeometry.containsPoint(66.9015, -180.0096)); - assertTrue(geofenceGeometry.containsPoint(66.9015, 179.991)); - assertFalse(geofenceGeometry.containsPoint(66.8368, -179.8792)); - + GeofenceGeometry geofenceGeometry = new GeofencePolygon( + "POLYGON ((66.9494 179.838, 66.9508 -179.8496, 66.8406 -180.0014))"); + assertTrue(geofenceGeometry.containsPoint(null, null, 66.9015, -180.0096)); + assertTrue(geofenceGeometry.containsPoint(null, null, 66.9015, 179.991)); + assertFalse(geofenceGeometry.containsPoint(null, null, 66.8368, -179.8792)); } @Test public void testContainsPolygon0() throws ParseException { - String test = "POLYGON ((51.1966 -0.6207, 51.1897 0.4147, 50.9377 0.5136, 50.8675 -0.6082))"; - GeofenceGeometry geofenceGeometry = new GeofencePolygon(); - geofenceGeometry.fromWkt(test); - assertTrue(geofenceGeometry.containsPoint(51.0466, -0.0165)); - assertTrue(geofenceGeometry.containsPoint(51.0466, 0.018)); - assertFalse(geofenceGeometry.containsPoint(50.9477, 0.5836)); - + GeofenceGeometry geofenceGeometry = new GeofencePolygon( + "POLYGON ((51.1966 -0.6207, 51.1897 0.4147, 50.9377 0.5136, 50.8675 -0.6082))"); + assertTrue(geofenceGeometry.containsPoint(null, null, 51.0466, -0.0165)); + assertTrue(geofenceGeometry.containsPoint(null, null, 51.0466, 0.018)); + assertFalse(geofenceGeometry.containsPoint(null, null, 50.9477, 0.5836)); } } diff --git a/src/test/java/org/traccar/geofence/GeofencePolylineTest.java b/src/test/java/org/traccar/geofence/GeofencePolylineTest.java index 0e8905319..b7ee14510 100644 --- a/src/test/java/org/traccar/geofence/GeofencePolylineTest.java +++ b/src/test/java/org/traccar/geofence/GeofencePolylineTest.java @@ -1,47 +1,59 @@ package org.traccar.geofence; import org.junit.Test; +import org.traccar.config.Config; +import org.traccar.config.Keys; +import org.traccar.model.Geofence; import java.text.ParseException; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class GeofencePolylineTest { @Test public void testPolylineWkt() throws ParseException { String test = "LINESTRING (55.75474 37.61823, 55.75513 37.61888, 55.7535 37.6222, 55.75315 37.62165)"; - GeofenceGeometry geofenceGeometry = new GeofencePolyline(); - geofenceGeometry.fromWkt(test); + GeofenceGeometry geofenceGeometry = new GeofencePolyline(test); assertEquals(geofenceGeometry.toWkt(), test); } @Test public void testContainsPolyline1Interval() throws ParseException { - String test = "LINESTRING (56.83777 60.59833, 56.83766 60.5968)"; - GeofenceGeometry geofenceGeometry = new GeofencePolyline(test, 35); - assertTrue(geofenceGeometry.containsPoint(56.83801, 60.59748)); - ((GeofencePolyline) geofenceGeometry).setDistance(15); - assertTrue(!geofenceGeometry.containsPoint(56.83801, 60.59748)); + GeofenceGeometry geofenceGeometry = new GeofencePolyline( + "LINESTRING (56.83777 60.59833, 56.83766 60.5968)"); + Config config = mock(Config.class); + when(config.getDouble(Keys.GEOFENCE_POLYLINE_DISTANCE)).thenReturn(35.0); + assertTrue(geofenceGeometry.containsPoint(config, mock(Geofence.class), 56.83801, 60.59748)); + when(config.getDouble(Keys.GEOFENCE_POLYLINE_DISTANCE)).thenReturn(15.0); + assertFalse(geofenceGeometry.containsPoint(config, mock(Geofence.class), 56.83801, 60.59748)); } @Test public void testContainsPolyline3Intervals() throws ParseException { - String test = "LINESTRING (56.836 60.6126, 56.8393 60.6114, 56.83887 60.60811, 56.83782 60.5988)"; - GeofenceGeometry geofenceGeometry = new GeofencePolyline(test, 15); - assertTrue(geofenceGeometry.containsPoint(56.83847, 60.60458)); - assertTrue(!geofenceGeometry.containsPoint(56.83764, 60.59725)); - assertTrue(!geofenceGeometry.containsPoint(56.83861, 60.60822)); + GeofenceGeometry geofenceGeometry = new GeofencePolyline( + "LINESTRING (56.836 60.6126, 56.8393 60.6114, 56.83887 60.60811, 56.83782 60.5988)"); + Config config = mock(Config.class); + when(config.getDouble(Keys.GEOFENCE_POLYLINE_DISTANCE)).thenReturn(15.0); + assertTrue(geofenceGeometry.containsPoint(config, mock(Geofence.class), 56.83847, 60.60458)); + assertFalse(geofenceGeometry.containsPoint(config, mock(Geofence.class), 56.83764, 60.59725)); + assertFalse(geofenceGeometry.containsPoint(config, mock(Geofence.class), 56.83861, 60.60822)); } @Test public void testContainsPolylineNear180() throws ParseException { - String test = "LINESTRING (66.9494 179.838, 66.9508 -179.8496)"; - GeofenceGeometry geofenceGeometry = new GeofencePolyline(test, 25); - assertTrue(geofenceGeometry.containsPoint(66.95, 180.0)); - assertTrue(!geofenceGeometry.containsPoint(66.96, 180.0)); - assertTrue(!geofenceGeometry.containsPoint(66.9509, -179.83)); + GeofenceGeometry geofenceGeometry = new GeofencePolyline( + "LINESTRING (66.9494 179.838, 66.9508 -179.8496)"); + Config config = mock(Config.class); + when(config.getDouble(Keys.GEOFENCE_POLYLINE_DISTANCE)).thenReturn(25.0); + assertTrue(geofenceGeometry.containsPoint(config, mock(Geofence.class), 66.95, 180.0)); + assertFalse(geofenceGeometry.containsPoint(config, mock(Geofence.class), 66.96, 180.0)); + assertFalse(geofenceGeometry.containsPoint(config, mock(Geofence.class), 66.9509, -179.83)); } + } -- cgit v1.2.3