LCOV - code coverage report
Current view: top level - src/netbuild - NBPTLine.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.2 % 166 148
Test Date: 2024-12-21 15:45:41 Functions: 94.4 % 18 17

            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    NBPTLine.cpp
      15              : /// @author  Gregor Laemmel
      16              : /// @author  Nikita Cherednychek
      17              : /// @date    Tue, 20 Mar 2017
      18              : ///
      19              : // The representation of one direction of a single pt line
      20              : /****************************************************************************/
      21              : #include <utils/iodevices/OutputDevice.h>
      22              : 
      23              : #include <utility>
      24              : #include <utils/common/ToString.h>
      25              : #include <utils/common/StringUtils.h>
      26              : #include <utils/common/MsgHandler.h>
      27              : #include "NBEdge.h"
      28              : #include "NBEdgeCont.h"
      29              : #include "NBPTStop.h"
      30              : #include "NBPTStopCont.h"
      31              : #include "NBPTLine.h"
      32              : 
      33              : 
      34              : // ===========================================================================
      35              : // method definitions
      36              : // ===========================================================================
      37         1354 : NBPTLine::NBPTLine(const std::string& id, const std::string& name, const std::string& type, const std::string& ref, int interval, const std::string& nightService,
      38         1354 :                    SUMOVehicleClass vClass, RGBColor color) :
      39         1354 :     myName(name),
      40         1354 :     myType(type),
      41         1354 :     myPTLineId(id),
      42         1354 :     myRef(ref != "" ? ref : name),
      43         1354 :     myColor(color),
      44         1354 :     myInterval(interval),
      45         1354 :     myNightService(nightService),
      46         1354 :     myVClass(vClass),
      47         1354 :     myNumOfStops(0),
      48         1354 :     myMissingStopsBefore(0),
      49         1354 :     myMissingStopsAfter(0)
      50         1354 : { }
      51              : 
      52              : 
      53              : void
      54         2972 : NBPTLine::addPTStop(std::shared_ptr<NBPTStop> pStop) {
      55         8574 :     if (!myPTStops.empty() && pStop->getName() != "" && myPTStops.back()->getName() == pStop->getName()) {
      56              :         // avoid duplicate stop when both platform and stop_position are given as nodes
      57          107 :         if (myPTStops.back()->isPlatform() && !pStop->isPlatform()) {
      58              :             myPTStops.pop_back();
      59           98 :         } else if (pStop->isPlatform()) {
      60              :             return;
      61              :         }
      62              :     }
      63         2886 :     myPTStops.push_back(pStop);
      64              : }
      65              : 
      66              : 
      67              : const std::vector<std::shared_ptr<NBPTStop> >&
      68        38460 : NBPTLine::getStops() {
      69        38460 :     return myPTStops;
      70              : }
      71              : 
      72              : 
      73              : void
      74          359 : NBPTLine::write(OutputDevice& device) {
      75          359 :     device.openTag(SUMO_TAG_PT_LINE);
      76          359 :     device.writeAttr(SUMO_ATTR_ID, myPTLineId);
      77          359 :     if (!myName.empty()) {
      78          714 :         device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName));
      79              :     }
      80              : 
      81          359 :     device.writeAttr(SUMO_ATTR_LINE, StringUtils::escapeXML(myRef));
      82          359 :     device.writeAttr(SUMO_ATTR_TYPE, myType);
      83          359 :     device.writeAttr(SUMO_ATTR_VCLASS, toString(myVClass));
      84          359 :     if (myInterval > 0) {
      85              :         // write seconds
      86          204 :         device.writeAttr(SUMO_ATTR_PERIOD, 60 * myInterval);
      87              :     }
      88          359 :     if (myNightService != "") {
      89           28 :         device.writeAttr("nightService", myNightService);
      90              :     }
      91              : 
      92          359 :     if (myColor.isValid()) {
      93              :         device.writeAttr(SUMO_ATTR_COLOR, myColor);
      94              :     }
      95          359 :     device.writeAttr("completeness", (double)myPTStops.size() / myNumOfStops);
      96          359 :     if (myMissingStopsBefore != 0) {
      97          552 :         device.writeAttr("missingBefore", myMissingStopsBefore);
      98              :     }
      99          359 :     if (myMissingStopsAfter != 0) {
     100          568 :         device.writeAttr("missingAfter", myMissingStopsAfter);
     101              :     }
     102              : 
     103          359 :     if (!myRoute.empty()) {
     104          316 :         device.openTag(SUMO_TAG_ROUTE);
     105          316 :         device.writeAttr(SUMO_ATTR_EDGES, myRoute);
     106          632 :         device.closeTag();
     107              :     }
     108              : 
     109         1429 :     for (auto& myPTStop : myPTStops) {
     110         1070 :         device.openTag(SUMO_TAG_BUS_STOP);
     111         2140 :         device.writeAttr(SUMO_ATTR_ID, myPTStop->getID());
     112         1070 :         device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myPTStop->getName()));
     113         2140 :         device.closeTag();
     114              :     }
     115          359 :     device.closeTag();
     116              : 
     117          359 : }
     118              : 
     119              : 
     120              : void
     121        89451 : NBPTLine::addWayNode(long long int way, long long int node) {
     122        89451 :     std::string wayStr = toString(way);
     123        89451 :     if (wayStr != myCurrentWay) {
     124              :         myCurrentWay = wayStr;
     125        13832 :         myWays.push_back(wayStr);
     126              :     }
     127        89451 :     myWayNodes[wayStr].push_back(node);
     128        89451 : }
     129              : 
     130              : 
     131              : const std::vector<long long int>*
     132         6625 : NBPTLine::getWayNodes(std::string wayId) {
     133         6625 :     if (myWayNodes.find(wayId) != myWayNodes.end()) {
     134         6625 :         return &myWayNodes[wayId];
     135              :     }
     136              :     return nullptr;
     137              : }
     138              : 
     139              : 
     140              : void
     141         1189 : NBPTLine::setEdges(const std::vector<NBEdge*>& edges) {
     142         1189 :     myRoute = edges;
     143              :     // ensure permissions
     144        31339 :     for (NBEdge* e : edges) {
     145        30150 :         SVCPermissions permissions = e->getPermissions();
     146        30150 :         if ((permissions & myVClass) != myVClass) {
     147              :             SVCPermissions nVuln = ~(SVC_PEDESTRIAN | SVC_BICYCLE);
     148           68 :             if (permissions != 0 && (permissions & nVuln) == 0) {
     149              :                 // this is a footpath or sidewalk. Add another lane
     150            7 :                 e->addRestrictedLane(SUMO_const_laneWidth, myVClass);
     151              :             } else {
     152              :                 // add permissions to the rightmost lane that is not exclusively used for pedestrians / bicycles
     153           61 :                 for (int i = 0; i < (int)e->getNumLanes(); i++) {
     154           61 :                     if ((e->getPermissions(i) & nVuln) != 0) {
     155           61 :                         e->allowVehicleClass(i, myVClass);
     156              :                         break;
     157              :                     }
     158              :                 }
     159              :             }
     160              :         }
     161              :     }
     162         1189 : }
     163              : 
     164              : 
     165              : void
     166         1355 : NBPTLine::setNumOfStops(int numStops, int missingBefore, int missingAfter) {
     167         1355 :     myNumOfStops = numStops;
     168         1355 :     myMissingStopsBefore = missingBefore;
     169         1355 :     myMissingStopsAfter = missingAfter;
     170         1355 : }
     171              : 
     172              : 
     173              : const std::vector<NBEdge*>&
     174         3202 : NBPTLine::getRoute() const {
     175         3202 :     return myRoute;
     176              : }
     177              : 
     178              : 
     179              : std::vector<std::pair<NBEdge*, std::string> >
     180          152 : NBPTLine::getStopEdges(const NBEdgeCont& ec) const {
     181              :     std::vector<std::pair<NBEdge*, std::string> > result;
     182          785 :     for (std::shared_ptr<NBPTStop> stop : myPTStops) {
     183          633 :         NBEdge* e = ec.retrieve(stop->getEdgeId());
     184          633 :         if (e != nullptr) {
     185         1266 :             result.push_back({e, stop->getID()});
     186              :         }
     187              :     }
     188          152 :     return result;
     189            0 : }
     190              : 
     191              : 
     192              : NBEdge*
     193          152 : NBPTLine::getRouteStart(const NBEdgeCont& ec) const {
     194              :     std::vector<NBEdge*> validEdges;
     195              :     // filter out edges that have been removed due to joining junctions
     196         5450 :     for (NBEdge* e : myRoute) {
     197         5298 :         if (ec.retrieve(e->getID())) {
     198         5298 :             validEdges.push_back(e);
     199              :         }
     200              :     }
     201          152 :     if (validEdges.size() == 0) {
     202              :         return nullptr;
     203              :     }
     204              :     // filter out edges after the first stop
     205          140 :     if (myPTStops.size() > 0) {
     206          139 :         NBEdge* firstStopEdge = ec.retrieve(myPTStops.front()->getEdgeId());
     207          139 :         if (firstStopEdge == nullptr) {
     208            0 :             WRITE_WARNINGF(TL("Could not retrieve edge '%' for first stop of line '%'."), myPTStops.front()->getEdgeId(), myPTLineId);
     209            9 :             return nullptr;
     210              : 
     211              :         }
     212          139 :         auto it = std::find(validEdges.begin(), validEdges.end(), firstStopEdge);
     213          139 :         if (it == validEdges.end()) {
     214           36 :             WRITE_WARNINGF(TL("First stop edge '%' is not part of the route of line '%'."), firstStopEdge->getID(), myPTLineId);
     215            9 :             return nullptr;
     216              :         }
     217              :     }
     218          131 :     return validEdges.front();
     219          152 : }
     220              : 
     221              : 
     222              : NBEdge*
     223          152 : NBPTLine::getRouteEnd(const NBEdgeCont& ec) const {
     224              :     std::vector<NBEdge*> validEdges;
     225              :     // filter out edges that have been removed due to joining junctions
     226         5450 :     for (NBEdge* e : myRoute) {
     227         5298 :         if (ec.retrieve(e->getID())) {
     228         5298 :             validEdges.push_back(e);
     229              :         }
     230              :     }
     231          152 :     if (validEdges.size() == 0) {
     232              :         return nullptr;
     233              :     }
     234              :     // filter out edges after the last stop
     235          140 :     if (myPTStops.size() > 0) {
     236          139 :         NBEdge* lastStopEdge = ec.retrieve(myPTStops.back()->getEdgeId());
     237          139 :         if (lastStopEdge == nullptr) {
     238            0 :             WRITE_WARNINGF(TL("Could not retrieve edge '%' for last stop of line '%'."), myPTStops.back()->getEdgeId(), myPTLineId);
     239           11 :             return nullptr;
     240              : 
     241              :         }
     242          139 :         auto it = std::find(validEdges.begin(), validEdges.end(), lastStopEdge);
     243          139 :         if (it == validEdges.end()) {
     244           44 :             WRITE_WARNINGF(TL("Last stop edge '%' is not part of the route of line '%'."), lastStopEdge->getID(), myPTLineId);
     245           11 :             return nullptr;
     246              :         }
     247              :     }
     248          129 :     return validEdges.back();
     249          152 : }
     250              : 
     251              : 
     252              : bool
     253          145 : NBPTLine::isConsistent(std::vector<NBEdge*> stops) const {
     254          145 :     if (myRoute.empty() || stops.empty()) {
     255              :         return true;
     256              :     }
     257          132 :     if (stops.size() > 1 && stops.front() == stops.back()) {
     258              :         // circular route where we don't expect the route edges to occur twice
     259            9 :         if (myRoute.front() == stops.front()) {
     260              :             stops.pop_back();
     261            2 :         } else if (myRoute.back() == stops.back()) {
     262              :             stops.erase(stops.begin());
     263              :         }
     264              :     }
     265              :     std::vector<NBEdge*>::const_iterator stopIt = stops.begin();
     266         4747 :     for (const NBEdge* const e : myRoute) {
     267         5321 :         while (stopIt != stops.end() && e == *stopIt) {
     268              :             ++stopIt;
     269              :         }
     270         4739 :         if (stopIt == stops.end()) {
     271              :             return true;
     272              :         }
     273              :     }
     274              :     return false;
     275              : }
     276              : 
     277              : 
     278              : void
     279           54 : NBPTLine::replaceStop(std::shared_ptr<NBPTStop> oldStop, std::shared_ptr<NBPTStop> newStop) {
     280          404 :     for (int i = 0; i < (int)myPTStops.size(); i++) {
     281          350 :         if (myPTStops[i] == oldStop) {
     282              :             myPTStops[i] = newStop;
     283              :         }
     284              :     }
     285           54 : }
     286              : 
     287              : 
     288              : void
     289         5121 : NBPTLine::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
     290         5121 :     EdgeVector oldRoute = myRoute;
     291              :     myRoute.clear();
     292       203223 :     for (NBEdge* e : oldRoute) {
     293       198102 :         if (e->getID() == edgeID) {
     294        10774 :             for (NBEdge* e2 : replacement) {
     295         5638 :                 if (myRoute.empty() || myRoute.back() != e2) {
     296          752 :                     myRoute.push_back(e2);
     297              :                 }
     298              :             }
     299              :         } else {
     300       192966 :             myRoute.push_back(e);
     301              :         }
     302              :     }
     303         5121 : }
     304              : 
     305              : 
     306              : void
     307         1233 : NBPTLine::deleteInvalidStops(const NBEdgeCont& ec, const NBPTStopCont& sc) {
     308              :     // delete stops that are missing or have no edge
     309         4708 :     for (auto it = myPTStops.begin(); it != myPTStops.end();) {
     310              :         std::shared_ptr<NBPTStop> stop = *it;
     311        10421 :         if (sc.get(stop->getID()) == nullptr ||
     312         3471 :                 ec.getByID(stop->getEdgeId()) == nullptr) {
     313          444 :             WRITE_WARNINGF(TL("Removed invalid stop '%' from line '%'."), stop->getID(), getLineID());
     314          148 :             it = myPTStops.erase(it);
     315              :         } else {
     316              :             it++;
     317              :         }
     318              : 
     319              :     }
     320         1233 : }
     321              : 
     322              : 
     323              : void
     324            0 : NBPTLine::deleteDuplicateStops() {
     325              :     // delete subsequent stops that belong to the same stopArea
     326            0 :     long long int lastAreaID = -1;
     327            0 :     std::string lastName = "";
     328            0 :     for (auto it = myPTStops.begin(); it != myPTStops.end();) {
     329              :         std::shared_ptr<NBPTStop> stop = *it;
     330            0 :         if (lastAreaID != -1 && stop->getAreaID() == lastAreaID) {
     331            0 :             WRITE_WARNINGF(TL("Removed duplicate stop '%' at area '%' from line '%'."), stop->getID(), toString(lastAreaID), getLineID());
     332            0 :             it = myPTStops.erase(it);
     333            0 :         } else if (lastName != "" && stop->getName() == lastName) {
     334            0 :             WRITE_WARNINGF(TL("Removed duplicate stop '%' named '%' from line '%'."), stop->getID(), lastName, getLineID());
     335            0 :             it = myPTStops.erase(it);
     336              :         } else {
     337              :             it++;
     338              :         }
     339            0 :         lastAreaID = stop->getAreaID();
     340            0 :         lastName = stop->getName();
     341              :     }
     342            0 : }
     343              : 
     344              : 
     345              : void
     346         1096 : NBPTLine::removeInvalidEdges(const NBEdgeCont& ec) {
     347        19952 :     for (int i = 0; i < (int)myRoute.size();) {
     348        18856 :         const std::pair<NBEdge*, NBEdge*>* split = ec.getSplit(myRoute[i]);
     349              :         if (split != nullptr) {
     350            0 :             myRoute[i] = split->first;
     351            0 :             myRoute.insert(myRoute.begin() + i + 1, split->second);
     352        18856 :         } else if (ec.retrieve(myRoute[i]->getID()) == nullptr) {
     353         2321 :             myRoute.erase(myRoute.begin() + i);
     354              :         } else {
     355        16535 :             i++;
     356              :         }
     357              :     }
     358         1096 : }
     359              : 
     360              : 
     361              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1