21 package org.matsim.core.population.routes;
23 import java.util.ArrayList;
24 import java.util.HashSet;
25 import java.util.List;
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.Logger;
58 final class CompressedNetworkRouteImpl
extends AbstractRoute implements NetworkRoute,
Cloneable {
60 private final static Logger log = LogManager.getLogger(CompressedNetworkRouteImpl.class);
62 private ArrayList<Id<Link>> route =
new ArrayList<>(0);
63 private final Map<Id<Link>, Id<Link>> subsequentLinks;
64 private double travelCost = Double.NaN;
66 private int uncompressedLength = -1;
67 private Id<Vehicle> vehicleId = null;
68 private final Network network;
69 private final Map<Id<Link>, ? extends Link> links;
71 public CompressedNetworkRouteImpl(
final Id<Link> startLinkId,
final Id<Link> endLinkId, Network network,
final Map<Id<Link>, Id<Link>> subsequentLinks) {
72 super(startLinkId, endLinkId);
73 this.network = network;
74 this.links = network.getLinks();
75 this.subsequentLinks = subsequentLinks;
79 public CompressedNetworkRouteImpl clone() {
80 CompressedNetworkRouteImpl cloned = (CompressedNetworkRouteImpl) super.clone();
81 ArrayList<Id<Link>> tmpRoute = cloned.route;
82 cloned.route =
new ArrayList<>(tmpRoute);
87 public List<Id<Link>> getLinkIds() {
88 if (this.uncompressedLength < 0) {
89 return new ArrayList<>(0);
91 ArrayList<Id<Link>> links =
new ArrayList<>(this.uncompressedLength);
94 if ((previousLinkId == null) || (endLinkId == null)) {
97 if (previousLinkId.equals(endLinkId) && this.uncompressedLength == 0) {
100 for (Id<Link> linkId : this.route) {
101 getLinksTillLink(links, linkId, previousLinkId);
103 previousLinkId = linkId;
105 getLinksTillLink(links, endLinkId, previousLinkId);
110 private void getLinksTillLink(
final List<Id<Link>> links,
final Id<Link> nextLinkId,
final Id<Link> startLinkId) {
111 Id<Link> linkId = startLinkId;
112 Link nextLink = this.links.get(nextLinkId);
114 Link link = this.links.get(linkId);
115 if (link.getToNode() == nextLink.getFromNode()) {
118 linkId = this.subsequentLinks.get(linkId);
124 public NetworkRoute getSubRoute(Id<Link> fromLinkId, Id<Link> toLinkId) {
125 List<Id<Link>> newLinkIds =
new ArrayList<>(10);
127 boolean collectLinks = foundFromLink;
128 boolean equalFromTo = fromLinkId.equals(toLinkId);
130 if (!foundFromLink || !equalFromTo) {
131 for (Id<Link> linkId : getLinkIds()) {
132 if (linkId.equals(toLinkId)) {
133 collectLinks =
false;
135 foundFromLink =
true;
143 newLinkIds.add(linkId);
145 if (linkId.equals(fromLinkId)) {
146 foundFromLink =
true;
151 if (!foundFromLink) {
153 collectLinks = foundFromLink;
155 if (!foundFromLink) {
156 throw new IllegalArgumentException(
"fromLinkId is not part of this route.");
158 if ((collectLinks) && (toLinkId.equals(
this.getEndLinkId()))) {
159 collectLinks =
false;
162 throw new IllegalArgumentException(
"toLinkId is not part of this route.");
165 NetworkRoute subRoute =
new CompressedNetworkRouteImpl(fromLinkId, toLinkId, this.network, this.subsequentLinks);
166 subRoute.setLinkIds(fromLinkId, newLinkIds, toLinkId);
171 public double getTravelCost() {
172 return this.travelCost;
176 public void setTravelCost(
final double travelCost) {
177 this.travelCost = travelCost;
181 public void setLinkIds(
final Id<Link> startLinkId,
final List<Id<Link>> srcRoute,
final Id<Link> endLinkId) {
183 Set<Id<Node>> visitedNodes =
new HashSet<>();
184 Set<Id<Node>> multiplyVisitedNodes =
new HashSet<>();
187 if ((srcRoute == null) || (srcRoute.size() == 0)) {
188 this.uncompressedLength = 0;
192 Id<Link> previousLinkId = startLinkId;
193 for (Id<Link> linkId : srcRoute) {
194 Link link = this.links.get(linkId);
195 Id<Node> fromNodeId = link.getFromNode().getId();
196 if (!visitedNodes.add(fromNodeId)) {
198 multiplyVisitedNodes.add(fromNodeId);
200 if (!this.subsequentLinks.get(previousLinkId).equals(linkId)) {
201 this.route.add(linkId);
203 previousLinkId = linkId;
205 Link endLink = this.links.get(endLinkId);
206 Id<Node> fromNodeId = endLink.getFromNode().getId();
207 if (!visitedNodes.add(fromNodeId)) {
209 multiplyVisitedNodes.add(fromNodeId);
212 if (!multiplyVisitedNodes.isEmpty()) {
216 previousLinkId = startLinkId;
217 for (Id<Link> linkId : srcRoute) {
218 Link link = this.links.get(linkId);
219 fromNodeId = link.getFromNode().getId();
220 if (!this.subsequentLinks.get(previousLinkId).equals(linkId) || multiplyVisitedNodes.contains(fromNodeId)) {
221 this.route.add(linkId);
223 previousLinkId = linkId;
227 this.route.trimToSize();
228 this.uncompressedLength = srcRoute.size();
235 public Id<Vehicle> getVehicleId() {
236 return this.vehicleId;
240 public void setVehicleId(
final Id<Vehicle> vehicleId) {
241 this.vehicleId = vehicleId;
245 public String getRouteType() {
250 public String getRouteDescription() {
251 StringBuilder desc =
new StringBuilder(100);
253 for (Id<Link> linkId : this.getLinkIds()) {
255 desc.append(linkId.toString());
262 return desc.toString();
266 public void setRouteDescription(String routeDescription) {
267 List<Id<Link>> linkIds = NetworkUtils.getLinkIds(routeDescription);
270 if (linkIds.size() > 0) {
271 startLinkId = linkIds.remove(0);
274 if (linkIds.size() > 0) {
275 endLinkId = linkIds.remove(linkIds.size() - 1);
278 this.setLinkIds(startLinkId, linkIds, endLinkId);
final void setEndLinkId(final Id< Link > linkId)
final Id< Link > getEndLinkId()
final void setStartLinkId(final Id< Link > linkId)
final Id< Link > getStartLinkId()