From 3365b9d702431e3dc937659badca7036914eaedc Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 14:16:08 +0200 Subject: [PATCH 1/9] fix: increase default max attempts for coordinate generation --- .../generators/AbstractCoordinateGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java index f2bb4d5d8e..9b1c508e75 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java @@ -24,7 +24,7 @@ */ public abstract class AbstractCoordinateGenerator { protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractCoordinateGenerator.class); - protected static final int DEFAULT_MAX_ATTEMPTS = 100; + protected static final int DEFAULT_MAX_ATTEMPTS = 10000; protected static final double COORDINATE_PRECISION = 1e-6; protected static final String DEFAULT_BASE_URL = "http://localhost:8082/ors"; From 4a036218011a47ae14c978202fb99e48d03d00cd Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 14:39:19 +0200 Subject: [PATCH 2/9] chore: add debug logging for request and response in coordinate generation services --- .../AbstractCoordinateGenerator.java | 3 + .../generators/CoordinateGeneratorRoute.java | 137 +++++++++++++++--- .../service/CoordinateSnapper.java | 5 + .../service/MatrixCalculator.java | 14 +- 4 files changed, 141 insertions(+), 18 deletions(-) diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java index 9b1c508e75..1f11084fa2 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java @@ -115,6 +115,9 @@ protected String processResponse(ClassicHttpResponse response) throws IOExceptio HttpEntity entity = response.getEntity(); if (entity == null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Received empty response"); + } return null; } diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java index 0404d9a61f..d158d1a1c3 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java @@ -55,8 +55,11 @@ public CoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profile this.routeRepository = new RouteRepository(Set.of(profiles)); Function requestExecutor = request -> { + LOGGER.debug("RequestExecutor: Preparing to execute request URI: {}", request.getRequestUri()); try (CloseableHttpClient client = createHttpClient()) { - return client.execute(request, this::processResponse); + String response = client.execute(request, this::processResponse); + LOGGER.debug("RequestExecutor: Raw response: {}", response); + return response; } catch (IOException e) { LOGGER.error("Error executing request: {}", e.getMessage()); return null; @@ -93,6 +96,7 @@ public void generateRoutes() { public void generate(int maxAttempts) { LOGGER.info("Starting route generation with {} threads and max attempts: {}", numThreads, maxAttempts); initializeCollections(); + LOGGER.debug("Collections initialized."); ExecutorService executor = null; AtomicBoolean shouldContinue = new AtomicBoolean(true); @@ -110,39 +114,52 @@ public void generate(int maxAttempts) { private void executeRouteGeneration(ExecutorService executor, int maxAttempts, AtomicBoolean shouldContinue, AtomicInteger consecutiveFailedAttempts) { + LOGGER.debug("executeRouteGeneration: Starting. Max attempts: {}, Should continue: {}, Consecutive Fails: {}", + maxAttempts, shouldContinue.get(), consecutiveFailedAttempts.get()); try (ProgressBar pb = createProgressBar()) { while (!routeRepository.areAllProfilesComplete(numRoutes) && consecutiveFailedAttempts.get() < maxAttempts && shouldContinue.get()) { + LOGGER.debug( + "executeRouteGeneration: Loop iteration. Profiles complete: {}, Consecutive Fails: {}, Should continue: {}", + routeRepository.areAllProfilesComplete(numRoutes), consecutiveFailedAttempts.get(), + shouldContinue.get()); int initialTotalRoutes = routeRepository.getTotalRouteCount(); + LOGGER.debug("executeRouteGeneration: Initial total routes: {}", initialTotalRoutes); List> futures = submitTasks(executor, shouldContinue); + LOGGER.debug("executeRouteGeneration: Submitted {} tasks.", futures.size()); // Wait for all tasks to complete for (Future future : futures) { try { - future.get(); + Boolean result = future.get(); + LOGGER.debug("executeRouteGeneration: Task completed with result: {}", result); } catch (InterruptedException e) { Thread.currentThread().interrupt(); shouldContinue.set(false); LOGGER.warn("Route generation interrupted"); } catch (ExecutionException e) { - LOGGER.error("Error in worker task: {}", e.getCause().getMessage()); + LOGGER.error("Error in worker task: {}", e.getCause().getMessage(), e.getCause()); } } updateProgressBar(pb); + LOGGER.debug("executeRouteGeneration: Progress bar updated."); // Check if we made progress in this iteration if (routeRepository.getTotalRouteCount() == initialTotalRoutes) { int attempts = consecutiveFailedAttempts.incrementAndGet(); + LOGGER.debug("executeRouteGeneration: No new routes. Consecutive failed attempts: {}", attempts); pb.setExtraMessage(String.format("Attempt %d/%d - No new routes", attempts, maxAttempts)); } else { + LOGGER.debug("executeRouteGeneration: New routes added. Resetting consecutive failed attempts."); consecutiveFailedAttempts.set(0); } } finalizeProgress(pb, maxAttempts, consecutiveFailedAttempts.get()); + LOGGER.debug("executeRouteGeneration: Finalized progress."); } } @@ -158,16 +175,20 @@ private ProgressBar createProgressBar() { private List> submitTasks(ExecutorService executor, AtomicBoolean shouldContinue) { List> futures = new ArrayList<>(); + LOGGER.debug("submitTasks: Starting. Should continue: {}", shouldContinue.get()); for (String profile : profiles) { + LOGGER.debug("submitTasks: Checking profile: {}. Is complete: {}", profile, + routeRepository.isProfileComplete(profile, numRoutes)); if (!routeRepository.isProfileComplete(profile, numRoutes)) { int tasksPerProfile = Math.max(1, numThreads / profiles.length); + LOGGER.debug("submitTasks: Submitting {} tasks for profile: {}", tasksPerProfile, profile); for (int i = 0; i < tasksPerProfile && shouldContinue.get(); i++) { futures.add(executor.submit(new RouteGenerationTask(profile, shouldContinue))); } } } - + LOGGER.debug("submitTasks: Finished. Total tasks submitted: {}", futures.size()); return futures; } @@ -210,131 +231,213 @@ public RouteGenerationTask(String profile, AtomicBoolean shouldContinue) { @Override public Boolean call() { + LOGGER.debug( + "RouteGenerationTask.call: Starting for profile: {}. Should continue: {}, Profile complete: {}", + profile, shouldContinue.get(), routeRepository.isProfileComplete(profile, numRoutes)); if (!shouldContinue.get() || routeRepository.isProfileComplete(profile, numRoutes)) { + LOGGER.debug("RouteGenerationTask.call: Exiting early for profile: {}", profile); return false; } try { - return generateRoutesForProfile(); + boolean result = generateRoutesForProfile(); + LOGGER.debug("RouteGenerationTask.call: generateRoutesForProfile returned {} for profile: {}", result, + profile); + return result; } catch (Exception e) { - LOGGER.error("Error generating routes for profile {}: {}", profile, e.getMessage()); + LOGGER.error("Error generating routes for profile {}: {}", profile, e.getMessage(), e); return false; } } private boolean generateRoutesForProfile() { + LOGGER.debug("generateRoutesForProfile: Starting for profile: {}", profile); // Get max distance for this profile double effectiveMaxDistance = maxDistanceByProfile.getOrDefault(profile, Double.MAX_VALUE); + LOGGER.debug("generateRoutesForProfile: Effective max distance: {} for profile: {}", effectiveMaxDistance, + profile); // Generate random coordinates List randomCoordinates = CoordinateGeneratorHelper.randomCoordinatesInExtent(DEFAULT_MATRIX_SIZE, extent); + LOGGER.debug("generateRoutesForProfile: Generated random coordinates: {} for profile: {}", + Arrays.deepToString(randomCoordinates.toArray()), profile); // Snap the coordinates to the road network + LOGGER.debug("generateRoutesForProfile: Snapping coordinates for profile: {}", profile); List snappedCoordinates = coordinateSnapper.snapCoordinates(randomCoordinates, profile); + LOGGER.debug("generateRoutesForProfile: Snapped coordinates: {} for profile: {}", + Arrays.deepToString(snappedCoordinates.toArray()), profile); if (snappedCoordinates.size() < 2) { + LOGGER.debug("generateRoutesForProfile: Not enough snapped coordinates ({}) for profile: {}. Skipping.", + snappedCoordinates.size(), profile); return false; } - return processSnappedCoordinates(snappedCoordinates, effectiveMaxDistance); + boolean result = processSnappedCoordinates(snappedCoordinates, effectiveMaxDistance); + LOGGER.debug("generateRoutesForProfile: processSnappedCoordinates returned {} for profile: {}", result, + profile); + return result; } private boolean processSnappedCoordinates(List snappedCoordinates, double maxDistance) { + LOGGER.debug( + "processSnappedCoordinates: Starting for profile: {}. Snapped coordinates: {}, Max distance: {}", + profile, Arrays.deepToString(snappedCoordinates.toArray()), maxDistance); boolean addedNewRoute = false; try { addedNewRoute = processCoordinatePairs(snappedCoordinates, maxDistance); + LOGGER.debug("processSnappedCoordinates: processCoordinatePairs returned {} for profile: {}", + addedNewRoute, profile); } catch (Exception e) { - LOGGER.error("Error processing snapped coordinates: {}", e.getMessage()); + LOGGER.error("Error processing snapped coordinates for profile {}: {}", profile, e.getMessage(), e); } + LOGGER.debug("processSnappedCoordinates: Finished for profile: {}. Added new route: {}", profile, + addedNewRoute); return addedNewRoute; } private boolean processCoordinatePairs(List snappedCoordinates, double maxDistance) { + LOGGER.debug("processCoordinatePairs: Starting for profile: {}. Snapped coordinates: {}, Max distance: {}", + profile, Arrays.deepToString(snappedCoordinates.toArray()), maxDistance); boolean addedNewRoute = false; // Process all pairs of coordinates for (double[] start : snappedCoordinates) { + LOGGER.debug("processCoordinatePairs: Processing start coordinate: {} for profile: {}", + Arrays.toString(start), profile); // Generate a destination point within max distance double[] end = CoordinateGeneratorHelper.randomCoordinateInRadiusAndExtent( start, maxDistance, extent); + LOGGER.debug("processCoordinatePairs: Generated end coordinate: {} for profile: {}", + Arrays.toString(end), profile); if (end.length > 0 && CoordinateGeneratorHelper.calculateHaversineDistance(start, end) <= maxDistance) { + LOGGER.debug("processCoordinatePairs: End coordinate is valid and within distance for profile: {}", + profile); + LOGGER.debug( + "processCoordinatePairs: Calculating matrix for profile: {} with start: {} and end: {}", + profile, Arrays.toString(start), Arrays.toString(end)); Optional matrixResultOpt = matrixCalculator.calculateMatrix( List.of(start, end), profile); + LOGGER.debug("processCoordinatePairs: Matrix calculation result present: {} for profile: {}", + matrixResultOpt.isPresent(), profile); if (matrixResultOpt.isPresent()) { - addedNewRoute |= processMatrixResult(matrixResultOpt.get()); + boolean processed = processMatrixResult(matrixResultOpt.get()); + LOGGER.debug("processCoordinatePairs: processMatrixResult returned {} for profile: {}", + processed, profile); + addedNewRoute |= processed; } + } else { + LOGGER.debug( + "processCoordinatePairs: End coordinate invalid or too far for profile: {}. End: {}, Haversine: {}", + profile, Arrays.toString(end), + (end.length > 0 ? CoordinateGeneratorHelper.calculateHaversineDistance(start, end) + : "N/A")); } } + LOGGER.debug("processCoordinatePairs: Finished for profile: {}. Added new route: {}", profile, + addedNewRoute); return addedNewRoute; } private boolean processMatrixResult(MatrixCalculator.MatrixResult result) { + LOGGER.debug("processMatrixResult: Starting for profile: {}", profile); if (!result.isValid()) { - LOGGER.info("Matrix result is invalid, skipping processing"); + LOGGER.info("Matrix result is invalid, skipping processing for profile: {}", profile); return false; } + LOGGER.debug("processMatrixResult: Matrix result is valid for profile: {}", profile); List> sources = result.getSources(); List> destinations = result.getDestinations(); List> distances = result.getDistances(); + LOGGER.debug("processMatrixResult: Sources: {}, Destinations: {}, Distances: {} for profile: {}", sources, + destinations, distances, profile); boolean addedNewRoute = false; for (int i = 0; i < destinations.size(); i++) { + LOGGER.debug("processMatrixResult: Processing destination index {} for profile: {}", i, profile); if (sources.get(i) == null || destinations.get(i) == null || distances.get(i) == null || distances.get(i).isEmpty()) { + LOGGER.debug("processMatrixResult: Skipping null or empty data at index {} for profile: {}", i, + profile); continue; } if (distances.get(i).get(0) != null) { + double distanceValue = distances.get(i).get(0); + LOGGER.debug("processMatrixResult: Distance value: {} for profile: {}", distanceValue, profile); boolean added = addRouteIfUnique(sources.get(i), destinations.get(i), - distances.get(i).get(0), profile); + distanceValue, profile); + LOGGER.debug("processMatrixResult: addRouteIfUnique returned {} for profile: {}", added, profile); if (added) { addedNewRoute = true; + LOGGER.debug("processMatrixResult: New route added for profile: {}", profile); } + } else { + LOGGER.debug("processMatrixResult: Distance at index {} is null for profile: {}", i, profile); } } + LOGGER.debug("processMatrixResult: Finished for profile: {}. Added new route: {}", profile, addedNewRoute); return addedNewRoute; } @SuppressWarnings("unchecked") private boolean addRouteIfUnique(Map start, Map end, double distance, String profile) { + LOGGER.debug("addRouteIfUnique: Starting for profile: {}. Start: {}, End: {}, Distance: {}", profile, start, + end, distance); try { List startCoord = (List) start.get(LOCATION_KEY); List endCoord = (List) end.get(LOCATION_KEY); if (startCoord != null && endCoord != null && startCoord.size() >= 2 && endCoord.size() >= 2) { + LOGGER.debug("addRouteIfUnique: Coordinates are valid for profile: {}", profile); double[] startPoint = new double[] { startCoord.get(0).doubleValue(), startCoord.get(1).doubleValue() }; double[] endPoint = new double[] { endCoord.get(0).doubleValue(), endCoord.get(1).doubleValue() }; + LOGGER.debug("addRouteIfUnique: Start point: {}, End point: {} for profile: {}", + Arrays.toString(startPoint), Arrays.toString(endPoint), profile); if (distance < minDistance) { - LOGGER.debug("Skipping route with distance {} < minimum {} meters", distance, minDistance); + LOGGER.debug( + "addRouteIfUnique: Distance {} is less than minDistance {} for profile: {}. Skipping.", + distance, minDistance, profile); return false; } Route route = new Route(startPoint, endPoint, distance, profile); + LOGGER.debug("addRouteIfUnique: Created route object: {} for profile: {}", route, profile); boolean added = routeRepository.addRouteIfUnique(route); + LOGGER.debug("addRouteIfUnique: routeRepository.addRouteIfUnique returned {} for profile: {}", + added, profile); if (added) { - LOGGER.debug("Added new unique route for profile: {}", profile); + LOGGER.info("Added new route for profile {}: {} -> {} ({}m)", profile, + Arrays.toString(startPoint), Arrays.toString(endPoint), distance); + return true; } else { - LOGGER.debug("Skipped duplicate route for profile: {}", profile); + LOGGER.debug("Route already exists or not added for profile {}: {} -> {} ({}m)", profile, + Arrays.toString(startPoint), Arrays.toString(endPoint), distance); + return false; } - - return added; + } else { + LOGGER.debug( + "addRouteIfUnique: Invalid coordinates (null or insufficient size) for profile: {}. Start: {}, End: {}", + profile, startCoord, endCoord); } } catch (Exception e) { - LOGGER.error("Error adding route: {}", e.getMessage()); + LOGGER.error("Error adding route for profile {}: {}", profile, e.getMessage(), e); } + LOGGER.debug("addRouteIfUnique: Finished for profile: {}. Returning false.", profile); return false; } } diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java index 5919a43770..ce16e48596 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java @@ -37,7 +37,11 @@ public List snapCoordinates(List coordinates, String profile try { HttpPost request = createSnapRequest(coordinates, profile); + LOGGER.debug("Snap Request URI: {}", request.getRequestUri()); + // Payload is logged in createSnapRequest + String response = requestExecutor.apply(request); + LOGGER.debug("Snap Raw Response: {}", response); if (response == null) { LOGGER.debug("Received null response from snap API"); @@ -55,6 +59,7 @@ private HttpPost createSnapRequest(List coordinates, String profile) t Map payload = new HashMap<>(); payload.put(LOCATIONS_KEY, coordinates); payload.put("radius", DEFAULT_SNAP_RADIUS); + LOGGER.debug("Snap Request Payload: {}", payload); // Log payload here HttpPost request = new HttpPost(baseUrl + "/v2/snap/" + profile); headers.forEach(request::addHeader); diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/MatrixCalculator.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/MatrixCalculator.java index b80ad4c4b8..0223e7a064 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/MatrixCalculator.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/MatrixCalculator.java @@ -36,7 +36,10 @@ public MatrixCalculator(String baseUrl, Map headers, ObjectMappe public Optional calculateMatrix(List coordinates, String profile) { try { HttpPost request = createMatrixRequest(coordinates, profile); + LOGGER.debug("Matrix Request URI: {}", request.getRequestUri()); + // Payload is logged in createMatrixRequest String response = requestExecutor.apply(request); + LOGGER.debug("Matrix Raw Response: {}", response); if (response == null) { LOGGER.debug("Received null response from matrix API"); @@ -53,7 +56,11 @@ public Optional calculateMatrix(List coordinates, String public String calculateMatrixRaw(List coordinates, String profile) { try { HttpPost request = createMatrixRequest(coordinates, profile); - return requestExecutor.apply(request); + LOGGER.debug("Matrix Raw Request URI: {}", request.getRequestUri()); + // Payload is logged in createMatrixRequest + String response = requestExecutor.apply(request); + LOGGER.debug("Matrix Raw Response (from calculateMatrixRaw): {}", response); + return response; } catch (IOException e) { LOGGER.error(ERROR_CALCULATING_MATRIX, e.getMessage()); return null; @@ -63,7 +70,10 @@ public String calculateMatrixRaw(List coordinates, String profile) { public Optional calculateAsymmetricMatrix(List coordinates, int[] sources, int[] destinations, String profile) { try { HttpPost request = createAsymmetricMatrixRequest(coordinates, sources, destinations, profile); + LOGGER.debug("Asymmetric Matrix Request URI: {}", request.getRequestUri()); + // Payload is logged in createAsymmetricMatrixRequest String response = requestExecutor.apply(request); + LOGGER.debug("Asymmetric Matrix Raw Response: {}", response); if (response == null) { LOGGER.debug("Received null response from matrix API"); @@ -84,6 +94,7 @@ private HttpPost createMatrixRequest(List coordinates, String profile) Map payload = new HashMap<>(); payload.put(LOCATIONS_KEY, coordinates); payload.put("metrics", new String[] { "distance" }); + LOGGER.debug("Matrix Request Payload: {}", payload); HttpPost request = new HttpPost(baseUrl + "/v2/matrix/" + profile); headers.forEach(request::addHeader); @@ -101,6 +112,7 @@ private HttpPost createAsymmetricMatrixRequest(List coordinates, int[] payload.put(SOURCES_KEY, sources); payload.put(DESTINATIONS_KEY, destinations); payload.put("metrics", new String[] { "distance" }); + LOGGER.debug("Asymmetric Matrix Request Payload: {}", payload); HttpPost request = new HttpPost(baseUrl + "/v2/matrix/" + profile); headers.forEach(request::addHeader); From da35e6f5a5d8e514ef294a439af37f686c1a029e Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 15:00:58 +0200 Subject: [PATCH 3/9] fix: enhance logging for HTTP response processing --- .../generators/AbstractCoordinateGenerator.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java index 1f11084fa2..a069de13d5 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java @@ -105,19 +105,16 @@ protected CloseableHttpClient createHttpClient() { * Processes an HTTP response */ protected String processResponse(ClassicHttpResponse response) throws IOException { + LOGGER.debug("Received response: {}", new StatusLine(response)); int status = response.getCode(); if (status >= HttpStatus.SC_REDIRECTION) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Received error response: {}", new StatusLine(response)); - } + LOGGER.debug("Received error response: {}", new StatusLine(response)); return null; } HttpEntity entity = response.getEntity(); if (entity == null) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Received empty response"); - } + LOGGER.debug("Received empty response"); return null; } From 1b015384b413a1e2c1dd75b6eed1836836fce146 Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 15:10:15 +0200 Subject: [PATCH 4/9] fix: update default snap radius to 1000 meters --- .../ors/coordinates_generator/service/CoordinateSnapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java index ce16e48596..879669168e 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java @@ -15,7 +15,7 @@ public class CoordinateSnapper { private static final Logger LOGGER = LoggerFactory.getLogger(CoordinateSnapper.class); - private static final double DEFAULT_SNAP_RADIUS = 350; // 350 meters radius for snapping + private static final double DEFAULT_SNAP_RADIUS = 1000; // 350 meters radius for snapping private static final String LOCATIONS_KEY = "locations"; private static final String LOCATION_KEY = "location"; From bf8f72279e9c22a88f90faf7eaedfac4d88282b7 Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 15:11:31 +0200 Subject: [PATCH 5/9] fix: change route addition logging from info to debug level --- .../generators/CoordinateGeneratorRoute.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java index d158d1a1c3..d51d2b8a07 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java @@ -421,8 +421,8 @@ private boolean addRouteIfUnique(Map start, Map added, profile); if (added) { - LOGGER.info("Added new route for profile {}: {} -> {} ({}m)", profile, - Arrays.toString(startPoint), Arrays.toString(endPoint), distance); + LOGGER.debug("Added new route for profile {}: {} -> {} ({}m)", profile, + Arrays.toString(startPoint), Arrays.toString(endPoint), distance); return true; } else { LOGGER.debug("Route already exists or not added for profile {}: {} -> {} ({}m)", profile, From 4c6ee75f787fc57606e2495dcb0bc44b0d4e9fd5 Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 15:14:21 +0200 Subject: [PATCH 6/9] chore: change error logging from error to debug level in coordinate generators --- .../generators/CoordinateGeneratorMatrix.java | 2 +- .../generators/CoordinateGeneratorRoute.java | 2 +- .../generators/CoordinateGeneratorSnapping.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java index 2253e51668..db0ac2ede0 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java @@ -71,7 +71,7 @@ public CoordinateGeneratorMatrix(int numMatrices, double[] extent, String[] prof try { return httpClient.execute(request, this::processResponse); } catch (IOException e) { - LOGGER.error("Error executing request: {}", e.getMessage()); + LOGGER.debug("Error executing request: {}", e.getMessage()); return null; } }; diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java index d51d2b8a07..c26a520d8c 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java @@ -61,7 +61,7 @@ public CoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profile LOGGER.debug("RequestExecutor: Raw response: {}", response); return response; } catch (IOException e) { - LOGGER.error("Error executing request: {}", e.getMessage()); + LOGGER.debug("Error executing request: {}", e.getMessage()); return null; } }; diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java index fc5f7a2444..04cfde7222 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java @@ -48,7 +48,7 @@ public CoordinateGeneratorSnapping(int numPoints, double[] extent, double radius try (CloseableHttpClient client = createHttpClient()) { return client.execute(request, this::processResponse); } catch (IOException e) { - LOGGER.error("Error executing request: {}", e.getMessage()); + LOGGER.debug("Error executing request: {}", e.getMessage()); return null; } }; From 275b1d97b62271e671cc82fe140a3288d6ac648c Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 15:43:48 +0200 Subject: [PATCH 7/9] feat: add snap radius option to command line parser and update related classes --- .../api-benchmarks/coordinate-generators.md | 22 ++++++++------- .../cli/RouteCommandLineParser.java | 15 ++++++++--- .../generators/CoordinateGeneratorMatrix.java | 19 +++++-------- .../generators/CoordinateGeneratorRoute.java | 12 +++------ .../CoordinateGeneratorSnapping.java | 2 +- .../service/CoordinateSnapper.java | 7 ++--- .../cli/RouteCommandLineParserTest.java | 27 +++++++++++++++++++ .../CoordinateGeneratorMatrixTest.java | 12 +-------- .../CoordinateGeneratorRouteTest.java | 13 +-------- 9 files changed, 68 insertions(+), 61 deletions(-) diff --git a/docs/technical-details/api-benchmarks/coordinate-generators.md b/docs/technical-details/api-benchmarks/coordinate-generators.md index e4e99bdf58..fba8908dfc 100644 --- a/docs/technical-details/api-benchmarks/coordinate-generators.md +++ b/docs/technical-details/api-benchmarks/coordinate-generators.md @@ -33,16 +33,17 @@ The tool generates random coordinates within a specified bounding box and then u ### Route Generator Options -| Option | Description | Default | -|--------|-------------|---------| -| `-n, --num-routes` | Number of routes to generate. | (required) | -| `-e, --extent` | Bounding box (minLon,minLat,maxLon,maxLat). Use to generate your extents. | (required). | -| `-p, --profiles` | Comma-separated routing profiles. | (required) | -| `-u, --url` | ORS API base URL. | | -| `-o, --output` | Output CSV file path. | route_coordinates.csv | -| `-d, --min-distance` | Minimum distance between start and endpoint in an a-to-b routing pair in meters. This is valid for all profiles. | 1 | -| `-m, --max-distances` | Maximum distances in meters **per profile** between the start and endpoint. | (none) | -| `-t, --threads` | Number of threads to use. | Available processors | +| Option | Description | Default | +|-----------------------|------------------------------------------------------------------------------------------------------------------|-----------------------------| +| `-n, --num-routes` | Number of routes to generate. | (required) | +| `-e, --extent` | Bounding box (minLon,minLat,maxLon,maxLat). Use to generate your extents. | (required). | +| `-p, --profiles` | Comma-separated routing profiles. | (required) | +| `-u, --url` | ORS API base URL. | | +| `-o, --output` | Output CSV file path. | route_coordinates.csv | +| `-d, --min-distance` | Minimum distance between start and endpoint in an a-to-b routing pair in meters. This is valid for all profiles. | 1 | +| `-m, --max-distances` | Maximum distances in meters **per profile** between the start and endpoint. | (none) | +| `-t, --threads` | Number of threads to use. | Available processors | +| `-sr, --snap-radius` | Search radius in meters for coordinate snapping. | 1000 | ### Route Generator Examples @@ -76,6 +77,7 @@ Generate 50 routes for both driving-car and cycling-regular profiles with differ --min-distance 2000 \ --max-distances 5000,3000 \ --threads 4 \ + --snap-radius 1500 \ --url http://localhost:8080/ors \ --output routes.csv" ``` diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java index 0694605b89..77518455a6 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java @@ -13,6 +13,7 @@ public class RouteCommandLineParser extends CommandLineParser { private static final Logger LOGGER = LoggerFactory.getLogger(RouteCommandLineParser.class); private static final String OPT_THREADS = "threads"; + private static final String OPT_SNAP_RADIUS = "snap-radius"; private static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors(); public RouteCommandLineParser(String[] args) { @@ -78,6 +79,13 @@ protected void setupOptions() { .hasArg() .desc("Number of threads to use (default: " + DEFAULT_THREAD_COUNT + ")") .build()); + + options.addOption(Option.builder("sr") + .longOpt(OPT_SNAP_RADIUS) + .hasArg() + .type(Number.class) + .desc("Search radius in meters for coordinate snapping (default: 1000)") + .build()); } @Override @@ -115,6 +123,7 @@ public CoordinateGeneratorRoute createGenerator() { String[] profiles = parseProfiles(cmd.getOptionValue("p")); String baseUrl = cmd.getOptionValue("u", "http://localhost:8080/ors"); double minDistance = Double.parseDouble(cmd.getOptionValue("d", "1")); + double snapRadius = Double.parseDouble(cmd.getOptionValue(OPT_SNAP_RADIUS, "1000")); // Parse the max distances if provided Map maxDistanceByProfile = parseMaxDistances(cmd.getOptionValue("m"), profiles); @@ -123,13 +132,13 @@ public CoordinateGeneratorRoute createGenerator() { if (LOGGER.isInfoEnabled()) { LOGGER.info( - "Creating CoordinateGeneratorRoute with numRoutes={}, extent={}, profiles={}, baseUrl={}, minDistance={}, maxDistances={}, numThreads={}", + "Creating CoordinateGeneratorRoute with numRoutes={}, extent={}, profiles={}, baseUrl={}, minDistance={}, maxDistances={}, numThreads={}, snapRadius={}", numRoutes, extent, java.util.Arrays.toString(profiles), baseUrl, minDistance, maxDistanceByProfile, - numThreads); + numThreads, snapRadius); } return new CoordinateGeneratorRoute(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, - numThreads); + numThreads, snapRadius); } /** diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java index db0ac2ede0..f9a94e82ee 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java @@ -13,8 +13,8 @@ import org.apache.hc.core5.util.Timeout; import org.heigit.ors.coordinates_generator.model.Matrix; import org.heigit.ors.coordinates_generator.model.MatrixRepository; -import org.heigit.ors.coordinates_generator.service.MatrixCalculator; import org.heigit.ors.coordinates_generator.service.CoordinateSnapper; +import org.heigit.ors.coordinates_generator.service.MatrixCalculator; import org.heigit.ors.util.CoordinateGeneratorHelper; import org.heigit.ors.util.ProgressBarLogger; import org.slf4j.Logger; @@ -34,7 +34,6 @@ public record MatrixDimensions(int numRows, int numCols) { protected static final Logger LOGGER = LoggerFactory.getLogger(CoordinateGeneratorMatrix.class); - private static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors(); private static final String LOCATION_KEY = "location"; private final int numMatrices; @@ -47,15 +46,9 @@ public record MatrixDimensions(int numRows, int numCols) { private final int numThreads; private final CloseableHttpClient httpClient; - protected CoordinateGeneratorMatrix(int numMatrices, double[] extent, String[] profiles, String baseUrl, - Map maxDistanceByProfile, - MatrixDimensions matrixDimensions) { - this(numMatrices, extent, profiles, baseUrl, maxDistanceByProfile, matrixDimensions, DEFAULT_THREAD_COUNT); - } - public CoordinateGeneratorMatrix(int numMatrices, double[] extent, String[] profiles, String baseUrl, - Map maxDistanceByProfile, - MatrixDimensions matrixDimensions, int numThreads) { + Map maxDistanceByProfile, + MatrixDimensions matrixDimensions, int numThreads, double snapRadius) { super(extent, profiles, baseUrl, "matrix"); validateInputs(numMatrices, numThreads); @@ -77,7 +70,7 @@ public CoordinateGeneratorMatrix(int numMatrices, double[] extent, String[] prof }; Map headers = createHeaders(); - this.coordinateSnapper = new CoordinateSnapper(baseUrl, headers, mapper, requestExecutor); + this.coordinateSnapper = new CoordinateSnapper(baseUrl, headers, mapper, requestExecutor, snapRadius); this.matrixCalculator = new MatrixCalculator(baseUrl, headers, mapper, requestExecutor); } @@ -310,7 +303,7 @@ public Boolean call() { /** * Main method generating a number of matrices - * + * * @return Whether a matrix was successfully added to the repository */ private boolean generateMatricesForProfile() { @@ -463,7 +456,7 @@ private boolean computeAndProcessMatrix(List snappedCoordinates) { /** * Check whether two points are connected in a forward way - * + * * @param from coordinate pair from * @param to coordinate pair to * @return true if matrix was successfully calculated and points are routeable, diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java index c26a520d8c..f97bbef5f8 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java @@ -8,8 +8,8 @@ import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.heigit.ors.coordinates_generator.model.Route; import org.heigit.ors.coordinates_generator.model.RouteRepository; -import org.heigit.ors.coordinates_generator.service.MatrixCalculator; import org.heigit.ors.coordinates_generator.service.CoordinateSnapper; +import org.heigit.ors.coordinates_generator.service.MatrixCalculator; import org.heigit.ors.util.CoordinateGeneratorHelper; import org.heigit.ors.util.ProgressBarLogger; import org.slf4j.Logger; @@ -27,7 +27,6 @@ public class CoordinateGeneratorRoute extends AbstractCoordinateGenerator { protected static final Logger LOGGER = LoggerFactory.getLogger(CoordinateGeneratorRoute.class); private static final int DEFAULT_MATRIX_SIZE = 2; - private static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors(); private static final String LOCATION_KEY = "location"; private final int numRoutes; @@ -38,13 +37,10 @@ public class CoordinateGeneratorRoute extends AbstractCoordinateGenerator { private final MatrixCalculator matrixCalculator; private final int numThreads; - protected CoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, String baseUrl, - double minDistance, Map maxDistanceByProfile) { - this(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, DEFAULT_THREAD_COUNT); - } public CoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, String baseUrl, - double minDistance, Map maxDistanceByProfile, int numThreads) { + double minDistance, Map maxDistanceByProfile, int numThreads, + double snapRadius) { super(extent, profiles, baseUrl, "matrix"); validateInputs(numRoutes, minDistance, numThreads); @@ -67,7 +63,7 @@ public CoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profile }; Map headers = createHeaders(); - this.coordinateSnapper = new CoordinateSnapper(baseUrl, headers, mapper, requestExecutor); + this.coordinateSnapper = new CoordinateSnapper(baseUrl, headers, mapper, requestExecutor, snapRadius); this.matrixCalculator = new MatrixCalculator(baseUrl, headers, mapper, requestExecutor); } diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java index 04cfde7222..8cfd4e976a 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java @@ -53,7 +53,7 @@ public CoordinateGeneratorSnapping(int numPoints, double[] extent, double radius } }; Map headers = createHeaders(); - this.coordinateSnapper = new CoordinateSnapper(baseUrl, headers, mapper, requestExecutor); + this.coordinateSnapper = new CoordinateSnapper(baseUrl, headers, mapper, requestExecutor, radius); } @Override diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java index 879669168e..9f012c131d 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/service/CoordinateSnapper.java @@ -15,7 +15,6 @@ public class CoordinateSnapper { private static final Logger LOGGER = LoggerFactory.getLogger(CoordinateSnapper.class); - private static final double DEFAULT_SNAP_RADIUS = 1000; // 350 meters radius for snapping private static final String LOCATIONS_KEY = "locations"; private static final String LOCATION_KEY = "location"; @@ -23,13 +22,15 @@ public class CoordinateSnapper { private final Map headers; private final ObjectMapper mapper; private final Function requestExecutor; + private final double snapRadius; public CoordinateSnapper(String baseUrl, Map headers, ObjectMapper mapper, - Function requestExecutor) { + Function requestExecutor, double snapRadius) { this.baseUrl = baseUrl; this.headers = headers; this.mapper = mapper; this.requestExecutor = requestExecutor; + this.snapRadius = snapRadius; } public List snapCoordinates(List coordinates, String profile) { @@ -58,7 +59,7 @@ public List snapCoordinates(List coordinates, String profile private HttpPost createSnapRequest(List coordinates, String profile) throws JsonProcessingException { Map payload = new HashMap<>(); payload.put(LOCATIONS_KEY, coordinates); - payload.put("radius", DEFAULT_SNAP_RADIUS); + payload.put("radius", snapRadius); LOGGER.debug("Snap Request Payload: {}", payload); // Log payload here HttpPost request = new HttpPost(baseUrl + "/v2/snap/" + profile); diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java index 5b0b10aa6f..8f0e1b017f 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java @@ -2,6 +2,7 @@ import org.heigit.ors.benchmark.exceptions.CommandLineParsingException; import org.heigit.ors.coordinates_generator.generators.CoordinateGeneratorRoute; +import org.heigit.ors.coordinates_generator.service.CoordinateSnapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -324,4 +325,30 @@ void testSpaceExtentCommandLine() { CoordinateGeneratorRoute generator = cli.createGenerator(); assertNotNull(generator); } + + @Test + void testSnapRadius() { + String[] args = { + "-n", "50", + "-e", "8.6 49.3 8.7 49.4", + "-p", "driving-car", + "-m", "5000", + "-sr", "3000" + }; + + RouteCommandLineParser cli = new RouteCommandLineParser(args); + CoordinateGeneratorRoute generator = cli.createGenerator(); + assertNotNull(generator); + + // Test snapRadius using reflection + assertDoesNotThrow(() -> { + Field coordinateSnapperField = CoordinateGeneratorRoute.class.getDeclaredField("coordinateSnapper"); + coordinateSnapperField.setAccessible(true); + CoordinateSnapper snapper = (CoordinateSnapper) coordinateSnapperField.get(generator); + + Field snapRadiusField = CoordinateSnapper.class.getDeclaredField("snapRadius"); + snapRadiusField.setAccessible(true); + assertEquals(3000.0, snapRadiusField.getDouble(snapper), 0.001); + }); + } } diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java index f13d70f2d9..73fc0b0738 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java @@ -333,19 +333,9 @@ private static Stream invalidConstructorParameters() { private static class TestCoordinateGeneratorMatrix extends CoordinateGeneratorMatrix { private CloseableHttpClient testClient; - public TestCoordinateGeneratorMatrix(int numRoutes, double[] extent, String[] profiles, - String baseUrl, MatrixDimensions matrixDimensions) { - super(numRoutes, extent, profiles, baseUrl, new HashMap<>(), matrixDimensions); - } - public TestCoordinateGeneratorMatrix(int numRoutes, double[] extent, String[] profiles, String baseUrl, Map maxDistanceByProfile, MatrixDimensions matrixDimensions) { - super(numRoutes, extent, profiles, baseUrl, maxDistanceByProfile, matrixDimensions); - } - - public TestCoordinateGeneratorMatrix(int numRoutes, double[] extent, String[] profiles, - String baseUrl, Map maxDistanceByProfile, MatrixDimensions matrixDimensions, int numThreads) { - super(numRoutes, extent, profiles, baseUrl, maxDistanceByProfile, matrixDimensions, numThreads); + super(numRoutes, extent, profiles, baseUrl, maxDistanceByProfile, matrixDimensions, 1, 1); } void setHttpClient(CloseableHttpClient client) { diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java index cc9ef438cf..38e553f214 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java @@ -362,21 +362,10 @@ void testInvalidConstructorParameters(int numRoutes, double[] extent, String[] p private static class TestCoordinateGeneratorRoute extends CoordinateGeneratorRoute { private CloseableHttpClient testClient; - public TestCoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, - String baseUrl, double minDistance) { - super(numRoutes, extent, profiles, baseUrl, minDistance, new HashMap<>()); - } - public TestCoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, String baseUrl, double minDistance, Map maxDistanceByProfile) { - super(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile); - } - - public TestCoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, - String baseUrl, double minDistance, - Map maxDistanceByProfile, int numThreads) { - super(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, numThreads); + super(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, 1, 1); } void setHttpClient(CloseableHttpClient client) { From 05f83254e1161e7d470203e98419f52e8068b05c Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 16:33:23 +0200 Subject: [PATCH 8/9] feat: add max attempts option to command line parsers and update related generators --- .../api-benchmarks/coordinate-generators.md | 20 ++++++++----- .../RouteGeneratorApp.java | 2 +- .../cli/RouteCommandLineParser.java | 20 +++++++++---- .../cli/SnappingCommandLineParser.java | 19 ++++++++++-- .../AbstractCoordinateGenerator.java | 18 +++++------ .../generators/CoordinateGeneratorMatrix.java | 26 ++++++++-------- .../generators/CoordinateGeneratorRoute.java | 30 ++++++++----------- .../CoordinateGeneratorSnapping.java | 19 ++++++------ .../cli/RouteCommandLineParserTest.java | 20 +++++++++++++ .../cli/SnappingCommandLineParserTest.java | 19 ++++++++++++ .../CoordinateGeneratorMatrixTest.java | 2 +- .../CoordinateGeneratorRouteTest.java | 10 +++---- .../CoordinateGeneratorSnappingTest.java | 2 +- 13 files changed, 132 insertions(+), 75 deletions(-) diff --git a/docs/technical-details/api-benchmarks/coordinate-generators.md b/docs/technical-details/api-benchmarks/coordinate-generators.md index fba8908dfc..04e66fe21b 100644 --- a/docs/technical-details/api-benchmarks/coordinate-generators.md +++ b/docs/technical-details/api-benchmarks/coordinate-generators.md @@ -44,6 +44,7 @@ The tool generates random coordinates within a specified bounding box and then u | `-m, --max-distances` | Maximum distances in meters **per profile** between the start and endpoint. | (none) | | `-t, --threads` | Number of threads to use. | Available processors | | `-sr, --snap-radius` | Search radius in meters for coordinate snapping. | 1000 | +| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 1000 | ### Route Generator Examples @@ -78,6 +79,7 @@ Generate 50 routes for both driving-car and cycling-regular profiles with differ --max-distances 5000,3000 \ --threads 4 \ --snap-radius 1500 \ + --max-attempts 1500 \ --url http://localhost:8080/ors \ --output routes.csv" ``` @@ -94,14 +96,15 @@ The tool generates random coordinates within a specified bounding box and then u ### Snapping Generator Options -| Option | Description | Default | -|--------|-------------|---------| -| `-n, --num-points` | Number of points to generate per profile. | (required) | -| `-e, --extent` | Bounding box (minLon,minLat,maxLon,maxLat). | (required) | -| `-p, --profiles` | Comma-separated list of routing profiles. | (required) | -| `-r, --radius` | Search radius in meters. | 350 | -| `-u, --url` | ORS API base URL. | | -| `-o, --output` | Output CSV file path. | snapped_coordinates.csv | +| Option | Description | Default | +|-----------------------|-------------------------------------------------------|-----------------------------| +| `-n, --num-points` | Number of points to generate per profile. | (required) | +| `-e, --extent` | Bounding box (minLon,minLat,maxLon,maxLat). | (required) | +| `-p, --profiles` | Comma-separated list of routing profiles. | (required) | +| `-r, --radius` | Search radius in meters. | 350 | +| `-u, --url` | ORS API base URL. | | +| `-o, --output` | Output CSV file path. | snapped_coordinates.csv | +| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 1000 | ### Snapping Generator Examples @@ -133,6 +136,7 @@ Generate 50 snapped points for both driving-car and cycling-regular profiles: --extent 8.681495,49.411721,8.695485,49.419365 \ --profiles driving-car,cycling-regular \ --radius 250 \ + --max-attempts 1500 \ --url http://localhost:8080/ors \ --output snapped.csv" ``` diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/RouteGeneratorApp.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/RouteGeneratorApp.java index 815be2d89b..4076fa5b2b 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/RouteGeneratorApp.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/RouteGeneratorApp.java @@ -25,7 +25,7 @@ public static void main(String[] args) { CoordinateGeneratorRoute generator = cli.createGenerator(); LOGGER.info("Generating {} routes...", generator.getNumRoutes()); - generator.generateRoutes(); + generator.generate(); LOGGER.info("\n"); List result = generator.getResult(); diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java index 77518455a6..5ff441e156 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParser.java @@ -14,6 +14,7 @@ public class RouteCommandLineParser extends CommandLineParser { private static final String OPT_THREADS = "threads"; private static final String OPT_SNAP_RADIUS = "snap-radius"; + private static final String OPT_MAX_ATTEMPTS = "max-attempts"; private static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors(); public RouteCommandLineParser(String[] args) { @@ -73,7 +74,6 @@ protected void setupOptions() { .hasArg() .desc("Maximum distances between coordinates in meters, comma-separated in profile order (e.g., 5000,3000)") .build()); - options.addOption(Option.builder("t") .longOpt(OPT_THREADS) .hasArg() @@ -86,6 +86,13 @@ protected void setupOptions() { .type(Number.class) .desc("Search radius in meters for coordinate snapping (default: 1000)") .build()); + + options.addOption(Option.builder("ma") + .longOpt(OPT_MAX_ATTEMPTS) + .hasArg() + .type(Number.class) + .desc("Maximum number of attempts for coordinate generation (default: 1000)") + .build()); } @Override @@ -124,6 +131,7 @@ public CoordinateGeneratorRoute createGenerator() { String baseUrl = cmd.getOptionValue("u", "http://localhost:8080/ors"); double minDistance = Double.parseDouble(cmd.getOptionValue("d", "1")); double snapRadius = Double.parseDouble(cmd.getOptionValue(OPT_SNAP_RADIUS, "1000")); + int maxAttempts = Integer.parseInt(cmd.getOptionValue(OPT_MAX_ATTEMPTS, String.valueOf(100))); // Parse the max distances if provided Map maxDistanceByProfile = parseMaxDistances(cmd.getOptionValue("m"), profiles); @@ -132,13 +140,15 @@ public CoordinateGeneratorRoute createGenerator() { if (LOGGER.isInfoEnabled()) { LOGGER.info( - "Creating CoordinateGeneratorRoute with numRoutes={}, extent={}, profiles={}, baseUrl={}, minDistance={}, maxDistances={}, numThreads={}, snapRadius={}", + "Creating CoordinateGeneratorRoute with numRoutes={}, extent={}, profiles={}, baseUrl={}, minDistance={}, maxDistances={}, numThreads={}, snapRadius={}, maxAttempts={}", numRoutes, extent, java.util.Arrays.toString(profiles), baseUrl, minDistance, maxDistanceByProfile, - numThreads, snapRadius); + numThreads, snapRadius, maxAttempts); } - return new CoordinateGeneratorRoute(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, - numThreads, snapRadius); + CoordinateGeneratorRoute generator = new CoordinateGeneratorRoute(numRoutes, extent, profiles, baseUrl, + minDistance, maxDistanceByProfile, numThreads, snapRadius, maxAttempts); + generator.generate(); + return generator; } /** diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java index 547f0896cf..11d17b7ebf 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java @@ -8,6 +8,7 @@ public class SnappingCommandLineParser extends CommandLineParser { private static final Logger LOGGER = LoggerFactory.getLogger(SnappingCommandLineParser.class); + private static final String OPT_MAX_ATTEMPTS = "max-attempts"; public SnappingCommandLineParser(String[] args) { super(args); @@ -60,6 +61,13 @@ protected void setupOptions() { .hasArg() .desc("Output CSV file path") .build()); + + options.addOption(Option.builder("ma") + .longOpt(OPT_MAX_ATTEMPTS) + .hasArg() + .type(Number.class) + .desc("Maximum number of attempts for coordinate generation (default: 1000)") + .build()); } @Override @@ -88,12 +96,17 @@ public CoordinateGeneratorSnapping createGenerator() { String[] profiles = parseProfiles(cmd.getOptionValue("p")); double radius = Double.parseDouble(cmd.getOptionValue("r", "350")); String baseUrl = cmd.getOptionValue("u", "http://localhost:8080/ors"); + int maxAttempts = Integer.parseInt( + cmd.getOptionValue(OPT_MAX_ATTEMPTS, "100")); LOGGER.info( - "Creating CoordinateGeneratorSnapping with numPoints={}, extent={}, radius={}, profiles={}, baseUrl={}", - numPoints, extent, radius, profiles, baseUrl); + "Creating CoordinateGeneratorSnapping with numPoints={}, extent={}, radius={}, profiles={}, baseUrl={}, maxAttempts={}", + numPoints, extent, radius, profiles, baseUrl, maxAttempts); - return new CoordinateGeneratorSnapping(numPoints, extent, radius, profiles, baseUrl); + CoordinateGeneratorSnapping generator = new CoordinateGeneratorSnapping(numPoints, extent, radius, profiles, + baseUrl, maxAttempts); + generator.generate(); + return generator; } /** diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java index a069de13d5..c6d8499dee 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/AbstractCoordinateGenerator.java @@ -24,7 +24,6 @@ */ public abstract class AbstractCoordinateGenerator { protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractCoordinateGenerator.class); - protected static final int DEFAULT_MAX_ATTEMPTS = 10000; protected static final double COORDINATE_PRECISION = 1e-6; protected static final String DEFAULT_BASE_URL = "http://localhost:8082/ors"; @@ -35,6 +34,7 @@ public abstract class AbstractCoordinateGenerator { protected final Random random; protected final ObjectMapper mapper; protected final String apiKey; + protected final int maxAttempts; /** * Creates a new coordinate generator @@ -44,7 +44,8 @@ public abstract class AbstractCoordinateGenerator { * @param baseUrl API base URL * @param endpoint API endpoint name (for logging) */ - protected AbstractCoordinateGenerator(double[] extent, String[] profiles, String baseUrl, String endpoint) { + protected AbstractCoordinateGenerator(double[] extent, String[] profiles, String baseUrl, String endpoint, + int maxAttempts) { this.baseUrl = baseUrl != null ? baseUrl : DEFAULT_BASE_URL; validateBaseInputParameters(extent, profiles, endpoint); this.extent = extent; @@ -52,6 +53,7 @@ protected AbstractCoordinateGenerator(double[] extent, String[] profiles, String this.random = new SecureRandom(); this.mapper = new ObjectMapper(); this.apiKey = getApiKey(); + this.maxAttempts = maxAttempts; } private void validateBaseInputParameters(double[] extent, String[] profiles, String endpoint) { @@ -130,11 +132,6 @@ protected String processResponse(ClassicHttpResponse response) throws IOExceptio */ public abstract void writeToCSV(String filePath) throws IOException; - /** - * Main generation method with specified maximum attempts - */ - protected abstract void generate(int maxAttempts); - /** * Gets the generated results */ @@ -146,9 +143,8 @@ protected String processResponse(ClassicHttpResponse response) throws IOExceptio protected abstract void initializeCollections(); /** - * Main generation method with default maximum attempts + * Main generation method */ - public void generate() { - generate(DEFAULT_MAX_ATTEMPTS); - } + protected abstract void generate(); + } diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java index f9a94e82ee..7cf1c4c2dd 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrix.java @@ -48,8 +48,8 @@ public record MatrixDimensions(int numRows, int numCols) { public CoordinateGeneratorMatrix(int numMatrices, double[] extent, String[] profiles, String baseUrl, Map maxDistanceByProfile, - MatrixDimensions matrixDimensions, int numThreads, double snapRadius) { - super(extent, profiles, baseUrl, "matrix"); + MatrixDimensions matrixDimensions, int numThreads, double snapRadius, int maxAttempts) { + super(extent, profiles, baseUrl, "matrix", maxAttempts); validateInputs(numMatrices, numThreads); this.numMatrices = numMatrices; @@ -111,12 +111,12 @@ private Map normalizeMaxDistances(String[] profiles, Map= maxAttempts) { + if (attempts >= this.maxAttempts) { LOGGER.warn("Stopped route generation after {} attempts. Routes per profile: {}", - maxAttempts, matrixRepository.getProgressMessage()); + this.maxAttempts, matrixRepository.getProgressMessage()); } } diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java index f97bbef5f8..59c8f38d71 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRoute.java @@ -40,8 +40,8 @@ public class CoordinateGeneratorRoute extends AbstractCoordinateGenerator { public CoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, String baseUrl, double minDistance, Map maxDistanceByProfile, int numThreads, - double snapRadius) { - super(extent, profiles, baseUrl, "matrix"); + double snapRadius, int maxAttempts) { + super(extent, profiles, baseUrl, "matrix", maxAttempts); validateInputs(numRoutes, minDistance, numThreads); this.numRoutes = numRoutes; @@ -84,13 +84,9 @@ private Map normalizeMaxDistances(String[] profiles, Map= maxAttempts) { + if (attempts >= this.maxAttempts) { LOGGER.warn("Stopped route generation after {} attempts. Routes per profile: {}", - maxAttempts, routeRepository.getProgressMessage()); + this.maxAttempts, routeRepository.getProgressMessage()); } } diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java index 8cfd4e976a..e3a91a63c1 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnapping.java @@ -29,8 +29,8 @@ public class CoordinateGeneratorSnapping extends AbstractCoordinateGenerator { private final Map> uniquePointsByProfile; public CoordinateGeneratorSnapping(int numPoints, double[] extent, double radius, String[] profiles, - String baseUrl) { - super(extent, profiles, baseUrl, "snap"); + String baseUrl, int maxAttempts) { + super(extent, profiles, baseUrl, "snap", maxAttempts); if (numPoints <= 0) throw new IllegalArgumentException("Number of points must be positive"); if (radius <= 0) @@ -57,7 +57,7 @@ public CoordinateGeneratorSnapping(int numPoints, double[] extent, double radius } @Override - protected void generate(int maxAttempts) { + public void generate() { initializeCollections(); Map lastSizes = initializeLastSizes(); @@ -71,7 +71,7 @@ protected void generate(int maxAttempts) { try (ProgressBar pb = pbb.build()) { pb.setExtraMessage("Starting..."); - generatePoints(pb, lastSizes, maxAttempts); + generatePoints(pb, lastSizes); } catch (Exception e) { LOGGER.error("Error generating points", e); @@ -86,15 +86,14 @@ private Map initializeLastSizes() { return lastSizes; } - private void generatePoints(ProgressBar pb, Map lastSizes, - int maxAttempts) { + private void generatePoints(ProgressBar pb, Map lastSizes) { int attempts = 0; - while (!isGenerationComplete() && attempts < maxAttempts) { + while (!isGenerationComplete() && attempts < this.maxAttempts) { boolean newPointsFound = processProfiles(lastSizes); if (!newPointsFound) { attempts++; - pb.setExtraMessage(String.format("Attempt %d/%d - No new points", attempts, maxAttempts)); + pb.setExtraMessage(String.format("Attempt %d/%d - No new points", attempts, this.maxAttempts)); } else { updateProgress(pb); attempts = 0; @@ -102,9 +101,9 @@ private void generatePoints(ProgressBar pb, Map lastSizes, } pb.stepTo(getTotalPoints()); - if (attempts >= maxAttempts && LOGGER.isWarnEnabled()) { + if (attempts >= this.maxAttempts && LOGGER.isWarnEnabled()) { LOGGER.warn("Stopped point generation after {} attempts. Points per profile: {}", - maxAttempts, formatProgressMessage()); + this.maxAttempts, formatProgressMessage()); } } diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java index 8f0e1b017f..9462ab062f 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/RouteCommandLineParserTest.java @@ -351,4 +351,24 @@ void testSnapRadius() { assertEquals(3000.0, snapRadiusField.getDouble(snapper), 0.001); }); } + + @Test + void testMaxAttempts() { + String[] args = { + "-n", "50", + "-e", "8.6 49.3 8.7 49.4", + "-p", "driving-car", + "-m", "5000", + "-ma", "5" + }; + + RouteCommandLineParser cli = new RouteCommandLineParser(args); + CoordinateGeneratorRoute generator = cli.createGenerator(); + assertNotNull(generator); + + // No direct way to test maxAttempts after generation, as it's just a parameter + // passed to generate() + // We're verifying that the CLI parser correctly reads the value and the + // generator is created successfully + } } diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java index 7ede231b6d..4e475b67de 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java @@ -181,4 +181,23 @@ void testEmptyProfileList() { cli::createGenerator); assertNotNull(exception); } + + @Test + void testMaxAttempts() { + String[] args = { + "-n", "100", + "-e", "8.6 49.3 8.7 49.4", + "-p", "driving-car", + "-ma", "2000" + }; + + SnappingCommandLineParser cli = new SnappingCommandLineParser(args); + CoordinateGeneratorSnapping generator = cli.createGenerator(); + assertNotNull(generator); + + // No direct way to test maxAttempts after generation, as it's just a parameter + // passed to generate() + // We're verifying that the CLI parser correctly reads the value and the + // generator is created successfully + } } diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java index 73fc0b0738..f9fd5d893a 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorMatrixTest.java @@ -335,7 +335,7 @@ private static class TestCoordinateGeneratorMatrix extends CoordinateGeneratorMa public TestCoordinateGeneratorMatrix(int numRoutes, double[] extent, String[] profiles, String baseUrl, Map maxDistanceByProfile, MatrixDimensions matrixDimensions) { - super(numRoutes, extent, profiles, baseUrl, maxDistanceByProfile, matrixDimensions, 1, 1); + super(numRoutes, extent, profiles, baseUrl, maxDistanceByProfile, matrixDimensions, 1, 1, 1); } void setHttpClient(CloseableHttpClient client) { diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java index 38e553f214..201b4fbea1 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorRouteTest.java @@ -148,7 +148,7 @@ void testGenerateRoutesSuccessful() throws Exception { }); // Execute test - testGenerator.generateRoutes(); + testGenerator.generate(); // Verify results List result = testGenerator.getResult(); @@ -203,7 +203,7 @@ void testMultipleProfiles() throws Exception { }); // Execute test - testGenerator.generateRoutes(); + testGenerator.generate(); // Verify results List result = testGenerator.getResult(); @@ -248,7 +248,7 @@ void testWriteCSVToFile(@TempDir Path tempDir) throws Exception { }); // Execute test - testGenerator.generateRoutes(); + testGenerator.generate(); // Write results to CSV String filename = tempDir.resolve("test_routes.csv").toString(); @@ -312,7 +312,7 @@ void testMinimumDistanceFiltering() throws Exception { }); // Execute test - generator.generateRoutes(); + generator.generate(); // Verify all routes meet minimum distance requirement List result = generator.getResult(); @@ -365,7 +365,7 @@ private static class TestCoordinateGeneratorRoute extends CoordinateGeneratorRou public TestCoordinateGeneratorRoute(int numRoutes, double[] extent, String[] profiles, String baseUrl, double minDistance, Map maxDistanceByProfile) { - super(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, 1, 1); + super(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile, 1, 1, 1); } void setHttpClient(CloseableHttpClient client) { diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnappingTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnappingTest.java index 4014d66386..d9c857c58a 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnappingTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/generators/CoordinateGeneratorSnappingTest.java @@ -154,7 +154,7 @@ private class TestCoordinateGeneratorSnapping extends CoordinateGeneratorSnappin public TestCoordinateGeneratorSnapping(int numPoints, double[] extent, double radius, String[] profiles, String baseUrl) { - super(numPoints, extent, radius, profiles, baseUrl); + super(numPoints, extent, radius, profiles, baseUrl, 1); } void setHttpClient(CloseableHttpClient client) { From fd61f4a5fec4c563beeeb48854dd8a6d67ac50df Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 14 May 2025 17:25:21 +0200 Subject: [PATCH 9/9] feat: update snap radius and max attempts options in command line parser and tests --- .../api-benchmarks/coordinate-generators.md | 18 +++--- .../cli/SnappingCommandLineParser.java | 14 ++--- .../cli/SnappingCommandLineParserTest.java | 58 ++++++++++++++++++- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/docs/technical-details/api-benchmarks/coordinate-generators.md b/docs/technical-details/api-benchmarks/coordinate-generators.md index 04e66fe21b..3ebcb942a9 100644 --- a/docs/technical-details/api-benchmarks/coordinate-generators.md +++ b/docs/technical-details/api-benchmarks/coordinate-generators.md @@ -1,6 +1,10 @@ # Coordinate Generation Tools -The openrouteservice provides tools for generating test coordinates that can be used for benchmarking, testing, and development purposes. These tools allow you to create realistic coordinates that are compatible with the openrouteservice API and suited for different routing profiles. +The openroutes| `-r, --snap-radius` | Search radius in meters for coordinate snapping. | 350 | +| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 100 |vice provides tools for +generating test coordinates that can be used for benchmarking, testing, and development purposes. These tools allow you +to create realistic coordinates that are compatible with the openrouteservice API and suited for different routing +profiles. ## Prerequisites @@ -43,8 +47,8 @@ The tool generates random coordinates within a specified bounding box and then u | `-d, --min-distance` | Minimum distance between start and endpoint in an a-to-b routing pair in meters. This is valid for all profiles. | 1 | | `-m, --max-distances` | Maximum distances in meters **per profile** between the start and endpoint. | (none) | | `-t, --threads` | Number of threads to use. | Available processors | -| `-sr, --snap-radius` | Search radius in meters for coordinate snapping. | 1000 | -| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 1000 | +| `-sr, --snap-radius` | Search radius in meters for coordinate snapping. | 350 | +| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 100 | ### Route Generator Examples @@ -101,10 +105,10 @@ The tool generates random coordinates within a specified bounding box and then u | `-n, --num-points` | Number of points to generate per profile. | (required) | | `-e, --extent` | Bounding box (minLon,minLat,maxLon,maxLat). | (required) | | `-p, --profiles` | Comma-separated list of routing profiles. | (required) | -| `-r, --radius` | Search radius in meters. | 350 | +| `-sr, --snap-radius` | Search radius in metersfor coordinate snapping. | 350 | | `-u, --url` | ORS API base URL. | | | `-o, --output` | Output CSV file path. | snapped_coordinates.csv | -| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 1000 | +| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 100 | ### Snapping Generator Examples @@ -119,7 +123,7 @@ Generate 100 snapped points for the driving-car profile with a search radius of -n 100 \ -e 8.6,49.3,8.7,49.4 \ -p driving-car \ - -r 500 \ + -sr 500 \ -u http://localhost:8080/ors \ -o snapped.csv" ``` @@ -135,7 +139,7 @@ Generate 50 snapped points for both driving-car and cycling-regular profiles: --num-points 50 \ --extent 8.681495,49.411721,8.695485,49.419365 \ --profiles driving-car,cycling-regular \ - --radius 250 \ + --snap-radius 250 \ --max-attempts 1500 \ --url http://localhost:8080/ors \ --output snapped.csv" diff --git a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java index 11d17b7ebf..d1d59cc5c8 100644 --- a/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java +++ b/ors-benchmark/src/main/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParser.java @@ -36,8 +36,8 @@ protected void setupOptions() { .desc("Bounding box (minLon minLat maxLon maxLat)") .build()); - options.addOption(Option.builder("r") - .longOpt("radius") + options.addOption(Option.builder("sr") + .longOpt("snap-radius") .hasArg() .type(Number.class) .desc("Search radius in meters (default: 350)") @@ -66,7 +66,7 @@ protected void setupOptions() { .longOpt(OPT_MAX_ATTEMPTS) .hasArg() .type(Number.class) - .desc("Maximum number of attempts for coordinate generation (default: 1000)") + .desc("Maximum number of attempts for coordinate generation (default: 100)") .build()); } @@ -94,16 +94,16 @@ public CoordinateGeneratorSnapping createGenerator() { int numPoints = Integer.parseInt(cmd.getOptionValue("n")); double[] extent = parseExtent(cmd.getOptionValue("e")); String[] profiles = parseProfiles(cmd.getOptionValue("p")); - double radius = Double.parseDouble(cmd.getOptionValue("r", "350")); + double snapRadius = Double.parseDouble(cmd.getOptionValue("sr", "350")); String baseUrl = cmd.getOptionValue("u", "http://localhost:8080/ors"); int maxAttempts = Integer.parseInt( cmd.getOptionValue(OPT_MAX_ATTEMPTS, "100")); LOGGER.info( - "Creating CoordinateGeneratorSnapping with numPoints={}, extent={}, radius={}, profiles={}, baseUrl={}, maxAttempts={}", - numPoints, extent, radius, profiles, baseUrl, maxAttempts); + "Creating CoordinateGeneratorSnapping with numPoints={}, extent={}, snapRadius={}, profiles={}, baseUrl={}, maxAttempts={}", + numPoints, extent, snapRadius, profiles, baseUrl, maxAttempts); - CoordinateGeneratorSnapping generator = new CoordinateGeneratorSnapping(numPoints, extent, radius, profiles, + CoordinateGeneratorSnapping generator = new CoordinateGeneratorSnapping(numPoints, extent, snapRadius, profiles, baseUrl, maxAttempts); generator.generate(); return generator; diff --git a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java index 4e475b67de..c238d086d0 100644 --- a/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java +++ b/ors-benchmark/src/test/java/org/heigit/ors/coordinates_generator/cli/SnappingCommandLineParserTest.java @@ -2,11 +2,14 @@ import org.heigit.ors.benchmark.exceptions.CommandLineParsingException; import org.heigit.ors.coordinates_generator.generators.CoordinateGeneratorSnapping; +import org.heigit.ors.coordinates_generator.service.CoordinateSnapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; +import java.lang.reflect.Field; + import static org.junit.jupiter.api.Assertions.*; class SnappingCommandLineParserTest { @@ -17,8 +20,8 @@ void testValidCliArguments() { "-n", "100", "-e", "8.6,49.3,8.7,49.4", "-p", "driving-car,cycling-regular", - "-r", "350", - "-u", "http://localhost:8080/ors" + "-sr", "350", + "-u", "http://localhost:8080/ors" }; SnappingCommandLineParser cli = new SnappingCommandLineParser(args); @@ -200,4 +203,55 @@ void testMaxAttempts() { // We're verifying that the CLI parser correctly reads the value and the // generator is created successfully } + + @Test + void testSnapRadius() { + String[] args = { + "-n", "100", + "-e", "8.6 49.3 8.7 49.4", + "-p", "driving-car", + "-sr", "500" + }; + + SnappingCommandLineParser cli = new SnappingCommandLineParser(args); + CoordinateGeneratorSnapping generator = cli.createGenerator(); + assertNotNull(generator); + + // Test snapRadius using reflection to verify it was correctly passed to the + // coordinate snapper + assertDoesNotThrow(() -> { + Field coordinateSnapperField = CoordinateGeneratorSnapping.class.getDeclaredField("coordinateSnapper"); + coordinateSnapperField.setAccessible(true); + CoordinateSnapper snapper = (CoordinateSnapper) coordinateSnapperField.get(generator); + + Field snapRadiusField = CoordinateSnapper.class.getDeclaredField("snapRadius"); + snapRadiusField.setAccessible(true); + assertEquals(500.0, snapRadiusField.getDouble(snapper), 0.001, "Snap radius should be set correctly"); + }); + } + + @Test + void testDefaultSnapRadius() { + String[] args = { + "-n", "100", + "-e", "8.6 49.3 8.7 49.4", + "-p", "driving-car" + // No -sr parameter, should use default value + }; + + SnappingCommandLineParser cli = new SnappingCommandLineParser(args); + CoordinateGeneratorSnapping generator = cli.createGenerator(); + assertNotNull(generator); + + // Test snapRadius using reflection to verify the default value was used + assertDoesNotThrow(() -> { + Field coordinateSnapperField = CoordinateGeneratorSnapping.class.getDeclaredField("coordinateSnapper"); + coordinateSnapperField.setAccessible(true); + CoordinateSnapper snapper = (CoordinateSnapper) coordinateSnapperField.get(generator); + + Field snapRadiusField = CoordinateSnapper.class.getDeclaredField("snapRadius"); + snapRadiusField.setAccessible(true); + assertEquals(350.0, snapRadiusField.getDouble(snapper), 0.001, "Default snap radius should be 350"); + }); + } }