LCOV - code coverage report
Current view: top level - src/netbuild - NBContHelper.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 57 57
Test Date: 2024-11-21 15:56:26 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    NBContHelper.h
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Mon, 17 Dec 2001
      19              : ///
      20              : // Some methods for traversing lists of edges
      21              : /****************************************************************************/
      22              : #pragma once
      23              : #include <config.h>
      24              : 
      25              : #include <vector>
      26              : #include <iostream>
      27              : #include <cmath>
      28              : #include <algorithm>
      29              : #include <cassert>
      30              : #include "NBHelpers.h"
      31              : #include "NBCont.h"
      32              : #include "NBEdge.h"
      33              : #include "NBNode.h"
      34              : #include <utils/common/StdDefs.h>
      35              : #include <utils/geom/GeomHelper.h>
      36              : 
      37              : 
      38              : // ===========================================================================
      39              : // class definitions
      40              : // ===========================================================================
      41              : /**
      42              :  * NBContHelper
      43              :  * Some static helper methods that traverse a sorted list of edges in both
      44              :  * directions
      45              :  */
      46              : class NBContHelper {
      47              : public:
      48              :     /** Moves the given iterator clockwise within the given container
      49              :         of edges sorted clockwise */
      50              :     static void nextCW(const EdgeVector& edges,
      51              :                        EdgeVector::const_iterator& from);
      52              : 
      53              :     /** Moves the given iterator counter clockwise within the given container
      54              :         of edges sorted clockwise */
      55              :     static void nextCCW(const EdgeVector& edges,
      56              :                         EdgeVector::const_iterator& from);
      57              : 
      58              :     static double getMaxSpeed(const EdgeVector& edges);
      59              : 
      60              :     static double getMinSpeed(const EdgeVector& edges);
      61              : 
      62              :     /** writes the vector of bools to the given stream */
      63              :     static std::ostream& out(std::ostream& os, const std::vector<bool>& v);
      64              : 
      65              : 
      66              :     /**
      67              :      * relative_outgoing_edge_sorter
      68              :      * Class to sort edges by their angle in relation to the node the
      69              :      * edge using this class is incoming into. This is normally done to
      70              :      * sort edges outgoing from the node the using edge is incoming in
      71              :      * by their angle in relation to the using edge's angle (this angle
      72              :      * is the reference angle).
      73              :      */
      74              :     class relative_outgoing_edge_sorter {
      75              :     public:
      76              :         /// constructor
      77       119714 :         explicit relative_outgoing_edge_sorter(NBEdge* e) : myAngle(e->getEndAngle()) {}
      78              :         /// constructor
      79              :         explicit relative_outgoing_edge_sorter(double angle) : myAngle(angle) {}
      80              : 
      81              :     public:
      82              :         /// comparing operation
      83              :         bool operator()(const NBEdge* e1, const NBEdge* e2) const;
      84              : 
      85              :     private:
      86              :         /// @brief the reference angle to compare edges agains
      87              :         double myAngle;
      88              :     };
      89              : 
      90              : 
      91              :     /**
      92              :      * relative_incoming_edge_sorter
      93              :      * Class to sort edges by their angle in relation to an outgoing edge.
      94              :      * This is normally done to sort edges incoming at the starting node of this edge
      95              :      * by their angle in relation to the using edge's angle (this angle
      96              :      * is the reference angle).
      97              :      */
      98              :     class relative_incoming_edge_sorter {
      99              :     public:
     100              :         /// constructor
     101         3018 :         explicit relative_incoming_edge_sorter(NBEdge* e) : myAngle(e->getStartAngle()) {}
     102              :         /// constructor
     103              :         explicit relative_incoming_edge_sorter(double angle) : myAngle(angle) {}
     104              : 
     105              :     public:
     106              :         /// comparing operation
     107              :         bool operator()(const NBEdge* e1, const NBEdge* e2) const;
     108              : 
     109              :     private:
     110              :         /// @brief the reference angle to compare edges agains
     111              :         double myAngle;
     112              :     };
     113              : 
     114              : 
     115              :     /**
     116              :      * edge_by_priority_sorter
     117              :      * Class to sort edges by their priority
     118              :      */
     119              :     class edge_by_priority_sorter {
     120              :     public:
     121              :         /// comparing operator
     122       150971 :         int operator()(NBEdge* e1, NBEdge* e2) const {
     123       150971 :             if (e1->getPriority() != e2->getPriority()) {
     124        34699 :                 return e1->getPriority() > e2->getPriority();
     125              :             }
     126       116272 :             if (e1->getSpeed() != e2->getSpeed()) {
     127         8794 :                 return e1->getSpeed() > e2->getSpeed();
     128              :             }
     129       107478 :             return e1->getNumLanes() > e2->getNumLanes();
     130              :         }
     131              :     };
     132              : 
     133              :     // ---------------------------
     134              : 
     135              :     /**
     136              :      * @class edge_opposite_direction_sorter
     137              :      * @brief Class to sort edges by their angle in relation to the given edge
     138              :      *
     139              :      * The resulting sorted list has the edge in the most opposite direction
     140              :      *  to the given edge as her first entry.
     141              :      */
     142              :     class edge_opposite_direction_sorter {
     143              :     public:
     144              :         /** @brief Constructor
     145              :          * @param[in] e The edge to which the sorting relates
     146              :          * @param[in] n The node to consider
     147              :          */
     148       113121 :         explicit edge_opposite_direction_sorter(const NBEdge* const e, const NBNode* const n, bool regardPriority) :
     149       113121 :             myNode(n),
     150       113121 :             myEdge(e),
     151       113121 :             myRegardPriority(regardPriority) {
     152       113121 :             myAngle = getEdgeAngleAt(e, n);
     153              :         }
     154              : 
     155              :         /** @brief Comparing operation
     156              :          * @param[in] e1 The first edge to compare
     157              :          * @param[in] e2 The second edge to compare
     158              :          * @return Which edge is more opposite to the related one
     159              :          */
     160       347309 :         int operator()(NBEdge* e1, NBEdge* e2) const {
     161       347309 :             if (!myRegardPriority || e1->getPriority() == e2->getPriority() || e1 == myEdge || e2 == myEdge) {
     162       313295 :                 return getDiff(e1) > getDiff(e2);
     163              :             } else {
     164        34014 :                 return e1->getPriority() > e2->getPriority();
     165              :             }
     166              :         }
     167              : 
     168              :     protected:
     169              :         /** @brief Computes the angle difference between the related and the given edge
     170              :          * @param[in] e The edge to compare the angle difference of
     171              :          * @return The angle difference
     172              :          */
     173       626590 :         double getDiff(const NBEdge* const e) const {
     174       626590 :             return fabs(GeomHelper::angleDiff(getEdgeAngleAt(e, myNode), myAngle));
     175              :         }
     176              : 
     177              :         /** @brief Returns the given edge's angle at the given node
     178              :          *
     179              :          * Please note that we always consider the "outgoing direction".
     180              :          * @param[in] e The edge to which the sorting relates
     181              :          * @param[in] n The node to consider
     182              :          */
     183       739711 :         double getEdgeAngleAt(const NBEdge* const e, const NBNode* const n) const {
     184       739711 :             if (e->getFromNode() == n) {
     185       265766 :                 return e->getGeometry().angleAt2D(0);
     186              :             } else {
     187       473945 :                 return e->getGeometry()[-1].angleTo2D(e->getGeometry()[-2]);
     188              :             }
     189              :         }
     190              : 
     191              :     private:
     192              : 
     193              :         /// @brief The related node
     194              :         const NBNode* const myNode;
     195              : 
     196              :         /// @brief the reference edge
     197              :         const NBEdge* const myEdge;
     198              : 
     199              :         /// @brief The angle of the related edge at the given node
     200              :         double myAngle;
     201              : 
     202              :         /// @brief Whether edge priority may override closer angles
     203              :         bool myRegardPriority;
     204              : 
     205              :     };
     206              : 
     207              :     // ---------------------------
     208              : 
     209              :     /**
     210              :      * edge_similar_direction_sorter
     211              :      * Class to sort edges by their angle in relation to the given edge
     212              :      * The resulting list should have the edge in the most similar direction
     213              :      * to the given edge as its first entry
     214              :      */
     215              :     class edge_similar_direction_sorter {
     216              :     public:
     217              :         /// constructor
     218        45904 :         explicit edge_similar_direction_sorter(const NBEdge* const e, bool outgoing = true) :
     219        45904 :             myCompareOutgoing(outgoing),
     220        87247 :             myAngle(outgoing ? e->getShapeEndAngle() : e->getShapeStartAngle())
     221              :         {}
     222              : 
     223              :         /// comparing operation
     224        93858 :         int operator()(const NBEdge* e1, const NBEdge* e2) const {
     225        93858 :             const double d1 = angleDiff(myCompareOutgoing ? e1->getShapeStartAngle() : e1->getShapeEndAngle(), myAngle);
     226        93858 :             const double d2 = angleDiff(myCompareOutgoing ? e2->getShapeStartAngle() : e2->getShapeEndAngle(), myAngle);
     227        93858 :             if (fabs(fabs(d1) - fabs(d2)) < NUMERICAL_EPS) {
     228         6227 :                 if (fabs(d1 - d2) > NUMERICAL_EPS) {
     229         6075 :                     return d1 < d2;
     230              :                 } else {
     231          152 :                     return e1->getNumericalID() < e2->getNumericalID();
     232              :                 }
     233              :             }
     234        87631 :             return fabs(d1) < fabs(d2);
     235              :         }
     236              : 
     237              :     private:
     238              :         double angleDiff(const double angle1, const double angle2) const {
     239       187716 :             double d = angle2 - angle1;
     240       199177 :             while (d >= 180.) {
     241        11461 :                 d -= 360.;
     242              :             }
     243       206355 :             while (d < -180.) {
     244        18639 :                 d += 360.;
     245              :             }
     246              :             return d;
     247              :         }
     248              : 
     249              : 
     250              :     private:
     251              :         /// the angle to find the edge with the opposite direction
     252              :         bool myCompareOutgoing;
     253              :         double myAngle;
     254              :     };
     255              : 
     256              : 
     257              :     /**
     258              :      * @class node_with_incoming_finder
     259              :      */
     260              :     class node_with_incoming_finder {
     261              :     public:
     262              :         /// constructor
     263              :         node_with_incoming_finder(const NBEdge* const e);
     264              : 
     265              :         bool operator()(const NBNode* const n) const;
     266              : 
     267              :     private:
     268              :         const NBEdge* const myEdge;
     269              : 
     270              :     };
     271              : 
     272              : 
     273              :     /**
     274              :      * @class node_with_outgoing_finder
     275              :      */
     276              :     class node_with_outgoing_finder {
     277              :     public:
     278              :         /// constructor
     279              :         node_with_outgoing_finder(const NBEdge* const e);
     280              : 
     281              :         bool operator()(const NBNode* const n) const;
     282              : 
     283              :     private:
     284              :         const NBEdge* const myEdge;
     285              : 
     286              :     };
     287              : 
     288              : 
     289              : 
     290              : 
     291              :     class edge_with_destination_finder {
     292              :     public:
     293              :         /// constructor
     294              :         edge_with_destination_finder(NBNode* dest);
     295              : 
     296              :         bool operator()(NBEdge* e) const;
     297              : 
     298              :     private:
     299              :         NBNode* myDestinationNode;
     300              : 
     301              :     private:
     302              :         /// @brief invalidated assignment operator
     303              :         edge_with_destination_finder& operator=(const edge_with_destination_finder& s);
     304              : 
     305              :     };
     306              : 
     307              : 
     308              :     /** Tries to return the first edge within the given container which
     309              :         connects both given nodes */
     310              :     static NBEdge* findConnectingEdge(const EdgeVector& edges,
     311              :                                       NBNode* from, NBNode* to);
     312              : 
     313              : 
     314              :     /** returns the maximum speed allowed on the edges */
     315              :     static double maxSpeed(const EdgeVector& ev);
     316              : 
     317              :     /**
     318              :      * same_connection_edge_sorter
     319              :      * This class is used to sort edges which connect the same nodes.
     320              :      * The edges are sorted in dependence to edges connecting them. The
     321              :      * rightmost will be the first in the list; the leftmost the last one.
     322              :      */
     323              :     class same_connection_edge_sorter {
     324              :     public:
     325              :         /// constructor
     326              :         explicit same_connection_edge_sorter() { }
     327              : 
     328              :         /// comparing operation
     329           22 :         int operator()(NBEdge* e1, NBEdge* e2) const {
     330           22 :             std::pair<double, double> mm1 = getMinMaxRelAngles(e1);
     331           22 :             std::pair<double, double> mm2 = getMinMaxRelAngles(e2);
     332           22 :             if (mm1.first == mm2.first && mm1.second == mm2.second) {
     333              :                 // ok, let's simply sort them arbitrarily
     334           14 :                 return e1->getID() < e2->getID();
     335              :             }
     336              : 
     337              :             assert(
     338              :                 (mm1.first <= mm2.first && mm1.second <= mm2.second)
     339              :                 ||
     340              :                 (mm1.first >= mm2.first && mm1.second >= mm2.second));
     341           14 :             return (mm1.first >= mm2.first && mm1.second >= mm2.second);
     342              :         }
     343              : 
     344              :         /**
     345              :          *
     346              :          */
     347           44 :         std::pair<double, double> getMinMaxRelAngles(NBEdge* e) const {
     348              :             double min = 360;
     349              :             double max = 360;
     350           44 :             const EdgeVector& ev = e->getConnectedEdges();
     351          110 :             for (EdgeVector::const_iterator i = ev.begin(); i != ev.end(); ++i) {
     352           66 :                 double angle = NBHelpers::normRelAngle(
     353              :                                    e->getTotalAngle(), (*i)->getTotalAngle());
     354           66 :                 if (min == 360 || min > angle) {
     355              :                     min = angle;
     356              :                 }
     357           66 :                 if (max == 360 || max < angle) {
     358              :                     max = angle;
     359              :                 }
     360              :             }
     361           44 :             return std::pair<double, double>(min, max);
     362           44 :         }
     363              :     };
     364              : 
     365              : 
     366              :     friend std::ostream& operator<<(std::ostream& os, const EdgeVector& ev);
     367              : 
     368              :     class opposite_finder {
     369              :     public:
     370              :         /// constructor
     371              :         opposite_finder(NBEdge* edge)
     372        22439 :             : myReferenceEdge(edge) { }
     373              : 
     374        36646 :         bool operator()(NBEdge* e) const {
     375        57595 :             return e->isTurningDirectionAt(myReferenceEdge) ||
     376        20949 :                    myReferenceEdge->isTurningDirectionAt(e);
     377              :         }
     378              : 
     379              :     private:
     380              :         NBEdge* myReferenceEdge;
     381              : 
     382              :     };
     383              : 
     384              :     /**
     385              :      * edge_by_angle_to_nodeShapeCentroid_sorter
     386              :      * Class to sort edges by their angle in relation to the node shape
     387              :      * */
     388              :     class edge_by_angle_to_nodeShapeCentroid_sorter {
     389              :     public:
     390              :         /// constructor
     391              :         explicit edge_by_angle_to_nodeShapeCentroid_sorter(const NBNode* n) : myNode(n) {}
     392              : 
     393              :     public:
     394              :         /// comparing operation
     395              :         bool operator()(const NBEdge* e1, const NBEdge* e2) const;
     396              : 
     397              :     private:
     398              :         /// the edge to compute the relative angle of
     399              :         const NBNode* myNode;
     400              :     };
     401              : 
     402              : };
        

Generated by: LCOV version 2.0-1