From 25dd4d3498bebc886f50f46536dc2fb25d8063bb Mon Sep 17 00:00:00 2001 From: rakow Date: Mon, 9 Sep 2024 09:40:43 +0200 Subject: [PATCH] revert to old pseudo network creator --- .../matsim/pt/utils/CreatePseudoNetwork.java | 117 +++++++++----- .../CreatePseudoNetworkWithLoopLinks.java | 153 ++++++++++++++++++ 2 files changed, 229 insertions(+), 41 deletions(-) create mode 100644 matsim/src/main/java/org/matsim/pt/utils/CreatePseudoNetworkWithLoopLinks.java 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 30ab02ad413..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,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 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); @@ -157,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; + } + +}