LCOV - code coverage report
Current view: top level - src/netbuild - NBPTStopCont.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.4 % 247 238
Test Date: 2026-03-26 16:31:35 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         2483 : NBPTStopCont::~NBPTStopCont() {
      44              :     myPTStops.clear();
      45         2483 : }
      46              : 
      47              : 
      48              : bool
      49         2189 : NBPTStopCont::insert(std::shared_ptr<NBPTStop> ptStop, bool floating) {
      50         2189 :     std::string id = ptStop->getID();
      51              :     auto i = myPTStops.find(id);
      52         2189 :     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        10184 : NBPTStopCont::get(std::string id) const {
      65        10184 :     if (myPTStops.find(id) != myPTStops.end()) {
      66              :         return myPTStops.find(id)->second;
      67              :     }
      68              :     return nullptr;
      69              : }
      70              : 
      71              : 
      72              : void
      73          124 : 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         1293 :     for (const auto& ptStopIt : myPTStops) {
      77              :         std::shared_ptr<NBPTStop> const stop = ptStopIt.second;
      78         1169 :         bool multipleStopPositions = stop->getIsMultipleStopPositions();
      79         1169 :         bool platformsDefined = !stop->getPlatformCands().empty();
      80         1169 :         if (!platformsDefined) {
      81              :             //create pt stop for reverse edge if edge exists
      82         1764 :             std::shared_ptr<NBPTStop> reverseStop = getReverseStop(stop, cont);
      83          882 :             if (reverseStop != nullptr) {
      84          210 :                 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          334 :     for (std::shared_ptr<NBPTStop>& reverseStop : reverseStops) {
      99          420 :         insert(reverseStop);
     100              :     }
     101          124 : }
     102              : 
     103              : 
     104              : void
     105          343 : NBPTStopCont::assignLanes(NBEdgeCont& cont) {
     106              :     //scnd pass set correct lane
     107         4152 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     108              :         std::shared_ptr<NBPTStop> stop = i->second;
     109         3809 :         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          343 : }
     120              : 
     121              : 
     122              : int
     123          163 : NBPTStopCont::generateBidiStops(NBEdgeCont& ec) {
     124              :     int existingBidiStops = 0;
     125              :     std::vector<std::shared_ptr<NBPTStop> > toAdd;
     126         2083 :     for (auto i = myPTStops.begin(); i != myPTStops.end(); i++) {
     127              :         std::shared_ptr<NBPTStop> stop = i->second;
     128         1920 :         NBEdge* edge = ec.getByID(stop->getEdgeId());
     129         1920 :         if (edge != nullptr && edge->isBidiRail()) {
     130          329 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     131              :             assert(bidiEdge != 0);
     132          658 :             const std::string id = getReverseID(stop->getID());
     133          222 :             if (myPTStops.count(id) > 0) {
     134          222 :                 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          222 :                     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         1591 :         } else if (edge != nullptr) {
     158         1481 :             NBEdge* bidiEdge = edge->getTurnDestination(true);
     159         1481 :             if (bidiEdge != nullptr) {
     160         1374 :                 const std::string id = getReverseID(stop->getID());
     161              :                 if (myPTStops.count(id) > 0) {
     162          329 :                     existingBidiStops++;
     163              :                 }
     164              :             }
     165              :         }
     166              :     }
     167          270 :     for (std::shared_ptr<NBPTStop> newStop : toAdd) {
     168          214 :         myPTStops[newStop->getID()] = newStop;
     169              :     }
     170          163 :     if (toAdd.size() > 0) {
     171           24 :         WRITE_MESSAGEF(TL("Added % stops for superposed rail edges."), toString(toAdd.size()));
     172              :     }
     173          163 :     return (int)toAdd.size() + existingBidiStops;
     174          163 : }
     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         1009 : NBPTStopCont::getReverseStop(std::shared_ptr<NBPTStop> pStop, const NBEdgeCont& ec) {
     200         1009 :     std::string edgeId = pStop->getEdgeId();
     201         1009 :     NBEdge* edge = ec.getByID(edgeId);
     202         1009 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     203         1009 :     if (reverse != nullptr) {
     204          644 :         const std::string reverseID = getReverseID(pStop->getID());
     205              :         if (myPTStops.count(reverseID) == 0) {
     206          556 :             std::shared_ptr<NBPTStop> result = std::make_shared<NBPTStop>(pStop->getElement(), reverseID, pStop->getPosition(), reverse->getID(), reverse->getID(),
     207          834 :                                               pStop->getLength(), pStop->getName(), pStop->getPermissions());
     208          373 :             for (const std::string& line : pStop->getLines()) {
     209           95 :                 result->addLine(line);
     210              :             }
     211              :             return result;
     212              :         } else {
     213           44 :             return myPTStops[reverseID];
     214              :         }
     215              :     }
     216              :     return nullptr;
     217              : }
     218              : 
     219              : 
     220              : std::shared_ptr<NBPTStop>
     221           17 : NBPTStopCont::assignAndCreatNewPTStopAsNeeded(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     222           17 :     std::string edgeId = pStop->getEdgeId();
     223           17 :     NBEdge* edge = cont.getByID(edgeId);
     224           17 :     if (edge == nullptr) {
     225              :         return nullptr;
     226              :     }
     227              :     bool rightOfEdge = false;
     228              :     bool leftOfEdge = false;
     229              :     const NBPTPlatform* left = nullptr;
     230           33 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     231           17 :         double crossProd = computeCrossProductEdgePosition(edge, platform.getPos());
     232              :         //TODO consider driving on the left!!! [GL May '17]
     233           17 :         if (crossProd > 0) {
     234              :             leftOfEdge = true;
     235              :             left = &platform;
     236              :         } else {
     237              :             rightOfEdge = true;
     238           16 :             pStop->setPTStopLength(platform.getLength());
     239              :         }
     240              :     }
     241              : 
     242           16 :     if (leftOfEdge && rightOfEdge) {
     243            2 :         std::shared_ptr<NBPTStop> leftStop = getReverseStop(pStop, cont);
     244            1 :         if (leftStop) {
     245            0 :             leftStop->setPTStopLength(left->getLength());
     246              :         }
     247              :         return leftStop;
     248           15 :     } else if (leftOfEdge) {
     249            0 :         NBEdge* reverse = getReverseEdge(edge);
     250            0 :         if (reverse != nullptr) {
     251            0 :             pStop->setEdgeId(reverse->getID(), cont);
     252            0 :             pStop->setPTStopLength(left->getLength());
     253              :         }
     254              :     }
     255              : 
     256              :     return nullptr;
     257              : }
     258              : 
     259              : 
     260              : void
     261          270 : NBPTStopCont::assignPTStopToEdgeOfClosestPlatform(std::shared_ptr<NBPTStop> pStop, NBEdgeCont& cont) {
     262          270 :     std::string edgeId = pStop->getEdgeId();
     263          270 :     NBEdge* edge = cont.getByID(edgeId);
     264          270 :     NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
     265          540 :     const NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
     266          270 :     pStop->setPTStopLength(closestPlatform->getLength());
     267          270 :     if (reverse != nullptr) {
     268              : 
     269              :         //TODO make isLeft in PositionVector static [GL May '17]
     270              : //        if (PositionVector::isLeft(edge->getFromNode()->getPosition(),edge->getToNode()->getPosition(),closestPlatform)){
     271              : //
     272              : //        }
     273           99 :         double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getPos());
     274              : 
     275              :         //TODO consider driving on the left!!! [GL May '17]
     276           99 :         if (crossProd > 0) { //pt stop is on the left of the orig edge
     277          123 :             pStop->setEdgeId(reverse->getID(), cont);
     278              :         }
     279              :     }
     280          270 : }
     281              : 
     282              : 
     283              : double
     284          116 : NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const {
     285              :     PositionVector geom = edge->getGeometry();
     286          116 :     int idxTmp = geom.indexOfClosest(closestPlatform);
     287          116 :     double offset = geom.nearest_offset_to_point2D(closestPlatform, true);
     288          116 :     double offset2 = geom.offsetAtIndex2D(idxTmp);
     289              :     int idx1, idx2;
     290          116 :     if (offset2 < offset) {
     291              :         idx1 = idxTmp;
     292           41 :         idx2 = idx1 + 1;
     293              :     } else {
     294              :         idx2 = idxTmp;
     295           75 :         idx1 = idxTmp - 1;
     296              :     }
     297          116 :     if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
     298           63 :         WRITE_WARNINGF(TL("Could not determine cross product for edge '%'."), edge->getID());
     299           21 :         return 0;
     300              :     }
     301           95 :     Position p1 = geom[idx1];
     302           95 :     Position p2 = geom[idx2];
     303              : 
     304              :     double x0 = p1.x();
     305              :     double y0 = p1.y();
     306              :     double x1 = p2.x();
     307              :     double y1 = p2.y();
     308              :     double x2 = closestPlatform.x();
     309              :     double y2 = closestPlatform.y();
     310           95 :     double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
     311           95 :     return crossProd;
     312          116 : }
     313              : 
     314              : 
     315              : const NBPTPlatform*
     316          270 : NBPTStopCont::getClosestPlatformToPTStopPosition(std::shared_ptr<NBPTStop> pStop) {
     317          270 :     Position stopPosition = pStop->getPosition();
     318              :     const NBPTPlatform* closest = nullptr;
     319              :     double minSqrDist = std::numeric_limits<double>::max();
     320          999 :     for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
     321          729 :         double sqrDist = stopPosition.distanceSquaredTo2D(platform.getPos());
     322          729 :         if (sqrDist < minSqrDist) {
     323              :             minSqrDist = sqrDist;
     324              :             closest = &platform;
     325              :         }
     326              :     }
     327          270 :     return closest;
     328              : }
     329              : 
     330              : //static functions
     331              : 
     332              : NBEdge*
     333         1536 : NBPTStopCont::getReverseEdge(NBEdge* edge) {
     334         1536 :     if (edge != nullptr) {
     335         1346 :         const PositionVector rGeom = edge->getGeometry().reverse();
     336         1346 :         for (auto it = edge->getToNode()->getOutgoingEdges().begin();
     337         2396 :                 it != edge->getToNode()->getOutgoingEdges().end();
     338              :                 it++) {
     339         1644 :             if ((*it)->getToNode() == edge->getFromNode() && (*it)->getGeometry() == rGeom) {
     340          594 :                 return (*it);
     341              :             }
     342              :         }
     343         1346 :     }
     344              :     return nullptr;
     345              : }
     346              : 
     347              : 
     348              : int
     349         2690 : NBPTStopCont::cleanupDeleted(NBEdgeCont& cont) {
     350              :     int numDeleted = 0;
     351         6050 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     352         3360 :         if (cont.getByID(i->second->getEdgeId()) == nullptr) {
     353          528 :             WRITE_WARNINGF(TL("Removing pt stop '%' on non existing edge '%'."), i->first, i->second->getEdgeId());
     354              :             i = myPTStops.erase(i);
     355          176 :             numDeleted++;
     356              :         } else {
     357              :             i++;
     358              :         }
     359              :     }
     360         2690 :     return numDeleted;
     361              : }
     362              : 
     363              : 
     364              : void
     365         2096 : NBPTStopCont::addEdges2Keep(const OptionsCont& /* oc */, std::set<std::string>& into) {
     366         4056 :     for (auto stop : myPTStops) {
     367         1960 :         into.insert(stop.second->getEdgeId());
     368         1960 :     }
     369         2096 : }
     370              : 
     371              : 
     372              : void
     373         5566 : NBPTStopCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
     374         5566 :     if (myPTStops.size() > 0 && myPTStopLookup.size() == 0) {
     375              :         // init lookup once
     376         1176 :         for (auto& item : myPTStops) {
     377         1121 :             myPTStopLookup[item.second->getEdgeId()].push_back(item.second);
     378              :         }
     379              :     }
     380              :     // make a copy because the vector gets modified
     381         5566 :     const std::vector<std::shared_ptr<NBPTStop> > stops = myPTStopLookup[edgeID];
     382         6039 :     for (std::shared_ptr<NBPTStop> stop : stops) {
     383          473 :         if (!stop->replaceEdge(edgeID, replacement)) {
     384            0 :             WRITE_WARNINGF(TL("Could not re-assign pt stop '%' after replacing edge '%'."), stop->getID(), edgeID);
     385              :         } else {
     386          473 :             myPTStopLookup[stop->getEdgeId()].push_back(stop);
     387              :         }
     388              :     }
     389              :     myPTStopLookup.erase(edgeID);
     390         5566 : }
     391              : 
     392              : 
     393              : void
     394            4 : NBPTStopCont::postprocess(std::set<std::string>& usedStops) {
     395          192 :     for (auto i = myPTStops.begin(); i != myPTStops.end();) {
     396          376 :         if (usedStops.find(i->second->getID()) == usedStops.end()) {
     397              :             myPTStops.erase(i++);
     398              :         } else {
     399              :             i++;
     400              :         }
     401              :     }
     402            4 : }
     403              : 
     404              : std::string
     405         1525 : NBPTStopCont::getReverseID(const std::string& id) {
     406         1525 :     return id.size() > 0 && id[0] == '-' ? id.substr(1) : "-" + id;
     407              : }
     408              : 
     409              : void
     410          163 : NBPTStopCont::alignIdSigns() {
     411              :     PTStopsCont stops = myPTStops;
     412         2024 :     for (auto& i : stops) {
     413              :         std::shared_ptr<NBPTStop> s = i.second;
     414         1861 :         const std::string& stopId = s->getID();
     415         1861 :         if (s->getEdgeId() == "" || s->wasLoaded()) {
     416          188 :             continue;
     417              :         }
     418         3346 :         const char edgeSign = s->getEdgeId().at(0);
     419         1673 :         const char stopSign = stopId.at(0);
     420         1673 :         if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
     421          163 :             const std::string reverseID = getReverseID(stopId);
     422          326 :             std::shared_ptr<NBPTStop> rs = get(reverseID);
     423          163 :             if (rs != nullptr && rs->wasLoaded()) {
     424              :                 continue;
     425              :             }
     426          160 :             s->setPTStopId(reverseID);
     427              :             myPTStops.erase(stopId);
     428          160 :             myPTStops[reverseID] = s;
     429          160 :             if (rs != nullptr) {
     430            0 :                 rs->setPTStopId(stopId);
     431           55 :                 myPTStops[stopId] = rs;
     432              :             }
     433              :         }
     434              :     }
     435          163 : }
     436              : 
     437              : void
     438          176 : NBPTStopCont::assignEdgeForFloatingStops(NBEdgeCont& cont, double maxRadius) {
     439              :     NamedRTree r;
     440              :     SVCPermissions publicPermissions = SVC_BUS | SVC_TRAM | SVC_RAIL | SVC_RAIL_URBAN | SVC_TAXI;
     441        40358 :     for (const auto& item : cont) {
     442        40182 :         NBEdge* edge = item.second;
     443        40182 :         if ((edge->getPermissions() & publicPermissions) == 0) {
     444        18795 :             continue;
     445              :         }
     446        21387 :         const Boundary& bound = edge->getGeometry().getBoxBoundary();
     447        21387 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     448        21387 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     449        42774 :         r.Insert(min, max, edge);
     450              :     }
     451          315 :     for (std::shared_ptr<NBPTStop> ptStop : myFloatingStops) {
     452              :         std::set<const Named*> edges;
     453              :         Named::StoringVisitor visitor(edges);
     454          139 :         const Position& pos = ptStop->getPosition();
     455          139 :         float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     456          139 :         float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
     457              :         r.Search(min, max, visitor);
     458              :         std::vector<NBEdge*> nearby;
     459          304 :         for (const Named* namedEdge : edges) {
     460          165 :             NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     461          165 :             if ((e->getPermissions() & ptStop->getPermissions()) != 0) {
     462           81 :                 nearby.push_back(e);
     463              :             }
     464              :         }
     465          278 :         std::sort(nearby.begin(), nearby.end(), [pos](NBEdge * a, NBEdge * b) {
     466          148 :             return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     467              :         });
     468              : 
     469          139 :         for (NBEdge* e : nearby) {
     470           60 :             ptStop->setEdgeId(e->getID(), cont);
     471           20 :             if (ptStop->getLaneId() != "") {
     472              :                 break;
     473              :             }
     474              :         }
     475          139 :         if (ptStop->getLaneId() == "") {
     476          238 :             WRITE_WARNINGF(TL("Could not find corresponding edge or compatible lane for free-floating pt stop '%' (%). Thus, it will be removed!"),
     477              :                            ptStop->getID(), ptStop->getName());
     478          238 :             myPTStops.erase(ptStop->getID());
     479              :         }
     480          139 :     }
     481          176 : }
     482              : 
     483              : void
     484          167 : NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor) {
     485              :     NamedRTree r;
     486        33373 :     for (auto edge : cont) {
     487        33206 :         const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
     488        33206 :         float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
     489        33206 :         float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
     490        66412 :         r.Insert(min, max, edge.second);
     491              :     }
     492         2222 :     for (auto& ptStop : myPTStops) {
     493         2055 :         const std::string& stopEdgeID = ptStop.second->getEdgeId();
     494         2055 :         NBEdge* stopEdge = cont.getByID(stopEdgeID);
     495              :         //std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
     496         2055 :         if (stopEdge != nullptr && (stopEdge->getPermissions() & SVC_PEDESTRIAN) == 0) {
     497              :             //if (stopEdge != 0 && isRailway(stopEdge->getPermissions())) {
     498              :             std::set<const Named*> edges;
     499              :             Named::StoringVisitor visitor(edges);
     500         1156 :             const Position& pos = ptStop.second->getPosition();
     501         1156 :             float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
     502         1156 :             float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
     503              :             r.Search(min, max, visitor);
     504              :             std::vector<NBEdge*> edgCants;
     505       108227 :             for (const Named* namedEdge : edges) {
     506       107071 :                 NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
     507       107071 :                 edgCants.push_back(e);
     508              :             }
     509         2312 :             std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
     510       979769 :                 return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
     511              :             });
     512              :             int cnt = 0;
     513        13136 :             for (auto edge : edgCants) {
     514              :                 int laneIdx = 0;
     515        23983 :                 for (auto lane : edge->getLanes()) {
     516        14301 :                     if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
     517         2851 :                         double offset = lane.shape.nearest_offset_to_point2D(pos, false);
     518         2851 :                         double finalLength = edge->getFinalLength();
     519         2851 :                         double laneLength = lane.shape.length();
     520         2851 :                         double accessLength = pos.distanceTo2D(lane.shape.positionAtOffset2D(offset)) * accessFactor;
     521         2851 :                         ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength, accessLength);
     522         2851 :                         cnt++;
     523              :                         break;
     524              :                     }
     525        11450 :                     laneIdx++;
     526        14301 :                 }
     527        12533 :                 if (cnt == maxCount) {
     528              :                     break;
     529              :                 }
     530              :             }
     531         1156 :         }
     532              :     }
     533          167 : }
     534              : 
     535              : 
     536              : std::shared_ptr<NBPTStop>
     537            5 : NBPTStopCont::findStop(const std::string& origEdgeID, Position pos, double threshold) const {
     538          123 :     for (auto& item : myPTStops) {
     539          245 :         if (item.second->getOrigEdgeId() == origEdgeID &&
     540            5 :                 item.second->getPosition().distanceTo2D(pos) < threshold) {
     541              :             return item.second;
     542              :         }
     543              :     }
     544              :     return nullptr;
     545              : }
     546              : 
     547              : 
     548              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1