chosenCandidates = modeChoiceModel.chooseModes(plan.getPerson(), trips, random);
+
+ for (int i = 0; i < trips.size(); i++) {
+ DiscreteModeChoiceTrip trip = trips.get(i);
+ TripCandidate candidate = chosenCandidates.get(i);
+
+ List extends PlanElement> insertElements;
+
+ if (candidate instanceof RoutedTripCandidate) {
+ RoutedTripCandidate routedCandidate = (RoutedTripCandidate) candidate;
+ insertElements = routedCandidate.getRoutedPlanElements();
+ } else {
+ Leg insertLeg = populationFactory.createLeg(candidate.getMode());
+ insertElements = Collections.singletonList(insertLeg);
+ }
+
+ TripRouter.insertTrip(plan, trip.getOriginActivity(), insertElements, trip.getDestinationActivity());
+ }
+ plan.getAttributes().putAttribute("utility", chosenCandidates.stream().mapToDouble(UtilityCandidate::getUtility).sum());
+ } catch (NoFeasibleChoiceException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneSystemParams.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneSystemParams.java
index 5608a30b944..9e916128860 100644
--- a/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneSystemParams.java
+++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/analysis/zonal/DrtZoneSystemParams.java
@@ -24,6 +24,7 @@
import org.matsim.contrib.common.util.ReflectiveConfigGroupWithConfigurableParameterSets;
import org.matsim.contrib.common.zones.GridZoneSystem;
import org.matsim.contrib.common.zones.ZoneSystemParams;
+import org.matsim.contrib.common.zones.systems.geom_free_zones.GeometryFreeZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.GISFileZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.h3.H3GridZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams;
@@ -65,6 +66,10 @@ private void initSingletonParameterSets() {
addDefinition(H3GridZoneSystemParams.SET_NAME, H3GridZoneSystemParams::new,
() -> zoneSystemParams,
params -> zoneSystemParams = (H3GridZoneSystemParams)params);
+
+ addDefinition(GeometryFreeZoneSystemParams.SET_NAME, GeometryFreeZoneSystemParams::new,
+ () -> zoneSystemParams,
+ params -> zoneSystemParams = (GeometryFreeZoneSystemParams)params);
}
@Override
@@ -85,6 +90,9 @@ public void handleAddUnknownParam(String paramName, String value) {
addParameterSet(createParameterSet(H3GridZoneSystemParams.SET_NAME));
break;
}
+ case "GeometryFree":{
+ addParameterSet(createParameterSet(GeometryFreeZoneSystemParams.SET_NAME));
+ }
default:
super.handleAddUnknownParam(paramName, value);
}
diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java
index 77e717cfea7..a12930c5d42 100644
--- a/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java
+++ b/contribs/dvrp/src/main/java/org/matsim/contrib/zone/skims/DvrpTravelTimeMatrixParams.java
@@ -23,6 +23,7 @@
import jakarta.validation.constraints.PositiveOrZero;
import org.matsim.contrib.common.util.ReflectiveConfigGroupWithConfigurableParameterSets;
import org.matsim.contrib.common.zones.ZoneSystemParams;
+import org.matsim.contrib.common.zones.systems.geom_free_zones.GeometryFreeZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.GISFileZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.h3.H3GridZoneSystemParams;
import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams;
@@ -77,6 +78,10 @@ private void initSingletonParameterSets() {
addDefinition(H3GridZoneSystemParams.SET_NAME, H3GridZoneSystemParams::new,
() -> zoneSystemParams,
params -> zoneSystemParams = (H3GridZoneSystemParams)params);
+
+ addDefinition(GeometryFreeZoneSystemParams.SET_NAME, GeometryFreeZoneSystemParams::new,
+ () -> zoneSystemParams,
+ params -> zoneSystemParams = (GeometryFreeZoneSystemParams)params);
}
@Override
diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml
index f58a572c939..b480aa197dd 100644
--- a/contribs/hybridsim/pom.xml
+++ b/contribs/hybridsim/pom.xml
@@ -10,7 +10,7 @@
hybridsim
- 4.27.2
+ 4.28.0
1.65.1
diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java
index ee231f716ed..20c0b113bed 100644
--- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java
+++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/CarEgressWalkChanger.java
@@ -33,7 +33,7 @@
*
* This class allows to implicitly apply penalties to plans by changing the duration of the egress walk after car interactions.
* By construction this only works for plans involving car trips and can not be used if you want to penalize all plans that
- * fulfill a certain condition.
+ * fulfill a certain condition. Note that if you bind this, you should also bind the return value of {@link #getBackChanger()}!
*
*
* More precisely, the class will...
@@ -49,13 +49,14 @@
* @author tkohl / Senozon
*
*/
-class CarEgressWalkChanger implements BeforeMobsimListener, AfterMobsimListener {
+class CarEgressWalkChanger implements BeforeMobsimListener {
public static final String PENALTY_ATTRIBUTE = "parkingPenalty";
private final CarEgressWalkObserver observer;
private final AccessEgressFinder egressFinder = new AccessEgressFinder(TransportMode.car);
private final Iter0Method iter0Method;
+ private final CarEgressWalkBackChanger backChanger;
/**
* Sets the class up with the specified {@linkplain PenaltyGenerator} and {@linkplain PenaltyFunction}.
@@ -66,6 +67,21 @@ class CarEgressWalkChanger implements BeforeMobsimListener, AfterMobsimListener
public CarEgressWalkChanger(PenaltyGenerator penaltyGenerator, PenaltyFunction penaltyFunction, CarEgressWalkObserver observer, Iter0Method iter0Method) {
this.observer = observer;
this.iter0Method = iter0Method;
+ this.backChanger = new CarEgressWalkBackChanger(this);
+ }
+
+ @Override
+ public double priority() { //we want this to happen very late, because it should only affect the mobsim, not other listeners
+ return -1001;
+ }
+
+ /**
+ * Returns the class that changes the egress walks bag in AfterMobsim. Note that you need to bind this separately!
+ *
+ * @return the {@linkplain CarEgressWalkBackChanger} to this class
+ */
+ public CarEgressWalkBackChanger getBackChanger() {
+ return this.backChanger;
}
/**
@@ -93,33 +109,6 @@ public void notifyBeforeMobsim(BeforeMobsimEvent event) {
this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), false);
}
}
-
- /**
- * resets egress times before scoring / replanning
- */
- @Override
- public void notifyAfterMobsim(AfterMobsimEvent event) {
- // we need to roll back the changes we made before the mobsim, otherwise we can't apply
- // a different penalty next iteration.
- if (event.getIteration() == 0) {
- switch (this.iter0Method) {
- case noPenalty:
- case hourPenalty:
- case estimateFromPlans:
- this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true);
- break;
- case takeFromAttributes:
- this.changeEgressTimesByAttribute(event.getServices().getScenario().getPopulation().getPersons().values(), true);
- break;
- default:
- throw new RuntimeException("Unknown iter0 mode");
- }
- } else {
- this.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true);
- }
- // yyyy this is something we do not like: to just "fake" something and take it back afterwards. Would be good to find some other design
- // eventually. Not so obvious, though ... kai, mar'20
- }
/**
* Changes the egress times of all agents using cars according to the penalty for the corresponding space-time-gridcell and writes the penalty
@@ -130,12 +119,13 @@ public void notifyAfterMobsim(AfterMobsimEvent event) {
* by that time (calling this method twice, first with {@code false}, then with {@code true} should yield the original plans)
*/
private void changeEgressTimesByGridcell(Collection extends Person> population, boolean reverse) {
- int sign = reverse ? -1 : 1;
for (Person p : population) {
for (LegActPair walkActPair : this.egressFinder.findEgressWalks(p.getSelectedPlan())) {
- double penalty = sign * this.observer.getPenaltyCalculator().getPenalty(walkActPair.leg.getDepartureTime().seconds(), walkActPair.act.getCoord());
- setTimes(walkActPair, penalty);
- if (!reverse) {
+ double penalty = Math.round(this.observer.getPenaltyCalculator().getPenalty(walkActPair.leg.getDepartureTime().seconds(), walkActPair.act.getCoord()));
+ if (reverse) {
+ setTimes(walkActPair, -penalty);
+ } else {
+ setTimes(walkActPair, penalty);
walkActPair.leg.getAttributes().putAttribute(PENALTY_ATTRIBUTE, penalty);
}
}
@@ -171,4 +161,50 @@ private static void setTimes(LegActPair walkActPair, double penalty) {
walkActPair.leg.getRoute().setTravelTime(walkActPair.leg.getRoute().getTravelTime().seconds() + penalty);
walkActPair.act.setStartTime(walkActPair.act.getStartTime().seconds() + penalty);
}
+
+ /**
+ * The reverse to {@linkplain CarEgressWalkChanger}
+ *
+ * @author tkohl
+ *
+ */
+ static class CarEgressWalkBackChanger implements AfterMobsimListener {
+ private final CarEgressWalkChanger forwardChanger;
+
+ CarEgressWalkBackChanger(CarEgressWalkChanger forwardChanger) {
+ this.forwardChanger = forwardChanger;
+ }
+
+ @Override
+ public double priority() { //we want this to happen very early to undo what we did before the mobsim before other listeners can pick it up
+ return 1001;
+ }
+
+ /**
+ * resets egress times before scoring / replanning
+ */
+ @Override
+ public void notifyAfterMobsim(AfterMobsimEvent event) {
+ // we need to roll back the changes we made before the mobsim, otherwise we can't apply
+ // a different penalty next iteration.
+ if (event.getIteration() == 0) {
+ switch (forwardChanger.iter0Method) {
+ case noPenalty:
+ case hourPenalty:
+ case estimateFromPlans:
+ forwardChanger.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true);
+ break;
+ case takeFromAttributes:
+ forwardChanger.changeEgressTimesByAttribute(event.getServices().getScenario().getPopulation().getPersons().values(), true);
+ break;
+ default:
+ throw new RuntimeException("Unknown iter0 mode");
+ }
+ } else {
+ forwardChanger.changeEgressTimesByGridcell(event.getServices().getScenario().getPopulation().getPersons().values(), true);
+ }
+ // yyyy this is something we do not like: to just "fake" something and take it back afterwards. Would be good to find some other design
+ // eventually. Not so obvious, though ... kai, mar'20
+ }
+ }
}
diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java
index f356f0911e8..41f179d4977 100644
--- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java
+++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingproxy/ParkingProxyModule.java
@@ -92,7 +92,9 @@ public void install() {
if (parkingConfig.getObserveOnly()) {
super.addControlerListenerBinding().toInstance(walkObserver);
} else {
- super.addControlerListenerBinding().toInstance(new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method()));
+ CarEgressWalkChanger walkChanger = new CarEgressWalkChanger(parkingHandler, penaltyFunction, walkObserver, parkingConfig.getIter0Method());
+ super.addControlerListenerBinding().toInstance(walkChanger);
+ super.addControlerListenerBinding().toInstance(walkChanger.getBackChanger());
}
}
diff --git a/contribs/protobuf/pom.xml b/contribs/protobuf/pom.xml
index a2c8a4ef62b..a08c2d527c8 100644
--- a/contribs/protobuf/pom.xml
+++ b/contribs/protobuf/pom.xml
@@ -11,7 +11,7 @@
protobuf
- 4.27.2
+ 4.28.0
diff --git a/matsim/pom.xml b/matsim/pom.xml
index 7f768fffe76..e5c689b9261 100644
--- a/matsim/pom.xml
+++ b/matsim/pom.xml
@@ -222,7 +222,7 @@
com.github.luben
zstd-jni
- 1.5.6-3
+ 1.5.6-5
jakarta.validation
diff --git a/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java b/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java
index e2d6ff5078c..906c97396ee 100644
--- a/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java
+++ b/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java
@@ -41,15 +41,18 @@
import org.matsim.pt.transitSchedule.api.TransitRoute;
import org.matsim.pt.transitSchedule.api.TransitRouteStop;
import org.matsim.pt.transitSchedule.api.TransitSchedule;
+import org.matsim.pt.transitSchedule.api.TransitStopArea;
import org.matsim.pt.transitSchedule.api.TransitStopFacility;
/**
* Builds a network where transit vehicles can drive along and assigns the correct
- * links to the transit stop facilities and routes of transit lines. Each stop facility
- * is assigned to a loop link, located in a node with the same coordinates as the stop.
- * The stop facility ID is used for node and link IDs.
+ * links to the transit stop facilities and routes of transit lines. As each transit
+ * stop facility can only be connected to at most one link, the algorithm is forced
+ * to duplicated transit stop facilities in certain cases to build the network.
*
- * @author mrieser, davibicudo
+ * See {@link CreatePseudoNetworkWithLoopLinks} for a version that uses loop links instead of duplicating stop facilities.
+ *
+ * @author mrieser
*/
public class CreatePseudoNetwork {
@@ -59,8 +62,13 @@ public class CreatePseudoNetwork {
private final double linkFreeSpeed;
private final double linkCapacity;
- private final Map, Link> links = new HashMap<>();
- private final Map nodes = new HashMap<>();
+
+ private final Map, Link> links = new HashMap, Link>();
+ private final Map, TransitStopFacility> stopFacilities = new HashMap, TransitStopFacility>();
+ private final Map nodes = new HashMap();
+ private final Map> facilityCopies = new HashMap>();
+
+ private long linkIdCounter = 0;
private final Set transitModes = Collections.singleton(TransportMode.pt);
@@ -83,27 +91,24 @@ public CreatePseudoNetwork(final TransitSchedule schedule, final Network network
public void createNetwork() {
- createStopNodesAndLoopLinks();
+ List> toBeRemoved = new LinkedList>();
- List> toBeRemoved = new LinkedList<>();
for (TransitLine tLine : this.schedule.getTransitLines().values()) {
for (TransitRoute tRoute : tLine.getRoutes().values()) {
- ArrayList> routeLinks = new ArrayList<>();
+ ArrayList> routeLinks = new ArrayList>();
TransitRouteStop prevStop = null;
for (TransitRouteStop stop : tRoute.getStops()) {
- if (prevStop != null) {
- Link link = getNetworkLink(prevStop, stop);
- routeLinks.add(link.getId());
- }
+ Link link = getNetworkLink(prevStop, stop);
+ routeLinks.add(link.getId());
prevStop = stop;
}
- if (!routeLinks.isEmpty()) {
- NetworkRoute route = RouteUtils.createNetworkRoute(routeLinks);
+ if (routeLinks.size() > 0) {
+ NetworkRoute route = RouteUtils.createNetworkRoute(routeLinks );
tRoute.setRoute(route);
} else {
System.err.println("Line " + tLine.getId() + " route " + tRoute.getId() + " has less than two stops. Removing this route from schedule.");
- toBeRemoved.add(new Tuple<>(tLine, tRoute));
+ toBeRemoved.add(new Tuple(tLine, tRoute));
}
}
}
@@ -113,40 +118,64 @@ public void createNetwork() {
}
}
- private void createStopNodesAndLoopLinks() {
- for (TransitStopFacility stop : this.schedule.getFacilities().values()) {
- Node node = this.network.getFactory().createNode(Id.createNodeId(this.prefix + stop.getId()), stop.getCoord());
- this.network.addNode(node);
- this.nodes.put(stop, node);
-
- Link loopLink = this.network.getFactory().createLink(Id.createLinkId (this.prefix + stop.getId()), node, node);
- stop.setLinkId(loopLink.getId());
- this.network.addLink(loopLink);
- Tuple connection = new Tuple<>(node, node);
- this.links.put(connection, loopLink);
- }
- }
-
private Link getNetworkLink(final TransitRouteStop fromStop, final TransitRouteStop toStop) {
- TransitStopFacility fromFacility = fromStop.getStopFacility();
+ TransitStopFacility fromFacility = (fromStop == null) ? toStop.getStopFacility() : fromStop.getStopFacility();
TransitStopFacility toFacility = toStop.getStopFacility();
Node fromNode = this.nodes.get(fromFacility);
+ if (fromNode == null) {
+ fromNode = this.network.getFactory().createNode(Id.create(this.prefix + toFacility.getId(), Node.class), fromFacility.getCoord());
+ this.network.addNode(fromNode);
+ this.nodes.put(toFacility, fromNode);
+ }
+
Node toNode = this.nodes.get(toFacility);
+ if (toNode == null) {
+ toNode = this.network.getFactory().createNode(Id.create(this.prefix + toFacility.getId(), Node.class), toFacility.getCoord());
+ this.network.addNode(toNode);
+ this.nodes.put(toFacility, toNode);
+ }
- Tuple connection = new Tuple<>(fromNode, toNode);
+ Tuple connection = new Tuple(fromNode, toNode);
Link link = this.links.get(connection);
- return link == null ? createAndAddLink(connection) : link;
+ if (link == null) {
+ link = createAndAddLink(fromNode, toNode, connection);
+
+ if (toFacility.getLinkId() == null) {
+ toFacility.setLinkId(link.getId());
+ this.stopFacilities.put(connection, toFacility);
+ } else {
+ List copies = this.facilityCopies.get(toFacility);
+ if (copies == null) {
+ copies = new ArrayList();
+ this.facilityCopies.put(toFacility, copies);
+ }
+ Id newId = Id.create(toFacility.getId().toString() + "." + Integer.toString(copies.size() + 1), TransitStopFacility.class);
+ TransitStopFacility newFacility = this.schedule.getFactory().createTransitStopFacility(newId, toFacility.getCoord(), toFacility.getIsBlockingLane());
+ newFacility.setStopAreaId(Id.create(toFacility.getId(), TransitStopArea.class));
+ newFacility.setLinkId(link.getId());
+ newFacility.setName(toFacility.getName());
+ copies.add(newFacility);
+ this.nodes.put(newFacility, toNode);
+ this.schedule.addStopFacility(newFacility);
+ toStop.setStopFacility(newFacility);
+ this.stopFacilities.put(connection, newFacility);
+ }
+ } else {
+ toStop.setStopFacility(this.stopFacilities.get(connection));
+ }
+ return link;
}
- private Link createAndAddLink(Tuple connection) {
- Node fromNode = connection.getFirst();
- Node toNode = connection.getSecond();
+ private Link createAndAddLink(Node fromNode, Node toNode,
+ Tuple connection) {
Link link;
- link = this.network.getFactory().createLink(Id.createLinkId(this.prefix + fromNode.getId() + "-" + toNode.getId()), fromNode,
- toNode);
- link.setLength(CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord()));
-
+ link = this.network.getFactory().createLink(Id.create(this.prefix + this.linkIdCounter++, Link.class), fromNode, toNode);
+ if (fromNode == toNode) {
+ link.setLength(50);
+ } else {
+ link.setLength(CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord()));
+ }
link.setFreespeed(linkFreeSpeed);
link.setCapacity(linkCapacity);
link.setNumberOfLanes(1);
@@ -156,4 +185,11 @@ private Link createAndAddLink(Tuple connection) {
return link;
}
+ public Link getLinkBetweenStops(final TransitStopFacility fromStop, final TransitStopFacility toStop) {
+ Node fromNode = this.nodes.get(fromStop);
+ Node toNode = this.nodes.get(toStop);
+ Tuple connection = new Tuple(fromNode, toNode);
+ return this.links.get(connection);
+ }
+
}
diff --git a/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetworkWithLoopLinks.java b/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetworkWithLoopLinks.java
new file mode 100644
index 00000000000..d0532315137
--- /dev/null
+++ b/matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetworkWithLoopLinks.java
@@ -0,0 +1,153 @@
+/* *********************************************************************** *
+ * project: org.matsim.*
+ * CreatePseudoNetwork
+ * *
+ * *********************************************************************** *
+ * *
+ * copyright : (C) 2009 by the members listed in the COPYING, *
+ * LICENSE and WARRANTY file. *
+ * email : info at matsim dot org *
+ * *
+ * *********************************************************************** *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * See also COPYING, LICENSE and WARRANTY file *
+ * *
+ * *********************************************************************** */
+
+package org.matsim.pt.utils;
+
+import com.google.common.annotations.Beta;
+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.api.core.v01.network.Node;
+import org.matsim.core.population.routes.NetworkRoute;
+import org.matsim.core.population.routes.RouteUtils;
+import org.matsim.core.utils.collections.Tuple;
+import org.matsim.core.utils.geometry.CoordUtils;
+import org.matsim.pt.transitSchedule.api.*;
+
+import java.util.*;
+
+/**
+ * Builds a network where transit vehicles can drive along and assigns the correct
+ * links to the transit stop facilities and routes of transit lines. Each stop facility
+ * is assigned to a loop link, located in a node with the same coordinates as the stop.
+ * The stop facility ID is used for node and link IDs.
+ *
+ * @author mrieser, davibicudo
+ *
+ * @implNote THis functionality might be merged with {@link CreatePseudoNetwork}.
+ */
+@Beta
+public class CreatePseudoNetworkWithLoopLinks {
+
+ private final TransitSchedule schedule;
+ private final Network network;
+ private final String prefix;
+ private final double linkFreeSpeed;
+ private final double linkCapacity;
+
+ private final Map, Link> links = new HashMap<>();
+ private final Map nodes = new HashMap<>();
+
+ private final Set transitModes = Collections.singleton(TransportMode.pt);
+
+ public CreatePseudoNetworkWithLoopLinks(final TransitSchedule schedule, final Network network, final String networkIdPrefix) {
+ this.schedule = schedule;
+ this.network = network;
+ this.prefix = networkIdPrefix;
+ this.linkFreeSpeed = 100.0 / 3.6;
+ this.linkCapacity = 100000.0;
+ }
+
+ public CreatePseudoNetworkWithLoopLinks(final TransitSchedule schedule, final Network network, final String networkIdPrefix,
+ final double linkFreeSpeed, final double linkCapacity) {
+ this.schedule = schedule;
+ this.network = network;
+ this.prefix = networkIdPrefix;
+ this.linkFreeSpeed = linkFreeSpeed;
+ this.linkCapacity = linkCapacity;
+ }
+
+ public void createNetwork() {
+
+ createStopNodesAndLoopLinks();
+
+ List> toBeRemoved = new LinkedList<>();
+ for (TransitLine tLine : this.schedule.getTransitLines().values()) {
+ for (TransitRoute tRoute : tLine.getRoutes().values()) {
+ ArrayList> routeLinks = new ArrayList<>();
+ TransitRouteStop prevStop = null;
+ for (TransitRouteStop stop : tRoute.getStops()) {
+ if (prevStop != null) {
+ Link link = getNetworkLink(prevStop, stop);
+ routeLinks.add(link.getId());
+ }
+ prevStop = stop;
+ }
+
+ if (!routeLinks.isEmpty()) {
+ NetworkRoute route = RouteUtils.createNetworkRoute(routeLinks);
+ tRoute.setRoute(route);
+ } else {
+ System.err.println("Line " + tLine.getId() + " route " + tRoute.getId() + " has less than two stops. Removing this route from schedule.");
+ toBeRemoved.add(new Tuple<>(tLine, tRoute));
+ }
+ }
+ }
+
+ for (Tuple remove : toBeRemoved) {
+ remove.getFirst().removeRoute(remove.getSecond());
+ }
+ }
+
+ private void createStopNodesAndLoopLinks() {
+ for (TransitStopFacility stop : this.schedule.getFacilities().values()) {
+ Node node = this.network.getFactory().createNode(Id.createNodeId(this.prefix + stop.getId()), stop.getCoord());
+ this.network.addNode(node);
+ this.nodes.put(stop, node);
+
+ Link loopLink = this.network.getFactory().createLink(Id.createLinkId (this.prefix + stop.getId()), node, node);
+ stop.setLinkId(loopLink.getId());
+ this.network.addLink(loopLink);
+ Tuple connection = new Tuple<>(node, node);
+ this.links.put(connection, loopLink);
+ }
+ }
+
+ private Link getNetworkLink(final TransitRouteStop fromStop, final TransitRouteStop toStop) {
+ TransitStopFacility fromFacility = fromStop.getStopFacility();
+ TransitStopFacility toFacility = toStop.getStopFacility();
+
+ Node fromNode = this.nodes.get(fromFacility);
+ Node toNode = this.nodes.get(toFacility);
+
+ Tuple connection = new Tuple<>(fromNode, toNode);
+ Link link = this.links.get(connection);
+ return link == null ? createAndAddLink(connection) : link;
+ }
+
+ private Link createAndAddLink(Tuple connection) {
+ Node fromNode = connection.getFirst();
+ Node toNode = connection.getSecond();
+ Link link;
+ link = this.network.getFactory().createLink(Id.createLinkId(this.prefix + fromNode.getId() + "-" + toNode.getId()), fromNode,
+ toNode);
+ link.setLength(CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord()));
+
+ link.setFreespeed(linkFreeSpeed);
+ link.setCapacity(linkCapacity);
+ link.setNumberOfLanes(1);
+ this.network.addLink(link);
+ link.setAllowedModes(this.transitModes);
+ this.links.put(connection, link);
+ return link;
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index f7866d67c0a..cdecc6341d7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@
2.23.1
31.3
0.49.2
- 1.19.0
+ 1.20.0
7.0.0
2.17.2
2.5.0
@@ -103,12 +103,12 @@
com.google.guava
guava
- 33.2.1-jre
+ 33.3.0-jre
org.apache.commons
commons-lang3
- 3.14.0
+ 3.17.0
org.apache.commons
@@ -118,7 +118,7 @@
org.apache.commons
commons-compress
- 1.26.2
+ 1.27.1
commons-logging
@@ -242,7 +242,7 @@
org.slf4j
slf4j-api
- 2.0.13
+ 2.0.16
@@ -425,7 +425,7 @@
org.apache.maven.plugins
maven-failsafe-plugin
- 3.3.1
+ 3.5.0
org.apache.maven.plugins
@@ -445,12 +445,12 @@
org.apache.maven.plugins
maven-install-plugin
- 3.1.2
+ 3.1.3
org.apache.maven.plugins
maven-javadoc-plugin
- 3.7.0
+ 3.10.0
org.codehaus.mojo