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

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    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      166495 :         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        4703 :         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      207494 :         int operator()(NBEdge* e1, NBEdge* e2) const {
     123      207494 :             if (e1->getPriority() != e2->getPriority()) {
     124       54147 :                 return e1->getPriority() > e2->getPriority();
     125             :             }
     126      153347 :             if (e1->getSpeed() != e2->getSpeed()) {
     127       14884 :                 return e1->getSpeed() > e2->getSpeed();
     128             :             }
     129      138463 :             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      153224 :         explicit edge_opposite_direction_sorter(const NBEdge* const e, const NBNode* const n, bool regardPriority) :
     149      153224 :             myNode(n),
     150      153224 :             myEdge(e),
     151      153224 :             myRegardPriority(regardPriority) {
     152      153224 :             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      451980 :         int operator()(NBEdge* e1, NBEdge* e2) const {
     161      451980 :             if (!myRegardPriority || e1->getPriority() == e2->getPriority() || e1 == myEdge || e2 == myEdge) {
     162      398878 :                 return getDiff(e1) > getDiff(e2);
     163             :             } else {
     164       53102 :                 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      797756 :         double getDiff(const NBEdge* const e) const {
     174      797756 :             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      950980 :         double getEdgeAngleAt(const NBEdge* const e, const NBNode* const n) const {
     184      950980 :             if (e->getFromNode() == n) {
     185      327696 :                 return e->getGeometry().angleAt2D(0);
     186             :             } else {
     187      623284 :                 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       58238 :         explicit edge_similar_direction_sorter(const NBEdge* const e, bool outgoing = true) :
     219       58238 :             myCompareOutgoing(outgoing),
     220      115341 :             myAngle(outgoing ? e->getShapeEndAngle() : e->getShapeStartAngle())
     221             :         {}
     222             : 
     223             :         /// comparing operation
     224      117398 :         int operator()(const NBEdge* e1, const NBEdge* e2) const {
     225      117398 :             const double d1 = angleDiff(myCompareOutgoing ? e1->getShapeStartAngle() : e1->getShapeEndAngle(), myAngle);
     226      117398 :             const double d2 = angleDiff(myCompareOutgoing ? e2->getShapeStartAngle() : e2->getShapeEndAngle(), myAngle);
     227      117398 :             if (fabs(fabs(d1) - fabs(d2)) < NUMERICAL_EPS) {
     228        6706 :                 if (fabs(d1 - d2) > NUMERICAL_EPS) {
     229        6481 :                     return d1 < d2;
     230             :                 } else {
     231         225 :                     return e1->getNumericalID() < e2->getNumericalID();
     232             :                 }
     233             :             }
     234      110692 :             return fabs(d1) < fabs(d2);
     235             :         }
     236             : 
     237             :     private:
     238             :         double angleDiff(const double angle1, const double angle2) const {
     239      234796 :             double d = angle2 - angle1;
     240      249504 :             while (d >= 180.) {
     241       14708 :                 d -= 360.;
     242             :             }
     243      257361 :             while (d < -180.) {
     244       22565 :                 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          80 :             return std::pair<double, double>(min, max);
     362             :         }
     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       32326 :             : myReferenceEdge(edge) { }
     373             : 
     374       53603 :         bool operator()(NBEdge* e) const {
     375       85962 :             return e->isTurningDirectionAt(myReferenceEdge) ||
     376       32359 :                    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 1.14