From c2bc9a487a1d88e22840c7d3219c2073ab8c6c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 5 Dec 2023 07:55:11 +0100 Subject: [PATCH] feat: Control car departure access (#154) * Only allow access to/from car on viable links * Update tag --- .../preparation/FacilityPlacement.java | 58 +++++++++++++++++-- .../scenario/preparation/RunPreparation.java | 4 +- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/preparation/FacilityPlacement.java b/core/src/main/java/org/eqasim/core/scenario/preparation/FacilityPlacement.java index bd96fc4b6..949a47a78 100644 --- a/core/src/main/java/org/eqasim/core/scenario/preparation/FacilityPlacement.java +++ b/core/src/main/java/org/eqasim/core/scenario/preparation/FacilityPlacement.java @@ -3,11 +3,13 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import org.eqasim.core.misc.ParallelProgress; import org.eqasim.core.scenario.cutter.network.RoadNetwork; import org.matsim.api.core.v01.network.Link; -import org.matsim.core.network.NetworkUtils; +import org.matsim.core.utils.collections.QuadTree; +import org.matsim.core.utils.collections.QuadTrees; import org.matsim.facilities.ActivityFacilities; import org.matsim.facilities.ActivityFacility; import org.matsim.facilities.ActivityFacilityImpl; @@ -15,12 +17,14 @@ public class FacilityPlacement { private final int numberOfThreads; private final int batchSize; - private final RoadNetwork network; + private final QuadTree spatialIndex; - public FacilityPlacement(int numberOfThreads, int batchSize, RoadNetwork network) { - this.network = network; + public FacilityPlacement(int numberOfThreads, int batchSize, RoadNetwork network, FacilityPlacementVoter voter) { this.numberOfThreads = numberOfThreads; this.batchSize = batchSize; + + this.spatialIndex = QuadTrees.createQuadTree( + network.getLinks().values().stream().filter(voter::canPlaceFacility).collect(Collectors.toList())); } public void run(ActivityFacilities facilities) throws InterruptedException { @@ -69,7 +73,7 @@ public void run() { } for (ActivityFacility facility : localTasks) { - Link link = NetworkUtils.getNearestLink(network, facility.getCoord()); + Link link = spatialIndex.getClosest(facility.getCoord().getX(), facility.getCoord().getY()); ((ActivityFacilityImpl) facility).setLinkId(link.getId()); } @@ -77,4 +81,48 @@ public void run() { } while (localTasks.size() > 0); } } + + static public interface FacilityPlacementVoter { + boolean canPlaceFacility(Link link); + } + + static public class OSMFacilityPlacementVoter implements FacilityPlacementVoter { + private final static String HIGHWAY_TAG = "osm:way:highway"; + + public OSMFacilityPlacementVoter(RoadNetwork network) { + boolean foundAttribute = false; + + for (Link link : network.getLinks().values()) { + if (link.getAttributes().getAttribute(HIGHWAY_TAG) != null) { + foundAttribute = true; + break; + } + } + + if (!foundAttribute) { + throw new IllegalStateException("Did not find osm:highway attribute in network"); + } + } + + @Override + public boolean canPlaceFacility(Link link) { + String highway = (String) link.getAttributes().getAttribute(HIGHWAY_TAG); + + if (highway != null) { + if (highway.contains("motorway")) { + return false; + } + + if (highway.contains("trunk")) { + return false; + } + + if (highway.contains("_link")) { + return false; + } + } + + return true; + } + } } diff --git a/core/src/main/java/org/eqasim/core/scenario/preparation/RunPreparation.java b/core/src/main/java/org/eqasim/core/scenario/preparation/RunPreparation.java index e128b7b3f..29bbfe8fd 100644 --- a/core/src/main/java/org/eqasim/core/scenario/preparation/RunPreparation.java +++ b/core/src/main/java/org/eqasim/core/scenario/preparation/RunPreparation.java @@ -1,6 +1,7 @@ package org.eqasim.core.scenario.preparation; import org.eqasim.core.scenario.cutter.network.RoadNetwork; +import org.eqasim.core.scenario.preparation.FacilityPlacement.OSMFacilityPlacementVoter; import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; @@ -33,7 +34,8 @@ static public void main(String[] args) throws ConfigurationException, Interrupte int batchSize = cmd.getOption("batch-size").map(Integer::parseInt).orElse(10); RoadNetwork roadNetwork = new RoadNetwork(scenario.getNetwork()); - FacilityPlacement facilityPlacement = new FacilityPlacement(numberOfThreads, batchSize, roadNetwork); + OSMFacilityPlacementVoter voter = new OSMFacilityPlacementVoter(roadNetwork); + FacilityPlacement facilityPlacement = new FacilityPlacement(numberOfThreads, batchSize, roadNetwork, voter); facilityPlacement.run(scenario.getActivityFacilities()); // Fix freight activities (TODO: should go to the pipeline)