LCOV - code coverage report
Current view: top level - src/netbuild - NBPTStopCont.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.8 % 240 230
Test Date: 2025-11-13 15:38:19 Functions: 100.0 % 24 24

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 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         2113 : NBPTStopCont::~NBPTStopCont() {
      44              :     myPTStops.clear();
      45         2113 : }
      46              : 
      47              : 
      48              : bool
      49         2094 : NBPTStopCont::insert(std::shared_ptr<NBPTStop> ptStop, bool floating) {
      50         2094 :     std::string id = ptStop->getID();
      51              :     auto i = myPTStops.find(id);
      52         2094 :     if (i != myPTStops.end()) {
      53              :         return false;
      54              :     }
      55         2031 :     myPTStops[id] = ptStop;
      56         2031 :     if (floating) {
      57          124 :         myFloatingStops.push_back(ptStop);
      58              :     }
      59              :     return true;
      60              : }
      61              : 
      62              : 
      63              : std::shared_ptr<NBPTStop>
      64         9520 : NBPTStopCont::get(std::string id) const {
      65         9520 :     if (myPTStops.find(id) != myPTStops.end()) {
      66              :         return myPTStops.find(id)->second;
      67              :     }
      68              :     return nullptr;
      69              : }
      70              : 
      71              : 
      72              : void
      73          120 : 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         1268 :     for (const auto& ptStopIt : myPTStops) {
      77              :         std::shared_ptr<NBPTStop> const stop = ptStopIt.second;
      78         1148 :         bool multipleStopPositions = stop->getIsMultipleStopPositions();
      79         1148 :         bool platformsDefined = !stop->getPlatformCands().empty();
      80         1148 :         if (!platformsDefined) {
      81              :             //create pt stop for reverse edge if edge exists
      82         1722 :             std::shared_ptr<NBPTStop> reverseStop = getReverseStop(stop, cont);
      83          861 :             if (reverseStop != nullptr) {
      84          212 :                 reverseStops.push_back(reverseStop);
      85              :             }
      86          287 :         } else if (multipleStopPositions) {
      87              :             //create pt stop for closest platform at corresponding edge
      88          540 :             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          332 :     for (std::shared_ptr<NBPTStop>& reverseStop : reverseStops) {
      99          424 :         insert(reverseStop);
     100              :     }
     101          120 : }
     102              : 
     103              : 
     104              : void
     105          325 : NBPTStopCont::assignLanes(NBEdgeCont& cont) {
     106              :     //scnd pass set correct lane
     107         3983 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     108              :         std::shared_ptr<NBPTStop> stop = i->second;
     109         3658 :         if (!stop->findLaneAndComputeBusStopExtent(cont)) {
     110            6 :             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          325 : }
     120              : 
     121              : 
     122              : int
     123          156 : NBPTStopCont::generateBidiStops(NBEdgeCont& ec) {
     124              :     int existingBidiStops = 0;
     125              :     std::vector<std::shared_ptr<NBPTStop> > toAdd;
     126         2003 :     for (auto i = myPTStops.begin(); i != myPTStops.end(); i++) {
     127              :         std::shared_ptr<NBPTStop> stop = i->second;
     128         1847 :         NBEdge* edge = ec.getByID(stop->getEdgeId());
     129         1847 :         if (edge != nullptr && edge->isBidiRail()) {
     130          287 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     131              :             assert(bidiEdge != 0);
     132          574 :             const std::string id = getReverseID(stop->getID());
     133          154 :             if (myPTStops.count(id) > 0) {
     134          154 :                 if (myPTStops[id]->getEdgeId() != bidiEdge->getID()) {
     135            0 :                     WRITE_WARNINGF(TL("Could not create reverse-direction stop for superposed edge '%' (origStop '%'). Stop id '%' already in use by stop on edge '%'."),
     136              :                                    bidiEdge->getID(), i->first, id, myPTStops[id]->getEdgeId());
     137              :                 }
     138              :                 continue;
     139              :             }
     140              :             std::shared_ptr<NBPTStop> bidiStop = std::make_shared<NBPTStop>(id,
     141              :                                                  stop->getPosition(),
     142          133 :                                                  bidiEdge->getID(),
     143          266 :                                                  stop->getOrigEdgeId(),
     144          266 :                                                  stop->getLength(),
     145          266 :                                                  stop->getName(),
     146          399 :                                                  stop->getPermissions());
     147          133 :             if (bidiStop->findLaneAndComputeBusStopExtent(ec)) {
     148          133 :                 toAdd.push_back(bidiStop);
     149          133 :                 stop->setBidiStop(bidiStop);
     150          133 :                 bidiStop->setBidiStop(stop);
     151              :             } else {
     152              :                 // should not happen
     153              :                 assert(false);
     154              :             }
     155         1560 :         } else if (edge != nullptr) {
     156         1457 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     157         1457 :             if (bidiEdge != nullptr) {
     158         1366 :                 const std::string id = getReverseID(stop->getID());
     159              :                 if (myPTStops.count(id) > 0) {
     160          335 :                     existingBidiStops++;
     161              :                 }
     162              :             }
     163              :         }
     164              :     }
     165          289 :     for (std::shared_ptr<NBPTStop> newStop : toAdd) {
     166          266 :         myPTStops[newStop->getID()] = newStop;
     167              :     }
     168          156 :     if (toAdd.size() > 0) {
     169           48 :         WRITE_MESSAGEF(TL("Added % stops for superposed rail edges."), toString(toAdd.size()));
     170              :     }
     171          156 :     return (int)toAdd.size() + existingBidiStops;
     172          156 : }
     173              : 
     174              : 
     175              : int
     176            2 : NBPTStopCont::countBidiStops(NBEdgeCont& ec) const {
     177              :     int existingBidiStops = 0;
     178            6 :     for (auto item : myPTStops) {
     179              :         auto stop = item.second;
     180            4 :         NBEdge* edge = ec.getByID(stop->getEdgeId());
     181            4 :         if (edge != nullptr && edge->isBidiRail()) {
     182            4 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     183              :             assert(bidiEdge != 0);
     184            8 :             const std::string id = getReverseID(stop->getID());
     185              :             // @note loaded pairs of bidi-stops might have arbitrary ids and we should rather search through all stops on bidiEdge
     186              :             auto it = myPTStops.find(id);
     187            4 :             if (it != myPTStops.end() && it->second->getEdgeId() == bidiEdge->getID()) {
     188            0 :                 existingBidiStops++;
     189              :             }
     190              :         }
     191            4 :     }
     192            2 :     return existingBidiStops;
     193              : }
     194              : 
     195              : 
     196              : std::shared_ptr<NBPTStop>
     197          950 : NBPTStopCont::getReverseStop(std::shared_ptr<NBPTStop> pStop, const NBEdgeCont& ec) {
     198          950 :     std::string edgeId = pStop->getEdgeId();
     199          950 :     NBEdge* edge = ec.getByID(edgeId);
     200          950 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     201          950 :     if (reverse != nullptr) {
     202          600 :         const std::string reverseID = getReverseID(pStop->getID());
     203              :         if (myPTStops.count(reverseID) == 0) {
     204          237 :             return std::make_shared<NBPTStop>(reverseID, pStop->getPosition(), reverse->getID(), reverse->getID(),
     205          711 :                                               pStop->getLength(), pStop->getName(), pStop->getPermissions());
     206              :         } else {
     207           63 :             return myPTStops[reverseID];
     208              :         }
     209              :     }
     210              :     return nullptr;
     211              : }
     212              : 
     213              : 
     214              : std::shared_ptr<NBPTStop>
     215           17 : NBPTStopCont::assignAndCreatNewPTStopAsNeeded(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     216           17 :     std::string edgeId = pStop->getEdgeId();
     217           17 :     NBEdge* edge = cont.getByID(edgeId);
     218           17 :     if (edge == nullptr) {
     219              :         return nullptr;
     220              :     }
     221              :     bool rightOfEdge = false;
     222              :     bool leftOfEdge = false;
     223              :     const NBPTPlatform* left = nullptr;
     224           33 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     225           17 :         double crossProd = computeCrossProductEdgePosition(edge, platform.getPos());
     226              :         //TODO consider driving on the left!!! [GL May '17]
     227           17 :         if (crossProd > 0) {
     228              :             leftOfEdge = true;
     229              :             left = &platform;
     230              :         } else {
     231              :             rightOfEdge = true;
     232           16 :             pStop->setPTStopLength(platform.getLength());
     233              :         }
     234              :     }
     235              : 
     236           16 :     if (leftOfEdge && rightOfEdge) {
     237            2 :         std::shared_ptr<NBPTStop> leftStop = getReverseStop(pStop, cont);
     238            1 :         if (leftStop) {
     239            0 :             leftStop->setPTStopLength(left->getLength());
     240              :         }
     241              :         return leftStop;
     242           15 :     } else if (leftOfEdge) {
     243            0 :         NBEdge* reverse = getReverseEdge(edge);
     244            0 :         if (reverse != nullptr) {
     245            0 :             pStop->setEdgeId(reverse->getID(), cont);
     246            0 :             pStop->setPTStopLength(left->getLength());
     247              :         }
     248              :     }
     249              : 
     250              :     return nullptr;
     251              : }
     252              : 
     253              : 
     254              : void
     255          270 : NBPTStopCont::assignPTStopToEdgeOfClosestPlatform(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     256          270 :     std::string edgeId = pStop->getEdgeId();
     257          270 :     NBEdge* edge = cont.getByID(edgeId);
     258          270 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     259          540 :     const NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
     260          270 :     pStop->setPTStopLength(closestPlatform->getLength());
     261          270 :     if (reverse != nullptr) {
     262              : 
     263              :         //TODO make isLeft in PositionVector static [GL May '17]
     264              : //        if (PositionVector::isLeft(edge->getFromNode()->getPosition(),edge->getToNode()->getPosition(),closestPlatform)){
     265              : //
     266              : //        }
     267           99 :         double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getPos());
     268              : 
     269              :         //TODO consider driving on the left!!! [GL May '17]
     270           99 :         if (crossProd > 0) { //pt stop is on the left of the orig edge
     271          123 :             pStop->setEdgeId(reverse->getID(), cont);
     272              :         }
     273              :     }
     274          270 : }
     275              : 
     276              : 
     277              : double
     278          116 : NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const {
     279              :     PositionVector geom = edge->getGeometry();
     280          116 :     int idxTmp = geom.indexOfClosest(closestPlatform);
     281          116 :     double offset = geom.nearest_offset_to_point2D(closestPlatform, true);
     282          116 :     double offset2 = geom.offsetAtIndex2D(idxTmp);
     283              :     int idx1, idx2;
     284          116 :     if (offset2 < offset) {
     285              :         idx1 = idxTmp;
     286           41 :         idx2 = idx1 + 1;
     287              :     } else {
     288              :         idx2 = idxTmp;
     289           75 :         idx1 = idxTmp - 1;
     290              :     }
     291          116 :     if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
     292           63 :         WRITE_WARNINGF(TL("Could not determine cross product for edge '%'."), edge->getID());
     293           21 :         return 0;
     294              :     }
     295           95 :     Position p1 = geom[idx1];
     296           95 :     Position p2 = geom[idx2];
     297              : 
     298              :     double x0 = p1.x();
     299              :     double y0 = p1.y();
     300              :     double x1 = p2.x();
     301              :     double y1 = p2.y();
     302              :     double x2 = closestPlatform.x();
     303              :     double y2 = closestPlatform.y();
     304           95 :     double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
     305           95 :     return crossProd;
     306          116 : }
     307              : 
     308              : 
     309              : const NBPTPlatform*
     310          270 : NBPTStopCont::getClosestPlatformToPTStopPosition(std::shared_ptr<NBPTStop> pStop) {
     311          270 :     Position stopPosition = pStop->getPosition();
     312              :     const NBPTPlatform* closest = nullptr;
     313              :     double minSqrDist = std::numeric_limits<double>::max();
     314          999 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     315          729 :         double sqrDist = stopPosition.distanceSquaredTo2D(platform.getPos());
     316          729 :         if (sqrDist < minSqrDist) {
     317              :             minSqrDist = sqrDist;
     318              :             closest = &platform;
     319              :         }
     320              :     }
     321          270 :     return closest;
     322              : }
     323              : 
     324              : //static functions
     325              : 
     326              : NBEdge*
     327         1462 : NBPTStopCont::getReverseEdge(NBEdge* edge) {
     328         1462 :     if (edge != nullptr) {
     329         1284 :         for (auto it = edge->getToNode()->getOutgoingEdges().begin();
     330         2278 :                 it != edge->getToNode()->getOutgoingEdges().end();
     331              :                 it++) {
     332         1572 :             if ((*it)->getToNode() == edge->getFromNode()) {
     333              :                 return (*it);
     334              :             }
     335              :         }
     336              :     }
     337              :     return nullptr;
     338              : }
     339              : 
     340              : 
     341              : int
     342         1991 : NBPTStopCont::cleanupDeleted(NBEdgeCont& cont) {
     343              :     int numDeleted = 0;
     344         5240 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     345         3249 :         if (cont.getByID(i->second->getEdgeId()) == nullptr) {
     346          501 :             WRITE_WARNINGF(TL("Removing pt stop '%' on non existing edge '%'."), i->first, i->second->getEdgeId());
     347              :             i = myPTStops.erase(i);
     348          167 :             numDeleted++;
     349              :         } else {
     350              :             i++;
     351              :         }
     352              :     }
     353         1991 :     return numDeleted;
     354              : }
     355              : 
     356              : 
     357              : void
     358         1726 : NBPTStopCont::addEdges2Keep(const OptionsCont& /* oc */, std::set<std::string>& into) {
     359         3589 :     for (auto stop : myPTStops) {
     360         1863 :         into.insert(stop.second->getEdgeId());
     361         1863 :     }
     362         1726 : }
     363              : 
     364              : 
     365              : void
     366         5567 : NBPTStopCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
     367         5567 :     if (myPTStops.size() > 0 && myPTStopLookup.size() == 0) {
     368              :         // init lookup once
     369         1163 :         for (auto& item : myPTStops) {
     370         1108 :             myPTStopLookup[item.second->getEdgeId()].push_back(item.second);
     371              :         }
     372              :     }
     373              :     // make a copy because the vector gets modified
     374         5567 :     const std::vector<std::shared_ptr<NBPTStop> > stops = myPTStopLookup[edgeID];
     375         6033 :     for (std::shared_ptr<NBPTStop> stop : stops) {
     376          466 :         if (!stop->replaceEdge(edgeID, replacement)) {
     377            0 :             WRITE_WARNINGF(TL("Could not re-assign pt stop '%' after replacing edge '%'."), stop->getID(), edgeID);
     378              :         } else {
     379          466 :             myPTStopLookup[stop->getEdgeId()].push_back(stop);
     380              :         }
     381              :     }
     382              :     myPTStopLookup.erase(edgeID);
     383         5567 : }
     384              : 
     385              : 
     386              : void
     387            4 : NBPTStopCont::postprocess(std::set<std::string>& usedStops) {
     388          192 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     389          376 :         if (usedStops.find(i->second->getID()) == usedStops.end()) {
     390              :             myPTStops.erase(i++);
     391              :         } else {
     392              :             i++;
     393              :         }
     394              :     }
     395            4 : }
     396              : 
     397              : std::string
     398         1436 : NBPTStopCont::getReverseID(const std::string& id) {
     399         1436 :     return id.size() > 0 && id[0] == '-' ? id.substr(1) : "-" + id;
     400              : }
     401              : 
     402              : void
     403          156 : NBPTStopCont::alignIdSigns() {
     404              :     PTStopsCont stops = myPTStops;
     405         1983 :     for (auto& i : stops) {
     406              :         std::shared_ptr<NBPTStop> s = i.second;
     407         1827 :         const std::string& stopId = s->getID();
     408         1827 :         if (s->getEdgeId() == "" || s->wasLoaded()) {
     409          175 :             continue;
     410              :         }
     411         3304 :         const char edgeSign = s->getEdgeId().at(0);
     412         1652 :         const char stopSign = stopId.at(0);
     413         1652 :         if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
     414          162 :             const std::string reverseID = getReverseID(stopId);
     415          324 :             std::shared_ptr<NBPTStop> rs = get(reverseID);
     416          162 :             if (rs != nullptr && rs->wasLoaded()) {
     417              :                 continue;
     418              :             }
     419          160 :             s->setPTStopId(reverseID);
     420              :             myPTStops.erase(stopId);
     421          160 :             myPTStops[reverseID] = s;
     422          160 :             if (rs != nullptr) {
     423            0 :                 rs->setPTStopId(stopId);
     424           55 :                 myPTStops[stopId] = rs;
     425              :             }
     426              :         }
     427              :     }
     428          156 : }
     429              : 
     430              : void
     431          167 : NBPTStopCont::assignEdgeForFloatingStops(NBEdgeCont& cont, double maxRadius) {
     432              :     NamedRTree r;
     433              :     SVCPermissions publicPermissions = SVC_BUS | SVC_TRAM | SVC_RAIL | SVC_RAIL_URBAN | SVC_TAXI;
     434        40291 :     for (const auto& item : cont) {
     435        40124 :         NBEdge* edge = item.second;
     436        40124 :         if ((edge->getPermissions() & publicPermissions) == 0) {
     437        18806 :             continue;
     438              :         }
     439        21318 :         const Boundary& bound = edge->getGeometry().getBoxBoundary();
     440        21318 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     441        21318 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     442        42636 :         r.Insert(min, max, edge);
     443              :     }
     444          291 :     for (std::shared_ptr<NBPTStop> ptStop : myFloatingStops) {
     445              :         std::set<const Named*> edges;
     446              :         Named::StoringVisitor visitor(edges);
     447          124 :         const Position& pos = ptStop->getPosition();
     448          124 :         float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     449          124 :         float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
     450              :         r.Search(min, max, visitor);
     451              :         std::vector<NBEdge*> nearby;
     452          289 :         for (const Named* namedEdge : edges) {
     453          165 :             NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     454          165 :             if ((e->getPermissions() & ptStop->getPermissions()) != 0) {
     455           81 :                 nearby.push_back(e);
     456              :             }
     457              :         }
     458          248 :         std::sort(nearby.begin(), nearby.end(), [pos](NBEdge * a, NBEdge * b) {
     459          148 :             return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     460              :         });
     461              : 
     462          124 :         for (NBEdge* e : nearby) {
     463           60 :             ptStop->setEdgeId(e->getID(), cont);
     464           20 :             if (ptStop->getLaneId() != "") {
     465              :                 break;
     466              :             }
     467              :         }
     468          124 :         if (ptStop->getLaneId() == "") {
     469          208 :             WRITE_WARNINGF(TL("Could not find corresponding edge or compatible lane for free-floating pt stop '%' (%). Thus, it will be removed!"),
     470              :                            ptStop->getID(), ptStop->getName());
     471          208 :             myPTStops.erase(ptStop->getID());
     472              :         }
     473          124 :     }
     474          167 : }
     475              : 
     476              : void
     477          158 : NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor) {
     478              :     NamedRTree r;
     479        33225 :     for (auto edge : cont) {
     480        33067 :         const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
     481        33067 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     482        33067 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     483        66134 :         r.Insert(min, max, edge.second);
     484              :     }
     485         2142 :     for (auto& ptStop : myPTStops) {
     486         1984 :         const std::string& stopEdgeID = ptStop.second->getEdgeId();
     487         1984 :         NBEdge* stopEdge = cont.getByID(stopEdgeID);
     488              :         //std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
     489         1984 :         if (stopEdge != nullptr && (stopEdge->getPermissions() & SVC_PEDESTRIAN) == 0) {
     490              :             //if (stopEdge != 0 && isRailway(stopEdge->getPermissions())) {
     491              :             std::set<const Named*> edges;
     492              :             Named::StoringVisitor visitor(edges);
     493         1080 :             const Position& pos = ptStop.second->getPosition();
     494         1080 :             float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     495         1080 :             float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
     496              :             r.Search(min, max, visitor);
     497              :             std::vector<NBEdge*> edgCants;
     498       107048 :             for (const Named* namedEdge : edges) {
     499       105968 :                 NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     500       105968 :                 edgCants.push_back(e);
     501              :             }
     502         2160 :             std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
     503       971361 :                 return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     504              :             });
     505              :             int cnt = 0;
     506        12228 :             for (auto edge : edgCants) {
     507              :                 int laneIdx = 0;
     508        22227 :                 for (auto lane : edge->getLanes()) {
     509        13331 :                     if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
     510         2798 :                         double offset = lane.shape.nearest_offset_to_point2D(pos, false);
     511         2798 :                         double finalLength = edge->getFinalLength();
     512         2798 :                         double laneLength = lane.shape.length();
     513         2798 :                         double accessLength = pos.distanceTo2D(lane.shape.positionAtOffset2D(offset)) * accessFactor;
     514         2798 :                         ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength, accessLength);
     515         2798 :                         cnt++;
     516              :                         break;
     517              :                     }
     518        10533 :                     laneIdx++;
     519        13331 :                 }
     520        11694 :                 if (cnt == maxCount) {
     521              :                     break;
     522              :                 }
     523              :             }
     524         1080 :         }
     525              :     }
     526          158 : }
     527              : 
     528              : 
     529              : std::shared_ptr<NBPTStop>
     530            5 : NBPTStopCont::findStop(const std::string& origEdgeID, Position pos, double threshold) const {
     531          123 :     for (auto& item : myPTStops) {
     532          245 :         if (item.second->getOrigEdgeId() == origEdgeID &&
     533            5 :                 item.second->getPosition().distanceTo2D(pos) < threshold) {
     534              :             return item.second;
     535              :         }
     536              :     }
     537              :     return nullptr;
     538              : }
     539              : 
     540              : 
     541              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1