diff --git a/docs/technical-details/api-benchmarks/coordinate-generators.md b/docs/technical-details/api-benchmarks/coordinate-generators.md
index e4e99bdf58..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
@@ -33,16 +37,18 @@ 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. | 350 |
+| `-ma, --max-attempts` | Maximum number of attempts for coordinate generation. | 100 |
### Route Generator Examples
@@ -76,6 +82,8 @@ 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 \
+ --max-attempts 1500 \
--url http://localhost:8080/ors \
--output routes.csv"
```
@@ -92,14 +100,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) |
+| `-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. | 100 |
### Snapping Generator Examples
@@ -114,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"
```
@@ -130,7 +139,8 @@ 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/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 0694605b89..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
@@ -13,6 +13,8 @@ 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 String OPT_MAX_ATTEMPTS = "max-attempts";
private static final int DEFAULT_THREAD_COUNT = Runtime.getRuntime().availableProcessors();
public RouteCommandLineParser(String[] args) {
@@ -72,12 +74,25 @@ 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()
.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());
+
+ 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
@@ -115,6 +130,8 @@ 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"));
+ 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);
@@ -123,13 +140,15 @@ 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={}, maxAttempts={}",
numRoutes, extent, java.util.Arrays.toString(profiles), baseUrl, minDistance, maxDistanceByProfile,
- numThreads);
+ numThreads, snapRadius, maxAttempts);
}
- return new CoordinateGeneratorRoute(numRoutes, extent, profiles, baseUrl, minDistance, maxDistanceByProfile,
- numThreads);
+ 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..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
@@ -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);
@@ -35,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)")
@@ -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: 100)")
+ .build());
}
@Override
@@ -86,14 +94,19 @@ 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={}",
- numPoints, extent, radius, profiles, baseUrl);
+ "Creating CoordinateGeneratorSnapping with numPoints={}, extent={}, snapRadius={}, profiles={}, baseUrl={}, maxAttempts={}",
+ numPoints, extent, snapRadius, profiles, baseUrl, maxAttempts);
- return new CoordinateGeneratorSnapping(numPoints, extent, radius, profiles, baseUrl);
+ CoordinateGeneratorSnapping generator = new CoordinateGeneratorSnapping(numPoints, extent, snapRadius, 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 f2bb4d5d8e..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 = 100;
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) {
@@ -105,16 +107,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) {
+ LOGGER.debug("Received empty response");
return null;
}
@@ -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 2253e51668..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
@@ -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,16 +46,10 @@ 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) {
- super(extent, profiles, baseUrl, "matrix");
+ Map maxDistanceByProfile,
+ MatrixDimensions matrixDimensions, int numThreads, double snapRadius, int maxAttempts) {
+ super(extent, profiles, baseUrl, "matrix", maxAttempts);
validateInputs(numMatrices, numThreads);
this.numMatrices = numMatrices;
@@ -71,13 +64,13 @@ 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;
}
};
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);
}
@@ -118,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());
}
}
@@ -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 0404d9a61f..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
@@ -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,14 +37,11 @@ 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) {
- super(extent, profiles, baseUrl, "matrix");
+ double minDistance, Map maxDistanceByProfile, int numThreads,
+ double snapRadius, int maxAttempts) {
+ super(extent, profiles, baseUrl, "matrix", maxAttempts);
validateInputs(numRoutes, minDistance, numThreads);
this.numRoutes = numRoutes;
@@ -55,16 +51,19 @@ 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());
+ LOGGER.debug("Error executing request: {}", e.getMessage());
return null;
}
};
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);
}
@@ -85,14 +84,11 @@ private Map normalizeMaxDistances(String[] profiles, Map> 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());
+ finalizeProgress(pb, consecutiveFailedAttempts.get());
+ LOGGER.debug("executeRouteGeneration: Finalized progress.");
}
}
@@ -158,16 +167,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;
}
@@ -177,11 +190,11 @@ private void updateProgressBar(ProgressBar pb) {
pb.setExtraMessage(routeRepository.getProgressMessage());
}
- private void finalizeProgress(ProgressBar pb, int maxAttempts, int attempts) {
+ private void finalizeProgress(ProgressBar pb, int attempts) {
pb.stepTo(routeRepository.getTotalRouteCount());
- if (attempts >= maxAttempts) {
+ if (attempts >= this.maxAttempts) {
LOGGER.warn("Stopped route generation after {} attempts. Routes per profile: {}",
- maxAttempts, routeRepository.getProgressMessage());
+ this.maxAttempts, routeRepository.getProgressMessage());
}
}
@@ -210,131 +223,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