From f76b247e863721f365d02b7afb897cb3f46958f2 Mon Sep 17 00:00:00 2001 From: Seif Eddine GHAZOUANI Date: Mon, 13 May 2024 10:41:44 +0200 Subject: [PATCH] create new transform operation RemoveStopsOutsidePolygone: remove stops outside polygone/multiPolygone --- onebusaway-gtfs-transformer/pom.xml | 5 + .../impl/RemoveStopsOutsidePolygone.java | 99 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveStopsOutsidePolygone.java diff --git a/onebusaway-gtfs-transformer/pom.xml b/onebusaway-gtfs-transformer/pom.xml index 08c0c818..204f61a7 100644 --- a/onebusaway-gtfs-transformer/pom.xml +++ b/onebusaway-gtfs-transformer/pom.xml @@ -77,6 +77,11 @@ com.sun.xml.bind jaxb-impl + + org.locationtech.jts + jts-core + 1.19.0 + diff --git a/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveStopsOutsidePolygone.java b/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveStopsOutsidePolygone.java new file mode 100644 index 00000000..ecbf39a6 --- /dev/null +++ b/onebusaway-gtfs-transformer/src/main/java/org/onebusaway/gtfs_transformer/impl/RemoveStopsOutsidePolygone.java @@ -0,0 +1,99 @@ +package org.onebusaway.gtfs_transformer.impl; + +import java.util.ArrayList; +import java.util.List; + +import java.io.Serializable; + +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; +import org.locationtech.jts.geom.*; + +import org.onebusaway.csv_entities.schema.annotations.CsvField; +import org.onebusaway.gtfs.model.IdentityBean; +import org.onebusaway.gtfs.model.Stop; +import org.onebusaway.gtfs.serialization.GtfsEntitySchemaFactory; +import org.onebusaway.gtfs.services.GtfsMutableRelationalDao; +import org.onebusaway.gtfs_transformer.factory.EntityRetentionGraph; +import org.onebusaway.gtfs_transformer.services.GtfsTransformStrategy; +import org.onebusaway.gtfs_transformer.services.TransformContext; +import org.slf4j.Logger; + +import org.slf4j.LoggerFactory; + +public class RemoveStopsOutsidePolygone implements GtfsTransformStrategy { + private final Logger log = LoggerFactory.getLogger(RemoveStopsOutsidePolygone.class); + + @CsvField(optional = true) + private String polygone; + + public void setPolygone(String polygone) { + this.polygone = polygone; + } + + @Override + public String getName() { + return this.getClass().getSimpleName(); + } + + /* + * example: + * {"op":"transform","class":"org.onebusaway.gtfs_transformer.impl.RemoveStopsOutsidePolygone","polygone":wkt_polygone ..."} + */ + + @Override + public void run(TransformContext transformContext, GtfsMutableRelationalDao gtfsMutableRelationalDao) { + Geometry geometry = buildPolygone(polygone); + EntityRetentionGraph graph = new EntityRetentionGraph(gtfsMutableRelationalDao); + graph.setRetainBlocks(false); + // browse all stops and retain only those inside polygone/multiPolygone + if (geometry.isValid() && !geometry.isEmpty()){ + for (Stop stop : gtfsMutableRelationalDao.getAllStops()) { + if (insidePolygon(geometry,stop.getLon(),stop.getLat())){ + graph.retain(stop, true); + } + } + } + + // remove non retained objects + for (Class entityClass : GtfsEntitySchemaFactory.getEntityClasses()) { + List objectsToRemove = new ArrayList(); + for (Object entity : gtfsMutableRelationalDao.getAllEntitiesForType(entityClass)) { + if (!graph.isRetained(entity)){ + objectsToRemove.add(entity); + } + } + for (Object toRemove : objectsToRemove){ + gtfsMutableRelationalDao.removeEntity((IdentityBean) toRemove); + } + } + } + + /* + * create polygone/multiPolygone from 'polygone' variable in json file + * return Geometry variable + * return null if an exception is encountered when parsing the wkt string + */ + private Geometry buildPolygone(String wktPolygone) { + WKTReader reader = new WKTReader(); + try{ + return reader.read(wktPolygone); + } catch (ParseException e){ + String message = String.format("Error parsing WKT string : %s", e.getMessage()); + log.error(message); + return null; + } + + } + /* + * insidePolygone returns boolean variable + * true: if polygone contains point + * false if point is outside polygone + */ + private boolean insidePolygon(Geometry geometry, double lon, double lat) { + GeometryFactory geometryFactory = new GeometryFactory(); + Point point = geometryFactory.createPoint(new Coordinate(lon, lat)); + return geometry.contains(point); + } + +}