Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix pseudo network generator and add test #3476

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading