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

Generated by: LCOV version 2.0-1