Skip to content

Commit

Permalink
fix: delete routes that contain forbidden links instead of using cust…
Browse files Browse the repository at this point in the history
…om ModalLinkChooser
  • Loading branch information
tschlenther committed Nov 22, 2023
1 parent c90772a commit ae4a61a
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 26 deletions.
8 changes: 5 additions & 3 deletions src/main/java/org/matsim/run/RunLeipzigScenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
import org.matsim.core.controler.Controler;
import org.matsim.core.population.algorithms.PermissibleModesCalculator;
import org.matsim.core.population.algorithms.PermissibleModesCalculatorImpl;
import org.matsim.core.population.routes.NetworkRoute;
import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule;
import org.matsim.core.router.AnalysisMainModeIdentifier;
import org.matsim.core.router.MultimodalLinkChooser;
import org.matsim.core.router.TripStructureUtils;
import org.matsim.core.scoring.functions.ScoringParametersForPerson;
import org.matsim.run.prepare.*;
Expand Down Expand Up @@ -275,8 +275,9 @@ protected Config prepareConfig(Config config) {
@Override
protected void prepareScenario(Scenario scenario) {
//this has to be executed before DrtCaseSetup.prepareScenario() as the latter method relies on the drt mode being added to the network
networkOpt.prepare(scenario.getNetwork());
networkOpt.prepare(scenario);
// (passt das Netz an aus den mitgegebenen shape files, z.B. parking area, car-free area, ...)
// edited such that it also (conditionally) removes routes from the population.... ts nov' 22 2023

if (networkOpt.hasDrtArea()) {
DrtCaseSetup.prepareScenario(scenario, drtCase, new ShpOptions(networkOpt.getDrtArea(), null, null), VERSION);
Expand Down Expand Up @@ -315,7 +316,8 @@ public void install() {
bind(PermissibleModesCalculator.class).to(PermissibleModesCalculatorImpl.class);

if (networkOpt.hasCarFreeArea()) {
bind(MultimodalLinkChooser.class).to(CarfreeMultimodalLinkChooser.class);
//the default implementation actually covers the functionality of CarfreeMultimodalLinkChooser
// bind(MultimodalLinkChooser.class).to(CarfreeMultimodalLinkChooser.class);
}

if (networkOpt.hasParkingCostArea()) {
Expand Down
45 changes: 40 additions & 5 deletions src/main/java/org/matsim/run/prepare/NetworkOptions.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package org.matsim.run.prepare;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Population;
import org.matsim.api.core.v01.population.Route;
import org.matsim.application.options.ShpOptions;
import org.matsim.core.population.routes.NetworkRoute;
import org.matsim.core.router.TripStructureUtils;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.run.RunLeipzigScenario;
import org.matsim.utils.gis.shp2matsim.ShpGeometryUtils;
import picocli.CommandLine;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;

/**
* Defines all options and parameters related to network modifications.
Expand All @@ -22,8 +30,8 @@ public class NetworkOptions {
private String drtModes;
@CommandLine.Option(names = "--car-free-area", description = "Path to SHP file specifying car-free area")
private Path carFreeArea;
@CommandLine.Option(names = "--car-free-modes", description = "List of modes to remove. Use comma as delimiter", defaultValue = TransportMode.car)
private String carFreeModes;
@CommandLine.Option(names = "--car-free-modes-to-delete", description = "List of modes to remove. Use comma as delimiter", defaultValue = TransportMode.car + "," + TransportMode.ride)
private String carFreeModesToDelete;
@CommandLine.Option(names = "--parking-capacities-area", description = "Path to SHP file specifying parking area for adding parking capacities")
private Path parkingCapacitiesArea;
@CommandLine.Option(names = "--parking-capacities-input", description = "Path to csv file containing parking capacity data per link")
Expand Down Expand Up @@ -59,8 +67,8 @@ public boolean hasParkingCostArea() {
/**
* Prepare network with given options.
*/
public void prepare(Network network) {

public void prepare(Scenario scenario) {
Network network = scenario.getNetwork();
if (hasDrtArea()) {
if (!Files.exists(drtArea)) {
throw new IllegalArgumentException("Path to drt area not found: " + drtArea);
Expand Down Expand Up @@ -103,11 +111,38 @@ public void prepare(Network network) {
if (!Files.exists(carFreeArea)) {
throw new IllegalArgumentException("Path to car free area not found: " + carFreeArea);
} else {
PrepareNetwork.prepareCarFree(network, new ShpOptions(carFreeArea, null, null), carFreeModes);
// PrepareNetwork.prepareCarFree(network, new ShpOptions(carFreeArea, null, null), carFreeModesToDelete);
Set<Id<Link>> forbiddenLinks = PrepareNetwork.getModesLinksInArea(network, carFreeModesToDelete, new ShpOptions(carFreeArea, null, null));
PrepareNetwork.deleteModesFromLinks(network, forbiddenLinks, carFreeModesToDelete);
deleteCarAndRideRoutesThatHaveForbiddenLinks(scenario.getPopulation(), forbiddenLinks);
}
}
}


private static void deleteCarAndRideRoutesThatHaveForbiddenLinks(Population population, Set<Id<Link>> forbiddenLinks) {
// log.info("start deleting every car route that travels one or more links within car-free-zone");

population.getPersons().values().stream()
.forEach(person -> person.getPlans().stream().flatMap(plan ->
TripStructureUtils.getLegs(plan).stream())
.forEach(leg -> {
if(leg.getMode().equals(TransportMode.car) || leg.getMode().equals(TransportMode.ride)){
Route route = leg.getRoute();
if (route != null){
boolean routeTouchesZone = (route instanceof NetworkRoute && ((NetworkRoute) route).getLinkIds().stream().filter(l -> forbiddenLinks.contains(l)).findAny().isPresent() );
if(routeTouchesZone || forbiddenLinks.contains(route.getStartLinkId()) || forbiddenLinks.contains(route.getEndLinkId()) ){
leg.setRoute(null);
}
}
}
}));

// log.info(".... finished deleting every car route that travels one or more links within car-free-zone");
}



/**
* Return path to drt area.
*/
Expand Down
67 changes: 49 additions & 18 deletions src/main/java/org/matsim/run/prepare/PrepareNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
import org.apache.logging.log4j.Logger;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.options.ShpOptions;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.network.algorithms.MultimodalNetworkCleaner;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.geometry.geotools.MGC;
import org.matsim.core.utils.gis.ShapeFileReader;
import org.matsim.run.LeipzigUtils;
Expand Down Expand Up @@ -46,9 +50,10 @@ public static void main(String[] args) {
@Override
public Integer call() throws Exception {

Network network = NetworkUtils.readNetwork(networkFile);
options.prepare(network);
NetworkUtils.writeNetwork(network, outputPath);
Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig());
NetworkUtils.readNetwork(scenario.getNetwork(), networkFile);
options.prepare(scenario);
NetworkUtils.writeNetwork(scenario.getNetwork(), outputPath);

return 0;
}
Expand Down Expand Up @@ -114,18 +119,55 @@ static void prepareDRT(Network network, ShpOptions shp, String modes) {
log.log(Level.INFO, "The following modes have been added to the network: {}", modes);
}

@Deprecated
/**
* Adapt network to one or more car-free zones. Therefore, a shape file of the wished car-free area is needed.
*/
static void prepareCarFree(Network network, ShpOptions shp, String modes) {

Set<Id<Link>> modeLinksInArea = getModesLinksInArea(network, modes, shp);
deleteModesFromLinks(network, modeLinksInArea, modes);

log.info("Car free areas have been added to network.");
}

/**
*
* @param network
* @param linkIds
* @param modes provide modes with comma as a separator
*/
static void deleteModesFromLinks(Network network, Set<Id<Link>> linkIds, String modes){
Set<String> modesToRemove = new HashSet<>(Arrays.asList(modes.split(",")));
for(Id<Link> linkId: linkIds){
Link link = network.getLinks().get(linkId);
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());
for (String mode : modesToRemove) {
allowedModes.remove(mode);
}
link.setAllowedModes(allowedModes);
}

MultimodalNetworkCleaner multimodalNetworkCleaner = new MultimodalNetworkCleaner(network);
modesToRemove.forEach(m -> multimodalNetworkCleaner.run(Set.of(m)));
}

/**
* return all links inside the shp that contain one of the given modes
* @param network
* @param modes provide modes with comma as a separator
* @param shp
* @return
*/
static Set<Id<Link>> getModesLinksInArea(Network network, String modes, ShpOptions shp) {
Set<String> modesToRemove = new HashSet<>(Arrays.asList(modes.split(",")));
Geometry carFreeArea = shp.getGeometry();
GeometryFactory gf = new GeometryFactory();
Set<Id<Link>> modeLinksInArea = new HashSet<>();

for (Link link : network.getLinks().values()) {

if (!link.getAllowedModes().contains(TransportMode.car)) {
if (!link.getAllowedModes().stream().noneMatch(mode -> modesToRemove.contains(mode))) {
continue;
}

Expand All @@ -135,22 +177,11 @@ static void prepareCarFree(Network network, ShpOptions shp, String modes) {
});

boolean isInsideCarFreeZone = line.intersects(carFreeArea);

if (isInsideCarFreeZone) {
Set<String> allowedModes = new HashSet<>(link.getAllowedModes());

for (String mode : modesToRemove) {
allowedModes.remove(mode);
}
link.setAllowedModes(allowedModes);
if(isInsideCarFreeZone){
modeLinksInArea.add(link.getId());
}
}

MultimodalNetworkCleaner multimodalNetworkCleaner = new MultimodalNetworkCleaner(network);
modesToRemove.forEach(m -> multimodalNetworkCleaner.run(Set.of(m)));

log.info("Car free areas have been added to network.");

return modeLinksInArea;
}

/**
Expand Down

0 comments on commit ae4a61a

Please sign in to comment.