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 23, 2023
1 parent ce85ca3 commit 3c17493
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 24 deletions.
11 changes: 7 additions & 4 deletions src/main/java/org/matsim/run/RunLeipzigScenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,9 @@ protected void prepareScenario(Scenario scenario) {
if (networkOpt.hasDrtArea()) {
DrtCaseSetup.prepareScenario(scenario, drtCase, new ShpOptions(networkOpt.getDrtArea(), null, null), VERSION);
}

if(networkOpt.hasCarFreeArea()){
PreparePopulation.deleteCarAndRideRoutesThatHaveForbiddenLinks(scenario.getPopulation(), networkOpt.getNonPtLinksInCarFreeArea(scenario.getNetwork()));
}

}

Expand Down Expand Up @@ -314,9 +316,10 @@ public void install() {
// Normally this is bound with the default subtour mode choice, because we use our own variant this is bound again here
bind(PermissibleModesCalculator.class).to(PermissibleModesCalculatorImpl.class);

if (networkOpt.hasCarFreeArea()) {
bind(MultimodalLinkChooser.class).to(CarfreeMultimodalLinkChooser.class);
}
//this is obsolete, the default implementation covers all the functionality of CarfreeMultimodalLinkChooser
// if (networkOpt.hasCarFreeArea()) {
// bind(MultimodalLinkChooser.class).to(CarfreeMultimodalLinkChooser.class);
// }

if (networkOpt.hasParkingCostArea()) {

Expand Down
21 changes: 18 additions & 3 deletions src/main/java/org/matsim/run/prepare/NetworkOptions.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.matsim.run.prepare;

import org.matsim.api.core.v01.Id;
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.options.ShpOptions;
import org.matsim.core.utils.io.IOUtils;
Expand All @@ -10,6 +12,7 @@

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 +25,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 @@ -103,7 +106,7 @@ 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);
}
}
}
Expand All @@ -119,4 +122,16 @@ private boolean isDefined(Path p) {
return p != null;
}

/**
* returns ids for all links inside the car free area that do not allow public transport
* @param network
* @return
*/
public Set<Id<Link>> getNonPtLinksInCarFreeArea(Network network) {
if (!hasCarFreeArea()){
return null;
}
return PrepareNetwork.getFilteredLinksInArea(network, new ShpOptions(carFreeArea, null, null), l -> !l.getAllowedModes().contains(TransportMode.pt));
}

}
61 changes: 45 additions & 16 deletions src/main/java/org/matsim/run/prepare/PrepareNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
Expand All @@ -21,6 +22,7 @@

import java.nio.file.Path;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@CommandLine.Command(
Expand Down Expand Up @@ -120,12 +122,50 @@ static void prepareDRT(Network network, ShpOptions shp, String modes) {
static void prepareCarFree(Network network, ShpOptions shp, String modes) {
Set<String> modesToRemove = new HashSet<>(Arrays.asList(modes.split(",")));

//get all links in shp that allow at least one of modesToRemove
Set<Id<Link>> modeLinksInArea = getFilteredLinksInArea(network, shp,
link -> link.getAllowedModes().stream().anyMatch(mode -> modesToRemove.contains(mode)));
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
*/
private 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 in the network that are inside the shp and fulfill the predicate
* @param network
* @param shp
* @param filter
* @return
*/
static Set<Id<Link>> getFilteredLinksInArea(Network network, ShpOptions shp, Predicate<Link> filter) {

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(!filter.test(link)){
continue;
}

Expand All @@ -135,22 +175,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
30 changes: 29 additions & 1 deletion src/main/java/org/matsim/run/prepare/PreparePopulation.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.population.*;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.options.ShpOptions;
import org.matsim.core.population.PersonUtils;
import org.matsim.core.population.PopulationUtils;
import org.matsim.core.population.routes.NetworkRoute;
import org.matsim.core.router.TripStructureUtils;
import org.matsim.core.scenario.ProjectionUtils;
import org.matsim.run.RunLeipzigScenario;
Expand Down Expand Up @@ -215,7 +218,32 @@ private Coord setHomeCoordinate(Person person) {
return null;
}


enum Phase {pre, post}

/**
* @param population
* @param forbiddenLinks
*/
//TODO remove hardcoding of the transport modes??
public 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");
}

}

0 comments on commit 3c17493

Please sign in to comment.