LCOV - code coverage report
Current view: top level - src/netload - NLEdgeControlBuilder.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 87.2 % 109 95
Test Date: 2024-11-20 15:55:46 Functions: 87.5 % 16 14

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    NLEdgeControlBuilder.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @author  Leonhard Luecken
      19              : /// @date    Mon, 9 Jul 2001
      20              : ///
      21              : // Interface for building edges
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <vector>
      26              : #include <string>
      27              : #include <map>
      28              : #include <algorithm>
      29              : #include <iterator>
      30              : #include <mesosim/MELoop.h>
      31              : #include <microsim/MSGlobals.h>
      32              : #include <microsim/MSLane.h>
      33              : #include <microsim/MSEdge.h>
      34              : #include <microsim/MSEdgeControl.h>
      35              : #include <utils/common/StringTokenizer.h>
      36              : #include <utils/common/UtilExceptions.h>
      37              : #include <utils/options/OptionsCont.h>
      38              : #include "NLBuilder.h"
      39              : #include "NLEdgeControlBuilder.h"
      40              : #include <utils/iodevices/OutputDevice.h>
      41              : 
      42              : 
      43              : // ===========================================================================
      44              : // method definitions
      45              : // ===========================================================================
      46        42766 : NLEdgeControlBuilder::NLEdgeControlBuilder()
      47        42766 :     : myCurrentNumericalLaneID(0), myCurrentNumericalEdgeID(0), myEdges(0), myCurrentLaneIndex(-1) {
      48        42766 :     myActiveEdge = (MSEdge*) nullptr;
      49        42766 :     myLaneStorage = new std::vector<MSLane*>();
      50        42766 : }
      51              : 
      52              : 
      53        42766 : NLEdgeControlBuilder::~NLEdgeControlBuilder() {
      54        42766 :     delete myLaneStorage;
      55        85532 : }
      56              : 
      57              : 
      58              : void
      59      1729359 : NLEdgeControlBuilder::beginEdgeParsing(
      60              :     const std::string& id, const SumoXMLEdgeFunc function,
      61              :     const std::string& streetName,
      62              :     const std::string& edgeType,
      63              :     int priority,
      64              :     const std::string& bidi,
      65              :     double distance) {
      66              :     // closeEdge might not have been called because the last edge had an error, so we clear the lane storage
      67      1729359 :     myLaneStorage->clear();
      68      1729359 :     myActiveEdge = buildEdge(id, function, streetName, edgeType, priority, distance);
      69      1729359 :     if (MSEdge::dictionary(id) != nullptr) {
      70            8 :         throw InvalidArgument("Another edge with the id '" + id + "' exists.");
      71              :     }
      72      1729355 :     myEdges.push_back(myActiveEdge);
      73      1729355 :     if (bidi != "") {
      74        24894 :         myBidiEdges[myActiveEdge] = bidi;
      75              :     }
      76      1729355 : }
      77              : 
      78              : 
      79              : MSLane*
      80      1794908 : NLEdgeControlBuilder::addLane(const std::string& id,
      81              :                               double maxSpeed, double friction, double length,
      82              :                               const PositionVector& shape, double width,
      83              :                               SVCPermissions permissions,
      84              :                               SVCPermissions changeLeft, SVCPermissions changeRight,
      85              :                               int index, bool isRampAccel,
      86              :                               const std::string& type,
      87              :                               const PositionVector& outlineShape) {
      88      1794908 :     MSLane* lane = new MSLane(id, maxSpeed, friction, length, myActiveEdge, myCurrentNumericalLaneID++, shape, width, permissions, changeLeft, changeRight, index, isRampAccel, type, outlineShape);
      89      1794908 :     myLaneStorage->push_back(lane);
      90      1794908 :     myCurrentLaneIndex = index;
      91      1794908 :     return lane;
      92              : }
      93              : 
      94              : 
      95              : void
      96         2178 : NLEdgeControlBuilder::addStopOffsets(const StopOffset& stopOffset) {
      97         2178 :     if (myCurrentLaneIndex == -1) {
      98         1158 :         setDefaultStopOffset(stopOffset);
      99              :     } else {
     100         1020 :         updateCurrentLaneStopOffset(stopOffset);
     101              :     }
     102         2178 : }
     103              : 
     104              : 
     105              : std::string
     106            0 : NLEdgeControlBuilder::reportCurrentEdgeOrLane() const {
     107            0 :     std::stringstream ss;
     108            0 :     if (myCurrentLaneIndex != -1) {
     109            0 :         ss << "lane " << myCurrentLaneIndex << " of ";
     110              :     }
     111            0 :     ss << "edge '" << myActiveEdge->getID() << "'";
     112            0 :     return ss.str();
     113            0 : }
     114              : 
     115              : 
     116              : void
     117         1020 : NLEdgeControlBuilder::updateCurrentLaneStopOffset(const StopOffset& stopOffset) {
     118         1020 :     if (myLaneStorage->size() == 0) {
     119            0 :         throw ProcessError("myLaneStorage cannot be empty");
     120              :     }
     121         1020 :     if (stopOffset.isDefined()) {
     122         1020 :         if (myLaneStorage->back()->getLaneStopOffsets().isDefined()) {
     123            0 :             WRITE_WARNING("Duplicate stopOffset definition for lane " + toString(myLaneStorage->back()->getIndex()) +
     124              :                           " on edge " + myActiveEdge->getID() + "!")
     125              :         } else {
     126         1020 :             myLaneStorage->back()->setLaneStopOffset(stopOffset);
     127              :         }
     128              :     }
     129         1020 : }
     130              : 
     131              : 
     132              : void
     133         1158 : NLEdgeControlBuilder::setDefaultStopOffset(const StopOffset& stopOffsets) {
     134         1158 :     if (myCurrentDefaultStopOffset.isDefined()) {
     135            0 :         WRITE_WARNING("Duplicate stopOffset definition for edge " + myActiveEdge->getID() + ". Ignoring duplicate specification.")
     136              :     } else {
     137         1158 :         myCurrentDefaultStopOffset = stopOffsets;
     138              :     }
     139         1158 : }
     140              : 
     141              : 
     142              : void
     143      1729227 : NLEdgeControlBuilder::applyDefaultStopOffsetsToLanes() {
     144      1729227 :     if (myActiveEdge == nullptr) {
     145            0 :         throw ProcessError("myActiveEdge cannot be nullptr");
     146              :     }
     147      1729227 :     if (myCurrentDefaultStopOffset.isDefined()) {
     148         3118 :         for (const auto& l : *myLaneStorage) {
     149         1960 :             if (!l->getLaneStopOffsets().isDefined()) {
     150         1132 :                 l->setLaneStopOffset(myCurrentDefaultStopOffset);
     151              :             }
     152              :         }
     153              :     }
     154      1729227 : }
     155              : 
     156              : 
     157              : void
     158         7759 : NLEdgeControlBuilder::addNeigh(const std::string id) {
     159         7759 :     myOppositeLanes.push_back({myLaneStorage->back(), id});
     160         7759 : }
     161              : 
     162              : 
     163              : MSEdge*
     164      1729227 : NLEdgeControlBuilder::closeEdge() {
     165      1729227 :     applyDefaultStopOffsetsToLanes();
     166      1729227 :     std::vector<MSLane*>* lanes = new std::vector<MSLane*>();
     167      1729227 :     lanes->reserve(myLaneStorage->size());
     168      1729227 :     copy(myLaneStorage->begin(), myLaneStorage->end(), back_inserter(*lanes));
     169      1729227 :     myLaneStorage->clear();
     170      1729227 :     myActiveEdge->initialize(lanes);
     171      1729227 :     myCurrentDefaultStopOffset.reset();
     172      1729227 :     return myActiveEdge;
     173              : }
     174              : 
     175              : 
     176              : void
     177      2159635 : NLEdgeControlBuilder::closeLane() {
     178      2159635 :     myCurrentLaneIndex = -1;
     179      2159635 : }
     180              : 
     181              : 
     182              : MSEdgeControl*
     183        42345 : NLEdgeControlBuilder::build(const MMVersion& networkVersion) {
     184        47764 :     if (MSGlobals::gUseMesoSim && !OptionsCont::getOptions().getBool("meso-lane-queue")) {
     185        10762 :         MSEdge::setMesoIgnoredVClasses(parseVehicleClasses(OptionsCont::getOptions().getStringVector("meso-ignore-lanes-by-vclass")));
     186              :     }
     187              :     // connecting opposite lanes must happen before MSEdge::closeBuilding
     188        50104 :     for (auto item : myOppositeLanes) {
     189         7759 :         MSLane* oppo = MSLane::dictionary(item.second);
     190         7759 :         if (oppo == nullptr) {
     191            0 :             WRITE_ERRORF("Unknown neigh lane '%' for lane '%'", item.second, item.first->getID());
     192              :         } else {
     193         7759 :             item.first->setOpposite(oppo);
     194              :         }
     195              :     }
     196              :     // consistency check
     197        50104 :     for (auto item : myOppositeLanes) {
     198         7759 :         if (item.first->getOpposite() != nullptr && item.first->getOpposite()->getOpposite() != item.first) {
     199            3 :             WRITE_WARNINGF(TL("Asymmetrical neigh lane '%' for lane '%'"), item.second, item.first->getID());
     200            1 :             item.first->getOpposite()->setOpposite(item.first);
     201              :         }
     202              :     }
     203      1768950 :     for (MSEdge* const edge : myEdges) {
     204      1726605 :         edge->closeBuilding();
     205              :     }
     206      1768950 :     for (MSEdge* const edge : myEdges) {
     207      1726605 :         edge->rebuildAllowedTargets(false);
     208              :         // segment building depends on the finished list of successors (for multi-queue)
     209      1726605 :         if (MSGlobals::gUseMesoSim && !edge->getLanes().empty()) {
     210       256629 :             MSGlobals::gMesoNet->buildSegmentsFor(*edge, OptionsCont::getOptions());
     211              :         }
     212              :     }
     213              :     // mark internal edges belonging to a roundabout (after all edges are build)
     214        42345 :     if (MSGlobals::gUsingInternalLanes) {
     215      1505459 :         for (MSEdge* const edge : myEdges) {
     216      1468572 :             if (edge->isInternal()) {
     217       803734 :                 if (edge->getNumSuccessors() != 1 || edge->getNumPredecessors() != 1) {
     218            0 :                     throw ProcessError(TLF("Internal edge '%' is not properly connected (probably a manually modified net.xml).", edge->getID()));
     219              :                 }
     220       803734 :                 if (edge->getSuccessors()[0]->isRoundabout() || edge->getPredecessors()[0]->isRoundabout()) {
     221              :                     edge->markAsRoundabout();
     222              :                 }
     223              :             }
     224              :         }
     225              :     }
     226        42345 :     if (!deprecatedVehicleClassesSeen.empty()) {
     227            0 :         WRITE_WARNINGF(TL("Deprecated vehicle classes '%' in input network."), toString(deprecatedVehicleClassesSeen));
     228              :         deprecatedVehicleClassesSeen.clear();
     229              :     }
     230              :     // check for bi-directional edges (this are edges in opposing direction and superposable/congruent shapes)
     231        42345 :     if (myBidiEdges.size() > 0 || networkVersion > MMVersion(1, 0)) {
     232        40976 :         for (auto& item : myBidiEdges) {
     233        24894 :             item.first->checkAndRegisterBiDirEdge(item.second);
     234              :         }
     235              :         //WRITE_MESSAGEF(TL("Loaded % bidirectional edges"), toString(myBidiEdges.size()));
     236              :     } else {
     237              :         // legacy network
     238      1069240 :         for (MSEdge* e : myEdges) {
     239      2085954 :             e->checkAndRegisterBiDirEdge();
     240              :         }
     241              :     }
     242              :     // take into account bidi lanes when deciding on whether an edge allows changing
     243      1768950 :     for (MSEdge* const edge : myEdges) {
     244      1726605 :         edge->buildLaneChanger();
     245              :     }
     246        42345 :     return new MSEdgeControl(myEdges);
     247              : }
     248              : 
     249              : 
     250              : MSEdge*
     251      1624846 : NLEdgeControlBuilder::buildEdge(const std::string& id, const SumoXMLEdgeFunc function,
     252              :                                 const std::string& streetName, const std::string& edgeType, const int priority, const double distance) {
     253      1624846 :     return new MSEdge(id, myCurrentNumericalEdgeID++, function, streetName, edgeType, priority, distance);
     254              : }
     255              : 
     256        15711 : void NLEdgeControlBuilder::addCrossingEdges(const std::vector<std::string>& crossingEdges) {
     257        15711 :     myActiveEdge->setCrossingEdges(crossingEdges);
     258        15711 : }
     259              : 
     260              : 
     261              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1