Summary
The ABM — spawning agents near a central point in Germany — sometimes places them on water polygons. These agents instantly route to the target, breaking the intended pedestrian dynamics. The root cause is that the random distribution is calculated purely on latitude‑longitude space, ignoring land‑sea boundaries defined in the GIS data.
Root Cause
- Latitude‑longitude RNG: Points are generated by adding random offsets to a central coordinate without checking the map’s geometry.
- Absence of land filtering: The GIS region tool offers a
generateRandomPoint()that respects land polygons, but it cannot be directly constrained to a distance from a custom point. - Edge cases near coastlines: Small offsets can easily cross into adjacent water bodies, especially where coastlines are complex or the distance radius is large.
Why This Happens in Real Systems
- Simplified spatial models ignore land/sea constraints for performance or rapid prototyping.
- Distributed agent creation often relies on simple statistical spreads, but GIS layers contain intricate shapes that are not considered.
- Deployment to production: If unfiltered, agents may be placed outside mandatory zones, causing routing errors and unrealistic simulations.
Real-World Impact
- Routing anomalies: Agents on water are redirected immediately, leading to non‑representative travel paths.
- Data distortion: Metrics such as average speed, travel time, and congestion are skewed.
- User trust erosion: Stakeholders expect accurate geography‑aware behavior; inconsistent results reduce confidence.
Example or Code (if necessary and relevant)
// Create a buffered polygon (central point + radius)
Polygon searchArea = GeometryUtils.createBufferedShape(
centerLatitude, centerLongitude, radiusInMeters);
// Filter only land polygons
List landPolygons = gisRegion.getPolygons().stream()
.filter(p -> p.contains(searchArea))
.collect(Collectors.toList());
// Generate one random point inside the filtered polygons
Point p = GISUtils.generateRandomPointWithin(landPolygons);
agent.setLocation(p.getLatitude(), p.getLongitude());
The code uses helper functions (createBufferedShape, generateRandomPointWithin) that perform geometric operations and ensure the new point lies on land.
How Senior Engineers Fix It
- Use GIS region’s
generateRandomPointWithin(): Pass the buffered polygon as a constraint. - Pre‑filter land polygons around the central point to reduce computation time.
- Validate each point: After generation, check
gisRegion.isPointOnLand()before assigning it to an agent. - Iterative retry: If a point falls on water, regenerate until a land point is found.
Why Juniors Miss It
- Assumption that random offset ≈ random on land: Ignoring that GIS layers can be non‑contiguous.
- Overlooking helper functions: Junior code often bypasses built‑in GIS utilities to cut lines of code.
- Neglecting validation: Without a sanity check, water points slip through unnoticed until later stages.
- Performance anxiety: Adding land checks is perceived as an overhead, leading to quick fixes that omit spatial safety.