/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file NBNode.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Yun-Pang Floetteroed17/// @author Michael Behrisch18/// @date Tue, 20 Nov 200119///20// The representation of a single node21/****************************************************************************/22#pragma once23#include <config.h>2425#include <vector>26#include <deque>27#include <utility>28#include <string>29#include <set>30#include <memory>31#include <utils/common/StdDefs.h>32#include <utils/common/Named.h>33#include <utils/geom/Bresenham.h>34#include <utils/geom/GeomHelper.h>35#include <utils/common/VectorHelper.h>36#include <utils/geom/Position.h>37#include <utils/geom/PositionVector.h>38#include <utils/xml/SUMOXMLDefinitions.h>39#include "NBEdge.h"40#include "NBConnection.h"41#include "NBConnectionDefs.h"42#include "NBContHelper.h"434445// ===========================================================================46// class declarations47// ===========================================================================48class NBRequest;49class NBDistrict;50class OptionsCont;51class NBTrafficLightDefinition;52class NBTypeCont;53class NBTrafficLightLogicCont;54class NBDistrictCont;55class OutputDevice;565758// ===========================================================================59// class definitions60// ===========================================================================61/**62* @class NBNode63* @brief Represents a single node (junction) during network building64*/65class NBNode : public Named, public Parameterised {66friend class NBNodeCont;67friend class GNEJunction; // < used for visualization (netedit)68friend class NBNodesEdgesSorter; // < sorts the edges69friend class NBNodeTypeComputer; // < computes type70friend class NBEdgePriorityComputer; // < computes priorities of edges per intersection7172public:73/**74* @class ApproachingDivider75* @brief Computes lane-2-lane connections76*77* Being a bresenham-callback, this class computes which lanes78* are approached by the current lane (first callback parameter).79* The second callback parameter is the destination lane that is the80* middle of the computed lanes.81* The lanes are spreaded from this middle position both to left and right82* but may also be transposed in full when there is not enough space.83*/84class ApproachingDivider : public Bresenham::BresenhamCallBack {85public:86/**@brief Constructor87* @param[in] approaching The list of the edges that approach the outgoing edge88* @param[in] currentOutgoing The outgoing edge89*/90ApproachingDivider(const EdgeVector& approaching, NBEdge* currentOutgoing);9192/// @brief Destructor93~ApproachingDivider();9495/// @ get number of available lanes96int numAvailableLanes() const {97return (int)myAvailableLanes.size();98}99100/// @brief the bresenham-callback101void execute(const int src, const int dest);102103/// @brief the method that spreads the wished number of lanes from the lane given by the bresenham-call to both left and right104std::deque<int>* spread(int numLanes, int dest) const;105106private:107/// @brief The list of edges that approach the current edge108const EdgeVector& myApproaching;109110/// @brief The approached current edge111NBEdge* myCurrentOutgoing;112113/// @brief The available lanes to which connections shall be built114std::vector<int> myAvailableLanes;115116/// directions from each incoming edge to the outgoing edge117std::vector<LinkDirection> myDirections;118119/// @brief number of straight connections to the outgoing edge120int myNumStraight;121122/// @brief whether the outgoing edge is exclusively used by bikes123bool myIsBikeEdge;124125private:126/// @brief Invalidated assignment operator.127ApproachingDivider& operator=(const ApproachingDivider&) = delete;128129};130131/** @class Crossing132* @brief A definition of a pedestrian crossing133*/134class Crossing final : public Parameterised {135public:136/// @brief constructor137Crossing(const NBNode* _node, const EdgeVector& _edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector& _customShape);138/// @brief The parent node of this crossing139const NBNode* node;140/// @brief The edges being crossed141EdgeVector edges;142/// @brief The crossing's shape143PositionVector shape;144/// @brief The outline shape for this crossing145PositionVector outlineShape;146/// @brief This crossing's width147double customWidth;148/// @brief This crossing's width149double width;150/// @brief the (edge)-id of this crossing151std::string id;152/// @brief the lane-id of the previous walkingArea153std::string prevWalkingArea;154/// @brief the lane-id of the next walkingArea155std::string nextWalkingArea;156/// @brief whether the pedestrians have priority157bool priority;158/// @brief optional customShape for this crossing159PositionVector customShape;160/// @brief the traffic light index of this crossing (if controlled)161int tlLinkIndex;162int tlLinkIndex2;163/// @brief the custom traffic light index of this crossing (if controlled)164int customTLIndex;165int customTLIndex2;166/// @brief The id of the traffic light that controls this connection167std::string tlID;168/// @brief whether this crossing is valid (and can be written to the net.xml). This is needed for netedit because validity can only be checked during junction computation169bool valid;170};171172173/** @struct WalkingArea174* @brief A definition of a pedestrian walking area175*/176struct WalkingArea {177/// @brief constructor178WalkingArea(const std::string& _id, double _width) :179id(_id),180width(_width) {181}182/// @brief the (edge)-id of this walkingArea183std::string id;184/// @brief This lane's width185double width;186/// @brief This lane's width187double length = INVALID_DOUBLE;188/// @brief The polygonal shape189PositionVector shape;190/// @brief the lane-id of the next crossing(s)191std::vector<std::string> nextCrossings;192/// @brief the lane-id of the previous crossing(s)193std::vector<std::string> prevCrossings;194/// @brief the lane-id of the next sidewalk lane or ""195std::vector<std::string> nextSidewalks;196/// @brief the lane-id of the previous sidewalk lane or ""197std::vector<std::string> prevSidewalks;198/// @brief whether this walkingArea has a custom shape199bool hasCustomShape = false;200/// @brief minimum number of edges crossed by nextCrossings201int minNextCrossingEdges = std::numeric_limits<int>::max();202/// @brief minimum number of edges crossed by incoming crossings203int minPrevCrossingEdges = std::numeric_limits<int>::max();204/// @brief reference edges that uniquely identify this walkingarea205std::set<const NBEdge*, ComparatorIdLess> refEdges;206};207208struct WalkingAreaCustomShape {209std::set<const NBEdge*, ComparatorIdLess> edges;210PositionVector shape;211double width;212};213214/// @brief edge directions (for pedestrian related stuff)215static const int FORWARD;216static const int BACKWARD;217218/// @brief unspecified lane width219static const double UNSPECIFIED_RADIUS;220221/// @brief flags for controlling shape generation222static const int AVOID_WIDE_RIGHT_TURN;223static const int AVOID_WIDE_LEFT_TURN;224static const int FOUR_CONTROL_POINTS;225static const int AVOID_INTERSECTING_LEFT_TURNS;226static const int SCURVE_IGNORE;227static const int INDIRECT_LEFT;228229public:230/**@brief Constructor231* @param[in] id The id of the node232* @param[in] position The position of the node233* @param[in] type The type of the node234*/235NBNode(const std::string& id, const Position& position, SumoXMLNodeType type);236237/**@brief Constructor238* @param[in] id The id of the node239* @param[in] position The position of the node240* @param[in] district The district this district node represents, 0 means no district node241*/242NBNode(const std::string& id, const Position& position, NBDistrict* district = 0);243244/// @brief Destructor245~NBNode();246247/**@brief Resets initial values248* @param[in] position The position of the node249* @param[in] type The type of the node250* @param[in] updateEdgeGeometries Whether the geometires of all251* connected edges shall be updated252*/253void reinit(const Position& position, SumoXMLNodeType type,254bool updateEdgeGeometries = false);255256/// @name Atomar getter methods257/// @{258/// @brief Returns the position of this node259inline const Position& getPosition() const {260return myPosition;261}262263/// @brief Returns a position that is guaranteed to lie within the node shape264Position getCenter() const;265266/// @brief Returns this node's incoming edges (The edges which yield in this node)267inline const EdgeVector& getIncomingEdges() const {268return myIncomingEdges;269}270271/// @brief Returns this node's outgoing edges (The edges which start at this node)272inline const EdgeVector& getOutgoingEdges() const {273return myOutgoingEdges;274}275276/// @brief Returns all edges which participate in this node (Edges that start or end at this node)277inline const EdgeVector& getEdges() const {278return myAllEdges;279}280281/**@brief Returns the type of this node282* @see SumoXMLNodeType283*/284inline SumoXMLNodeType getType() const {285return myType;286}287288/// @brief Returns the turning radius of this node289inline double getRadius() const {290return myRadius;291}292293/// @brief Returns the keepClear flag294inline bool getKeepClear() const {295return myKeepClear;296}297298/// @brief Returns hint on how to compute right of way299inline RightOfWay getRightOfWay() const {300return myRightOfWay;301}302303/// @brief Returns fringe type304inline FringeType getFringeType() const {305return myFringeType;306}307308/// @brief Returns roundabout type309inline RoundaboutType getRoundaboutType() const {310return myRoundaboutType;311}312313/// @brief Returns intersection name314inline const std::string& getName() const {315return myName;316}317/// @}318319/// @name Methods for dealing with assigned traffic lights320/// @{321/**@brief Adds a traffic light to the list of traffic lights that control this node322* @param[in] tld The traffic light that controls this node323*/324void addTrafficLight(NBTrafficLightDefinition* tlDef);325326/// @brief Removes the given traffic light from this node327void removeTrafficLight(NBTrafficLightDefinition* tlDef);328329/// @brief Removes all references to traffic lights that control this tls330void removeTrafficLights(bool setAsPriority = false);331332/**@brief Returns whether this node is controlled by any tls333* @return Whether a traffic light was assigned to this node334*/335bool isTLControlled() const {336return myTrafficLights.size() != 0;337}338339340/// @brief whether this node was marked as having a signal in the (OSM) input341bool hadSignal() const;342343/// @brief Returns the traffic lights that were assigned to this node (The set of tls that control this node)344const std::set<NBTrafficLightDefinition*>& getControllingTLS() const {345return myTrafficLights;346}347348/// @brief causes the traffic light to be computed anew349void invalidateTLS(NBTrafficLightLogicCont& tlCont, bool addedConnections, bool removedConnections);350351/// @brief patches loaded signal plans by modifying lane indices above threshold by the given offset352void shiftTLConnectionLaneIndex(NBEdge* edge, int offset, int threshold = -1);353/// @}354355356/// @name Prunning the input357/// @{358359/**@brief Removes edges which are both incoming and outgoing into this node360*361* If given, the connections to other edges participating in this node are updated362*363* @param[in, opt. changed] dc The districts container to update364* @param[in, opt. changed] ec The edge container to remove the edges from365* @param[in, opt. changed] tc The traffic lights container to update366* @return The number of removed edges367*/368int removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc);369/// @}370371372/// @name Applying offset373/// @{374/**@brief Applies an offset to the node375* @param[in] xoff The x-offset to apply376* @param[in] yoff The y-offset to apply377*/378void reshiftPosition(double xoff, double yoff);379380/// @brief ensure consistency between input and output geometries381void roundGeometry();382383/// @brief mirror coordinates along the x-axis384void mirrorX();385/// @}386387/// @brief adds an incoming edge388void addIncomingEdge(NBEdge* edge);389390/// @brief adds an outgoing edge391void addOutgoingEdge(NBEdge* edge);392393/// @brief computes the connections of lanes to edges394void computeLanes2Lanes();395396/// @brief computes the node's type, logic and traffic light397void computeLogic(const NBEdgeCont& ec);398399/// @brief compute right-of-way logic for all lane-to-lane connections400void computeLogic2(bool checkLaneFoes);401402/// @brief compute keepClear status for all connections403void computeKeepClear();404405/// @brief writes the XML-representation of the logic as a bitset-logic XML representation406bool writeLogic(OutputDevice& into) const;407408/// @brief get the 'foes' string (conflict bit set) of the right-of-way logic409const std::string getFoes(int linkIndex) const;410411/// @brief get the 'response' string (right-of-way bit set) of the right-of-way logic412const std::string getResponse(int linkIndex) const;413414/// @brief whether there are conflicting streams of traffic at this node415bool hasConflict() const;416417/// @brief whether the given edge has a conflicting stream of traffic at this node418bool hasConflict(const NBEdge* e) const;419420/// @brief Returns something like the most unused direction Should only be used to add source or sink nodes421Position getEmptyDir() const;422423/**@brief Returns whether the given edge ends at this node424* @param[in] e The edge425* @return Whether the given edge is one of this node's incoming edges426*/427bool hasIncoming(const NBEdge* const e) const;428429/**@brief Returns whether the given edge starts at this node430* @param[in] e The edge431* @return Whether the given edge is one of this node's outgoing edges432*/433bool hasOutgoing(const NBEdge* const e) const;434435/// @brief returns the opposite incoming edge of certain edge436NBEdge* getOppositeIncoming(NBEdge* e) const;437438/// @brief invalidate incoming connections439void invalidateIncomingConnections(bool reallowSetting = false);440441/// @brief invalidate outgoing connections442void invalidateOutgoingConnections(bool reallowSetting = false);443444/// @brief remove duble edges445void removeDoubleEdges();446447/// @brief get connection to certain node448NBEdge* getConnectionTo(NBNode* n) const;449450/// @brief add shorted link FOES451void addSortedLinkFoes(const NBConnection& mayDrive, const NBConnection& mustStop);452453/// @brief get possibly splitted incoming edge454NBEdge* getPossiblySplittedIncoming(const std::string& edgeid);455456/// @brief get possibly splitted outgoing edge457NBEdge* getPossiblySplittedOutgoing(const std::string& edgeid);458459/// @brief Removes edge from this node and optionally removes connections as well460void removeEdge(NBEdge* edge, bool removeFromConnections = true);461462/**@brief Computes whether the given connection is a left mover across the junction463*464* It is assumed, that it is a left-mover if the clockwise angle is lower465* than the counter-clockwise angle.466*467* @param[in] from The incoming edge (the begin of the connection)468* @param[in] from The outgoing edge (the end of the connection)469* @return Whether the described connection is a left-mover470*/471bool isLeftMover(const NBEdge* const from, const NBEdge* const to) const;472473/**@brief Returns the information whether the described flow must let any other flow pass474* @param[in] from The connection's start edge475* @param[in] to The connection's end edge476* @param[in] fromLane The lane the connection start at477* @param[in] toLane The lane the connection ends at478* @param[in] includePedCrossings Whether braking due to a pedestrian crossing counts479* @return Whether the described connection must brake (has higher priorised foes)480*/481bool mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const;482483/**@brief Returns the information whether the described flow must brake for the given crossing484* @param[in] from The connection's start edge485* @param[in] to The connection's end edge486* @param[in] crossing The pedestrian crossing to check487* @return Whether the described connection must brake (has higher priorised foes)488*/489bool mustBrakeForCrossing(const NBEdge* const from, const NBEdge* const to, const Crossing& crossing) const;490491/// @brief whether a connection to the given edge must brake for a crossing when leaving the intersection492bool brakeForCrossingOnExit(const NBEdge* to, LinkDirection dir, bool indirect) const;493494/// @brief return whether the given laneToLane connection is a right turn which must yield to a bicycle crossings495static bool rightTurnConflict(const NBEdge* from, const NBEdge* to, int fromLane,496const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorFromLane);497498/// @brief whether one of multple connections from the same edge targeting the same lane must yield499bool mergeConflictYields(const NBEdge* from, int fromLane, int fromLaneFoe, NBEdge* to, int toLane) const;500501/// @brief whether multiple connections from the same edge target the same lane502bool mergeConflict(const NBEdge* from, const NBEdge::Connection& con,503const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const;504505/// @brief whether the foe connections is oncoming on the same lane506bool bidiConflict(const NBEdge* from, const NBEdge::Connection& con,507const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const;508509bool zipperConflict(const NBEdge* incoming, const NBEdge* outgoing, int fromLane, int toLane) const;510511/// @brief return whether the given laneToLane connection originate from the same edge and are in conflict due to turning across each other512bool turnFoes(const NBEdge* from, const NBEdge* to, int fromLane,513const NBEdge* from2, const NBEdge* to2, int fromLane2,514bool lefthand = false) const;515516/**@brief Returns the information whether "prohibited" flow must let "prohibitor" flow pass517* @param[in] possProhibitedFrom The maybe prohibited connection's begin518* @param[in] possProhibitedTo The maybe prohibited connection's end519* @param[in] possProhibitorFrom The maybe prohibiting connection's begin520* @param[in] possProhibitorTo The maybe prohibiting connection's end521* @param[in] regardNonSignalisedLowerPriority Whether the right of way rules without traffic lights shall be regarded522* @return Whether the second flow prohibits the first one523*/524bool forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,525const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,526bool regardNonSignalisedLowerPriority) const;527528/**@brief Returns the information whether the given flows cross529* @param[in] from1 The starting edge of the first stream530* @param[in] to1 The ending edge of the first stream531* @param[in] from2 The starting edge of the second stream532* @param[in] to2 The ending edge of the second stream533* @return Whether both stream are foes (cross)534*/535bool foes(const NBEdge* const from1, const NBEdge* const to1,536const NBEdge* const from2, const NBEdge* const to2) const;537538/**@brief Returns the representation of the described stream's direction539* @param[in] incoming The edge the stream starts at540* @param[in] outgoing The edge the stream ends at541* @param[in] leftHand Whether a lefthand network is being built. Should only be set at writing time542* @return The direction of the stream543*/544LinkDirection getDirection(const NBEdge* const incoming, const NBEdge* const outgoing, bool leftHand = false) const;545546/// @brief get link state547LinkState getLinkState(const NBEdge* incoming, const NBEdge* outgoing,548int fromLane, int toLane, bool mayDefinitelyPass, const std::string& tlID) const;549550/**@brief Compute the junction shape for this node551* @param[in] mismatchThreshold The threshold for warning about shapes which are away from myPosition552*/553void computeNodeShape(double mismatchThreshold);554555/// @brief update geometry of node and surrounding edges556void updateSurroundingGeometry();557558/// @brief retrieve the junction shape559const PositionVector& getShape() const;560561/// @brief set the junction shape562void setCustomShape(const PositionVector& shape);563564/// @brief reset node shape565void resetShape() {566myPoly.clear();567}568569/// @brief set the turning radius570void setRadius(double radius) {571myRadius = radius;572}573574/// @brief set the keepClear flag575void setKeepClear(bool keepClear) {576myKeepClear = keepClear;577}578579/// @brief set method for computing right-of-way580void setRightOfWay(RightOfWay rightOfWay) {581myRightOfWay = rightOfWay;582}583584/// @brief set fringe type585void setFringeType(FringeType fringeType) {586myFringeType = fringeType;587}588589/// @brief set roundabout type590void setRoundaboutType(RoundaboutType roundaboutType) {591myRoundaboutType = roundaboutType;592}593594/// @brief set intersection name595void setName(const std::string& name) {596myName = name;597}598599/// @brief return whether the shape was set by the user600bool hasCustomShape() const {601return myHaveCustomPoly;602}603604/// @brief check if node is removable605bool checkIsRemovable() const;606607/// @brief check if node is removable and return reason if not608bool checkIsRemovableReporting(std::string& reason) const;609610/// @brief get edges to join611std::vector<std::pair<NBEdge*, NBEdge*> > getEdgesToJoin() const;612613/// @chech if node is near district614bool isNearDistrict() const;615616/// @brief check if node is a district617bool isDistrict() const;618619/// @brief whether an internal junction should be built at from and respect other620bool needsCont(const NBEdge* fromE, const NBEdge* otherFromE,621const NBEdge::Connection& c, const NBEdge::Connection& otherC, bool checkOnlyTLS = false) const;622623/// @brief whether the connection must yield if the foe remains on the intersection after its phase ends624bool tlsStrandedConflict(const NBEdge* from, const NBEdge::Connection& c,625const NBEdge* foeFrom, const NBEdge::Connection& foe) const;626627628/**@brief Compute the shape for an internal lane629* @param[in] fromE The starting edge630* @param[in] con The connection for this internal lane631* @param[in] numPoints The number of geometry points for the internal lane632* @param[in] recordError The node itself if the displacement error during shape computation shall be recorded633* @return The shape of the internal lane634*/635PositionVector computeInternalLaneShape(const NBEdge* fromE, const NBEdge::Connection& con, int numPoints, NBNode* recordError = 0, int shapeFlag = 0) const;636637/**@brief Compute a smooth curve between the given geometries638* @param[in] begShape The geometry at the start639* @param[in] endShape The geometry at the end640* @param[in] numPoints The number of geometry points for the internal lane641* @param[in] isTurnaround Whether this shall be the shape for a turnaround642* @param[in] extrapolateBeg Extrapolation distance at the beginning643* @param[in] extrapolateEnd Extrapolation distance at the end644* @param[in] recordError The node itself if the displacement error during shape computation shall be recorded645* @return The shape of the internal lane646*/647PositionVector computeSmoothShape(const PositionVector& begShape, const PositionVector& endShape, int numPoints,648bool isTurnaround, double extrapolateBeg, double extrapolateEnd,649NBNode* recordError = 0, int shapeFlag = 0) const;650/// @brief get bezier control points651static PositionVector bezierControlPoints(const PositionVector& begShape, const PositionVector& endShape,652bool isTurnaround, double extrapolateBeg, double extrapolateEnd,653bool& ok, NBNode* recordError = 0, double straightThresh = DEG2RAD(5),654int shapeFlag = 0);655656/// @brief compute shape of indirect left turn657PositionVector indirectLeftShape(const PositionVector& begShape, const PositionVector& endShape, int numPoints) const;658659/// @brief compute the displacement error during s-curve computation660double getDisplacementError() const {661return myDisplacementError;662}663664/// @brief Replaces occurrences of the first edge within the list of incoming by the second Connections are remapped, too665void replaceIncoming(NBEdge* which, NBEdge* by, int laneOff);666667/// @brief Replaces occurrences of every edge from the given list within the list of incoming by the second Connections are remapped, too668void replaceIncoming(const EdgeVector& which, NBEdge* by);669670/// @brief Replaces occurrences of the first edge within the list of outgoing by the second Connections are remapped, too671void replaceOutgoing(NBEdge* which, NBEdge* by, int laneOff);672673/// @brief Replaces occurrences of every edge from the given list within the list of outgoing by the second Connections are remapped, too674void replaceOutgoing(const EdgeVector& which, NBEdge* by);675676/// @brief guess pedestrian crossings and return how many were guessed677int guessCrossings();678679/* @brief check whether a crossing should be build for the candiate edges and build 0 to n crossings680* @param[in] candidates The candidate vector of edges to be crossed681* @param[in] checkOnly Whether only checking (of user supplied) crossings shall be performed682* @return The number of crossings built683* */684int checkCrossing(EdgeVector candidates, bool checkOnly = false);685686/// @brief return true if there already exist a crossing with the same edges as the input687bool checkCrossingDuplicated(EdgeVector edges);688689/// @brief build internal lanes, pedestrian crossings and walking areas690double buildInnerEdges();691692/**@brief build pedestrian crossings693* @return The next index for creating internal lanes694**/695int buildCrossings();696697/**@brief build pedestrian walking areas and set connections from/to walkingAreas698* @param[in] cornerDetail The detail level when generating the inner curve699*/700void buildWalkingAreas(int cornerDetail, double joinMinDist);701702/// @brief build crossing outlines after walkingareas are finished703void buildCrossingOutlines();704705/// @brief build crossings, and walkingareas. Also removes invalid loaded crossings if wished706void buildCrossingsAndWalkingAreas();707708/// @brief return all edges that lie clockwise between the given edges709EdgeVector edgesBetween(const NBEdge* e1, const NBEdge* e2) const;710711/// @brief return true if the given edges are connected by a crossing712bool crossingBetween(const NBEdge* e1, const NBEdge* e2) const;713714/// @brief return true if the given pedestrian paths are connected at another junction within dist715bool alreadyConnectedPaths(const NBEdge* e1, const NBEdge* e2, double dist) const;716717/// @brief return true if the given sidewalks are separated by a fringe road718bool crossesFringe(const NBEdge* e1, const NBEdge* e2) const;719720/// @brief get prohibitions (BLocked connections)721const NBConnectionProhibits& getProhibitions() {722return myBlockedConnections;723}724725/// @brief whether this is structurally similar to a geometry node726bool geometryLike() const;727static bool geometryLike(const EdgeVector& incoming, const EdgeVector& outgoing);728729/// @brief update the type of this node as a roundabout730void setRoundabout();731732/// @brief return whether this node is part of a roundabout733bool isRoundabout() const;734735/// @brief add a pedestrian crossing to this node736NBNode::Crossing* addCrossing(EdgeVector edges, double width, bool priority, int tlIndex = -1, int tlIndex2 = -1,737const PositionVector& customShape = PositionVector::EMPTY, bool fromSumoNet = false, const Parameterised* params = nullptr);738739/// @brief add custom shape for walkingArea740void addWalkingAreaShape(EdgeVector edges, const PositionVector& shape, double width);741742/// @brief remove a pedestrian crossing from this node (identified by its edges)743void removeCrossing(const EdgeVector& edges);744745/// @brief discard all current (and optionally future) crossings746void discardAllCrossings(bool rejectAll);747748/// @brief discard previously built walkingareas (required for repeated computation by netedit)749void discardWalkingareas();750751/// @brief get num of crossings from sumo net752int numCrossingsFromSumoNet() const {753return myCrossingsLoadedFromSumoNet;754}755756/// @brief return this junctions pedestrian crossings757std::vector<Crossing*> getCrossings() const;758inline const std::vector<std::unique_ptr<Crossing> >& getCrossingsIncludingInvalid() const {759return myCrossings;760}761762/// @brief return this junctions pedestrian walking areas763inline const std::vector<WalkingArea>& getWalkingAreas() const {764return myWalkingAreas;765}766767const std::vector<WalkingAreaCustomShape>& getWalkingAreaCustomShapes() const {768return myWalkingAreaCustomShapes;769}770771/// @brief return the crossing with the given id772Crossing* getCrossing(const std::string& id) const;773774/// @brief return the crossing with the given Edges775Crossing* getCrossing(const EdgeVector& edges, bool hardFail = true) const;776777/// @brief return the walkingArea with the given ID778WalkingArea& getWalkingArea(const std::string& id);779780/* @brief set tl indices of this nodes crossing starting at the given index781* @return Whether a custom index was used782*/783bool setCrossingTLIndices(const std::string& tlID, int startIndex, bool ignoreCustom = false);784785/// @brief return the number of lane-to-lane connections at this junction (excluding crossings)786int numNormalConnections() const;787788/// @brief fix overlap789void avoidOverlap();790791/// @brief whether the given index must yield to the foeIndex while turing right on a red light792bool extraConflict(int index, int foeIndex) const;793794/// @brief sort all edge containers for this node795void sortEdges(bool useNodeShape);796797/// @brief return the index of the given connection798int getConnectionIndex(const NBEdge* from, const NBEdge::Connection& con) const;799800/**801* @class nodes_by_id_sorter802* @brief Used for sorting the cells by the begin time they describe803*/804class nodes_by_id_sorter {805public:806/// @brief Constructor807explicit nodes_by_id_sorter() { }808809/// @brief Comparing operator810int operator()(NBNode* n1, NBNode* n2) const {811return n1->getID() < n2->getID();812}813};814815/** @class edge_by_direction_sorter816* @brief Sorts outgoing before incoming edges817*/818class edge_by_direction_sorter {819public:820/// @brief constructor821explicit edge_by_direction_sorter(NBNode* n) : myNode(n) {}822823/// @brief operator of selection824int operator()(NBEdge* e1, NBEdge* e2) const {825UNUSED_PARAMETER(e2);826return e1->getFromNode() == myNode;827}828829private:830/// @brief The node to compute the relative angle of831NBNode* myNode;832833};834835/// @brief return whether the given type is a traffic light836static bool isTrafficLight(SumoXMLNodeType type);837838inline bool isTrafficLight() const {839return isTrafficLight(myType);840}841842/// @brief check if node is a simple continuation843bool isSimpleContinuation(bool checkLaneNumbers = true, bool checkWidth = false) const;844845/// @brief mark whether a priority road turns at this node846void markBentPriority(bool isBent) {847myIsBentPriority = isBent;848}849850/// @brief return whether a priority road turns at this node851bool isBentPriority() const {852return myIsBentPriority;853}854855/// @brief return whether a priority road turns at this node856bool typeWasGuessed() const {857return myTypeWasGuessed;858}859860/// @brief detects whether a given junction splits or merges lanes while keeping constant road width861bool isConstantWidthTransition() const;862863/// @brief return list of unique endpoint coordinates of all edges at this node864std::vector<std::pair<Position, std::string> > getEndPoints() const;865866/// @brief ensure connectivity for all vClasses867void recheckVClassConnections(NBEdge* currentOutgoing);868869/// @brief initialize signalized rail classes870static void initRailSignalClasses(const NBNodeCont& nc);871872private:873/// @brief sets the priorites in case of a priority junction874void setPriorityJunctionPriorities();875876/// @brief returns a list of edges which are connected to the given outgoing edge877void getEdgesThatApproach(NBEdge* currentOutgoing, EdgeVector& approaching);878879/// @brief replace incoming connections prohibitions880void replaceInConnectionProhibitions(NBEdge* which, NBEdge* by, int whichLaneOff, int byLaneOff);881882/// @brief remap removed883void remapRemoved(NBTrafficLightLogicCont& tc, NBEdge* removed, const EdgeVector& incoming, const EdgeVector& outgoing);884885/// @brief return whether there is a non-sidewalk lane after the given index;886bool forbidsPedestriansAfter(std::vector<std::pair<NBEdge*, bool> > normalizedLanes, int startIndex);887888/// @brief returns the list of all edges sorted clockwise by getAngleAtNodeToCenter889EdgeVector getEdgesSortedByAngleAtNodeCenter() const;890891/// @brief check if is long enough892static bool isLongEnough(NBEdge* out, double minLength);893894/// @brief remove all traffic light definitions that are part of a joined tls895void removeJoinedTrafficLights();896897/// @brief displace lane shapes to account for change in lane width at this node898void displaceShapeAtWidthChange(const NBEdge* from, const NBEdge::Connection& con, PositionVector& fromShape, PositionVector& toShape) const;899900/// @brief returns whether sub is a subset of super901static bool includes(const std::set<const NBEdge*, ComparatorIdLess>& super,902const std::set<const NBEdge*, ComparatorIdLess>& sub);903904NBEdge* getNextCompatibleOutgoing(const NBEdge* incoming, SVCPermissions vehPerm, EdgeVector::const_iterator start, bool clockwise) const;905906/// @brief get the reduction in driving lanes at this junction907void getReduction(const NBEdge* in, const NBEdge* out, int& inOffset, int& inEnd, int& outOffset, int& outEnd, int& reduction) const;908909/// @brief helper function to add connections for unsatisfied modes910SVCPermissions findToLaneForPermissions(NBEdge* currentOutgoing, int fromLane, NBEdge* incoming, SVCPermissions unsatisfied);911912/// @brief check whether this edge has extra lanes on the right side913int addedLanesRight(NBEdge* out, int addedLanes) const;914915/// @brief check whether the candidate edge is more likely to be the straight continuation916bool isStraighter(const NBEdge* const incoming, const double angle, const SVCPermissions vehPerm, const int modeLanes, const NBEdge* const candidate) const;917918/// @brief return edges that permit passengers (either incoming or outgoing)919EdgeVector getPassengerEdges(bool incoming) const;920921/// @brief detect explict rail turns with potential geometry problem922static bool isExplicitRailNoBidi(const NBEdge* incoming, const NBEdge* outgoing);923924/// @brief geometry helper that cuts the first shape where bordered by the other two925PositionVector cutAtShapes(const PositionVector& cut, const PositionVector& border1, const PositionVector& border2, const PositionVector& def);926927/// @brief compute offset for centering path-across-street crossings928void patchOffset_pathAcrossStreet(double& offset);929930/// @brief whether the given rail connections at this node may run in unsignalized (right-of-way) mode931bool unsignalizedOperation() const;932933/// @brief ensure connectivity for all special vClass934void recheckSpecialConnections(NBEdge* incoming, NBEdge* currentOutgoing, SVCPermissions svcSpecial);935936/// @brief helper function for recheckSpecialConnections937bool avoidConfict(NBEdge* incoming, NBEdge* currentOutgoing, SVCPermissions svcSpecial, LinkDirection dir, int i);938939private:940/// @brief The position the node lies at941Position myPosition;942943/// @brief Vector of incoming edges944EdgeVector myIncomingEdges;945946/// @brief Vector of outgoing edges947EdgeVector myOutgoingEdges;948949/// @brief Vector of incoming and outgoing edges950EdgeVector myAllEdges;951952/// @brief Vector of crossings953std::vector<std::unique_ptr<Crossing> > myCrossings;954955/// @brief Vector of walking areas956std::vector<WalkingArea> myWalkingAreas;957958/// @brief Vector of custom walking areas shapes959std::vector<WalkingAreaCustomShape> myWalkingAreaCustomShapes;960961/// @brief The type of the junction962SumoXMLNodeType myType;963964/// @brief The container for connection block dependencies965NBConnectionProhibits myBlockedConnections;966967/// @brief The district the node is the centre of968NBDistrict* myDistrict;969970/// @brief the (outer) shape of the junction971PositionVector myPoly;972973/// @brief whether this nodes shape was set by the user974bool myHaveCustomPoly;975976/// @brief Node requests977NBRequest* myRequest;978979/// @brief traffic lights of node980std::set<NBTrafficLightDefinition*> myTrafficLights;981982/// @brief the turning radius (for all corners) at this node in m.983double myRadius;984985/// @brief whether the junction area must be kept clear986bool myKeepClear;987988/// @brief how to compute right of way for this node989RightOfWay myRightOfWay;990991/// @brief fringe type of this node992FringeType myFringeType;993994/// @brief roundabout type of this node995RoundaboutType myRoundaboutType;996997/// @brief The intersection name (or whatever arbitrary string you wish to attach)998std::string myName;9991000/// @brief whether to discard all pedestrian crossings1001bool myDiscardAllCrossings;10021003/// @brief number of crossings loaded from a sumo net1004int myCrossingsLoadedFromSumoNet;10051006/// @brief geometry error after computation of internal lane shapes1007double myDisplacementError;10081009/* @brief whether this junction is a bent priority junction (main direction turns)1010* @note see NBEdgePriorityComputer1011*/1012bool myIsBentPriority;10131014/// @brief whether the node type was guessed rather than loaded1015bool myTypeWasGuessed;10161017/// @brief all vehicle classes for which rail signals exist1018static SVCPermissions myHaveRailSignalClasses;10191020/// @brief all rail classes for which operation without rail signals is permitted1021static SVCPermissions myPermitUnsignalizedClasses;10221023private:1024/// @brief invalidated copy constructor1025NBNode(const NBNode& s);10261027/// @brief invalidated assignment operator1028NBNode& operator=(const NBNode& s);1029};103010311032