/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file ROHelper.cpp14/// @author Daniel Krajzewicz15/// @author Michael Behrisch16/// @date Sept 200217///18// Some helping methods for router19/****************************************************************************/20#include <config.h>2122#include <functional>23#include <vector>24#include "ROEdge.h"25#include "ROVehicle.h"26#include "ROHelper.h"272829// ===========================================================================30// class definitions31// ===========================================================================323334namespace ROHelper {35void36recheckForLoops(ConstROEdgeVector& edges, const ConstROEdgeVector& mandatory) {37// for simplicities sake, prevent removal of any mandatory edges38// in theory these edges could occur multiple times so it might be possible39// to delete some of them anyway.40// XXX check for departLane, departPos, departSpeed, ....4142// removal of edge loops within the route (edge occurs twice)43// call repeatedly until no more loops have been found44bool findLoop = true;45while (findLoop) {46findLoop = false;47std::map<const ROEdge*, int> lastOccurrence; // index of the last occurrence of this edge48for (int ii = 0; ii < (int)edges.size(); ++ii) {49std::map<const ROEdge*, int>::iterator it_pre = lastOccurrence.find(edges[ii]);50if (it_pre != lastOccurrence.end() &&51noMandatory(mandatory, edges.begin() + it_pre->second, edges.begin() + ii)) {52edges.erase(edges.begin() + it_pre->second, edges.begin() + ii);53ii = it_pre->second;54findLoop = true;55break;56} else {57lastOccurrence[edges[ii]] = ii;58}59}60}6162// remove loops at the route's begin63// (vehicle makes a turnaround to get into the right direction at an already passed node)64const RONode* start = edges[0]->getFromJunction();65if (start == nullptr && edges.size() > 1) {66// taz edge has no fromJunction67start = edges[1]->getFromJunction();68}69if (start != nullptr) {70int lastStart = 0;71for (int i = 1; i < (int)edges.size(); i++) {72if (edges[i]->getFromJunction() == start) {73lastStart = i;74}75}76if (lastStart > 0 && noMandatory(mandatory, edges.begin(), edges.begin() + lastStart - 1)) {77edges.erase(edges.begin(), edges.begin() + lastStart - 1);78}79}80// remove loops at the route's end81// (vehicle makes a turnaround to get into the right direction at an already passed node)82const RONode* end = edges.back()->getToJunction();83if (end == nullptr && edges.size() > 1) {84// taz edge has no toJunction85end = edges[edges.size() - 2]->getToJunction();86}87if (end != nullptr) {88for (int i = 0; i < (int)edges.size() - 1; i++) {89if (edges[i]->getToJunction() == end && noMandatory(mandatory, edges.begin() + i + 2, edges.end())) {90edges.erase(edges.begin() + i + 2, edges.end());91break;92}93}94}9596// removal of node loops (node occurs twice) is not done because these may occur legitimately97/*98std::vector<RONode*> nodes;99for (ConstROEdgeVector::iterator i = edges.begin(); i != edges.end(); ++i) {100nodes.push_back((*i)->getFromJunction());101}102nodes.push_back(edges.back()->getToJunction());103bool changed = false;104do {105changed = false;106for (int b = 0; b < nodes.size() && !changed; ++b) {107RONode* bn = nodes[b];108for (int e = b + 1; e < nodes.size() && !changed; ++e) {109if (bn == nodes[e]) {110changed = true;111nodes.erase(nodes.begin() + b, nodes.begin() + e);112edges.erase(edges.begin() + b, edges.begin() + e);113}114}115}116} while (changed);117*/118}119120bool121noMandatory(const ConstROEdgeVector& mandatory,122ConstROEdgeVector::const_iterator start,123ConstROEdgeVector::const_iterator end) {124for (const ROEdge* m : mandatory) {125for (auto it = start; it != end; it++) {126if (*it == m) {127return false;128}129}130}131return true;132}133134135}136137138/****************************************************************************/139140141