From 0728bcc7d96130b0b985bc68d89b1faf8b240cc2 Mon Sep 17 00:00:00 2001 From: anterakotoarison <113263127+anterakotoarison@users.noreply.github.com> Date: Fri, 30 Jun 2023 13:14:22 +0200 Subject: [PATCH 1/3] filtering rides task - created functions to read and write json files - filtered rides to process only new ones by comparing the last updated timestamp to ride files creation dates - cleaned up code by creating functions for duplicate/similar lines --- pom.xml | 5 + src/main/java/Graph/SegmentMapper.java | 368 +++++++++++++++++-- src/main/java/Leaflet/GeoJsonPrinter.java | 1 + src/main/java/Rides/Ride.java | 2 + src/main/java/Segments/Junction.java | 114 +++++- src/main/java/Segments/Segment.java | 4 + src/main/java/Segments/Street.java | 107 +++++- src/main/kotlin/main/CommandLineArguments.kt | 3 + src/main/kotlin/main/Main.kt | 3 +- 9 files changed, 549 insertions(+), 58 deletions(-) diff --git a/pom.xml b/pom.xml index dd73a90..d5d1800 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,11 @@ log4j-core 2.14.1 + + com.googlecode.json-simple + json-simple + 1.1.1 + diff --git a/src/main/java/Graph/SegmentMapper.java b/src/main/java/Graph/SegmentMapper.java index f110bc8..32d3e21 100644 --- a/src/main/java/Graph/SegmentMapper.java +++ b/src/main/java/Graph/SegmentMapper.java @@ -8,10 +8,19 @@ import Segments.Street; import geobroker.Raster; -import java.io.File; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.BasicFileAttributes; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; -import static Leaflet.GeoJsonPrinter.writeGeoJSON; +import static Leaflet.GeoJsonPrinter.*; import static Leaflet.LeafletPrinter.leafletMarker; import static Rides.Ride.isInBoundingBox; import static main.UtilKt.getRidesOfRegionAndUNKNOWN; @@ -19,6 +28,10 @@ import main.CommandLineArguments; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + public class SegmentMapper { @@ -28,6 +41,8 @@ public class SegmentMapper { static List mostDangerousStreetsSouthWest = new ArrayList<>(); static List mostDangerousStreetsNorthEast = new ArrayList<>(); static int numberOfRelevantSegments = 0; + static HashMap recentStatsMap = new HashMap<>(); // holds the values of the number of recent rides, incidents, and segments + static HashMap prevStatsMap = new HashMap<>(); // holds the values of the number of previous rides, incidents, and segments public static void doSegmentMapping(CommandLineArguments cla) { // Creating the Geobroker Raster. See the documentation of the Geobroker: https://github.com/MoeweX/geobroker @@ -37,10 +52,15 @@ public static void doSegmentMapping(CommandLineArguments cla) { // as value and their Id(s) as their key. HashMap segmentMap = SegmentImporter.importSegments(raster, cla); - // These Lists contain junctions and steet segments only. Their purpose is to sort them according to their + // These Lists contain junctions and street segments only. Their purpose is to sort them according to their // dangerousness score. - List streetList = new ArrayList<>(); - List junctionList = new ArrayList<>(); + List recentStreetList = new ArrayList<>(); + List recentJunctionList = new ArrayList<>(); + + // These Lists contain the previous junctions and street read from the json file + List oldJunctionsList = new ArrayList<>(); + List oldStreetList = new ArrayList<>(); + // Contains the ride files of specified region. List rideFolder = getRidesOfRegionAndUNKNOWN(cla.getSimraRoot(), cla.getRegion()); @@ -52,31 +72,112 @@ public static void doSegmentMapping(CommandLineArguments cla) { List unmatchedIncidents = new ArrayList<>(); StringBuilder geoJSONContent = new StringBuilder(); StringBuilder geoJSONLiteContent = new StringBuilder(); + StringBuilder detailJSONContent = new StringBuilder(); + LocalDateTime date = getDate(cla); // this gets the last updated timestamp + getPrevStats(cla); for (int i = 0; i < rideFolder.size(); i++) { - Ride ride = new Ride(rideFolder.get(i).getPath(),segmentMap,raster, cla); - if ( ride.rideBuckets.size() > 0 && isInBoundingBox(ride.rideBuckets.get(0).lat,ride.rideBuckets.get(0).lon,cla.getBBOX_LATS(),cla.getBBOX_LONS()) && ride.isBikeRide) { - numberOfIncludedRides++; - numberOfMatchedIncidents += ride.numberOfMatchedIncidents; - unmatchedIncidents.addAll(ride.unmatchedIncidents); + Path ridePath = rideFolder.get(i).toPath(); + /*the creation date of each ride file is read and compared to the timestamp*/ + LocalDateTime creationDateTime = null; + try{ + BasicFileAttributes fileAttr = Files.readAttributes(ridePath, BasicFileAttributes.class); + creationDateTime = LocalDateTime.ofInstant(fileAttr.creationTime().toInstant(), ZoneId.systemDefault()); + } catch (Exception e){ + e.printStackTrace(); + } + /*if the the creation date is before the timestamp, continue to the next ride file*/ + if (date != null && creationDateTime.compareTo(date) < 0) { + continue; + } + if (rideFolder.get(i).getPath().contains("VM2_")){ + Ride ride = new Ride(rideFolder.get(i).getPath(), segmentMap, raster, cla); + if (ride.rideBuckets.size() > 0 && isInBoundingBox(ride.rideBuckets.get(0).lat, ride.rideBuckets.get(0).lon, cla.getBBOX_LATS(), cla.getBBOX_LONS()) && ride.isBikeRide) { + numberOfIncludedRides++; + numberOfMatchedIncidents += ride.numberOfMatchedIncidents; + unmatchedIncidents.addAll(ride.unmatchedIncidents); + } + numberOfAllRides++; + ArrayList unmatchedRideBuckets = ride.getUnmatchedRideBuckets(); + numberOfUnmatchedRideBuckets += unmatchedRideBuckets.size(); } - numberOfAllRides ++; - ArrayList unmatchedRideBuckets = ride.getUnmatchedRideBuckets(); - numberOfUnmatchedRideBuckets += unmatchedRideBuckets.size(); } + for (int i = 0; i < unmatchedIncidents.size(); i++) { Incident thisIncident = unmatchedIncidents.get(i); content.append(leafletMarker(thisIncident.lat,thisIncident.lon,thisIncident.rideName,thisIncident.timestamp)); } - logger.debug("number of unmatched ride buckets: " + numberOfUnmatchedRideBuckets); - logger.debug("number of all rides: " + numberOfAllRides); - logger.debug("number of included rides: " + numberOfIncludedRides); - logger.debug("number of all incidents: " + (numberOfMatchedIncidents + unmatchedIncidents.size())); - logger.debug("number of included incidents: " + numberOfMatchedIncidents); + logger.debug("number of unmatched ride buckets: " + (prevStatsMap.get("unmatchedRideBuckets")+ numberOfUnmatchedRideBuckets) + " (+" + numberOfUnmatchedRideBuckets + ")"); + logger.debug("number of all rides: " + (prevStatsMap.get("allRides") + numberOfAllRides) + " (+" + numberOfAllRides + ")"); + logger.debug("number of included rides: " + (prevStatsMap.get("includedRides") + numberOfIncludedRides) + " (+" + numberOfIncludedRides + ")"); + logger.debug("number of all incidents: " + (prevStatsMap.get("allIncidents") + numberOfMatchedIncidents + unmatchedIncidents.size()) + " (+" + (numberOfMatchedIncidents + unmatchedIncidents.size()) + ")"); + logger.debug("number of included incidents: " + (prevStatsMap.get("includedIncidents") + numberOfMatchedIncidents) + " (+" + numberOfMatchedIncidents + ")"); + + recentStatsMap.put("unmatchedRideBuckets", numberOfUnmatchedRideBuckets); + recentStatsMap.put("allRides", numberOfAllRides); + recentStatsMap.put("includedRides", numberOfIncludedRides); + recentStatsMap.put("allIncidents", (numberOfMatchedIncidents + unmatchedIncidents.size())); + recentStatsMap.put("includedIncidents", numberOfMatchedIncidents); int numberOfSegmentsWithRides = 0; int segmentIndex = 0; - boolean added = true; // stores wether a segment was added + boolean added = true; // stores whether a segment was added + boolean bool = true; + + File file = cla.getJsonDetailOutputFile(); + if (file.exists()) { + getElements(oldJunctionsList, oldStreetList, file); // gets the previous details of the junctions and street + + // looping through each old junctions and street, matching the id to the id(s) of the new segments + // the number of rides and incidents are added together + // the scores will be recalculated + for (Junction j : oldJunctionsList) { + if (segmentMap.containsKey(j.id)) { + Segment segment = segmentMap.get(j.id); + Junction junction = (Junction) segment; + junction.numberOfRides += j.numberOfRides; + junction.numberOfNonScaryIncidents += j.numberOfNonScaryIncidents; + junction.numberOfScaryIncidents += j.numberOfScaryIncidents; + junction.numberOfIncidents += j.numberOfIncidents; + junction.clopa += j.clopa; + junction.spiot += j.spiot; + junction.nlorh += j.nlorh; + junction.ssho += j.ssho; + junction.tailgating += j.tailgating; + junction.near_dooring += j.near_dooring; + junction.dao += j.dao; + junction.other += j.other; + + } else { + segmentMap.put(j.id, j); + } + } + for (Street s : oldStreetList) { + if (segmentMap.containsKey(s.id)) { + Segment segment = segmentMap.get(s.id); + Street street = (Street) segment; + street.numberOfRidesNorthEast += s.numberOfRidesNorthEast; + street.numberOfRidesSouthWest += s.numberOfRidesSouthWest; + street.numberOfScaryIncidentsNorthEast += s.numberOfScaryIncidentsNorthEast; + street.numberOfScaryIncidentsSouthWest += s.numberOfScaryIncidentsSouthWest; + street.numberOfNonScaryIncidentsNorthEast += s.numberOfNonScaryIncidentsNorthEast; + street.numberOfNonScaryIncidentsSouthWest += s.numberOfNonScaryIncidentsSouthWest; + street.clopa += s.clopa; + street.spiot += s.spiot; + street.nlorh += s.nlorh; + street.saho += s.saho; + street.tailgating += s.tailgating; + street.nd += s.nd; + street.dao += s.dao; + street.other += s.other; + } else { + segmentMap.put(s.id, s); + } + } + + } + + // calculating the scores for each segment for (Map.Entry stringSegmentEntry : segmentMap.entrySet()) { Segment segment = stringSegmentEntry.getValue(); if (hasRide(segment)) { @@ -101,9 +202,8 @@ public static void doSegmentMapping(CommandLineArguments cla) { } break; } - } - junctionList.add(junction); + recentJunctionList.add(junction); } else { Street street = (Street) segment; if (mostDangerousStreetsSouthWest.size() < 3) { @@ -145,39 +245,235 @@ public static void doSegmentMapping(CommandLineArguments cla) { break; } } - streetList.add(street); + recentStreetList.add(street); } + added = addSegmentToGeoJson(segment, geoJSONContent, cla); + bool = addSegmentToDetailJson(segment, detailJSONContent, cla); if (cla.getCreateAlsoLiteDashboard()) { addSegmentToGeoJsonLite(segment, geoJSONLiteContent, cla); } - if (added && segmentIndex < segmentMap.size() - 1) { + if (added && bool && segmentIndex < segmentMap.size() - 1) { // add comma and line breaks since there will be more segments geoJSONContent.append(",\n\n"); geoJSONLiteContent.append(",\n"); - } else if (added) { + detailJSONContent.append(",\n\n"); + } else if (added && bool) { // only add line breaks since last line geoJSONContent.append("\n\n"); geoJSONLiteContent.append("\n"); + detailJSONContent.append(",\n\n"); } segmentIndex++; } + // remove trailing comma which occurs if there was not a segment added in the end - if (!added && geoJSONContent.length() > 3) { + if (!added && !bool && geoJSONContent.length() > 3) { // logger.info(geoJSONContent.substring(geoJSONContent.length()-10)); geoJSONContent.deleteCharAt(geoJSONContent.length()-3); + detailJSONContent.deleteCharAt(detailJSONContent.length()-3); geoJSONLiteContent.deleteCharAt(geoJSONLiteContent.length()-2); } - logger.info("Number of Segments: " + segmentMap.size()); - logger.info("Number of Segments with at least 1 ride: " + numberOfSegmentsWithRides); - logger.info("Number of relevant segments: " + numberOfRelevantSegments); + logger.info("Number of Segments: " + (prevStatsMap.get("segments") + segmentMap.size()) + " (+" + segmentMap.size() + ")"); + logger.info("Number of Segments with at least 1 ride: " + (prevStatsMap.get("segmentWOneRide") + numberOfSegmentsWithRides) + " (+" + numberOfSegmentsWithRides + ")"); + logger.info("Number of relevant segments: " + (prevStatsMap.get("relevantSegments") + numberOfRelevantSegments) + " (+" + numberOfRelevantSegments + ")"); + + recentStatsMap.put("segments",segmentMap.size()); + recentStatsMap.put("segmentWOneRide", numberOfSegmentsWithRides); + recentStatsMap.put("relevantSegments", numberOfRelevantSegments); + + writeStats(cla); writeGeoJSON(geoJSONContent.toString(), cla.getJsonOutputFile()); + writeGeoJSON(detailJSONContent.toString(),cla.getJsonDetailOutputFile()); if (cla.getCreateAlsoLiteDashboard()) { writeGeoJSON(geoJSONLiteContent.toString(), cla.getJsonLiteOutputFile()); } } + /** + * Reads a json file containing the values of the number of rides, ride buckets, incidents, and segments from the previous iteration + * Puts each value into a hashmap with the corresponding key + * */ + private static void getPrevStats(CommandLineArguments cla) { + int prevRideBuckets = 0, prevAllRides = 0, prevIncRides = 0, prevSegments = 0, prevAllInci = 0, prevIncInci = 0, prevSegWOneRides = 0, prevRelSeg = 0; + File file = cla.getStatsJsonFile(); + if (file.exists()) { + try (FileReader reader = new FileReader(file)) { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(reader); + JSONObject jsonObject = (JSONObject) obj; + prevRideBuckets = ((Long) jsonObject.get("unmatchedRideBuckets")).intValue(); + prevAllRides = ((Long) jsonObject.get("allRides")).intValue(); + prevIncRides = ((Long) jsonObject.get("includedRides")).intValue(); + prevAllInci = ((Long) jsonObject.get("allIncidents")).intValue(); + prevIncInci = ((Long) jsonObject.get("includedIncidents")).intValue(); + prevSegments = ((Long) jsonObject.get("segments")).intValue(); + prevSegWOneRides = ((Long) jsonObject.get("segmentWOneRide")).intValue(); + prevRelSeg = ((Long) jsonObject.get("relevantSegments")).intValue(); + } catch (Exception e) { + e.printStackTrace(); + } + } + prevStatsMap.put("unmatchedRideBuckets", prevRideBuckets); + prevStatsMap.put("allRides", prevAllRides); + prevStatsMap.put("includedRides", prevIncRides); + prevStatsMap.put("allIncidents", prevAllInci); + prevStatsMap.put("includedIncidents", prevIncInci); + prevStatsMap.put("segments", prevSegments); + prevStatsMap.put("segmentWOneRide", prevSegWOneRides); + prevStatsMap.put("relevantSegments", prevRelSeg); + } + + /** + * Adds the new values of the rides, incidents, and segments to the previous ones + * Writes the values into a json file + * */ + private static void writeStats(CommandLineArguments cla){ + JSONObject content = new JSONObject(); + for (Map.Entry entry : recentStatsMap.entrySet()){ + String key = entry.getKey(); + content.put(key, (entry.getValue() + prevStatsMap.get(key))); + } + try { + String json = content.toString(); + json = new String(json.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); + Files.deleteIfExists(cla.getStatsJsonFile().toPath()); + Files.write(cla.getStatsJsonFile().toPath(), json.getBytes(), + StandardOpenOption.CREATE_NEW); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Creates double or string arrays from a JSON array + */ + private static double[] doubleArray(JSONArray jsonArray){ + double[] array = new double[jsonArray.size()]; + for(int i=0; i oldJunctionsList, List oldStreetList, File file){ + JSONParser parser = new JSONParser(); + + if (file.exists()){ + try(FileReader reader = new FileReader(file)){ + Object obj = parser.parse(reader); + JSONObject jsonObject = (JSONObject) obj; + JSONArray features = (JSONArray) jsonObject.get("features"); + for(Object featureObj : features) { + JSONObject feature = (JSONObject) featureObj; + JSONObject properties = (JSONObject) feature.get("properties"); + + String type = (String) properties.get("type"); // the type of each segment: Junction or Street + String id = (String) feature.get("id"); // the id of each segment + + if ("Junction".equalsIgnoreCase(type)){ + // gets the objects to pass as arguments needed to create a Junction object + double[] lats = doubleArray((JSONArray) properties.get("lats")); + double[] lons = doubleArray((JSONArray) properties.get("lons")); + String[] nameArr = strArray((JSONArray) properties.get("highway names")); + HashSet highwayName = new HashSet<>(Arrays.asList(nameArr)); + String[] highwayTypes = strArray((JSONArray) properties.get("highway types")); + double[] highwayLanes = doubleArray((JSONArray) properties.get("highway lanes")); + double[] lanes_bw = doubleArray((JSONArray) properties.get("lanes backward")); + double[] polyLats = doubleArray((JSONArray) properties.get("poly lats")); + double[] polyLons = doubleArray((JSONArray) properties.get("poly lons")); + + // creates a new Junction object and updates its statistics/features + Junction junction = new Junction(id,lats,lons,highwayName,highwayTypes,highwayLanes,lanes_bw,polyLats,polyLons); + junction.numberOfRides = ((Long) properties.get("rides")).intValue(); + junction.numberOfIncidents = ((Long) properties.get("incidents")).intValue(); + junction.numberOfScaryIncidents = ((Long) properties.get("scary incidents")).intValue(); + junction.numberOfNonScaryIncidents = ((Long) properties.get("non-scary incidents")).intValue(); + junction.clopa = ((Long) properties.get("clopa")).intValue(); + junction.spiot = ((Long) properties.get("spiot")).intValue(); + junction.nlorh = ((Long) properties.get("nlorh")).intValue(); + junction.ssho = ((Long) properties.get("ssho")).intValue(); + junction.tailgating = ((Long) properties.get("tailgating")).intValue(); + junction.near_dooring = ((Long) properties.get("near-dooring")).intValue(); + junction.dao = ((Long) properties.get("dao")).intValue(); + junction.other = ((Long) properties.get("other")).intValue(); + oldJunctionsList.add(junction); // add Junction object into the List + } + if ("Street".equalsIgnoreCase(type)){ + // gets the object to pass as arguments needed to create a Street object + String highWayName = (String) properties.get("highway names"); + String[] highWayTypes = strArray((JSONArray) properties.get("highway types")); + double highwayLanes = 0; + double[] highwayLanes_backward = doubleArray((JSONArray) properties.get("lanes backward")); + String[] segment_nodes = strArray((JSONArray) properties.get("segment nodes")); + double seg_length = (double) properties.get("segment length"); + double[] poly_vertices_latsArray = doubleArray((JSONArray) properties.get("poly lats")); + double[] poly_vertices_lonsArray = doubleArray((JSONArray) properties.get("poly lons")); + if(properties.get("highway lanes") != null){ + highwayLanes = (double) properties.get("highway lanes"); + } + + // creates a new Street object and updates its statistics/features + Street street = new Street(id, highWayName, highWayTypes,highwayLanes,highwayLanes_backward,segment_nodes,seg_length,poly_vertices_latsArray,poly_vertices_lonsArray); + street.numberOfRidesSouthWest = ((Long) properties.get("rides south west")).intValue(); + street.numberOfRidesNorthEast = ((Long) properties.get("rides north east")).intValue(); + street.numberOfIncidentsSouthWest = ((Long) properties.get("incidents south west")).intValue(); + street.numberOfIncidentsNorthEast = ((Long) properties.get("incidents north east")).intValue(); + street.numberOfScaryIncidentsSouthWest = ((Long) properties.get("scary incidents south west")).intValue(); + street.numberOfScaryIncidentsNorthEast = ((Long) properties.get("scary incidents north east")).intValue(); + street.numberOfNonScaryIncidentsSouthWest = ((Long) properties.get("non-scary incidents south west")).intValue(); + street.numberOfNonScaryIncidentsNorthEast = ((Long) properties.get("non-scary incidents north east")).intValue(); + street.clopa = ((Long) properties.get("clopa")).intValue(); + street.spiot = ((Long) properties.get("spiot")).intValue(); + street.nlorh = ((Long) properties.get("nlorh")).intValue(); + street.saho = ((Long) properties.get("saho")).intValue(); + street.tailgating = ((Long) properties.get("tailgating")).intValue(); + street.nd = ((Long) properties.get("nd")).intValue(); + street.dao = ((Long) properties.get("dao")).intValue(); + street.other = ((Long) properties.get("other")).intValue(); + + oldStreetList.add(street); // add Street object into List + } + } + + } catch (Exception e){ + e.printStackTrace(); + } + } + } + /** + * Reads the region-meta json file to get the latest timestamp + * */ + private static LocalDateTime getDate(CommandLineArguments cla){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-d'T'HH:mm:ss.SSSSSS"); + LocalDateTime dateTime = null; + File file = cla.getMetaJsonFile(); + if (file.exists()){ + try(FileReader reader = new FileReader(file)){ + JSONParser parser = new JSONParser(); + Object obj = parser.parse(reader); + JSONObject jsonObject = (JSONObject) obj; + String dateStr = (String) jsonObject.get("timeStamp"); + dateTime = LocalDateTime.parse(dateStr, formatter); + logger.debug("date of last update: " + dateTime); + } catch (Exception e){ + e.printStackTrace(); + } + } + return dateTime; + } private static boolean hasRide(Segment segment) { return segment.rides.size() > 0; } @@ -185,6 +481,22 @@ private static boolean hasRide(Segment segment) { /** * Returns true, if a segment was added, and false otherwise (e.g., because it was not relevant). */ + + private static boolean addSegmentToDetailJson(Segment segment, StringBuilder geoJSONContent, + CommandLineArguments cla) { + if (!cla.getIgnoreIrrelevantSegments()) { + geoJSONContent.append(segment.detailJson().replaceAll("NaN","-1")); + numberOfRelevantSegments++; + return true; + } else { + if (isRelevant(segment, cla)) { + geoJSONContent.append(segment.detailJson().replaceAll("NaN","-1")); + numberOfRelevantSegments++; + return true; + } + } + return false; + } private static boolean addSegmentToGeoJson(Segment segment, StringBuilder geoJSONContent, CommandLineArguments cla) { if (!cla.getIgnoreIrrelevantSegments()) { diff --git a/src/main/java/Leaflet/GeoJsonPrinter.java b/src/main/java/Leaflet/GeoJsonPrinter.java index 93225c4..baec7cc 100644 --- a/src/main/java/Leaflet/GeoJsonPrinter.java +++ b/src/main/java/Leaflet/GeoJsonPrinter.java @@ -40,6 +40,7 @@ public static void writeGeoJSON(String content, File outputFile) { } + public static void writeGeoJSONLite(String content, File outputFile) { try { String json = geoJSONHead() + content + geoJSONTail(); diff --git a/src/main/java/Rides/Ride.java b/src/main/java/Rides/Ride.java index 084f3de..470c06c 100644 --- a/src/main/java/Rides/Ride.java +++ b/src/main/java/Rides/Ride.java @@ -11,6 +11,7 @@ import java.nio.file.Paths; import java.util.*; + public class Ride { public List rideBuckets = new ArrayList<>(); @@ -72,6 +73,7 @@ public Ride(String pathToRide, HashMap segmentMap, Raster raste if (incidentPart) { String[] lineArray = line.split(",", -1); // skip incident if it is "nothing" or corrupted + if (line.endsWith(",,,,,") || line.length()<6 || lineArray[8].equals("0")||lineArray[8].equals("") || lineArray[8].equals("-5")) { continue; } diff --git a/src/main/java/Segments/Junction.java b/src/main/java/Segments/Junction.java index 33f2daf..028571d 100644 --- a/src/main/java/Segments/Junction.java +++ b/src/main/java/Segments/Junction.java @@ -10,6 +10,7 @@ public class Junction extends Segment implements Comparable { public int numberOfRides, numberOfIncidents, numberOfScaryIncidents, numberOfNonScaryIncidents; + public int clopa, spiot, nlorh, ssho, tailgating, near_dooring, dao, other; // previous number of types of incidents public HashMap scaryIncidentTypes, nonScaryIncidentTypes = new HashMap<>(); public double[] lanes_bw; public double dangerousnessScore; @@ -82,30 +83,119 @@ public int compareTo(@NotNull Junction o) { return this.getScore().compareTo(o.getScore()); } - public String toGeoJson() { - StringBuilder result = new StringBuilder(); + public void appendFeatures(StringBuilder result){ result.append("{\"type\":\"Feature\",\"id\":\"").append(id) .append("\",\"properties\":{\"type\":\"Junction\",") .append("\n\"score\":").append(getScore()) .append(",\n\"incidents\":").append((numberOfNonScaryIncidents + numberOfScaryIncidents)) + .append(",\n\"scary incidents\":").append((numberOfScaryIncidents)) + .append(",\n\"non-scary incidents\":").append((numberOfNonScaryIncidents)) .append(",\n\"rides\":").append(numberOfRides) - .append(",\n\"clopa\":").append((nonScaryIncidentTypes.get("-2") + scaryIncidentTypes.get("-2") + nonScaryIncidentTypes.get("1") + scaryIncidentTypes.get("1"))) - .append(",\n\"spiot\":").append((nonScaryIncidentTypes.get("2") + scaryIncidentTypes.get("2"))) - .append(",\n\"nlorh\":").append((nonScaryIncidentTypes.get("3") + scaryIncidentTypes.get("3"))) - .append(",\n\"ssho\":").append((nonScaryIncidentTypes.get("4") + scaryIncidentTypes.get("4"))) - .append(",\n\"tailgating\":").append((nonScaryIncidentTypes.get("5") + scaryIncidentTypes.get("5"))) - .append(",\n\"near-dooring\":").append((nonScaryIncidentTypes.get("6") + scaryIncidentTypes.get("6"))) - .append(",\n\"dao\":").append((nonScaryIncidentTypes.get("7") + scaryIncidentTypes.get("7"))) - .append(",\n\"other\":").append((nonScaryIncidentTypes.get("8") + scaryIncidentTypes.get("8"))) - .append(super.toGeoJson()) - .append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); + .append(",\n\"clopa\":").append((nonScaryIncidentTypes.get("-2") + scaryIncidentTypes.get("-2") + nonScaryIncidentTypes.get("1") + scaryIncidentTypes.get("1") + clopa)) + .append(",\n\"spiot\":").append((nonScaryIncidentTypes.get("2") + scaryIncidentTypes.get("2")+spiot)) + .append(",\n\"nlorh\":").append((nonScaryIncidentTypes.get("3") + scaryIncidentTypes.get("3")+nlorh)) + .append(",\n\"ssho\":").append((nonScaryIncidentTypes.get("4") + scaryIncidentTypes.get("4")+ssho)) + .append(",\n\"tailgating\":").append((nonScaryIncidentTypes.get("5") + scaryIncidentTypes.get("5")+tailgating)) + .append(",\n\"near-dooring\":").append((nonScaryIncidentTypes.get("6") + scaryIncidentTypes.get("6")+near_dooring)) + .append(",\n\"dao\":").append((nonScaryIncidentTypes.get("7") + scaryIncidentTypes.get("7")+dao)) + .append(",\n\"other\":").append((nonScaryIncidentTypes.get("8") + scaryIncidentTypes.get("8")+other)); + } + public String detailJson() { + StringBuilder result = new StringBuilder(); + appendFeatures(result); + //Lats + result.append(",\n\"lats\":["); + for (int i = 0; i < lats.length; i++){ + result.append(lats[i]); + if (i != lats.length - 1){ + result.append(","); + } + } + result.append("]"); + //Lons + result.append(",\n\"lons\":["); + for (int i = 0; i < lons.length; i++){ + result.append(lons[i]); + if (i != lons.length - 1){ + result.append(","); + } + } + result.append("]"); + //Highway Lanes + result.append(",\n\"highway lanes\":["); + for (int i = 0; i < highWayLanes.length; i++){ + result.append(highWayLanes[i]); + if (i != highWayLanes.length - 1){ + result.append(","); + } + } + result.append("]"); + //Lanes backward + result.append(",\n\"lanes backward\":["); + for (int i = 0; i < lanes_bw.length; i++){ + result.append(lanes_bw[i]); + if (i != lanes_bw.length - 1){ + result.append(","); + } + } + result.append("]"); + //Highway Name + result.append(",\n\"highway names\":["); + Iterator iterator = highwayName.iterator(); + while (iterator.hasNext()) { + result.append("\"").append(iterator.next()).append("\""); + if (iterator.hasNext()){ + result.append(","); + } + } + result.append("]"); + //Highway Types + result.append(",\n\"highway types\":["); + for (int i = 0; i < highWayTypes.length; i++){ + result.append("\"").append(highWayTypes[i]).append("\""); + if (i != highWayTypes.length - 1){ + result.append(","); + } + } + result.append("]"); + //Poly_lats + result.append(",\n\"poly lats\":["); + for (int i = 0; i < poly_vertices_latsArray.length; i++){ + result.append(poly_vertices_latsArray[i]); + if (i != poly_vertices_latsArray.length - 1){ + result.append(","); + } + } + result.append("]"); + //Poly lons + result.append(",\n\"poly lons\":["); + for (int i = 0; i < poly_vertices_lonsArray.length; i++){ + result.append(poly_vertices_lonsArray[i]); + if (i != poly_vertices_lonsArray.length - 1){ + result.append(","); + } + } + result.append("]"); + result.append(super.toGeoJson()); + result.append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); for (int i = 0; i < poly_vertices_latsArray.length-1; i++) { result.append("[").append(poly_vertices_lonsArray[i]).append(",").append(poly_vertices_latsArray[i]).append("],"); } result.append("[").append(poly_vertices_lonsArray[poly_vertices_lonsArray.length-1]).append(",").append(poly_vertices_latsArray[poly_vertices_latsArray.length-1]).append("]]]}}"); + return result.toString(); + } + public String toGeoJson() { + StringBuilder result = new StringBuilder(); + appendFeatures(result); + result.append(super.toGeoJson()) + .append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); + for (int i = 0; i < poly_vertices_latsArray.length-1; i++) { + result.append("[").append(poly_vertices_lonsArray[i]).append(",").append(poly_vertices_latsArray[i]).append("],"); + } + result.append("[").append(poly_vertices_lonsArray[poly_vertices_lonsArray.length-1]).append(",").append(poly_vertices_latsArray[poly_vertices_latsArray.length-1]).append("]]]}}"); return result.toString(); } diff --git a/src/main/java/Segments/Segment.java b/src/main/java/Segments/Segment.java index 6914949..a78d1b7 100644 --- a/src/main/java/Segments/Segment.java +++ b/src/main/java/Segments/Segment.java @@ -51,6 +51,10 @@ public String determineColor(double score) { ? "#ffff00" : "#1a9641"; } + public String detailJson() { + StringBuilder result = new StringBuilder(); + return result.toString(); + } public String toGeoJson() { StringBuilder result = new StringBuilder(); diff --git a/src/main/java/Segments/Street.java b/src/main/java/Segments/Street.java index c29e83e..93569ca 100644 --- a/src/main/java/Segments/Street.java +++ b/src/main/java/Segments/Street.java @@ -17,6 +17,7 @@ public class Street extends Segment implements Comparable { public String partOfStreetWithId; public String[] segment_nodes; public int numberOfRidesSouthWest, numberOfRidesNorthEast, numberOfIncidentsSouthWest, numberOfIncidentsNorthEast, numberOfScaryIncidentsSouthWest, numberOfScaryIncidentsNorthEast, numberOfNonScaryIncidentsSouthWest, numberOfNonScaryIncidentsNorthEast; + public int clopa, spiot, nlorh, saho, tailgating, nd, dao, other; public HashMap scaryIncidentTypesSouthWest,scaryIncidentTypesNorthEast, nonScaryIncidentTypesSouthWest, nonScaryIncidentTypesNorthEast= new HashMap<>(); public double[] lanes_backward; public double seg_length, scoreSouthWest, scoreNorthEast, score; @@ -105,14 +106,7 @@ public String toString() { return result.toString(); } - - @Override - public int compareTo(@NotNull Street o) { - return this.getScore().compareTo(o.getScore()); - } - - public String toGeoJson() { - StringBuilder result = new StringBuilder(); + public void appendFeatures(StringBuilder result){ result.append("{\"type\":\"Feature\",\"id\":\"").append(id) .append("\",\"properties\":{\"type\":\"Street\",") .append("\n\"score\":").append(getScore()) @@ -125,15 +119,94 @@ public String toGeoJson() { .append(",\n\"rides north east\":").append(numberOfRidesNorthEast) .append(",\n\"incidents north east\":").append((numberOfNonScaryIncidentsNorthEast + numberOfScaryIncidentsNorthEast)) .append(",\n\"score north east\":").append(scoreNorthEast) - .append(",\n\"clopa\":").append((scaryIncidentTypesSouthWest.get("-2") + nonScaryIncidentTypesSouthWest.get("-2") + scaryIncidentTypesNorthEast.get("-2") + nonScaryIncidentTypesNorthEast.get("-2") + scaryIncidentTypesSouthWest.get("1") + nonScaryIncidentTypesSouthWest.get("1") + scaryIncidentTypesNorthEast.get("1") + nonScaryIncidentTypesNorthEast.get("1"))) - .append(",\n\"spiot\":").append((scaryIncidentTypesSouthWest.get("2") + nonScaryIncidentTypesSouthWest.get("2") + scaryIncidentTypesNorthEast.get("2") + nonScaryIncidentTypesNorthEast.get("2"))) - .append(",\n\"nlorh\":").append((scaryIncidentTypesSouthWest.get("3") + nonScaryIncidentTypesSouthWest.get("3") + scaryIncidentTypesNorthEast.get("3") + nonScaryIncidentTypesNorthEast.get("3"))) - .append(",\n\"saho\":").append((scaryIncidentTypesSouthWest.get("4") + nonScaryIncidentTypesSouthWest.get("4") + scaryIncidentTypesNorthEast.get("4") + nonScaryIncidentTypesNorthEast.get("4"))) - .append(",\n\"tailgating\":").append((scaryIncidentTypesSouthWest.get("5") + nonScaryIncidentTypesSouthWest.get("5") + scaryIncidentTypesNorthEast.get("5") + nonScaryIncidentTypesNorthEast.get("5"))) - .append(",\n\"nd\":").append((scaryIncidentTypesSouthWest.get("6") + nonScaryIncidentTypesSouthWest.get("6") + scaryIncidentTypesNorthEast.get("6") + nonScaryIncidentTypesNorthEast.get("6"))) - .append(",\n\"dao\":").append((scaryIncidentTypesSouthWest.get("7") + nonScaryIncidentTypesSouthWest.get("7") + scaryIncidentTypesNorthEast.get("7") + nonScaryIncidentTypesNorthEast.get("7"))) - .append(",\n\"other\":").append((scaryIncidentTypesSouthWest.get("8") + nonScaryIncidentTypesSouthWest.get("8") + scaryIncidentTypesNorthEast.get("8") + nonScaryIncidentTypesNorthEast.get("8"))) - .append(super.toGeoJson()) + .append(",\n\"clopa\":").append((scaryIncidentTypesSouthWest.get("-2") + nonScaryIncidentTypesSouthWest.get("-2") + scaryIncidentTypesNorthEast.get("-2") + nonScaryIncidentTypesNorthEast.get("-2") + scaryIncidentTypesSouthWest.get("1") + nonScaryIncidentTypesSouthWest.get("1") + scaryIncidentTypesNorthEast.get("1") + nonScaryIncidentTypesNorthEast.get("1")+clopa)) + .append(",\n\"spiot\":").append((scaryIncidentTypesSouthWest.get("2") + nonScaryIncidentTypesSouthWest.get("2") + scaryIncidentTypesNorthEast.get("2") + nonScaryIncidentTypesNorthEast.get("2")+spiot)) + .append(",\n\"nlorh\":").append((scaryIncidentTypesSouthWest.get("3") + nonScaryIncidentTypesSouthWest.get("3") + scaryIncidentTypesNorthEast.get("3") + nonScaryIncidentTypesNorthEast.get("3")+nlorh)) + .append(",\n\"saho\":").append((scaryIncidentTypesSouthWest.get("4") + nonScaryIncidentTypesSouthWest.get("4") + scaryIncidentTypesNorthEast.get("4") + nonScaryIncidentTypesNorthEast.get("4")+saho)) + .append(",\n\"tailgating\":").append((scaryIncidentTypesSouthWest.get("5") + nonScaryIncidentTypesSouthWest.get("5") + scaryIncidentTypesNorthEast.get("5") + nonScaryIncidentTypesNorthEast.get("5")+tailgating)) + .append(",\n\"nd\":").append((scaryIncidentTypesSouthWest.get("6") + nonScaryIncidentTypesSouthWest.get("6") + scaryIncidentTypesNorthEast.get("6") + nonScaryIncidentTypesNorthEast.get("6")+nd)) + .append(",\n\"dao\":").append((scaryIncidentTypesSouthWest.get("7") + nonScaryIncidentTypesSouthWest.get("7") + scaryIncidentTypesNorthEast.get("7") + nonScaryIncidentTypesNorthEast.get("7")+dao)) + .append(",\n\"other\":").append((scaryIncidentTypesSouthWest.get("8") + nonScaryIncidentTypesSouthWest.get("8") + scaryIncidentTypesNorthEast.get("8") + nonScaryIncidentTypesNorthEast.get("8")+other)); + } + @Override + public int compareTo(@NotNull Street o) { + return this.getScore().compareTo(o.getScore()); + } + public String detailJson() { + StringBuilder result = new StringBuilder(); + appendFeatures(result); + //Highway Name + result.append(",\n\"highway names\":"); + Iterator iterator = highwayName.iterator(); + while (iterator.hasNext()) { + result.append("\"").append(iterator.next()).append("\""); + if (iterator.hasNext()){ + result.append(","); + } + } + //Highway Type + result.append(",\n\"highway types\":["); + for (int i = 0; i < highWayTypes.length; i++){ + result.append("\"").append(highWayTypes[i]).append("\""); + if (i != highWayTypes.length - 1){ + result.append(","); + } + } + result.append("]"); + //Highway Lanes + result.append(",\n\"highway lanes\":").append(highWayLanes); + //Highway Lanes Backward + result.append(",\n\"lanes backward\":["); + for (int i = 0; i < lanes_backward.length; i++){ + result.append(lanes_backward[i]); + if (i != lanes_backward.length - 1){ + result.append(","); + } + } + result.append("]"); + //Segment nodes + result.append(",\n\"segment nodes\":["); + for (int i = 0; i < segment_nodes.length; i++){ + result.append("\"").append(segment_nodes[i]).append("\""); + if (i != segment_nodes.length - 1){ + result.append(","); + } + } + result.append("]"); + //Segment length + result.append(",\n\"segment length\":").append(seg_length); + //Poly_lats + result.append(",\n\"poly lats\":["); + for (int i = 0; i < poly_vertices_latsArray.length; i++){ + result.append(poly_vertices_latsArray[i]); + if (i != poly_vertices_latsArray.length - 1){ + result.append(","); + } + } + result.append("]"); + //Poly lons + result.append(",\n\"poly lons\":["); + for (int i = 0; i < poly_vertices_lonsArray.length; i++){ + result.append(poly_vertices_lonsArray[i]); + if (i != poly_vertices_lonsArray.length - 1){ + result.append(","); + } + } + result.append("]"); + result.append(super.toGeoJson()); + result.append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); + for (int i = 0; i < poly_vertices_latsArray.length-1; i++) { + result.append("[").append(poly_vertices_lonsArray[i]).append(",").append(poly_vertices_latsArray[i]).append("],"); + } + result.append("[").append(poly_vertices_lonsArray[poly_vertices_lonsArray.length-1]).append(",").append(poly_vertices_latsArray[poly_vertices_latsArray.length-1]).append("]]]}}"); + + return result.toString(); + } + + public String toGeoJson() { + StringBuilder result = new StringBuilder(); + appendFeatures(result); + result.append(super.toGeoJson()) .append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); for (int i = 0; i < poly_vertices_latsArray.length-1; i++) { diff --git a/src/main/kotlin/main/CommandLineArguments.kt b/src/main/kotlin/main/CommandLineArguments.kt index cbe816d..f4d4115 100644 --- a/src/main/kotlin/main/CommandLineArguments.kt +++ b/src/main/kotlin/main/CommandLineArguments.kt @@ -111,6 +111,9 @@ class CommandLineArguments(parser: ArgParser) { // Specify name of JSON output file depending on relevanceThresholdRideCount (= minRides) val jsonOutputFile = if (relevanceThresholdRideCount == 1) File("$outputDir/${region}_all.json") else File("$outputDir/$region.json") val jsonLiteOutputFile = if (relevanceThresholdRideCount == 1) File("$outputDir/${region}_all_lite.json") else File("$outputDir/${region}_lite.json") + val jsonDetailOutputFile = if (relevanceThresholdRideCount == 1) File("$outputDir/${region}_all.json") else File("$outputDir/${region}-detail.json") + val metaJsonFile = File("$outputDir/${region}-meta.json") + val statsJsonFile = File("$outputDir/${region}-stats.json") val osmJunctionFile = File(osmDataDir).listFiles()!!.filter { it.name.lowercase().startsWith("${region.lowercase()}_junctions") }.sorted().last() val osmSegmentsFile = File(osmDataDir).listFiles()!!.filter { it.name.lowercase().startsWith("${region.lowercase()}_segments") }.sorted().last() diff --git a/src/main/kotlin/main/Main.kt b/src/main/kotlin/main/Main.kt index 387e09a..8691d54 100644 --- a/src/main/kotlin/main/Main.kt +++ b/src/main/kotlin/main/Main.kt @@ -11,7 +11,8 @@ fun main(args: Array) { val cla = mainBody { ArgParser(args).parseInto(::CommandLineArguments) } logger.info(cla.toString()) - cla.toMetaFile() + //cla.toMetaFile() doSegmentMapping(cla) + cla.toMetaFile() // moved this to after segment mapping so that the previous timestamp can be read before it updates } \ No newline at end of file From dbf956ea1167aaa5856338eec30219417fd88275 Mon Sep 17 00:00:00 2001 From: anterakotoarison <113263127+anterakotoarison@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:02:12 +0200 Subject: [PATCH 2/3] init --- pom.xml | 52 +++- src/main/java/Graph/SegmentImporter.java | 341 +++++++++++++---------- src/main/java/Graph/SegmentMapper.java | 106 +++++-- src/main/java/Rides/Ride.java | 20 ++ src/main/java/Rides/RideBucket.java | 20 +- src/main/java/Segments/Hexagon.java | 157 +++++++++++ src/main/java/Segments/Junction.java | 1 - 7 files changed, 531 insertions(+), 166 deletions(-) create mode 100644 src/main/java/Segments/Hexagon.java diff --git a/pom.xml b/pom.xml index d5d1800..fe7e0db 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,9 @@ 1.5.20 11 UTF-8 + UTF-8 + 29-SNAPSHOT + true @@ -70,8 +73,44 @@ json-simple 1.1.1 + + junit + junit + 4.13.2 + test + + + org.geotools + gt-shapefile + ${geotools.version} + + + org.geotools + gt-swing + ${geotools.version} + + + org.geotools + gt-grid + ${geotools.version} + - + + + osgeo + OSGeo Release Repository + https://repo.osgeo.org/repository/release/ + false + true + + + osgeo-snapshot + OSGeo Snapshot Repository + https://repo.osgeo.org/repository/snapshot/ + true + false + + @@ -176,6 +215,17 @@ + + + true + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 1.8 + 1.8 + + diff --git a/src/main/java/Graph/SegmentImporter.java b/src/main/java/Graph/SegmentImporter.java index bc8cd2c..fa39f88 100644 --- a/src/main/java/Graph/SegmentImporter.java +++ b/src/main/java/Graph/SegmentImporter.java @@ -1,15 +1,34 @@ package Graph; +import Segments.Hexagon; import Segments.Junction; import Segments.Segment; import Segments.Street; +import geobroker.Geofence; import geobroker.Raster; import main.CommandLineArguments; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.locationtech.spatial4j.exception.InvalidShapeException; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureIterator; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.grid.DefaultGridFeatureBuilder; +import org.geotools.grid.GridFeatureBuilder; +import org.geotools.grid.hexagon.HexagonOrientation; +import org.geotools.grid.hexagon.Hexagons; +import org.geotools.referencing.crs.DefaultGeographicCRS; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import java.awt.geom.Point2D; import java.io.*; import java.util.*; @@ -19,158 +38,132 @@ public class SegmentImporter { private static Map segmentMap = new HashMap<>(); public static HashMap importSegments(Raster raster, CommandLineArguments cla) { + // getting the bounding box coordinates to know the size of hexagon grid + File osmMetaFile = cla.getOsmMetaFile(); + double[] bounding_box = getBoundingBox(osmMetaFile); + double minX = bounding_box[0]; + double minY = bounding_box[1]; + double maxX = bounding_box[2]; + double maxY = bounding_box[3]; + + // test + List hexagons = createHexagonalGrid(bounding_box); // new function to create a hexagon grid + for(Geometry g : hexagons){ + Coordinate[] vertices = g.getCoordinates(); + List latsArray = new ArrayList<>(); + List lonsArray = new ArrayList<>(); + for (Coordinate point : vertices){ + latsArray.add(point.getX()); + lonsArray.add(point.getY()); + } + double[] polyLats = latsArray.stream().mapToDouble(Double::doubleValue).toArray(); + logger.debug("LATS: " + Arrays.toString(polyLats)); + double[] polyLons = lonsArray.stream().mapToDouble(Double::doubleValue).toArray(); + logger.debug("LONS: " + Arrays.toString(polyLons)); + String uniqueID = UUID.randomUUID().toString(); + Hexagon hexagon = new Hexagon(uniqueID, polyLats, polyLons, polyLats, polyLons); + logger.debug(hexagon.geofence); + segmentMap.put(uniqueID, hexagon); + logger.debug("putting in raster..."); + // everything works until here idk y + raster.putSubscriptionIdIntoRasterEntries(hexagon.geofence, new ImmutablePair<>("", uniqueID)); // this seems to be create a problem that idk + logger.debug("done"); + System.exit(-1); + } + // end of test + // read the junctions and put the into segmentMap - logger.info("Importing junctions from: " + cla.getOsmJunctionFile().getAbsolutePath()); - File file = cla.getOsmJunctionFile(); - try (BufferedReader br = new BufferedReader(new FileReader(file))) { - // Skip header id|lat|lon|highwayName|highwaytypes|highwaylanes|poly_vertices_lats|poly_vertices_lons - String line = br.readLine(); - while ((line = br.readLine()) != null) { - String[] junctionLineArray = line.split("\\|",-1); - String id = junctionLineArray[0].split(" ,")[0] + ".0"; - String[] latsAsStrings = junctionLineArray[1].split(", "); - double[] lats = convertStringArrayToDoubleArray(latsAsStrings); - String[] lonsAsStrings = junctionLineArray[2].split(", "); - double[] lons = convertStringArrayToDoubleArray(lonsAsStrings); - String[] highwayNamesArray = junctionLineArray[4] - .replace("[","") - .replace("]","") - .replaceAll("'","") - .replaceAll("\"","") - .split(", "); - HashSet highWayNamesHashSet = new HashSet<>(Arrays.asList(highwayNamesArray)); - String[] highWayTypesArray = junctionLineArray[5] - .replaceAll("\"","") - .replace("[","") - .replace("]","") - .replaceAll("'","") - .split(", "); - String[] highWayLanesStrings = junctionLineArray[6] - .replaceAll("\"","") - .replaceAll(", ",",") // might work - .replace("[","") - .replace("]","") - .replaceAll("'","") - .split(","); - //.split(",/s|,"); - double[] highWayLanesArray = new double[highWayLanesStrings.length]; - for (int i = 0; i < highWayLanesStrings.length; i++) { - if(highWayLanesStrings[i].equals("unknown")) { - highWayLanesArray[i] = -1; - } else { - highWayLanesArray[i] = Double.valueOf(highWayLanesStrings[i]); - } - } - String[] lanes_bwStrings = junctionLineArray[7] - .replaceAll("\"","") - .replace("[","") - .replace("]","") - .replaceAll("'","") - .split(", "); - double[] lanes_bwArray = new double[lanes_bwStrings.length]; - for (int i = 0; i < lanes_bwStrings.length; i++) { - if(lanes_bwStrings[i].equals("unknown")) { - lanes_bwArray[i] = -1.0; - } else { - lanes_bwArray[i] = Double.valueOf(lanes_bwStrings[i]); + File jsonDetailFile = cla.getJsonDetailOutputFile(); + JSONParser parser = new JSONParser(); + // read the streets and put the into segmentMap + if(jsonDetailFile.exists()){ + try(FileReader reader = new FileReader(jsonDetailFile)){ + Object obj = parser.parse(reader); + JSONObject jsonObject = (JSONObject) obj; + JSONArray features = (JSONArray) jsonObject.get("features"); + + for(Object featureObj : features) { + JSONObject feature = (JSONObject) featureObj; + JSONObject properties = (JSONObject) feature.get("properties"); + + String type = (String) properties.get("type"); // the type of each segment: Junction or Street + String id = (String) feature.get("id"); // the id of each segment + if ("Hexagon".equalsIgnoreCase(type)) { + double[] lats = convertJSONArrayToDoubleArray((JSONArray) properties.get("lats")); + double[] lons = convertJSONArrayToDoubleArray((JSONArray) properties.get("lons")); + double[] polyLats = convertJSONArrayToDoubleArray((JSONArray) properties.get("poly lats")); + double[] polyLons = convertJSONArrayToDoubleArray((JSONArray) properties.get("poly lons")); + + Hexagon hexagon = new Hexagon(id, lats, lons, polyLats, polyLons); + segmentMap.put(hexagon.id, hexagon); + raster.putSubscriptionIdIntoRasterEntries(hexagon.geofence, new ImmutablePair<>("", hexagon.id)); } } - String[] polyLatsStrings = junctionLineArray[9] - .replace("[","") - .replace("]","") - .replace("array('d', ", "") - .replace(")","") - .split(", "); - double[] polyLatsArray = convertStringArrayToDoubleArray(polyLatsStrings); - String[] polyLonsStrings = junctionLineArray[10] - .replace("[","") - .replace("]","") - .replace("array('d', ", "") - .replace(")","") - .split(", "); - double[] polyLonsArray = convertStringArrayToDoubleArray(polyLonsStrings); - Junction junction = new Junction(id,lats,lons,highWayNamesHashSet,highWayTypesArray,highWayLanesArray,lanes_bwArray,polyLatsArray,polyLonsArray); - int segment_nr = 0; - while (segmentMap.containsKey(id)) { - segment_nr++; - id = id.split("\\.")[0] + "." + segment_nr; - } - segmentMap.put(id, junction); - raster.putSubscriptionIdIntoRasterEntries(junction.geofence, new ImmutablePair<>("", id)); + }catch (Exception e){ + e.printStackTrace(); } - } catch (IOException e) { - e.printStackTrace(); } - logger.info("SegmentMap size after adding junctions: " + segmentMap.size()); - // read the streets and put the into segmentMap - logger.info("Importing street segments from: " + cla.getOsmSegmentsFile().getAbsolutePath()); - file = cla.getOsmSegmentsFile(); - try (BufferedReader br = new BufferedReader(new FileReader(file))) { - // Skip header id|lats|lons|highwayName|highwaytype|highwaylanes|poly_vertices_lats|poly_vertices_lons - String line = br.readLine(); - while ((line = br.readLine()) != null) { - try { - String[] streetsLineArray = line.replaceAll(" \\| "," \\ ").split("\\|",-1); - String id = streetsLineArray[1] + ".0"; - String highwayname = streetsLineArray[2].split(",",-1)[0].replaceAll("\"",""); - String[] highWayTypesArray = {streetsLineArray[3]}; - double highwaylanes = -1; - if (streetsLineArray[4].length()==1) { - highwaylanes = Double.valueOf(streetsLineArray[4]); - } else if (streetsLineArray[4].length()>1 && !streetsLineArray[4].contains("u") && !streetsLineArray[4].contains("p")) { - highwaylanes = Double.valueOf(streetsLineArray[4].split(",")[0]); - } + else { + List> hexagonGrid = createHexagons(minX, minY, maxX, maxY); + for (List shape : hexagonGrid) { + List latsArray = new ArrayList<>(); + List lonsArray = new ArrayList<>(); - String[] lanes_BackwardStrings = streetsLineArray[5] - .replace("unknown","") - .replace("[","") - .replace("}","") - .split(", ",-1); - double[] lanes_Backward = new double[lanes_BackwardStrings.length]; - for (int i = 0; i < lanes_BackwardStrings.length; i++) { - if (lanes_BackwardStrings[i].length()>0) { - lanes_Backward[i] = Double.valueOf(lanes_BackwardStrings[i]); - } - } - if (lanes_Backward.length<1) { - lanes_Backward = new double[1]; - lanes_Backward[0] = -1; - } - String[] segment_nodesStrings = streetsLineArray[6] - .replace("[","") - .replace("]","") - .split(", "); - - double seg_length = Double.valueOf(streetsLineArray[7]); - String[] poly_vertices_latsStrings = streetsLineArray[9] - .replace("[","") - .replace("]","") - .split(", "); - double[] poly_vertices_latsArray = convertStringArrayToDoubleArray(poly_vertices_latsStrings); - String[] poly_vertices_lonsStrings = streetsLineArray[10] - .replace("[","") - .replace("]","") - .split(", "); - double[] poly_vertices_lonsArray = convertStringArrayToDoubleArray(poly_vertices_lonsStrings); - Street streetSegment = new Street(id, highwayname, highWayTypesArray, highwaylanes, lanes_Backward, segment_nodesStrings, seg_length, poly_vertices_latsArray, poly_vertices_lonsArray); - - // linkStreetSegmentToJunction(streetSegment,(HashMap)segmentMap); - int segment_nr = 0; - while (segmentMap.containsKey(id)) { - segment_nr++; - id = id.split("\\.")[0] + "." + segment_nr; - } - segmentMap.put(id, streetSegment); - raster.putSubscriptionIdIntoRasterEntries(streetSegment.geofence, new ImmutablePair<>("", id)); - } catch (InvalidShapeException e) { - e.getLocalizedMessage(); + for (Point2D.Double point : shape) { + latsArray.add(point.getY()); + lonsArray.add(point.getX()); } + double[] polyLats = latsArray.stream().mapToDouble(Double::doubleValue).toArray(); + logger.debug("LATS: " + Arrays.toString(polyLats)); + double[] polyLons = lonsArray.stream().mapToDouble(Double::doubleValue).toArray(); + logger.debug("LONS: " + Arrays.toString(polyLons)); + String uniqueID = UUID.randomUUID().toString(); + Hexagon hexagon = new Hexagon(uniqueID, polyLats, polyLons, polyLats, polyLons); + logger.debug(hexagon.geofence); + segmentMap.put(uniqueID, hexagon); + raster.putSubscriptionIdIntoRasterEntries(hexagon.geofence, new ImmutablePair<>("", uniqueID)); + System.exit(-1); } - } catch (IOException e) { - e.printStackTrace(); } + + logger.info("SegmentMap size after adding hexagons: " + segmentMap.size()); + return (HashMap)segmentMap; } + private static List> createHexagons(double minX, double minY, double maxX, double maxY) { + List> hexagonGrid = new ArrayList<>(); + + double width = maxX - minX; + double height = maxY - minY; + + double hexagonSize = 0.03; + double hDist = hexagonSize * Math.sqrt(3.0); + double vDist = 3.0 * hexagonSize / 2.0; + + int numHorHexagon = (int) Math.floor(width / hDist); + int numVerHexagon = (int) Math.floor(height / vDist); + + double startX = minX + (width - numHorHexagon * hDist) / 2.0; + double startY = minY + (height - numVerHexagon * vDist) / 2.0; + + for (int row = 0; row < numVerHexagon; row++) { + for (int col = 0; col < numHorHexagon; col++) { + double offsetX = (row % 2 == 0) ? 0.0 : hDist / 2.0; + double hexagonX = startX + col * hDist + offsetX; + double hexagonY = startY + row * vDist; + + // Check if the hexagon extends beyond the bounding box + if (hexagonX + hexagonSize > maxX || hexagonY + hexagonSize > maxY) { + continue; // Skip this hexagon as it is outside the bounding box + } + + List vertices = calculateHexagonVertices(hexagonX, hexagonY, hexagonSize); + hexagonGrid.add(vertices); + } + } + + return hexagonGrid; + } private static double[] convertStringArrayToDoubleArray(String[] inputArray) { @@ -183,7 +176,7 @@ private static double[] convertStringArrayToDoubleArray(String[] inputArray) { return result; } - private static void linkStreetSegmentToJunction(Street thisStreetSegment, HashMap segmentMap) { + private static void linkStreetSegmentToJunction(Street thisStreetSegment,HashMap segmentMap) { for (Map.Entry segmentEntry : segmentMap.entrySet()) { String entryId = (String) ((Map.Entry) segmentEntry).getKey(); @@ -204,4 +197,66 @@ private static void linkStreetSegmentToJunction(Street thisStreetSegment, HashMa } } } + private static double[] convertJSONArrayToDoubleArray(JSONArray jsonArray){ + double[] array = new double[jsonArray.size()]; + for(int i=0; i createHexagonalGrid(double[] box){ + List hexagons = new ArrayList<>(); + CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84; + ReferencedEnvelope gridBounds = new ReferencedEnvelope(box[1], box[0], box[3], box[2], sourceCRS); + double sideLen = 5.0; + GridFeatureBuilder builder = new DefaultGridFeatureBuilder(); + SimpleFeatureSource grid = Hexagons.createGrid(gridBounds, sideLen, HexagonOrientation.ANGLED, builder); + try{ + SimpleFeatureCollection collection = grid.getFeatures(); + FeatureIterator iterator = collection.features(); + while (iterator.hasNext()){ + Feature feature = iterator.next(); + SimpleFeature sFeature = (SimpleFeature) feature; + //logger.debug(sFeature.getAttribute(0)); + Geometry geometry = (Geometry) sFeature.getAttribute(0); + hexagons.add(geometry); +// Coordinate[] coordinates = geofence.getCoordinates(); +// logger.debug(Arrays.toString(coordinates)); + /* String uniqueID = UUID.randomUUID().toString(); + raster.putSubscriptionIdIntoRasterEntries(geofence, new ImmutablePair<>("", uniqueID));*/ + } + + } catch(Exception e){ + e.printStackTrace(); + } + return hexagons; + } + //also need to calculate centre? + public static List calculateHexagonVertices(double centerX, double centerY, double size) { + List vertices = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + double angle = 2.0 * Math.PI / 6.0 * (i + 0.5); + double x = centerX + size * Math.cos(angle); + double y = centerY + size * Math.sin(angle); + vertices.add(new Point2D.Double(x, y)); + } + return vertices; + } + } diff --git a/src/main/java/Graph/SegmentMapper.java b/src/main/java/Graph/SegmentMapper.java index 32d3e21..b1e36dd 100644 --- a/src/main/java/Graph/SegmentMapper.java +++ b/src/main/java/Graph/SegmentMapper.java @@ -3,6 +3,7 @@ import Rides.Incident; import Rides.Ride; import Rides.RideBucket; +import Segments.Hexagon; import Segments.Junction; import Segments.Segment; import Segments.Street; @@ -38,11 +39,16 @@ public class SegmentMapper { private static Logger logger = LogManager.getLogger(); static List mostDangerousJunctions = new ArrayList<>(); + static List mostDangerousHexagons = new ArrayList<>(); static List mostDangerousStreetsSouthWest = new ArrayList<>(); static List mostDangerousStreetsNorthEast = new ArrayList<>(); static int numberOfRelevantSegments = 0; static HashMap recentStatsMap = new HashMap<>(); // holds the values of the number of recent rides, incidents, and segments static HashMap prevStatsMap = new HashMap<>(); // holds the values of the number of previous rides, incidents, and segments + // These Lists contain the previous junctions and street read from the json file + static List oldHexagonList = new ArrayList<>(); + static List oldJunctionsList = new ArrayList<>(); + static List oldStreetList = new ArrayList<>(); public static void doSegmentMapping(CommandLineArguments cla) { // Creating the Geobroker Raster. See the documentation of the Geobroker: https://github.com/MoeweX/geobroker @@ -56,11 +62,7 @@ public static void doSegmentMapping(CommandLineArguments cla) { // dangerousness score. List recentStreetList = new ArrayList<>(); List recentJunctionList = new ArrayList<>(); - - // These Lists contain the previous junctions and street read from the json file - List oldJunctionsList = new ArrayList<>(); - List oldStreetList = new ArrayList<>(); - + List recentHexagonList = new ArrayList<>(); // Contains the ride files of specified region. List rideFolder = getRidesOfRegionAndUNKNOWN(cla.getSimraRoot(), cla.getRegion()); @@ -77,7 +79,7 @@ public static void doSegmentMapping(CommandLineArguments cla) { getPrevStats(cla); for (int i = 0; i < rideFolder.size(); i++) { Path ridePath = rideFolder.get(i).toPath(); - /*the creation date of each ride file is read and compared to the timestamp*/ +// the creation date of each ride file is read and compared to the timestamp LocalDateTime creationDateTime = null; try{ BasicFileAttributes fileAttr = Files.readAttributes(ridePath, BasicFileAttributes.class); @@ -85,7 +87,7 @@ public static void doSegmentMapping(CommandLineArguments cla) { } catch (Exception e){ e.printStackTrace(); } - /*if the the creation date is before the timestamp, continue to the next ride file*/ +// if the creation date is before the timestamp, continue to the next ride file if (date != null && creationDateTime.compareTo(date) < 0) { continue; } @@ -126,12 +128,12 @@ public static void doSegmentMapping(CommandLineArguments cla) { File file = cla.getJsonDetailOutputFile(); if (file.exists()) { - getElements(oldJunctionsList, oldStreetList, file); // gets the previous details of the junctions and street + getElements(file); // gets the previous details of the junctions and street // looping through each old junctions and street, matching the id to the id(s) of the new segments // the number of rides and incidents are added together // the scores will be recalculated - for (Junction j : oldJunctionsList) { + /*for (Junction j : oldJunctionsList) { if (segmentMap.containsKey(j.id)) { Segment segment = segmentMap.get(j.id); Junction junction = (Junction) segment; @@ -173,6 +175,27 @@ public static void doSegmentMapping(CommandLineArguments cla) { } else { segmentMap.put(s.id, s); } + }*/ + for (Hexagon h : oldHexagonList) { + if (segmentMap.containsKey(h.id)) { + Segment segment = segmentMap.get(h.id); + Hexagon hexagon = (Hexagon) segment; + hexagon.numberOfRides += h.numberOfRides; + hexagon.numberOfNonScaryIncidents += h.numberOfNonScaryIncidents; + hexagon.numberOfScaryIncidents += h.numberOfScaryIncidents; + hexagon.numberOfIncidents += h.numberOfIncidents; + hexagon.clopa += h.clopa; + hexagon.spiot += h.spiot; + hexagon.nlorh += h.nlorh; + hexagon.ssho += h.ssho; + hexagon.tailgating += h.tailgating; + hexagon.near_dooring += h.near_dooring; + hexagon.dao += h.dao; + hexagon.other += h.other; + + } else { + segmentMap.put(h.id, h); + } } } @@ -183,7 +206,7 @@ public static void doSegmentMapping(CommandLineArguments cla) { if (hasRide(segment)) { numberOfSegmentsWithRides++; } - if (segment instanceof Junction) { + /*if (segment instanceof Junction) { Junction junction = (Junction) segment; if (mostDangerousJunctions.size() < 3) { mostDangerousJunctions.add(junction); @@ -204,7 +227,28 @@ public static void doSegmentMapping(CommandLineArguments cla) { } } recentJunctionList.add(junction); - } else { + } else*/ if (segment instanceof Hexagon) { + Hexagon hexagon = (Hexagon) segment; + if (mostDangerousHexagons.size() < 3) { + mostDangerousHexagons.add(hexagon); + mostDangerousHexagons.add(hexagon); + mostDangerousHexagons.add(hexagon); + } + hexagon.dangerousnessScore = ((cla.getScarinessFactor() * hexagon.numberOfScaryIncidents + hexagon.numberOfNonScaryIncidents) / + hexagon.numberOfRides); + for (int j = 0; j < 3; j++) { + Hexagon thisHexagon = mostDangerousHexagons.get(j); + if (hexagon.dangerousnessScore > thisHexagon.dangerousnessScore) { + Hexagon tempHexagon = mostDangerousHexagons.get(j); + mostDangerousHexagons.set(j, hexagon); + if (j < 2) { + mostDangerousHexagons.set(j + 1, tempHexagon); + } + break; + } + } + recentHexagonList.add(hexagon); + } /*else { Street street = (Street) segment; if (mostDangerousStreetsSouthWest.size() < 3) { mostDangerousStreetsSouthWest.add(street); @@ -217,12 +261,12 @@ public static void doSegmentMapping(CommandLineArguments cla) { mostDangerousStreetsNorthEast.add(street); } street.scoreSouthWest = (((cla.getScarinessFactor() * street.numberOfScaryIncidentsSouthWest + street.numberOfNonScaryIncidentsSouthWest) / - street.numberOfRidesSouthWest)/*/street.seg_length)*10000*/); + street.numberOfRidesSouthWest)*//*//*street.seg_length)*10000*//*); street.scoreNorthEast = (((cla.getScarinessFactor() * street.numberOfScaryIncidentsNorthEast + street.numberOfNonScaryIncidentsNorthEast) / - street.numberOfRidesNorthEast)/*/street.seg_length)*10000*/); + street.numberOfRidesNorthEast)*//*//*street.seg_length)*10000*//*); street.score = (((cla.getScarinessFactor() * (street.numberOfScaryIncidentsSouthWest + street.numberOfScaryIncidentsNorthEast) + (street.numberOfNonScaryIncidentsSouthWest + street.numberOfNonScaryIncidentsNorthEast)) / - (street.numberOfRidesSouthWest + street.numberOfRidesNorthEast))/*/street.seg_length)*10000*/); + (street.numberOfRidesSouthWest + street.numberOfRidesNorthEast))*//*//*street.seg_length)*10000*//*); for (int j = 0; j < 3; j++) { Street thisStreetSouthWest = mostDangerousStreetsSouthWest.get(j); if (street.scoreSouthWest > thisStreetSouthWest.scoreSouthWest) { @@ -246,7 +290,7 @@ public static void doSegmentMapping(CommandLineArguments cla) { } } recentStreetList.add(street); - } + }*/ added = addSegmentToGeoJson(segment, geoJSONContent, cla); bool = addSegmentToDetailJson(segment, detailJSONContent, cla); @@ -367,7 +411,7 @@ private static String[] strArray(JSONArray jsonArray){ * Creates new Junction and Street objects for each element * Puts each Junction and Street into respective Lists * */ - private static void getElements(List oldJunctionsList, List oldStreetList, File file){ + private static void getElements(File file){ JSONParser parser = new JSONParser(); if (file.exists()){ @@ -411,7 +455,7 @@ private static void getElements(List oldJunctionsList, List ol oldJunctionsList.add(junction); // add Junction object into the List } - if ("Street".equalsIgnoreCase(type)){ + else if ("Street".equalsIgnoreCase(type)){ // gets the object to pass as arguments needed to create a Street object String highWayName = (String) properties.get("highway names"); String[] highWayTypes = strArray((JSONArray) properties.get("highway types")); @@ -445,6 +489,27 @@ private static void getElements(List oldJunctionsList, List ol street.other = ((Long) properties.get("other")).intValue(); oldStreetList.add(street); // add Street object into List + } else if ("Hexagon".equalsIgnoreCase(type)) { + double[] lats = doubleArray((JSONArray) properties.get("lats")); + double[] lons = doubleArray((JSONArray) properties.get("lons")); + double[] polyLats = doubleArray((JSONArray) properties.get("poly lats")); + double[] polyLons = doubleArray((JSONArray) properties.get("poly lons")); + + Hexagon hexagon = new Hexagon(id,lats,lons,polyLats,polyLons); + hexagon.numberOfRides = ((Long) properties.get("rides")).intValue(); + hexagon.numberOfIncidents = ((Long) properties.get("incidents")).intValue(); + hexagon.numberOfScaryIncidents = ((Long) properties.get("scary incidents")).intValue(); + hexagon.numberOfNonScaryIncidents = ((Long) properties.get("non-scary incidents")).intValue(); + hexagon.clopa = ((Long) properties.get("clopa")).intValue(); + hexagon.spiot = ((Long) properties.get("spiot")).intValue(); + hexagon.nlorh = ((Long) properties.get("nlorh")).intValue(); + hexagon.ssho = ((Long) properties.get("ssho")).intValue(); + hexagon.tailgating = ((Long) properties.get("tailgating")).intValue(); + hexagon.near_dooring = ((Long) properties.get("near-dooring")).intValue(); + hexagon.dao = ((Long) properties.get("dao")).intValue(); + hexagon.other = ((Long) properties.get("other")).intValue(); + + oldHexagonList.add(hexagon); // add Hexagon object into the List } } @@ -542,6 +607,13 @@ public static boolean isRelevant(Segment segment, CommandLineArguments cla) { boolean score = (junction.getScore() >= cla.getRelevanceThresholdScore()) && (junction.numberOfRides >= cla.getRelevanceThresholdScoreRideCount()); + return rides || score; + } else if (segment instanceof Hexagon) { + Hexagon hexagon = (Hexagon) segment; + boolean rides = hexagon.numberOfRides >= cla.getRelevanceThresholdRideCount(); + boolean score = (hexagon.getScore() >= cla.getRelevanceThresholdScore()) && + (hexagon.numberOfRides >= cla.getRelevanceThresholdScoreRideCount()); + return rides || score; } else { Street street = (Street) segment; diff --git a/src/main/java/Rides/Ride.java b/src/main/java/Rides/Ride.java index 470c06c..d069f43 100644 --- a/src/main/java/Rides/Ride.java +++ b/src/main/java/Rides/Ride.java @@ -1,5 +1,6 @@ package Rides; +import Segments.Hexagon; import Segments.Junction; import Segments.Segment; import Segments.Street; @@ -176,6 +177,25 @@ private void updateSegmentStatistics(RideBucket rideBucket, ArrayList System.exit(1); } } + } else if (rideBucket.segment instanceof Hexagon) { + ((Hexagon)rideBucket.segment).numberOfRides++; + ((Hexagon)rideBucket.segment).numberOfIncidents += incidentsOfOneSegment.size(); + for (int i = 0; i < incidentsOfOneSegment.size(); i++) { + Incident thisIncident = incidentsOfOneSegment.get(i); + rideBucket.segment.incidents.add(thisIncident); + try { + if (thisIncident.scary) { + ((Hexagon)rideBucket.segment).scaryIncidentTypes.merge(String.valueOf(thisIncident.incident),1,Integer::sum); + ((Hexagon)rideBucket.segment).numberOfScaryIncidents++; + } else { + ((Hexagon)rideBucket.segment).nonScaryIncidentTypes.merge(String.valueOf(thisIncident.incident),1,Integer::sum); + ((Hexagon)rideBucket.segment).numberOfNonScaryIncidents++; + } + } catch (ArrayIndexOutOfBoundsException | NullPointerException aioobe) { + aioobe.printStackTrace(); + System.exit(1); + } + } } else { if (!rideBucketsOfOneSegment.isEmpty()) { if (towardsSouthWest > 0) { diff --git a/src/main/java/Rides/RideBucket.java b/src/main/java/Rides/RideBucket.java index 239e69d..68ec182 100644 --- a/src/main/java/Rides/RideBucket.java +++ b/src/main/java/Rides/RideBucket.java @@ -1,5 +1,6 @@ package Rides; +import Segments.Hexagon; import Segments.Junction; import Segments.Segment; import Segments.Street; @@ -46,6 +47,8 @@ private Segment findSegment(HashMap segmentMap, Raster raster, double distanceToNearestJunction = Double.MAX_VALUE; Street nearestStreet = null; double distanceToNearestStreet = Double.MAX_VALUE; + Hexagon nearestHexagon = null; + double distanceToNearestHexagon = Double.MAX_VALUE; Location location = new Location(lat, lon); // contains all segments that are near the RideBucket List> segmentCandidates = raster.getSubscriptionIdsInRasterEntryForPublisherLocation(location); @@ -70,16 +73,24 @@ private Segment findSegment(HashMap segmentMap, Raster raster, distanceToNearestStreet = distance; } + } else if (actualSegment instanceof Hexagon && distance <= distanceToNearestHexagon) { + if (distance <= MATCH_THRESHOLD) { + nearestHexagon = (Hexagon) actualSegment; + distanceToNearestHexagon = distance; + } } } - if (nearestJunction == null && nearestStreet == null && segmentCandidates.size() > 0) { + if (nearestJunction == null && nearestStreet == null && nearestHexagon == null && segmentCandidates.size() > 0) { matchedToSegment = false; } // return nearest segment - if (distanceToNearestJunction <= distanceToNearestStreet) { + if (distanceToNearestJunction <= distanceToNearestStreet && distanceToNearestJunction <= distanceToNearestHexagon) { return nearestJunction; - } else { + } else if (distanceToNearestHexagon <= distanceToNearestStreet && distanceToNearestHexagon <= distanceToNearestJunction) { + return nearestHexagon; + } + else { return nearestStreet; } } @@ -87,10 +98,11 @@ private Segment findSegment(HashMap segmentMap, Raster raster, private double calculateDistanceFromPointToPolygon(Segment actualSegment, double lat, double lon) { double[] polyLats = actualSegment.poly_vertices_latsArray; double[] polyLons = actualSegment.poly_vertices_lonsArray; - Coordinate[] polygonCoordinates = new Coordinate[polyLats.length]; + Coordinate[] polygonCoordinates = new Coordinate[polyLats.length+1]; for (int j = 0; j < polyLats.length; j++) { polygonCoordinates[j] = new Coordinate(polyLats[j], polyLons[j]); } + polygonCoordinates[polyLats.length] = polygonCoordinates[0]; Polygon polygon = new GeometryFactory().createPolygon(polygonCoordinates); Point point = new GeometryFactory().createPoint(new Coordinate(lat, lon)); DistanceOp distanceOp = new DistanceOp(polygon, point); diff --git a/src/main/java/Segments/Hexagon.java b/src/main/java/Segments/Hexagon.java new file mode 100644 index 0000000..73b82c9 --- /dev/null +++ b/src/main/java/Segments/Hexagon.java @@ -0,0 +1,157 @@ +package Segments; + +import geobroker.Geofence; +import geobroker.Location; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class Hexagon extends Segment implements Comparable{ + public int numberOfRides, numberOfIncidents, numberOfScaryIncidents, numberOfNonScaryIncidents; + public int clopa, spiot, nlorh, ssho, tailgating, near_dooring, dao, other; + public HashMap scaryIncidentTypes, nonScaryIncidentTypes = new HashMap<>(); + public double dangerousnessScore; + + + public Hexagon(String id, double[] lats, double[] lons, double[] polyLats, double[] polyLons) { + this.id = id; + this.lats = lats; + this.lons = lons; + this.poly_vertices_latsArray = polyLats; + this.poly_vertices_lonsArray = polyLons; + List locations = new ArrayList<>(); + for (int i = 0; i < polyLats.length-1; i++) { + locations.add(new Location(polyLats[i],polyLons[i])); + } + this.geofence = Geofence.Companion.polygon(locations); + scaryIncidentTypes = new HashMap<>(); + scaryIncidentTypes.put("-2",0); + scaryIncidentTypes.put("1",0); + scaryIncidentTypes.put("2",0); + scaryIncidentTypes.put("3",0); + scaryIncidentTypes.put("4",0); + scaryIncidentTypes.put("5",0); + scaryIncidentTypes.put("6",0); + scaryIncidentTypes.put("7",0); + scaryIncidentTypes.put("8",0); + nonScaryIncidentTypes = new HashMap<>(); + nonScaryIncidentTypes.put("-2",0); + nonScaryIncidentTypes.put("1",0); + nonScaryIncidentTypes.put("2",0); + nonScaryIncidentTypes.put("3",0); + nonScaryIncidentTypes.put("4",0); + nonScaryIncidentTypes.put("5",0); + nonScaryIncidentTypes.put("6",0); + nonScaryIncidentTypes.put("7",0); + nonScaryIncidentTypes.put("8",0); + } + + public Double getScore() { + if (String.valueOf(this.dangerousnessScore).equals("NaN")) { + return -1.0; + } else { + return this.dangerousnessScore; + } + } + + public String toString() { + StringBuilder result = new StringBuilder(); + + result.append("HEXAGON:"); + result.append("|score:").append(dangerousnessScore); + result.append("|id:").append(id); + result.append("|coordinates:["); + for (int i = 0; i < lats.length; i++) { + result.append(lats[i]).append(",").append(lons[i]).append(" "); + } + result.append(lats[lats.length-1]).append(",").append((lons[lons.length-1])).append("]"); + result.append(super.toString()); + return result.toString(); + } + + public void appendFeatures(StringBuilder result){ + result.append("{\"type\":\"Feature\",\"id\":\"").append(id) + .append("\",\"properties\":{\"type\":\"Hexagon\",") + .append("\n\"score\":").append(getScore()) + .append(",\n\"incidents\":").append((numberOfNonScaryIncidents + numberOfScaryIncidents)) + .append(",\n\"scary incidents\":").append((numberOfScaryIncidents)) + .append(",\n\"non-scary incidents\":").append((numberOfNonScaryIncidents)) + .append(",\n\"rides\":").append(numberOfRides) + .append(",\n\"clopa\":").append((nonScaryIncidentTypes.get("-2") + scaryIncidentTypes.get("-2") + nonScaryIncidentTypes.get("1") + scaryIncidentTypes.get("1") + clopa)) + .append(",\n\"spiot\":").append((nonScaryIncidentTypes.get("2") + scaryIncidentTypes.get("2")+spiot)) + .append(",\n\"nlorh\":").append((nonScaryIncidentTypes.get("3") + scaryIncidentTypes.get("3")+nlorh)) + .append(",\n\"ssho\":").append((nonScaryIncidentTypes.get("4") + scaryIncidentTypes.get("4")+ssho)) + .append(",\n\"tailgating\":").append((nonScaryIncidentTypes.get("5") + scaryIncidentTypes.get("5")+tailgating)) + .append(",\n\"near-dooring\":").append((nonScaryIncidentTypes.get("6") + scaryIncidentTypes.get("6")+near_dooring)) + .append(",\n\"dao\":").append((nonScaryIncidentTypes.get("7") + scaryIncidentTypes.get("7")+dao)) + .append(",\n\"other\":").append((nonScaryIncidentTypes.get("8") + scaryIncidentTypes.get("8")+other)); + } + public String detailJson() { + StringBuilder result = new StringBuilder(); + appendFeatures(result); + //Lats + result.append(",\n\"lats\":["); + for (int i = 0; i < lats.length; i++){ + result.append(lats[i]); + if (i != lats.length - 1){ + result.append(","); + } + } + result.append("]"); + //Lons + result.append(",\n\"lons\":["); + for (int i = 0; i < lons.length; i++){ + result.append(lons[i]); + if (i != lons.length - 1){ + result.append(","); + } + } + result.append("]"); + + //Poly_lats + result.append(",\n\"poly lats\":["); + for (int i = 0; i < poly_vertices_latsArray.length; i++){ + result.append(poly_vertices_latsArray[i]); + if (i != poly_vertices_latsArray.length - 1){ + result.append(","); + } + } + result.append("]"); + //Poly lons + result.append(",\n\"poly lons\":["); + for (int i = 0; i < poly_vertices_lonsArray.length; i++){ + result.append(poly_vertices_lonsArray[i]); + if (i != poly_vertices_lonsArray.length - 1){ + result.append(","); + } + } + result.append("]"); + result.append(super.toGeoJson()); + result.append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); + for (int i = 0; i < poly_vertices_latsArray.length-1; i++) { + result.append("[").append(poly_vertices_lonsArray[i]).append(",").append(poly_vertices_latsArray[i]).append("],"); + } + result.append("[").append(poly_vertices_lonsArray[poly_vertices_lonsArray.length-1]).append(",").append(poly_vertices_latsArray[poly_vertices_latsArray.length-1]).append("]]]}}"); + return result.toString(); + } + public String toGeoJson() { + StringBuilder result = new StringBuilder(); + appendFeatures(result); + result.append(super.toGeoJson()) + .append("},\n\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[["); + + for (int i = 0; i < poly_vertices_latsArray.length-1; i++) { + result.append("[").append(poly_vertices_lonsArray[i]).append(",").append(poly_vertices_latsArray[i]).append("],"); + } + result.append("[").append(poly_vertices_lonsArray[poly_vertices_lonsArray.length-1]).append(",").append(poly_vertices_latsArray[poly_vertices_latsArray.length-1]).append("]]]}}"); + + return result.toString(); + } + + @Override + public int compareTo(@NotNull Hexagon o) { + return this.getScore().compareTo(o.getScore()); + } +} diff --git a/src/main/java/Segments/Junction.java b/src/main/java/Segments/Junction.java index 028571d..cbe7fc2 100644 --- a/src/main/java/Segments/Junction.java +++ b/src/main/java/Segments/Junction.java @@ -77,7 +77,6 @@ public String toString() { return result.toString(); } - @Override public int compareTo(@NotNull Junction o) { return this.getScore().compareTo(o.getScore()); From dd3c66ea649b237de90a1da202c26b12ea15573d Mon Sep 17 00:00:00 2001 From: anterakotoarison <113263127+anterakotoarison@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:53:39 +0200 Subject: [PATCH 3/3] epsg:3857 --- pom.xml | 5 ++ src/main/java/Graph/SegmentImporter.java | 76 ++++++++++-------------- src/main/java/Graph/SegmentMapper.java | 4 +- src/main/java/Rides/RideBucket.java | 6 +- src/main/java/Segments/Hexagon.java | 2 +- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index fe7e0db..5a7421f 100644 --- a/pom.xml +++ b/pom.xml @@ -94,6 +94,11 @@ gt-grid ${geotools.version} + + org.geotools + gt-epsg-hsql + ${geotools.version} + diff --git a/src/main/java/Graph/SegmentImporter.java b/src/main/java/Graph/SegmentImporter.java index fa39f88..8d7fd45 100644 --- a/src/main/java/Graph/SegmentImporter.java +++ b/src/main/java/Graph/SegmentImporter.java @@ -18,6 +18,7 @@ import org.geotools.grid.GridFeatureBuilder; import org.geotools.grid.hexagon.HexagonOrientation; import org.geotools.grid.hexagon.Hexagons; +import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -41,35 +42,9 @@ public static HashMap importSegments(Raster raster, CommandLineA // getting the bounding box coordinates to know the size of hexagon grid File osmMetaFile = cla.getOsmMetaFile(); double[] bounding_box = getBoundingBox(osmMetaFile); - double minX = bounding_box[0]; - double minY = bounding_box[1]; - double maxX = bounding_box[2]; - double maxY = bounding_box[3]; // test - List hexagons = createHexagonalGrid(bounding_box); // new function to create a hexagon grid - for(Geometry g : hexagons){ - Coordinate[] vertices = g.getCoordinates(); - List latsArray = new ArrayList<>(); - List lonsArray = new ArrayList<>(); - for (Coordinate point : vertices){ - latsArray.add(point.getX()); - lonsArray.add(point.getY()); - } - double[] polyLats = latsArray.stream().mapToDouble(Double::doubleValue).toArray(); - logger.debug("LATS: " + Arrays.toString(polyLats)); - double[] polyLons = lonsArray.stream().mapToDouble(Double::doubleValue).toArray(); - logger.debug("LONS: " + Arrays.toString(polyLons)); - String uniqueID = UUID.randomUUID().toString(); - Hexagon hexagon = new Hexagon(uniqueID, polyLats, polyLons, polyLats, polyLons); - logger.debug(hexagon.geofence); - segmentMap.put(uniqueID, hexagon); - logger.debug("putting in raster..."); - // everything works until here idk y - raster.putSubscriptionIdIntoRasterEntries(hexagon.geofence, new ImmutablePair<>("", uniqueID)); // this seems to be create a problem that idk - logger.debug("done"); - System.exit(-1); - } + // end of test // read the junctions and put the into segmentMap @@ -104,7 +79,7 @@ public static HashMap importSegments(Raster raster, CommandLineA } } else { - List> hexagonGrid = createHexagons(minX, minY, maxX, maxY); + /*List> hexagonGrid = createHexagons(bounding_box); for (List shape : hexagonGrid) { List latsArray = new ArrayList<>(); List lonsArray = new ArrayList<>(); @@ -114,15 +89,29 @@ public static HashMap importSegments(Raster raster, CommandLineA lonsArray.add(point.getX()); } double[] polyLats = latsArray.stream().mapToDouble(Double::doubleValue).toArray(); - logger.debug("LATS: " + Arrays.toString(polyLats)); double[] polyLons = lonsArray.stream().mapToDouble(Double::doubleValue).toArray(); - logger.debug("LONS: " + Arrays.toString(polyLons)); String uniqueID = UUID.randomUUID().toString(); Hexagon hexagon = new Hexagon(uniqueID, polyLats, polyLons, polyLats, polyLons); - logger.debug(hexagon.geofence); segmentMap.put(uniqueID, hexagon); raster.putSubscriptionIdIntoRasterEntries(hexagon.geofence, new ImmutablePair<>("", uniqueID)); - System.exit(-1); + }*/ + List hexagons = createHexagonalGrid(bounding_box); // new function to create a hexagon grid + for(Geometry g : hexagons){ + Coordinate[] vertices = g.getCoordinates(); + List latsArray = new ArrayList<>(); + List lonsArray = new ArrayList<>(); + for (Coordinate point : vertices){ + latsArray.add(point.getX()); + lonsArray.add(point.getY()); + } + double[] polyLats = latsArray.stream().mapToDouble(Double::doubleValue).toArray(); + double[] polyLons = lonsArray.stream().mapToDouble(Double::doubleValue).toArray(); + String uniqueID = UUID.randomUUID().toString(); + Hexagon hexagon = new Hexagon(uniqueID, polyLats, polyLons, polyLats, polyLons); + // logger.debug(hexagon.geofence); + segmentMap.put(uniqueID, hexagon); + raster.putSubscriptionIdIntoRasterEntries(hexagon.geofence, new ImmutablePair<>("", uniqueID)); + } } @@ -130,13 +119,17 @@ public static HashMap importSegments(Raster raster, CommandLineA return (HashMap)segmentMap; } - private static List> createHexagons(double minX, double minY, double maxX, double maxY) { + private static List> createHexagons(double[] box) { + double minX = box[0]; + double minY = box[1]; + double maxX = box[2]; + double maxY = box[3]; List> hexagonGrid = new ArrayList<>(); double width = maxX - minX; double height = maxY - minY; - double hexagonSize = 0.03; + double hexagonSize = 0.01; double hDist = hexagonSize * Math.sqrt(3.0); double vDist = 3.0 * hexagonSize / 2.0; @@ -223,23 +216,20 @@ private static double[] getBoundingBox(File file){ private static List createHexagonalGrid(double[] box){ List hexagons = new ArrayList<>(); CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84; - ReferencedEnvelope gridBounds = new ReferencedEnvelope(box[1], box[0], box[3], box[2], sourceCRS); - double sideLen = 5.0; - GridFeatureBuilder builder = new DefaultGridFeatureBuilder(); - SimpleFeatureSource grid = Hexagons.createGrid(gridBounds, sideLen, HexagonOrientation.ANGLED, builder); + ReferencedEnvelope gridBounds = new ReferencedEnvelope(box[0], box[2], box[1], box[3], sourceCRS); try{ + ReferencedEnvelope nGridBounds = gridBounds.transform(CRS.decode("EPSG:3857"),true); + double sideLen = 1.0; + GridFeatureBuilder builder = new DefaultGridFeatureBuilder(); + SimpleFeatureSource grid = Hexagons.createGrid(nGridBounds, sideLen, HexagonOrientation.FLAT, builder); + SimpleFeatureCollection collection = grid.getFeatures(); FeatureIterator iterator = collection.features(); while (iterator.hasNext()){ Feature feature = iterator.next(); SimpleFeature sFeature = (SimpleFeature) feature; - //logger.debug(sFeature.getAttribute(0)); Geometry geometry = (Geometry) sFeature.getAttribute(0); hexagons.add(geometry); -// Coordinate[] coordinates = geofence.getCoordinates(); -// logger.debug(Arrays.toString(coordinates)); - /* String uniqueID = UUID.randomUUID().toString(); - raster.putSubscriptionIdIntoRasterEntries(geofence, new ImmutablePair<>("", uniqueID));*/ } } catch(Exception e){ diff --git a/src/main/java/Graph/SegmentMapper.java b/src/main/java/Graph/SegmentMapper.java index b1e36dd..1239efd 100644 --- a/src/main/java/Graph/SegmentMapper.java +++ b/src/main/java/Graph/SegmentMapper.java @@ -29,6 +29,7 @@ import main.CommandLineArguments; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.geotools.referencing.ReferencingFactoryFinder; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -52,8 +53,9 @@ public class SegmentMapper { public static void doSegmentMapping(CommandLineArguments cla) { // Creating the Geobroker Raster. See the documentation of the Geobroker: https://github.com/MoeweX/geobroker - Raster raster = new Raster(1000); + Raster raster = new Raster(100); + logger.debug(ReferencingFactoryFinder.getCRSAuthorityFactories(null)); // Contains the Junctions and Street Segments, including their statistics and dangerousness score // as value and their Id(s) as their key. HashMap segmentMap = SegmentImporter.importSegments(raster, cla); diff --git a/src/main/java/Rides/RideBucket.java b/src/main/java/Rides/RideBucket.java index 68ec182..ef9c670 100644 --- a/src/main/java/Rides/RideBucket.java +++ b/src/main/java/Rides/RideBucket.java @@ -50,9 +50,11 @@ private Segment findSegment(HashMap segmentMap, Raster raster, Hexagon nearestHexagon = null; double distanceToNearestHexagon = Double.MAX_VALUE; Location location = new Location(lat, lon); + System.out.println(location); + System.out.println(raster.getNumberOfExistingRasterEntries()); // contains all segments that are near the RideBucket List> segmentCandidates = raster.getSubscriptionIdsInRasterEntryForPublisherLocation(location); - + System.out.println(segmentCandidates); // loop through all segment candidates and find the segment in which the RideBucket lies // Junction beats Street if RideBucket lies in both for (int i = 0; i < segmentCandidates.size(); i++) { @@ -98,7 +100,7 @@ private Segment findSegment(HashMap segmentMap, Raster raster, private double calculateDistanceFromPointToPolygon(Segment actualSegment, double lat, double lon) { double[] polyLats = actualSegment.poly_vertices_latsArray; double[] polyLons = actualSegment.poly_vertices_lonsArray; - Coordinate[] polygonCoordinates = new Coordinate[polyLats.length+1]; + Coordinate[] polygonCoordinates = new Coordinate[polyLats.length+1]; //+1 for (int j = 0; j < polyLats.length; j++) { polygonCoordinates[j] = new Coordinate(polyLats[j], polyLons[j]); } diff --git a/src/main/java/Segments/Hexagon.java b/src/main/java/Segments/Hexagon.java index 73b82c9..630957c 100644 --- a/src/main/java/Segments/Hexagon.java +++ b/src/main/java/Segments/Hexagon.java @@ -22,7 +22,7 @@ public Hexagon(String id, double[] lats, double[] lons, double[] polyLats, doubl this.poly_vertices_latsArray = polyLats; this.poly_vertices_lonsArray = polyLons; List locations = new ArrayList<>(); - for (int i = 0; i < polyLats.length-1; i++) { + for (int i = 0; i < polyLats.length-2; i++) { locations.add(new Location(polyLats[i],polyLons[i])); } this.geofence = Geofence.Companion.polygon(locations);