Skip to content

Commit

Permalink
fix pseudo network generator and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
davibicudo committed Sep 12, 2024
1 parent 33c07d3 commit 38c5fa8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 241 deletions.
137 changes: 49 additions & 88 deletions matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@

package org.matsim.pt.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

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;
Expand All @@ -37,23 +30,21 @@
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.TransitLine;
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;
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. 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.
* 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.
*
* See {@link CreatePseudoNetworkWithLoopLinks} for a version that uses loop links instead of duplicating stop facilities.
* @author mrieser, davibicudo
*
* @author mrieser
* @implNote THis functionality might be merged with {@link CreatePseudoNetwork}.
*/
@Beta
public class CreatePseudoNetwork {

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


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 Map<Connection, Link> links = new HashMap<Connection, Link>();
private final Map<TransitStopFacility, Node> nodes = new HashMap<>();

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

Expand All @@ -81,7 +67,7 @@ public CreatePseudoNetwork(final TransitSchedule schedule, final Network network
}

public CreatePseudoNetwork(final TransitSchedule schedule, final Network network, final String networkIdPrefix,
final double linkFreeSpeed, final double linkCapacity) {
final double linkFreeSpeed, final double linkCapacity) {
this.schedule = schedule;
this.network = network;
this.prefix = networkIdPrefix;
Expand All @@ -91,24 +77,29 @@ public CreatePseudoNetwork(final TransitSchedule schedule, final Network network

public void createNetwork() {

List<Tuple<TransitLine, TransitRoute>> toBeRemoved = new LinkedList<Tuple<TransitLine, TransitRoute>>();
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<Id<Link>>();
ArrayList<Id<Link>> routeLinks = new ArrayList<>();
TransitRouteStop prevStop = null;
for (TransitRouteStop stop : tRoute.getStops()) {
Link link = getNetworkLink(prevStop, stop);
routeLinks.add(link.getId());
if (prevStop != null) {
Link link = getNetworkLink(prevStop.getStopFacility(), stop.getStopFacility());
routeLinks.add(link.getId());
}
Link loopLink = getNetworkLink(stop.getStopFacility(), stop.getStopFacility());
routeLinks.add(loopLink.getId());
prevStop = stop;
}

if (routeLinks.size() > 0) {
NetworkRoute route = RouteUtils.createNetworkRoute(routeLinks );
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<TransitLine, TransitRoute>(tLine, tRoute));
toBeRemoved.add(new Tuple<>(tLine, tRoute));
}
}
}
Expand All @@ -118,64 +109,39 @@ public void createNetwork() {
}
}

private Link getNetworkLink(final TransitRouteStop fromStop, final TransitRouteStop toStop) {
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);
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 = getNetworkLink(stop, stop);
stop.setLinkId(loopLink.getId());
}
}

private Link getNetworkLink(final TransitStopFacility fromFacility, final TransitStopFacility toFacility) {
Node fromNode = this.nodes.get(fromFacility);
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<Node, Node>(fromNode, toNode);
Connection connection = new Connection(fromNode, toNode);
Link link = this.links.get(connection);
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;
return link == null ? createAndAddLink(connection) : link;
}

private Link createAndAddLink(Node fromNode, Node toNode,
Tuple<Node, Node> connection) {
private Link createAndAddLink(Connection connection) {
Link link;
link = this.network.getFactory().createLink(Id.create(this.prefix + this.linkIdCounter++, Link.class), fromNode, toNode);
if (fromNode == toNode) {
link.setLength(50);
Id<Link> id;
double length;
if (connection.fromNode == connection.toNode) {
id = Id.createLinkId (this.prefix + connection.fromNode.getId());
length = 50.0;
} else {
link.setLength(CoordUtils.calcEuclideanDistance(fromNode.getCoord(), toNode.getCoord()));
id = Id.createLinkId(this.prefix + connection.fromNode.getId() + "-" + connection.toNode.getId());
length = CoordUtils.calcEuclideanDistance(connection.fromNode.getCoord(), connection.toNode.getCoord());
}
link = this.network.getFactory().createLink(id, connection.fromNode, connection.toNode);
link.setLength(length);

link.setFreespeed(linkFreeSpeed);
link.setCapacity(linkCapacity);
link.setNumberOfLanes(1);
Expand All @@ -185,11 +151,6 @@ private Link createAndAddLink(Node fromNode, Node toNode,
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);
}
record Connection (Node fromNode, Node toNode) {}

}

This file was deleted.

Loading

0 comments on commit 38c5fa8

Please sign in to comment.