LCOV - code coverage report
Current view: top level - src/netbuild - NBPTStopCont.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 218 227 96.0 %
Date: 2024-05-07 15:28:01 Functions: 23 23 100.0 %

          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        2337 : NBPTStopCont::~NBPTStopCont() {
      44             :     myPTStops.clear();
      45        2337 : }
      46             : 
      47             : 
      48             : bool
      49        2680 : NBPTStopCont::insert(std::shared_ptr<NBPTStop> ptStop, bool floating) {
      50        2680 :     std::string id = ptStop->getID();
      51             :     auto i = myPTStops.find(id);
      52        2680 :     if (i != myPTStops.end()) {
      53             :         return false;
      54             :     }
      55        2605 :     myPTStops[id] = ptStop;
      56        2605 :     if (floating) {
      57         127 :         myFloatingStops.push_back(ptStop);
      58             :     }
      59             :     return true;
      60             : }
      61             : 
      62             : 
      63             : std::shared_ptr<NBPTStop>
      64       13749 : NBPTStopCont::get(std::string id) const {
      65       13749 :     if (myPTStops.find(id) != myPTStops.end()) {
      66             :         return myPTStops.find(id)->second;
      67             :     }
      68             :     return nullptr;
      69             : }
      70             : 
      71             : 
      72             : void
      73         106 : 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        1678 :     for (const auto& ptStopIt : myPTStops) {
      77             :         std::shared_ptr<NBPTStop> const stop = ptStopIt.second;
      78        1572 :         bool multipleStopPositions = stop->getIsMultipleStopPositions();
      79        1572 :         bool platformsDefined = !stop->getPlatformCands().empty();
      80        1572 :         if (!platformsDefined) {
      81             :             //create pt stop for reverse edge if edge exists
      82        2258 :             std::shared_ptr<NBPTStop> reverseStop = getReverseStop(stop, cont);
      83        1129 :             if (reverseStop != nullptr) {
      84         255 :                 reverseStops.push_back(reverseStop);
      85             :             }
      86         443 :         } else if (multipleStopPositions) {
      87             :             //create pt stop for closest platform at corresponding edge
      88         822 :             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          64 :             std::shared_ptr<NBPTStop> additionalStop = assignAndCreatNewPTStopAsNeeded(stop, cont);
      92          32 :             if (additionalStop != nullptr) {
      93           0 :                 reverseStops.push_back(additionalStop);
      94             :             }
      95             :         }
      96             :     }
      97             :     //insert new stops if any
      98         361 :     for (std::shared_ptr<NBPTStop>& reverseStop : reverseStops) {
      99         510 :         insert(reverseStop);
     100             :     }
     101         106 : }
     102             : 
     103             : 
     104             : void
     105         293 : NBPTStopCont::assignLanes(NBEdgeCont& cont) {
     106             :     //scnd pass set correct lane
     107        4977 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     108             :         std::shared_ptr<NBPTStop> stop = i->second;
     109        4684 :         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         293 : }
     120             : 
     121             : 
     122             : int
     123         138 : NBPTStopCont::generateBidiStops(NBEdgeCont& ec) {
     124             :     //scnd pass set correct lane
     125             :     int existingBidiStops = 0;
     126             :     std::vector<std::shared_ptr<NBPTStop> > toAdd;
     127        2441 :     for (auto i = myPTStops.begin(); i != myPTStops.end(); i++) {
     128             :         std::shared_ptr<NBPTStop> stop = i->second;
     129        2303 :         NBEdge* edge = ec.getByID(stop->getEdgeId());
     130        2303 :         if (edge != nullptr && edge->isBidiRail()) {
     131         336 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     132             :             assert(bidiEdge != 0);
     133         672 :             const std::string id = getReverseID(stop->getID());
     134         176 :             if (myPTStops.count(id) > 0) {
     135         176 :                 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         160 :                                                  bidiEdge->getID(),
     144         320 :                                                  stop->getOrigEdgeId(),
     145         320 :                                                  stop->getLength(),
     146         320 :                                                  stop->getName(),
     147         480 :                                                  stop->getPermissions());
     148         160 :             if (bidiStop->findLaneAndComputeBusStopExtent(ec)) {
     149         160 :                 toAdd.push_back(bidiStop);
     150         160 :                 stop->setBidiStop(bidiStop);
     151         160 :                 bidiStop->setBidiStop(stop);
     152             :             } else {
     153             :                 // should not happen
     154             :                 assert(false);
     155             :             }
     156        1967 :         } else if (edge != nullptr) {
     157        1967 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     158        1967 :             if (bidiEdge != nullptr) {
     159        1756 :                 const std::string id = getReverseID(stop->getID());
     160             :                 if (myPTStops.count(id) > 0) {
     161         389 :                     existingBidiStops++;
     162             :                 }
     163             :             }
     164             :         }
     165             :     }
     166         298 :     for (std::shared_ptr<NBPTStop> newStop : toAdd) {
     167         320 :         myPTStops[newStop->getID()] = newStop;
     168             :     }
     169         138 :     if (toAdd.size() > 0) {
     170          50 :         WRITE_MESSAGEF(TL("Added % stops for superposed rail edges."), toString(toAdd.size()));
     171             :     }
     172         138 :     return (int)toAdd.size() + existingBidiStops;
     173         138 : }
     174             : 
     175             : 
     176             : std::shared_ptr<NBPTStop>
     177        1219 : NBPTStopCont::getReverseStop(std::shared_ptr<NBPTStop> pStop, const NBEdgeCont& ec) {
     178        1219 :     std::string edgeId = pStop->getEdgeId();
     179        1219 :     NBEdge* edge = ec.getByID(edgeId);
     180        1219 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     181        1219 :     if (reverse != nullptr) {
     182         688 :         const std::string reverseID = getReverseID(pStop->getID());
     183             :         if (myPTStops.count(reverseID) == 0) {
     184         269 :             return std::make_shared<NBPTStop>(reverseID, pStop->getPosition(), reverse->getID(), reverse->getID(),
     185         962 :                                               pStop->getLength(), pStop->getName(), pStop->getPermissions());
     186             :         } else {
     187          75 :             return myPTStops[reverseID];
     188             :         }
     189             :     }
     190             :     return nullptr;
     191             : }
     192             : 
     193             : 
     194             : std::shared_ptr<NBPTStop>
     195          32 : NBPTStopCont::assignAndCreatNewPTStopAsNeeded(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     196          32 :     std::string edgeId = pStop->getEdgeId();
     197          32 :     NBEdge* edge = cont.getByID(edgeId);
     198          32 :     if (edge == nullptr) {
     199             :         return nullptr;
     200             :     }
     201             :     bool rightOfEdge = false;
     202             :     bool leftOfEdge = false;
     203             :     const NBPTPlatform* left = nullptr;
     204          63 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     205          32 :         double crossProd = computeCrossProductEdgePosition(edge, platform.getPos());
     206             :         //TODO consider driving on the left!!! [GL May '17]
     207          32 :         if (crossProd > 0) {
     208             :             leftOfEdge = true;
     209             :             left = &platform;
     210             :         } else {
     211             :             rightOfEdge = true;
     212          31 :             pStop->setPTStopLength(platform.getLength());
     213             :         }
     214             :     }
     215             : 
     216          31 :     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          30 :     } 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         411 : NBPTStopCont::assignPTStopToEdgeOfClosestPlatform(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     236         411 :     std::string edgeId = pStop->getEdgeId();
     237         411 :     NBEdge* edge = cont.getByID(edgeId);
     238         411 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     239         822 :     const NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
     240         411 :     pStop->setPTStopLength(closestPlatform->getLength());
     241         411 :     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         151 :         double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getPos());
     248             : 
     249             :         //TODO consider driving on the left!!! [GL May '17]
     250         151 :         if (crossProd > 0) { //pt stop is on the left of the orig edge
     251         189 :             pStop->setEdgeId(reverse->getID(), cont);
     252             :         }
     253             :     }
     254         411 : }
     255             : 
     256             : 
     257             : double
     258         183 : NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const {
     259             :     PositionVector geom = edge->getGeometry();
     260         183 :     int idxTmp = geom.indexOfClosest(closestPlatform);
     261         183 :     double offset = geom.nearest_offset_to_point2D(closestPlatform, true);
     262         183 :     double offset2 = geom.offsetAtIndex2D(idxTmp);
     263             :     int idx1, idx2;
     264         183 :     if (offset2 < offset) {
     265             :         idx1 = idxTmp;
     266          71 :         idx2 = idx1 + 1;
     267             :     } else {
     268             :         idx2 = idxTmp;
     269         112 :         idx1 = idxTmp - 1;
     270             :     }
     271         183 :     if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
     272          99 :         WRITE_WARNINGF(TL("Could not determine cross product for edge '%'."), edge->getID());
     273          33 :         return 0;
     274             :     }
     275         150 :     Position p1 = geom[idx1];
     276         150 :     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         150 :     double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
     285             :     return crossProd;
     286         183 : }
     287             : 
     288             : 
     289             : const NBPTPlatform*
     290         411 : NBPTStopCont::getClosestPlatformToPTStopPosition(std::shared_ptr<NBPTStop> pStop) {
     291         411 :     Position stopPosition = pStop->getPosition();
     292             :     const NBPTPlatform* closest = nullptr;
     293             :     double minSqrDist = std::numeric_limits<double>::max();
     294        1557 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     295        1146 :         double sqrDist = stopPosition.distanceSquaredTo2D(platform.getPos());
     296        1146 :         if (sqrDist < minSqrDist) {
     297             :             minSqrDist = sqrDist;
     298             :             closest = &platform;
     299             :         }
     300             :     }
     301         411 :     return closest;
     302             : }
     303             : 
     304             : //static functions
     305             : 
     306             : NBEdge*
     307        1950 : NBPTStopCont::getReverseEdge(NBEdge* edge) {
     308        1950 :     if (edge != nullptr) {
     309        1765 :         for (auto it = edge->getToNode()->getOutgoingEdges().begin();
     310        3240 :                 it != edge->getToNode()->getOutgoingEdges().end();
     311             :                 it++) {
     312        2187 :             if ((*it)->getToNode() == edge->getFromNode()) {
     313             :                 return (*it);
     314             :             }
     315             :         }
     316             :     }
     317             :     return nullptr;
     318             : }
     319             : 
     320             : 
     321             : int
     322        2007 : NBPTStopCont::cleanupDeleted(NBEdgeCont& cont) {
     323             :     int numDeleted = 0;
     324        6356 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     325        4349 :         if (cont.getByID(i->second->getEdgeId()) == nullptr) {
     326         522 :             WRITE_WARNINGF(TL("Removing pt stop '%' on non existing edge '%'."), i->first, i->second->getEdgeId());
     327             :             i = myPTStops.erase(i);
     328         174 :             numDeleted++;
     329             :         } else {
     330             :             i++;
     331             :         }
     332             :     }
     333        2007 :     return numDeleted;
     334             : }
     335             : 
     336             : 
     337             : void
     338        1747 : NBPTStopCont::addEdges2Keep(const OptionsCont& /* oc */, std::set<std::string>& into) {
     339        4062 :     for (auto stop : myPTStops) {
     340        2315 :         into.insert(stop.second->getEdgeId());
     341        2315 :     }
     342        1747 : }
     343             : 
     344             : 
     345             : void
     346        9409 : NBPTStopCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
     347        9409 :     if (myPTStops.size() > 0 && myPTStopLookup.size() == 0) {
     348             :         // init lookup once
     349        1675 :         for (auto& item : myPTStops) {
     350        1622 :             myPTStopLookup[item.second->getEdgeId()].push_back(item.second);
     351             :         }
     352             :     }
     353             :     // make a copy because the vector gets modified
     354        9409 :     const std::vector<std::shared_ptr<NBPTStop> > stops = myPTStopLookup[edgeID];
     355       10192 :     for (std::shared_ptr<NBPTStop> stop : stops) {
     356         783 :         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         783 :             myPTStopLookup[stop->getEdgeId()].push_back(stop);
     360             :         }
     361             :     }
     362             :     myPTStopLookup.erase(edgeID);
     363        9409 : }
     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        1771 : NBPTStopCont::getReverseID(const std::string& id) {
     379        1771 :     return id.size() > 0 && id[0] == '-' ? id.substr(1) : "-" + id;
     380             : }
     381             : 
     382             : void
     383         138 : NBPTStopCont::alignIdSigns() {
     384             :     PTStopsCont stops = myPTStops;
     385        2420 :     for (auto& i : stops) {
     386             :         std::shared_ptr<NBPTStop> s = i.second;
     387        2282 :         const std::string& stopId = s->getID();
     388        4564 :         if (s->getEdgeId() == "") {
     389             :             continue;
     390             :         }
     391        4564 :         const char edgeSign = s->getEdgeId().at(0);
     392        2282 :         const char stopSign = stopId.at(0);
     393        2282 :         if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
     394         213 :             const std::string reverseID = getReverseID(stopId);
     395         426 :             std::shared_ptr<NBPTStop> rs = get(reverseID);
     396         213 :             s->setPTStopId(reverseID);
     397             :             myPTStops.erase(stopId);
     398         213 :             myPTStops[reverseID] = s;
     399         213 :             if (rs != nullptr) {
     400           0 :                 rs->setPTStopId(stopId);
     401          73 :                 myPTStops[stopId] = rs;
     402             :             }
     403             :         }
     404             :     }
     405         138 : }
     406             : 
     407             : void
     408         153 : NBPTStopCont::assignEdgeForFloatingStops(NBEdgeCont& cont, double maxRadius) {
     409             :     NamedRTree r;
     410             :     SVCPermissions publicPermissions = SVC_BUS | SVC_TRAM | SVC_RAIL | SVC_RAIL_URBAN | SVC_TAXI;
     411       61507 :     for (const auto& item : cont) {
     412       61354 :         NBEdge* edge = item.second;
     413       61354 :         if ((edge->getPermissions() & publicPermissions) == 0) {
     414       31063 :             continue;
     415             :         }
     416       30291 :         const Boundary& bound = edge->getGeometry().getBoxBoundary();
     417       30291 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     418       30291 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     419       30291 :         r.Insert(min, max, edge);
     420       30291 :     }
     421         280 :     for (std::shared_ptr<NBPTStop> ptStop : myFloatingStops) {
     422             :         std::set<const Named*> edges;
     423             :         Named::StoringVisitor visitor(edges);
     424         127 :         const Position& pos = ptStop->getPosition();
     425         127 :         float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     426         127 :         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         296 :         for (const Named* namedEdge : edges) {
     430         169 :             NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     431         169 :             if ((e->getPermissions() & ptStop->getPermissions()) != 0) {
     432          81 :                 nearby.push_back(e);
     433             :             }
     434             :         }
     435         127 :         std::sort(nearby.begin(), nearby.end(), [pos](NBEdge * a, NBEdge * b) {
     436         147 :             return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     437             :         });
     438             : 
     439         127 :         for (NBEdge* e : nearby) {
     440          60 :             ptStop->setEdgeId(e->getID(), cont);
     441          20 :             if (ptStop->getLaneId() != "") {
     442             :                 break;
     443             :             }
     444             :         }
     445         127 :         if (ptStop->getLaneId() == "") {
     446         214 :             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         214 :             myPTStops.erase(ptStop->getID());
     449             :         }
     450             :     }
     451         153 : }
     452             : 
     453             : void
     454         140 : NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor) {
     455             :     NamedRTree r;
     456       49321 :     for (auto edge : cont) {
     457       49181 :         const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
     458       49181 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     459       49181 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     460       49181 :         r.Insert(min, max, edge.second);
     461       49181 :     }
     462        2607 :     for (auto& ptStop : myPTStops) {
     463        2467 :         const std::string& stopEdgeID = ptStop.second->getEdgeId();
     464        2467 :         NBEdge* stopEdge = cont.getByID(stopEdgeID);
     465             :         //std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
     466        2467 :         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        1408 :             const Position& pos = ptStop.second->getPosition();
     471        1408 :             float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     472        1408 :             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      187716 :             for (const Named* namedEdge : edges) {
     476      186308 :                 NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     477      186308 :                 edgCants.push_back(e);
     478             :             }
     479        1408 :             std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
     480     1762014 :                 return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     481             :             });
     482             :             int cnt = 0;
     483       15439 :             for (auto edge : edgCants) {
     484             :                 int laneIdx = 0;
     485       27016 :                 for (auto lane : edge->getLanes()) {
     486       16482 :                     if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
     487        4355 :                         double offset = lane.shape.nearest_offset_to_point2D(pos, false);
     488        4355 :                         double finalLength = edge->getFinalLength();
     489        4355 :                         double laneLength = lane.shape.length();
     490        4355 :                         double accessLength = pos.distanceTo2D(lane.shape.positionAtOffset2D(offset)) * accessFactor;
     491        4355 :                         ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength, accessLength);
     492        4355 :                         cnt++;
     493             :                         break;
     494             :                     }
     495       12127 :                     laneIdx++;
     496       16482 :                 }
     497       14889 :                 if (cnt == maxCount) {
     498             :                     break;
     499             :                 }
     500             :             }
     501             :         }
     502             :     }
     503         140 : }
     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 1.14