Skip to content

Commit

Permalink
Merge pull request #3459 from matsim-org/pt-pseudonetwork-looplinks
Browse files Browse the repository at this point in the history
Revert to old pseudo pt network creator
  • Loading branch information
jfbischoff authored Sep 9, 2024
2 parents a90faed + 25dd4d3 commit fb31f6e
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 41 deletions.
117 changes: 76 additions & 41 deletions matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -59,8 +62,13 @@ public class CreatePseudoNetwork {
private final double linkFreeSpeed;
private final double linkCapacity;

private final Map<Tuple<Node, Node>, Link> links = new HashMap<>();
private final Map<TransitStopFacility, Node> nodes = new HashMap<>();

private final Map<Tuple<Node, Node>, Link> links = new HashMap<Tuple<Node, Node>, Link>();
private final Map<Tuple<Node, Node>, TransitStopFacility> stopFacilities = new HashMap<Tuple<Node, Node>, TransitStopFacility>();
private final Map<TransitStopFacility, Node> nodes = new HashMap<TransitStopFacility, Node>();
private final Map<TransitStopFacility, List<TransitStopFacility>> facilityCopies = new HashMap<TransitStopFacility, List<TransitStopFacility>>();

private long linkIdCounter = 0;

private final Set<String> transitModes = Collections.singleton(TransportMode.pt);

Expand All @@ -83,27 +91,24 @@ public CreatePseudoNetwork(final TransitSchedule schedule, final Network network

public void createNetwork() {

createStopNodesAndLoopLinks();
List<Tuple<TransitLine, TransitRoute>> toBeRemoved = new LinkedList<Tuple<TransitLine, TransitRoute>>();

List<Tuple<TransitLine, TransitRoute>> toBeRemoved = new LinkedList<>();
for (TransitLine tLine : this.schedule.getTransitLines().values()) {
for (TransitRoute tRoute : tLine.getRoutes().values()) {
ArrayList<Id<Link>> routeLinks = new ArrayList<>();
ArrayList<Id<Link>> routeLinks = new ArrayList<Id<Link>>();
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<TransitLine, TransitRoute>(tLine, tRoute));
}
}
}
Expand All @@ -113,41 +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);
loopLink.setAllowedModes(this.transitModes);
stop.setLinkId(loopLink.getId());
this.network.addLink(loopLink);
Tuple<Node, Node> 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<Node, Node> connection = new Tuple<>(fromNode, toNode);
Tuple<Node, Node> connection = new Tuple<Node, Node>(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<TransitStopFacility> copies = this.facilityCopies.get(toFacility);
if (copies == null) {
copies = new ArrayList<TransitStopFacility>();
this.facilityCopies.put(toFacility, copies);
}
Id<TransitStopFacility> 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<Node, Node> connection) {
Node fromNode = connection.getFirst();
Node toNode = connection.getSecond();
private Link createAndAddLink(Node fromNode, Node toNode,
Tuple<Node, Node> 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);
Expand All @@ -157,4 +185,11 @@ private Link createAndAddLink(Tuple<Node, Node> 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<Node, Node> connection = new Tuple<Node, Node>(fromNode, toNode);
return this.links.get(connection);
}

}
Original file line number Diff line number Diff line change
@@ -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<Tuple<Node, Node>, Link> links = new HashMap<>();
private final Map<TransitStopFacility, Node> nodes = new HashMap<>();

private final Set<String> 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<Tuple<TransitLine, TransitRoute>> toBeRemoved = new LinkedList<>();
for (TransitLine tLine : this.schedule.getTransitLines().values()) {
for (TransitRoute tRoute : tLine.getRoutes().values()) {
ArrayList<Id<Link>> 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<TransitLine, TransitRoute> 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<Node, Node> 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<Node, Node> connection = new Tuple<>(fromNode, toNode);
Link link = this.links.get(connection);
return link == null ? createAndAddLink(connection) : link;
}

private Link createAndAddLink(Tuple<Node, Node> 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;
}

}

0 comments on commit fb31f6e

Please sign in to comment.