LCOV - code coverage report
Current view: top level - src/netbuild - NBPTStopCont.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.1 % 229 220
Test Date: 2024-12-21 15:45:41 Functions: 100.0 % 23 23

            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    NBPTStopCont.cpp
      15              : /// @author  Gregor Laemmel
      16              : /// @date    Tue, 20 Mar 2017
      17              : ///
      18              : // Container for pt stops during the netbuilding process
      19              : /****************************************************************************/
      20              : #include <config.h>
      21              : #include <utils/common/MsgHandler.h>
      22              : #include <utils/geom/Boundary.h>
      23              : #include <utils/geom/Position.h>
      24              : #include <utils/options/OptionsCont.h>
      25              : #include <microsim/MSLane.h>
      26              : #include "NBEdgeCont.h"
      27              : #include "NBEdge.h"
      28              : #include "NBNode.h"
      29              : #include "NBPTPlatform.h"
      30              : #include "NBPTStop.h"
      31              : #include "NBPTStopCont.h"
      32              : 
      33              : 
      34              : // ===========================================================================
      35              : // static members
      36              : // ===========================================================================
      37              : std::set<std::string> NBPTStopCont::myIgnoredStops;
      38              : 
      39              : 
      40              : // ===========================================================================
      41              : // method definitions
      42              : // ===========================================================================
      43         2002 : NBPTStopCont::~NBPTStopCont() {
      44              :     myPTStops.clear();
      45         2002 : }
      46              : 
      47              : 
      48              : bool
      49         2043 : NBPTStopCont::insert(std::shared_ptr<NBPTStop> ptStop, bool floating) {
      50         2043 :     std::string id = ptStop->getID();
      51              :     auto i = myPTStops.find(id);
      52         2043 :     if (i != myPTStops.end()) {
      53              :         return false;
      54              :     }
      55         1982 :     myPTStops[id] = ptStop;
      56         1982 :     if (floating) {
      57          116 :         myFloatingStops.push_back(ptStop);
      58              :     }
      59              :     return true;
      60              : }
      61              : 
      62              : 
      63              : std::shared_ptr<NBPTStop>
      64         9410 : NBPTStopCont::get(std::string id) const {
      65         9410 :     if (myPTStops.find(id) != myPTStops.end()) {
      66              :         return myPTStops.find(id)->second;
      67              :     }
      68              :     return nullptr;
      69              : }
      70              : 
      71              : 
      72              : void
      73          103 : NBPTStopCont::localizePTStops(NBEdgeCont& cont) {
      74              :     std::vector<std::shared_ptr<NBPTStop> > reverseStops;
      75              :     //first pass localize pt stop at correct side of the street; create stop for opposite side if needed
      76         1218 :     for (const auto& ptStopIt : myPTStops) {
      77              :         std::shared_ptr<NBPTStop> const stop = ptStopIt.second;
      78         1115 :         bool multipleStopPositions = stop->getIsMultipleStopPositions();
      79         1115 :         bool platformsDefined = !stop->getPlatformCands().empty();
      80         1115 :         if (!platformsDefined) {
      81              :             //create pt stop for reverse edge if edge exists
      82         1660 :             std::shared_ptr<NBPTStop> reverseStop = getReverseStop(stop, cont);
      83          830 :             if (reverseStop != nullptr) {
      84          206 :                 reverseStops.push_back(reverseStop);
      85              :             }
      86          285 :         } else if (multipleStopPositions) {
      87              :             //create pt stop for closest platform at corresponding edge
      88          536 :             assignPTStopToEdgeOfClosestPlatform(stop, cont);
      89              :         } else {
      90              :             //create pt stop for each side of the street where a platform is defined (create additional pt stop as needed)
      91           34 :             std::shared_ptr<NBPTStop> additionalStop = assignAndCreatNewPTStopAsNeeded(stop, cont);
      92           17 :             if (additionalStop != nullptr) {
      93            0 :                 reverseStops.push_back(additionalStop);
      94              :             }
      95              :         }
      96              :     }
      97              :     //insert new stops if any
      98          309 :     for (std::shared_ptr<NBPTStop>& reverseStop : reverseStops) {
      99          412 :         insert(reverseStop);
     100              :     }
     101          103 : }
     102              : 
     103              : 
     104              : void
     105          284 : NBPTStopCont::assignLanes(NBEdgeCont& cont) {
     106              :     //scnd pass set correct lane
     107         3769 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     108              :         std::shared_ptr<NBPTStop> stop = i->second;
     109         3485 :         if (!stop->findLaneAndComputeBusStopExtent(cont)) {
     110           12 :             WRITE_WARNINGF(TL("Could not find corresponding edge or compatible lane for pt stop '%' (%). Thus, it will be removed!"),
     111              :                            i->first, i->second->getName());
     112              :             //EdgeVector edgeVector = cont.getGeneratedFrom((*i).second->getOrigEdgeId());
     113              :             //std::cout << edgeVector.size() << std::endl;
     114              :             myPTStops.erase(i++);
     115              :         } else {
     116              :             i++;
     117              :         }
     118              :     }
     119          284 : }
     120              : 
     121              : 
     122              : int
     123          133 : NBPTStopCont::generateBidiStops(NBEdgeCont& ec) {
     124              :     //scnd pass set correct lane
     125              :     int existingBidiStops = 0;
     126              :     std::vector<std::shared_ptr<NBPTStop> > toAdd;
     127         1837 :     for (auto i = myPTStops.begin(); i != myPTStops.end(); i++) {
     128              :         std::shared_ptr<NBPTStop> stop = i->second;
     129         1704 :         NBEdge* edge = ec.getByID(stop->getEdgeId());
     130         1704 :         if (edge != nullptr && edge->isBidiRail()) {
     131          284 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     132              :             assert(bidiEdge != 0);
     133          568 :             const std::string id = getReverseID(stop->getID());
     134          150 :             if (myPTStops.count(id) > 0) {
     135          150 :                 if (myPTStops[id]->getEdgeId() != bidiEdge->getID()) {
     136            0 :                     WRITE_WARNINGF(TL("Could not create reverse-direction stop for superposed edge '%' (origStop '%'). Stop id '%' already in use by stop on edge '%'."),
     137              :                                    bidiEdge->getID(), i->first, id, myPTStops[id]->getEdgeId());
     138              :                 }
     139              :                 continue;
     140              :             }
     141              :             std::shared_ptr<NBPTStop> bidiStop = std::make_shared<NBPTStop>(id,
     142              :                                                  stop->getPosition(),
     143          134 :                                                  bidiEdge->getID(),
     144          268 :                                                  stop->getOrigEdgeId(),
     145          268 :                                                  stop->getLength(),
     146          268 :                                                  stop->getName(),
     147          402 :                                                  stop->getPermissions());
     148          134 :             if (bidiStop->findLaneAndComputeBusStopExtent(ec)) {
     149          134 :                 toAdd.push_back(bidiStop);
     150          134 :                 stop->setBidiStop(bidiStop);
     151          134 :                 bidiStop->setBidiStop(stop);
     152              :             } else {
     153              :                 // should not happen
     154              :                 assert(false);
     155              :             }
     156         1420 :         } else if (edge != nullptr) {
     157         1420 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     158         1420 :             if (bidiEdge != nullptr) {
     159         1346 :                 const std::string id = getReverseID(stop->getID());
     160              :                 if (myPTStops.count(id) > 0) {
     161          329 :                     existingBidiStops++;
     162              :                 }
     163              :             }
     164              :         }
     165              :     }
     166          267 :     for (std::shared_ptr<NBPTStop> newStop : toAdd) {
     167          268 :         myPTStops[newStop->getID()] = newStop;
     168              :     }
     169          133 :     if (toAdd.size() > 0) {
     170           48 :         WRITE_MESSAGEF(TL("Added % stops for superposed rail edges."), toString(toAdd.size()));
     171              :     }
     172          133 :     return (int)toAdd.size() + existingBidiStops;
     173          133 : }
     174              : 
     175              : 
     176              : std::shared_ptr<NBPTStop>
     177          919 : NBPTStopCont::getReverseStop(std::shared_ptr<NBPTStop> pStop, const NBEdgeCont& ec) {
     178          919 :     std::string edgeId = pStop->getEdgeId();
     179          919 :     NBEdge* edge = ec.getByID(edgeId);
     180          919 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     181          919 :     if (reverse != nullptr) {
     182          588 :         const std::string reverseID = getReverseID(pStop->getID());
     183              :         if (myPTStops.count(reverseID) == 0) {
     184          233 :             return std::make_shared<NBPTStop>(reverseID, pStop->getPosition(), reverse->getID(), reverse->getID(),
     185          699 :                                               pStop->getLength(), pStop->getName(), pStop->getPermissions());
     186              :         } else {
     187           61 :             return myPTStops[reverseID];
     188              :         }
     189              :     }
     190              :     return nullptr;
     191              : }
     192              : 
     193              : 
     194              : std::shared_ptr<NBPTStop>
     195           17 : NBPTStopCont::assignAndCreatNewPTStopAsNeeded(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     196           17 :     std::string edgeId = pStop->getEdgeId();
     197           17 :     NBEdge* edge = cont.getByID(edgeId);
     198           17 :     if (edge == nullptr) {
     199              :         return nullptr;
     200              :     }
     201              :     bool rightOfEdge = false;
     202              :     bool leftOfEdge = false;
     203              :     const NBPTPlatform* left = nullptr;
     204           33 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     205           17 :         double crossProd = computeCrossProductEdgePosition(edge, platform.getPos());
     206              :         //TODO consider driving on the left!!! [GL May '17]
     207           17 :         if (crossProd > 0) {
     208              :             leftOfEdge = true;
     209              :             left = &platform;
     210              :         } else {
     211              :             rightOfEdge = true;
     212           16 :             pStop->setPTStopLength(platform.getLength());
     213              :         }
     214              :     }
     215              : 
     216           16 :     if (leftOfEdge && rightOfEdge) {
     217            2 :         std::shared_ptr<NBPTStop> leftStop = getReverseStop(pStop, cont);
     218            1 :         if (leftStop) {
     219            0 :             leftStop->setPTStopLength(left->getLength());
     220              :         }
     221              :         return leftStop;
     222           15 :     } else if (leftOfEdge) {
     223            0 :         NBEdge* reverse = getReverseEdge(edge);
     224            0 :         if (reverse != nullptr) {
     225            0 :             pStop->setEdgeId(reverse->getID(), cont);
     226            0 :             pStop->setPTStopLength(left->getLength());
     227              :         }
     228              :     }
     229              : 
     230              :     return nullptr;
     231              : }
     232              : 
     233              : 
     234              : void
     235          268 : NBPTStopCont::assignPTStopToEdgeOfClosestPlatform(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     236          268 :     std::string edgeId = pStop->getEdgeId();
     237          268 :     NBEdge* edge = cont.getByID(edgeId);
     238          268 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     239          536 :     const NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
     240          268 :     pStop->setPTStopLength(closestPlatform->getLength());
     241          268 :     if (reverse != nullptr) {
     242              : 
     243              :         //TODO make isLeft in PositionVector static [GL May '17]
     244              : //        if (PositionVector::isLeft(edge->getFromNode()->getPosition(),edge->getToNode()->getPosition(),closestPlatform)){
     245              : //
     246              : //        }
     247           99 :         double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getPos());
     248              : 
     249              :         //TODO consider driving on the left!!! [GL May '17]
     250           99 :         if (crossProd > 0) { //pt stop is on the left of the orig edge
     251          123 :             pStop->setEdgeId(reverse->getID(), cont);
     252              :         }
     253              :     }
     254          268 : }
     255              : 
     256              : 
     257              : double
     258          116 : NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const {
     259              :     PositionVector geom = edge->getGeometry();
     260          116 :     int idxTmp = geom.indexOfClosest(closestPlatform);
     261          116 :     double offset = geom.nearest_offset_to_point2D(closestPlatform, true);
     262          116 :     double offset2 = geom.offsetAtIndex2D(idxTmp);
     263              :     int idx1, idx2;
     264          116 :     if (offset2 < offset) {
     265              :         idx1 = idxTmp;
     266           41 :         idx2 = idx1 + 1;
     267              :     } else {
     268              :         idx2 = idxTmp;
     269           75 :         idx1 = idxTmp - 1;
     270              :     }
     271          116 :     if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
     272           63 :         WRITE_WARNINGF(TL("Could not determine cross product for edge '%'."), edge->getID());
     273           21 :         return 0;
     274              :     }
     275           95 :     Position p1 = geom[idx1];
     276           95 :     Position p2 = geom[idx2];
     277              : 
     278              :     double x0 = p1.x();
     279              :     double y0 = p1.y();
     280              :     double x1 = p2.x();
     281              :     double y1 = p2.y();
     282              :     double x2 = closestPlatform.x();
     283              :     double y2 = closestPlatform.y();
     284           95 :     double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
     285              :     return crossProd;
     286          116 : }
     287              : 
     288              : 
     289              : const NBPTPlatform*
     290          268 : NBPTStopCont::getClosestPlatformToPTStopPosition(std::shared_ptr<NBPTStop> pStop) {
     291          268 :     Position stopPosition = pStop->getPosition();
     292              :     const NBPTPlatform* closest = nullptr;
     293              :     double minSqrDist = std::numeric_limits<double>::max();
     294          993 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     295          725 :         double sqrDist = stopPosition.distanceSquaredTo2D(platform.getPos());
     296          725 :         if (sqrDist < minSqrDist) {
     297              :             minSqrDist = sqrDist;
     298              :             closest = &platform;
     299              :         }
     300              :     }
     301          268 :     return closest;
     302              : }
     303              : 
     304              : //static functions
     305              : 
     306              : NBEdge*
     307         1429 : NBPTStopCont::getReverseEdge(NBEdge* edge) {
     308         1429 :     if (edge != nullptr) {
     309         1259 :         for (auto it = edge->getToNode()->getOutgoingEdges().begin();
     310         2244 :                 it != edge->getToNode()->getOutgoingEdges().end();
     311              :                 it++) {
     312         1557 :             if ((*it)->getToNode() == edge->getFromNode()) {
     313              :                 return (*it);
     314              :             }
     315              :         }
     316              :     }
     317              :     return nullptr;
     318              : }
     319              : 
     320              : 
     321              : int
     322         1870 : NBPTStopCont::cleanupDeleted(NBEdgeCont& cont) {
     323              :     int numDeleted = 0;
     324         5063 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     325         3193 :         if (cont.getByID(i->second->getEdgeId()) == nullptr) {
     326          483 :             WRITE_WARNINGF(TL("Removing pt stop '%' on non existing edge '%'."), i->first, i->second->getEdgeId());
     327              :             i = myPTStops.erase(i);
     328          161 :             numDeleted++;
     329              :         } else {
     330              :             i++;
     331              :         }
     332              :     }
     333         1870 :     return numDeleted;
     334              : }
     335              : 
     336              : 
     337              : void
     338         1617 : NBPTStopCont::addEdges2Keep(const OptionsCont& /* oc */, std::set<std::string>& into) {
     339         3333 :     for (auto stop : myPTStops) {
     340         1716 :         into.insert(stop.second->getEdgeId());
     341         1716 :     }
     342         1617 : }
     343              : 
     344              : 
     345              : void
     346         5471 : NBPTStopCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
     347         5471 :     if (myPTStops.size() > 0 && myPTStopLookup.size() == 0) {
     348              :         // init lookup once
     349         1068 :         for (auto& item : myPTStops) {
     350         1022 :             myPTStopLookup[item.second->getEdgeId()].push_back(item.second);
     351              :         }
     352              :     }
     353              :     // make a copy because the vector gets modified
     354         5471 :     const std::vector<std::shared_ptr<NBPTStop> > stops = myPTStopLookup[edgeID];
     355         5935 :     for (std::shared_ptr<NBPTStop> stop : stops) {
     356          464 :         if (!stop->replaceEdge(edgeID, replacement)) {
     357            0 :             WRITE_WARNINGF(TL("Could not re-assign pt stop '%' after replacing edge '%'."), stop->getID(), edgeID);
     358              :         } else {
     359          464 :             myPTStopLookup[stop->getEdgeId()].push_back(stop);
     360              :         }
     361              :     }
     362              :     myPTStopLookup.erase(edgeID);
     363         5471 : }
     364              : 
     365              : 
     366              : void
     367            2 : NBPTStopCont::postprocess(std::set<std::string>& usedStops) {
     368           29 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     369           54 :         if (usedStops.find(i->second->getID()) == usedStops.end()) {
     370              :             myPTStops.erase(i++);
     371              :         } else {
     372              :             i++;
     373              :         }
     374              :     }
     375            2 : }
     376              : 
     377              : std::string
     378         1413 : NBPTStopCont::getReverseID(const std::string& id) {
     379         1413 :     return id.size() > 0 && id[0] == '-' ? id.substr(1) : "-" + id;
     380              : }
     381              : 
     382              : void
     383          133 : NBPTStopCont::alignIdSigns() {
     384              :     PTStopsCont stops = myPTStops;
     385         1817 :     for (auto& i : stops) {
     386              :         std::shared_ptr<NBPTStop> s = i.second;
     387         1684 :         const std::string& stopId = s->getID();
     388         1684 :         if (s->getEdgeId() == "") {
     389              :             continue;
     390              :         }
     391         3368 :         const char edgeSign = s->getEdgeId().at(0);
     392         1684 :         const char stopSign = stopId.at(0);
     393         1684 :         if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
     394          162 :             const std::string reverseID = getReverseID(stopId);
     395          324 :             std::shared_ptr<NBPTStop> rs = get(reverseID);
     396          162 :             s->setPTStopId(reverseID);
     397              :             myPTStops.erase(stopId);
     398          162 :             myPTStops[reverseID] = s;
     399          162 :             if (rs != nullptr) {
     400            0 :                 rs->setPTStopId(stopId);
     401           57 :                 myPTStops[stopId] = rs;
     402              :             }
     403              :         }
     404              :     }
     405          133 : }
     406              : 
     407              : void
     408          149 : NBPTStopCont::assignEdgeForFloatingStops(NBEdgeCont& cont, double maxRadius) {
     409              :     NamedRTree r;
     410              :     SVCPermissions publicPermissions = SVC_BUS | SVC_TRAM | SVC_RAIL | SVC_RAIL_URBAN | SVC_TAXI;
     411        39949 :     for (const auto& item : cont) {
     412        39800 :         NBEdge* edge = item.second;
     413        39800 :         if ((edge->getPermissions() & publicPermissions) == 0) {
     414        18814 :             continue;
     415              :         }
     416        20986 :         const Boundary& bound = edge->getGeometry().getBoxBoundary();
     417        20986 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     418        20986 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     419        20986 :         r.Insert(min, max, edge);
     420        20986 :     }
     421          265 :     for (std::shared_ptr<NBPTStop> ptStop : myFloatingStops) {
     422              :         std::set<const Named*> edges;
     423              :         Named::StoringVisitor visitor(edges);
     424          116 :         const Position& pos = ptStop->getPosition();
     425          116 :         float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     426          116 :         float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
     427              :         r.Search(min, max, visitor);
     428              :         std::vector<NBEdge*> nearby;
     429          271 :         for (const Named* namedEdge : edges) {
     430          155 :             NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     431          155 :             if ((e->getPermissions() & ptStop->getPermissions()) != 0) {
     432           81 :                 nearby.push_back(e);
     433              :             }
     434              :         }
     435          116 :         std::sort(nearby.begin(), nearby.end(), [pos](NBEdge * a, NBEdge * b) {
     436          146 :             return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     437              :         });
     438              : 
     439          116 :         for (NBEdge* e : nearby) {
     440           60 :             ptStop->setEdgeId(e->getID(), cont);
     441           20 :             if (ptStop->getLaneId() != "") {
     442              :                 break;
     443              :             }
     444              :         }
     445          116 :         if (ptStop->getLaneId() == "") {
     446          192 :             WRITE_WARNINGF(TL("Could not find corresponding edge or compatible lane for free-floating pt stop '%' (%). Thus, it will be removed!"),
     447              :                            ptStop->getID(), ptStop->getName());
     448          192 :             myPTStops.erase(ptStop->getID());
     449              :         }
     450          116 :     }
     451          149 : }
     452              : 
     453              : void
     454          135 : NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor) {
     455              :     NamedRTree r;
     456        32883 :     for (auto edge : cont) {
     457        32748 :         const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
     458        32748 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     459        32748 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     460        32748 :         r.Insert(min, max, edge.second);
     461        32748 :     }
     462         1977 :     for (auto& ptStop : myPTStops) {
     463         1842 :         const std::string& stopEdgeID = ptStop.second->getEdgeId();
     464         1842 :         NBEdge* stopEdge = cont.getByID(stopEdgeID);
     465              :         //std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
     466         1842 :         if (stopEdge != nullptr && (stopEdge->getPermissions() & SVC_PEDESTRIAN) == 0) {
     467              :             //if (stopEdge != 0 && isRailway(stopEdge->getPermissions())) {
     468              :             std::set<const Named*> edges;
     469              :             Named::StoringVisitor visitor(edges);
     470         1064 :             const Position& pos = ptStop.second->getPosition();
     471         1064 :             float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     472         1064 :             float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
     473              :             r.Search(min, max, visitor);
     474              :             std::vector<NBEdge*> edgCants;
     475       107033 :             for (const Named* namedEdge : edges) {
     476       105969 :                 NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     477       105969 :                 edgCants.push_back(e);
     478              :             }
     479         1064 :             std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
     480       975499 :                 return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     481              :             });
     482              :             int cnt = 0;
     483        12107 :             for (auto edge : edgCants) {
     484              :                 int laneIdx = 0;
     485        21962 :                 for (auto lane : edge->getLanes()) {
     486        13155 :                     if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
     487         2779 :                         double offset = lane.shape.nearest_offset_to_point2D(pos, false);
     488         2779 :                         double finalLength = edge->getFinalLength();
     489         2779 :                         double laneLength = lane.shape.length();
     490         2779 :                         double accessLength = pos.distanceTo2D(lane.shape.positionAtOffset2D(offset)) * accessFactor;
     491         2779 :                         ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength, accessLength);
     492         2779 :                         cnt++;
     493              :                         break;
     494              :                     }
     495        10376 :                     laneIdx++;
     496        13155 :                 }
     497        11586 :                 if (cnt == maxCount) {
     498              :                     break;
     499              :                 }
     500              :             }
     501         1064 :         }
     502              :     }
     503          135 : }
     504              : 
     505              : 
     506              : std::shared_ptr<NBPTStop>
     507            5 : NBPTStopCont::findStop(const std::string& origEdgeID, Position pos, double threshold) const {
     508          123 :     for (auto& item : myPTStops) {
     509          245 :         if (item.second->getOrigEdgeId() == origEdgeID &&
     510            5 :                 item.second->getPosition().distanceTo2D(pos) < threshold) {
     511              :             return item.second;
     512              :         }
     513              :     }
     514              :     return nullptr;
     515              : }
     516              : 
     517              : 
     518              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1