/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 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 NBEdge.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Michael Behrisch17/// @date Tue, 20 Nov 200118///19// The representation of a single edge during network building20/****************************************************************************/21#pragma once22#include <config.h>2324#include <map>25#include <vector>26#include <string>27#include <set>28#include <cassert>29#include <utils/common/Named.h>30#include <utils/common/Parameterised.h>31#include <utils/common/UtilExceptions.h>32#include <utils/common/VectorHelper.h>33#include <utils/geom/Bresenham.h>34#include <utils/geom/PositionVector.h>35#include <utils/common/SUMOVehicleClass.h>36#include <utils/xml/SUMOXMLDefinitions.h>37#include "NBCont.h"38#include "NBHelpers.h"39#include "NBSign.h"404142// ===========================================================================43// class declarations44// ===========================================================================45class NBNode;46class NBConnection;47class NBNodeCont;48class NBEdgeCont;49class OutputDevice;50class GNELane;51class NBVehicle;525354// ===========================================================================55// class definitions56// ===========================================================================57/**58* @class NBRouterEdge59* @brief Superclass for NBEdge and NBEdge::Connection to initialize Router60*/61class NBRouterEdge {62public:63virtual ~NBRouterEdge() {}64virtual const std::string& getID() const = 0;65virtual double getSpeed() const = 0;66virtual double getLength() const = 0;67virtual const NBRouterEdge* getBidiEdge() const = 0;68virtual int getNumericalID() const = 0;69virtual const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const = 0;70virtual bool isInternal() const {71return false;72}73inline bool prohibits(const NBVehicle* const /*veh*/) const {74return false;75}76inline bool restricts(const NBVehicle* const /*veh*/) const {77return false;78}798081static inline double getTravelTimeStatic(const NBRouterEdge* const edge, const NBVehicle* const /*veh*/, double /*time*/) {82return edge->getLength() / edge->getSpeed();83}84};858687/**88* @class NBEdge89* @brief The representation of a single edge during network building90*/91class NBEdge : public Named, public Parameterised, public NBRouterEdge {92friend class NBEdgeCont;9394/** used for visualization (netedit) */95friend class GNELane;96friend class GNEEdge;97friend class GNEJunction;9899public:100101/** @enum EdgeBuildingStep102* @brief Current state of the edge within the building process103*104* As the network is build in a cascaded way, considering loaded105* information, a counter holding the current step is needed. This is done106* by using this enumeration.107*/108enum class EdgeBuildingStep {109/// @brief The edge has been loaded and connections shall not be added110INIT_REJECT_CONNECTIONS,111/// @brief The edge has been loaded, nothing is computed yet112INIT,113/// @brief The relationships between edges are computed/loaded114EDGE2EDGES,115/// @brief Lanes to edges - relationships are computed/loaded116LANES2EDGES,117/// @brief Lanes to lanes - relationships are computed; should be rechecked118LANES2LANES_RECHECK,119/// @brief Lanes to lanes - relationships are computed; no recheck is necessary/wished120LANES2LANES_DONE,121/// @brief Lanes to lanes - relationships are loaded; no recheck is necessary/wished122LANES2LANES_USER123};124125126/** @enum Lane2LaneInfoType127* @brief Modes of setting connections between lanes128*/129enum class Lane2LaneInfoType {130/// @brief The connection was computed131COMPUTED,132/// @brief The connection was given by the user133USER,134/// @brief The connection was computed and validated135VALIDATED136};137138139/** @struct Lane140* @brief An (internal) definition of a single lane of an edge141*/142struct Lane final : public Parameterised {143/// @brief constructor144Lane(NBEdge* e, const std::string& _origID);145146/// @brief The lane's shape147PositionVector shape;148149/// @brief The speed allowed on this lane150double speed;151152/// @brief The friction on this lane153double friction;154155/// @brief List of vehicle types that are allowed on this lane156SVCPermissions permissions;157158/// @brief List of vehicle types that are preferred on this lane159SVCPermissions preferred;160161/// @brief List of vehicle types that are allowed to change Left from this lane162SVCPermissions changeLeft;163164/// @brief List of vehicle types that are allowed to change right from this lane165SVCPermissions changeRight;166167/// @brief This lane's offset to the intersection begin168double endOffset;169170/// @brief stopOffsets.second - The stop offset for vehicles stopping at the lane's end.171/// Applies if vClass is in in stopOffset.first bitset172StopOffset laneStopOffset;173174/// @brief This lane's width175double width;176177/// @brief An opposite lane ID, if given178std::string oppositeID;179180/// @brief Whether this lane is an acceleration lane181bool accelRamp;182183/// @brief Whether connection information for this lane is already completed184// @note (see NIImporter_DlrNavteq::ConnectedLanesHandler)185bool connectionsDone;186187/// @brief A custom shape for this lane set by the user188PositionVector customShape;189190/// @brief the type of this lane191std::string type;192193/// @brief turning signs printed on the road, bitset of LinkDirection (imported from OSM)194int turnSigns = 0;195};196197/** @struct Connection198* @brief A structure which describes a connection between edges or lanes199*/200struct Connection final : public Parameterised, public NBRouterEdge {201/** @brief Constructor202* @param[in] fromLane_ The lane the connections starts at203* @param[in] toEdge_ The edge the connections yields in204* @param[in] toLane_ The lane the connections yields in205*/206Connection(int fromLane_, NBEdge* toEdge_, int toLane_, const bool mayDefinitelyPass_ = false);207208/// @brief The lane the connections starts at209int fromLane;210211/// @brief The edge the connections yields in212NBEdge* toEdge;213214/// @brief The lane the connections yields in215int toLane;216217/// @brief The id of the traffic light that controls this connection218std::string tlID;219220/// @brief The index of this connection within the controlling traffic light221int tlLinkIndex = -1;222223/// @brief The index of the internal junction within the controlling traffic light (optional)224int tlLinkIndex2 = -1;225226/// @brief Information about being definitely free to drive (on-ramps)227bool mayDefinitelyPass;228229/// @brief whether the junction must be kept clear when using this connection230KeepClear keepClear = KEEPCLEAR_UNSPECIFIED;231232/// @brief custom position for internal junction on this connection233double contPos = UNSPECIFIED_CONTPOS;234235/// @brief custom foe visiblity for connection236double visibility = UNSPECIFIED_VISIBILITY_DISTANCE;237238/// @brief custom speed for connection239double speed = UNSPECIFIED_SPEED;240241// @brief custom friction for connection242double friction = UNSPECIFIED_FRICTION;243244/// @brief custom length for connection245double customLength;246247/// @brief custom shape for connection248PositionVector customShape;249250/// @brief List of vehicle types that are allowed on this connection251SVCPermissions permissions = SVC_UNSPECIFIED;252253/// @brief List of vehicle types that are allowed to change Left from this connections internal lane(s)254SVCPermissions changeLeft = SVC_UNSPECIFIED;255256/// @brief List of vehicle types that are allowed to change right from this connections internal lane(s)257SVCPermissions changeRight = SVC_UNSPECIFIED;258259/// @brief Whether this connection is an indirect left turn260bool indirectLeft = false;261262/// @brief optional type of Connection263std::string edgeType;264265/// @brief id of Connection266std::string id;267268/// @brief shape of Connection269PositionVector shape;270271/// @brief maximum velocity272double vmax = UNSPECIFIED_SPEED;273274/// @brief check if Connection have a Via275bool haveVia = false;276277/// @brief if Connection have a via, ID of it278std::string viaID;279280/// @brief shape of via281PositionVector viaShape;282283/// @brief the length of the via shape (maybe customized)284double viaLength = 0.;285286/// @brief FOE Internal links287std::vector<int> foeInternalLinks;288289/// @brief FOE Incomings lanes290std::vector<std::string> foeIncomingLanes;291292/// @brief The lane index of this internal lane within the internal edge293int internalLaneIndex = UNSPECIFIED_INTERNAL_LANE_INDEX;294int internalViaLaneIndex = 0;295296/// @brief check if Connection is uncontrolled297bool uncontrolled = false;298299/// @brief get ID of internal lane300std::string getInternalLaneID() const;301302/// @brief get ID of internal lane (second part)303std::string getInternalViaLaneID() const;304305/// @brief get string describing this connection306std::string getDescription(const NBEdge* parent) const;307308/// @brief computed length (average of all internal lane shape lengths that share an internal edge)309double length = UNSPECIFIED_LOADED_LENGTH;310311/// @name NBRouterEdge interface312/// @{313static ConstRouterEdgePairVector myViaSuccessors; // always empty314const std::string& getID() const {315return id;316}317double getSpeed() const {318return vmax;319}320// @brief needed for NBRouterEdge321double getLength() const {322return shape.length() + viaShape.length();323}324int getNumericalID() const {325throw ProcessError("NBEdge::Connection does not implement getNumericalID()");326}327const Connection* getBidiEdge() const {328return nullptr;329}330bool isInternal() const {331return true;332}333const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {334UNUSED_PARAMETER(vClass);335UNUSED_PARAMETER(ignoreTransientPermissions);336return myViaSuccessors;337}338/// }@339};340341/// @brief Dummy edge to use when a reference must be supplied in the no-arguments constructor (FOX technicality)342static NBEdge DummyEdge;343344/// @brief unspecified lane width345static const double UNSPECIFIED_WIDTH;346347/// @brief unspecified lane offset348static const double UNSPECIFIED_OFFSET;349350/// @brief unspecified lane speed351static const double UNSPECIFIED_SPEED;352353/// @brief unspecified lane friction354static const double UNSPECIFIED_FRICTION;355356/// @brief unspecified internal junction position357static const double UNSPECIFIED_CONTPOS;358359/// @brief unspecified foe visibility for connections360static const double UNSPECIFIED_VISIBILITY_DISTANCE;361362/// @brief no length override given363static const double UNSPECIFIED_LOADED_LENGTH;364365/// @brief unspecified signal offset366static const double UNSPECIFIED_SIGNAL_OFFSET;367368/// @brief the distance at which to take the default angle369static const double ANGLE_LOOKAHEAD;370371/// @brief internal lane computation not yet done372static const int UNSPECIFIED_INTERNAL_LANE_INDEX;373374/// @brief TLS-controlled despite its node controlled not specified.375static const bool UNSPECIFIED_CONNECTION_UNCONTROLLED;376377/// @brief shift values for decoding turn signs378static const int TURN_SIGN_SHIFT_BUS = 8;379static const int TURN_SIGN_SHIFT_TAXI = 16;380static const int TURN_SIGN_SHIFT_BICYCLE = 24;381382/// @brief junction priority values set by setJunctionPriority383enum JunctionPriority {384MINOR_ROAD = 0,385PRIORITY_ROAD = 1,386ROUNDABOUT = 1000387};388389static void setDefaultConnectionLength(double length) {390myDefaultConnectionLength = length;391}392393public:394/** @brief Constructor395*396* Use this if no edge geometry is given.397*398* @param[in] id The id of the edge399* @param[in] from The node the edge starts at400* @param[in] to The node the edge ends at401* @param[in] type The type of the edge (my be =="")402* @param[in] speed The maximum velocity allowed on this edge403* @param[in] friction The current friction coefficient on this edge404* @param[in] nolanes The number of lanes this edge has405* @param[in] priority This edge's priority406* @param[in] width This edge's lane width407* @param[in] endOffset Additional offset to the destination node408* @param[in] spread How the lateral offset of the lanes shall be computed409* @param[in] streetName The street name (need not be unique)410* @see init411* @see LaneSpreadFunction412*/413NBEdge(const std::string& id,414NBNode* from, NBNode* to, std::string type,415double speed, double friction, int nolanes, int priority,416double width, double endOffset,417LaneSpreadFunction spread,418const std::string& streetName = "");419420/** @brief Constructor421*422* Use this if the edge's geometry is given.423*424* @param[in] id The id of the edge425* @param[in] from The node the edge starts at426* @param[in] to The node the edge ends at427* @param[in] type The type of the edge (may be =="")428* @param[in] speed The maximum velocity allowed on this edge429* @param[in] friction The current friction coefficient on this edge430* @param[in] nolanes The number of lanes this edge has431* @param[in] priority This edge's priority432* @param[in] width This edge's lane width433* @param[in] endOffset Additional offset to the destination node434* @param[in] geom The edge's geometry435* @param[in] spread How the lateral offset of the lanes shall be computed436* @param[in] streetName The street name (need not be unique)437* @param[in] origID The original ID in the source network (need not be unique)438* @param[in] spread How the lateral offset of the lanes shall be computed439* @param[in] tryIgnoreNodePositions Does not add node geometries if geom.size()>=2440* @see init441*/442NBEdge(const std::string& id,443NBNode* from, NBNode* to, std::string type,444double speed, double friction, int nolanes, int priority,445double width, double endOffset,446PositionVector geom,447LaneSpreadFunction spread,448const std::string& streetName = "",449const std::string& origID = "",450bool tryIgnoreNodePositions = false);451452/** @brief Constructor453*454* Use this to copy attributes from another edge455*456* @param[in] id The id of the edge457* @param[in] from The node the edge starts at458* @param[in] to The node the edge ends at459* @param[in] tpl The template edge to copy attributes from460* @param[in] geom The geometry to use (may be empty)461* @param[in] numLanes The number of lanes of the new edge (copy from tpl by default)462*/463NBEdge(const std::string& id,464NBNode* from, NBNode* to,465const NBEdge* tpl,466const PositionVector& geom = PositionVector(),467int numLanes = -1);468469/// @brief Destructor470~NBEdge();471472473/** @brief Resets initial values474*475* @param[in] from The node the edge starts at476* @param[in] to The node the edge ends at477* @param[in] type The type of the edge (may be =="")478* @param[in] speed The maximum velocity allowed on this edge479* @param[in] nolanes The number of lanes this edge has480* @param[in] priority This edge's priority481* @param[in] geom The edge's geometry482* @param[in] width This edge's lane width483* @param[in] endOffset Additional offset to the destination node484* @param[in] streetName The street name (need not be unique)485* @param[in] spread How the lateral offset of the lanes shall be computed486* @param[in] tryIgnoreNodePositions Does not add node geometries if geom.size()>=2487*/488void reinit(NBNode* from, NBNode* to, const std::string& type,489double speed, double friction, int nolanes, int priority,490PositionVector geom, double width, double endOffset,491const std::string& streetName,492LaneSpreadFunction spread,493bool tryIgnoreNodePositions = false);494495/** @brief Resets nodes but keeps all other values the same (used when joining)496* @param[in] from The node the edge starts at497* @param[in] to The node the edge ends at498*/499void reinitNodes(NBNode* from, NBNode* to);500501/// @name Applying offset502/// @{503/** @brief Applies an offset to the edge504* @param[in] xoff The x-offset to apply505* @param[in] yoff The y-offset to apply506*/507void reshiftPosition(double xoff, double yoff);508509/// @brief ensure consistency between input and output geometries510void roundGeometry();511512/// @brief ensure consistency between input and output speed513void roundSpeed();514515/// @brief mirror coordinates along the x-axis516void mirrorX();517/// @}518519/// @name Atomar getter methods520//@{521522/** @brief Returns the number of lanes523* @returns This edge's number of lanes524*/525int getNumLanes() const {526return (int)myLanes.size();527}528529/** @brief Returns the priority of the edge530* @return This edge's priority531*/532int getPriority() const {533return myPriority;534}535536/// @brief Sets the priority of the edge537void setPriority(int priority) {538myPriority = priority;539}540541/** @brief Returns the origin node of the edge542* @return The node this edge starts at543*/544inline NBNode* getFromNode() const {545return myFrom;546}547548/** @brief Returns the destination node of the edge549* @return The node this edge ends at550*/551inline NBNode* getToNode() const {552return myTo;553}554555/** @brief Returns the angle at the start of the edge556* (relative to the node shape center)557* The angle is computed in computeAngle()558* @return This edge's start angle559*/560inline double getStartAngle() const {561return myStartAngle;562}563564/** @brief Returns the angle at the end of the edge565* (relative to the node shape center)566* The angle is computed in computeAngle()567* @return This edge's end angle568*/569inline double getEndAngle() const {570return myEndAngle;571}572573/** @brief Returns the angle at the start of the edge574* @note only using edge shape575* @return This edge's start angle576*/577double getShapeStartAngle() const;578579580/** @brief Returns the angle at the end of the edge581* @note only using edge shape582* @note The angle is computed in computeAngle()583* @return This edge's end angle584*/585double getShapeEndAngle() const;586587/** @brief Returns the angle at the start of the edge588* @note The angle is computed in computeAngle()589* @return This edge's angle590*/591inline double getTotalAngle() const {592return myTotalAngle;593}594595/** @brief Returns the computed length of the edge596* @return The edge's computed length597*/598double getLength() const {599return myLength;600}601602603/** @brief Returns the length was set explicitly or the computed length if it wasn't set604* @todo consolidate use of myLength and myLoaded length605* @return The edge's specified length606*/607double getLoadedLength() const {608return myLoadedLength > 0 ? myLoadedLength : myLength;609}610611/// @brief get length that will be assigned to the lanes in the final network612double getFinalLength() const;613614/** @brief Returns whether a length was set explicitly615* @return Wether the edge's length was specified616*/617bool hasLoadedLength() const {618return myLoadedLength > 0;619}620621/** @brief Returns the speed allowed on this edge622* @return The maximum speed allowed on this edge623*/624double getSpeed() const {625return mySpeed;626}627628/** @brief Returns the friction on this edge629* @return The friction on this edge630*/631double getFriction() const {632return myFriction;633}634635/** @brief The building step of this edge636* @return The current building step for this edge637* @todo Recheck usage!638* @see EdgeBuildingStep639*/640EdgeBuildingStep getStep() const {641return myStep;642}643644/** @brief Returns the default width of lanes of this edge645* @return The width of lanes of this edge646*/647double getLaneWidth() const {648return myLaneWidth;649}650651/** @brief Returns the width of the lane of this edge652* @return The width of the lane of this edge653*/654double getLaneWidth(int lane) const;655656/** @brief Returns the width of the internal lane associated with the connection657* @param[in] node The node for which this edge is an incoming one658* @param[in] connection The connection from this edge to the successor lane659* @param[in] successor The outgoing lane of the connection660* @param[in] isVia Whether it is computing the Via stage661* @return The width of the internal lane662* @todo validity checks663*/664double getInternalLaneWidth(665const NBNode& node,666const NBEdge::Connection& connection,667const NBEdge::Lane& successor,668bool isVia) const;669670/// @brief Returns the combined width of all lanes of this edge671double getTotalWidth() const;672673/// @brief Returns the street name of this edge674const std::string& getStreetName() const {675return myStreetName;676}677678/// @brief sets the street name of this edge679void setStreetName(const std::string& name) {680myStreetName = name;681}682683/// @brief get distance684double getDistance() const {685return myDistance;686}687688/// @brief get distance at the given offset689double getDistancAt(double pos) const;690691/** @brief Returns the offset to the destination node692* @return The offset to the destination node693*/694double getEndOffset() const {695return myEndOffset;696}697698/** @brief Returns the offset to the destination node a the specified lane699* @return The offset to the destination node700*/701double getEndOffset(int lane) const;702703/** @brief Returns the stopOffset to the end of the edge704* @return The offset to the end of the edge705*/706const StopOffset& getEdgeStopOffset() const;707708/** @brief Returns the stop offset to the specified lane's end709* @return The stop offset to the specified lane's end710*/711const StopOffset& getLaneStopOffset(int lane) const;712713/// @brief Returns the offset of a traffic signal from the end of this edge714double getSignalOffset() const;715716/// @brief Returns the position of a traffic signal on this edge717const Position& getSignalPosition() const {718return mySignalPosition;719}720721/// @brief Returns the node that (possibly) represents a traffic signal controlling at the end of this edge722const NBNode* getSignalNode() const {723return mySignalNode;724}725726/// @brief sets the offset of a traffic signal from the end of this edge727void setSignalPosition(const Position& pos, const NBNode* signalNode) {728mySignalPosition = pos;729mySignalNode = signalNode;730}731732/** @brief Returns the lane definitions733* @return The stored lane definitions734*/735const std::vector<NBEdge::Lane>& getLanes() const {736return myLanes;737}738//@}739740/** @brief return the first lane with permissions other than SVC_PEDESTRIAN and 0741* @param[in] direction The direction in which the lanes shall be checked742* @param[in] exclusive Whether lanes that allow pedestrians along with other classes shall be counted as non-pedestrian743*/744int getFirstNonPedestrianLaneIndex(int direction, bool exclusive = false) const;745746/** @brief return the first lane with permissions other than SVC_PEDESTRIAN, SVC_BICYCLE and 0747* @param[in] direction The direction in which the lanes shall be checked748* @param[in] exclusive Whether lanes that allow pedestrians along with other classes shall be counted as non-pedestrian749*/750int getFirstNonPedestrianNonBicycleLaneIndex(int direction, bool exclusive = false) const;751752/// @brief return index of the first lane that allows the given permissions753int getSpecialLane(SVCPermissions permissions) const;754755/** @brief return the first lane that permits at least 1 vClass or the last lane if search direction of there is no such lane756* @param[in] direction The direction in which the lanes shall be checked757*/758int getFirstAllowedLaneIndex(int direction) const;759760/// @brief get first non-pedestrian lane761NBEdge::Lane getFirstNonPedestrianLane(int direction) const;762763/// @brief return all permission variants within the specified lane range [iStart, iEnd[764std::set<SVCPermissions> getPermissionVariants(int iStart, int iEnd) const;765766/* @brief get lane indices that allow the given permissions767* @param[in] allPermissions: whether all the given permissions must be allowed (or just some of them)768*/769int getNumLanesThatAllow(SVCPermissions permissions, bool allPermissions = true) const;770771/** @brief Returns whether the given vehicle class may change left from this lane */772bool allowsChangingLeft(int lane, SUMOVehicleClass vclass) const;773774/** @brief Returns whether the given vehicle class may change left from this lane */775bool allowsChangingRight(int lane, SUMOVehicleClass vclass) const;776777/// @brief return the angle for computing pedestrian crossings at the given node778double getCrossingAngle(NBNode* node);779780/// @brief get the lane id for the canonical sidewalk lane781std::string getSidewalkID();782783/// @name Edge geometry access and computation784//@{785/** @brief Returns the geometry of the edge786* @return The edge's geometry787*/788const PositionVector& getGeometry() const {789return myGeom;790}791792/// @brief Returns the geometry of the edge without the endpoints793const PositionVector getInnerGeometry() const;794795/// @brief Returns whether the geometry consists only of the node positions796bool hasDefaultGeometry() const;797798/** @brief Returns whether the geometry is terminated by the node positions799* This default may be violated by initializing with800* tryIgnoreNodePositions=true' or with setGeometry()801* non-default endpoints are useful to control the generated node shape802*/803bool hasDefaultGeometryEndpoints() const;804805/** @brief Returns whether the geometry is terminated by the node positions806* This default may be violated by initializing with807* tryIgnoreNodePositions=true' or with setGeometry()808* non-default endpoints are useful to control the generated node shape809*/810bool hasDefaultGeometryEndpointAtNode(const NBNode* node) const;811812Position getEndpointAtNode(const NBNode* node) const;813814void resetEndpointAtNode(const NBNode* node);815816/** @brief (Re)sets the edge's geometry817*818* Replaces the edge's prior geometry by the given. Then, computes819* the geometries of all lanes using computeLaneShapes.820* Definitely not the best way to have it accessible from outside...821* @param[in] g The edge's new geometry822* @param[in] inner whether g should be interpreted as inner points823* @todo Recheck usage, disallow access824* @see computeLaneShapes825*/826void setGeometry(const PositionVector& g, bool inner = false);827828/** @brief Adds a further geometry point829*830* Some importer do not know an edge's geometry when it is initialised.831* This method allows to insert further geometry points after the edge832* has been built.833*834* @param[in] index The position at which the point shall be added835* @param[in] p The point to add836*/837void addGeometryPoint(int index, const Position& p);838839/// @brief linearly extend the geometry at the given node840void extendGeometryAtNode(const NBNode* node, double maxExtent);841842/// @brief linearly extend the geometry at the given node843void shortenGeometryAtNode(const NBNode* node, double reduction);844845/// @brief shift geometry at the given node to avoid overlap and return whether geometry was changed846bool shiftPositionAtNode(NBNode* node, NBEdge* opposite);847848/// @brief return position taking into account loaded length849Position geometryPositionAtOffset(double offset) const;850851/** @brief Recomputeds the lane shapes to terminate at the node shape852* For every lane the intersection with the fromNode and toNode is853* calculated and the lane shorted accordingly. The edge length is then set854* to the average of all lane lengths (which may differ). This average length is used as the lane855* length when writing the network.856* @note All lanes of an edge in a sumo net must have the same nominal length857* but may differ in actual geomtric length.858* @note Depends on previous call to NBNodeCont::computeNodeShapes859*/860void computeEdgeShape(double smoothElevationThreshold = -1);861862/** @brief Returns the shape of the nth lane863* @return The shape of the lane given by its index (counter from right)864*/865const PositionVector& getLaneShape(int i) const;866867/** @brief (Re)sets how the lanes lateral offset shall be computed868* @param[in] spread The type of lateral offset to apply869* @see LaneSpreadFunction870*/871void setLaneSpreadFunction(LaneSpreadFunction spread);872873/** @brief Returns how this edge's lanes' lateral offset is computed874* @return The type of lateral offset that is applied on this edge875* @see LaneSpreadFunction876*/877LaneSpreadFunction getLaneSpreadFunction() const;878879/** @brief Removes points with a distance lesser than the given880* @param[in] minDist The minimum distance between two position to keep the second881*/882void reduceGeometry(const double minDist);883884/** @brief Check the angles of successive geometry segments885* @param[in] maxAngle The maximum angle allowed886* @param[in] minRadius The minimum turning radius allowed at the start and end887* @param[in] fix Whether to prune geometry points to avoid sharp turns at start and end888*/889void checkGeometry(const double maxAngle, bool fixAngle, const double minRadius, bool fix, bool silent);890//@}891892/// @name Setting and getting connections893/// @{894/** @brief Adds a connection to another edge895*896* If the given edge does not start at the node this edge ends on, false is returned.897*898* All other cases return true. Though, a connection may not been added if this edge899* is in step "INIT_REJECT_CONNECTIONS". Also, this method assures that a connection900* to an edge is set only once, no multiple connections to next edge are stored.901*902* After a first connection to an edge was set, the process step is set to "EDGE2EDGES".903* @note Passing 0 implicitly removes all existing connections904*905* @param[in] dest The connection's destination edge906* @return Whether the connection was valid907*/908bool addEdge2EdgeConnection(NBEdge* dest, bool overrideRemoval = false, SVCPermissions permission = SVC_UNSPECIFIED);909910/** @brief Adds a connection between the specified this edge's lane and an approached one911*912* If the given edge does not start at the node this edge ends on, false is returned.913*914* All other cases return true. Though, a connection may not been added if this edge915* is in step "INIT_REJECT_CONNECTIONS". Before the lane-to-lane connection is set,916* a connection between edges is established using "addEdge2EdgeConnection". Then,917* "setConnection" is called for inserting the lane-to-lane connection.918*919* @param[in] fromLane The connection's starting lane (of this edge)920* @param[in] dest The connection's destination edge921* @param[in] toLane The connection's destination lane922* @param[in] type The connections's type923* @param[in] mayUseSameDestination Whether this connection may be set though connecting an already connected lane924* @param[in] mayDefinitelyPass Whether this connection is definitely undistrubed (special case for on-ramps)925* @return Whether the connection was added / exists926* @see addEdge2EdgeConnection927* @see setConnection928* @todo Check difference between "setConnection" and "addLane2LaneConnection"929*/930bool addLane2LaneConnection(int fromLane, NBEdge* dest,931int toLane, Lane2LaneInfoType type,932bool mayUseSameDestination = false,933bool mayDefinitelyPass = false,934KeepClear keepClear = KEEPCLEAR_UNSPECIFIED,935double contPos = UNSPECIFIED_CONTPOS,936double visibility = UNSPECIFIED_VISIBILITY_DISTANCE,937double speed = UNSPECIFIED_SPEED,938double friction = UNSPECIFIED_FRICTION,939double length = myDefaultConnectionLength,940const PositionVector& customShape = PositionVector::EMPTY,941const bool uncontrolled = UNSPECIFIED_CONNECTION_UNCONTROLLED,942SVCPermissions permissions = SVC_UNSPECIFIED,943const bool indirectLeft = false,944const std::string& edgeType = "",945SVCPermissions changeLeft = SVC_UNSPECIFIED,946SVCPermissions changeRight = SVC_UNSPECIFIED,947bool postProcess = false);948949/** @brief Builds no connections starting at the given lanes950*951* If "invalidatePrevious" is true, a call to "invalidateConnections(true)" is done.952* This method loops through the given connections to set, calling "addLane2LaneConnection"953* for each.954*955* @param[in] fromLane The first of the connections' starting lanes (of this edge)956* @param[in] dest The connections' destination edge957* @param[in] toLane The first of the connections' destination lanes958* @param[in] no The number of connections to set959* @param[in] type The connections' type960* @param[in] invalidatePrevious Whether previously set connection shall be deleted961* @param[in] mayDefinitelyPass Whether these connections are definitely undistrubed (special case for on-ramps)962* @return Whether the connections were added / existed963* @see addLane2LaneConnection964* @see invalidateConnections965*/966bool addLane2LaneConnections(int fromLane,967NBEdge* dest, int toLane, int no,968Lane2LaneInfoType type, bool invalidatePrevious = false,969bool mayDefinitelyPass = false);970971/** @brief Adds a connection to a certain lane of a certain edge972*973* @param[in] lane The connection's starting lane (of this edge)974* @param[in] destEdge The connection's destination edge975* @param[in] destLane The connection's destination lane976* @param[in] type The connections's type977* @param[in] mayUseSameDestination Whether this connection may be set though connecting an already connected lane978* @param[in] mayDefinitelyPass Whether this connection is definitely undistrubed (special case for on-ramps)979* @todo Check difference between "setConnection" and "addLane2LaneConnection"980*/981bool setConnection(int lane, NBEdge* destEdge,982int destLane,983Lane2LaneInfoType type,984bool mayUseSameDestination = false,985bool mayDefinitelyPass = false,986KeepClear keepClear = KEEPCLEAR_UNSPECIFIED,987double contPos = UNSPECIFIED_CONTPOS,988double visibility = UNSPECIFIED_VISIBILITY_DISTANCE,989double speed = UNSPECIFIED_SPEED,990double friction = UNSPECIFIED_FRICTION,991double length = myDefaultConnectionLength,992const PositionVector& customShape = PositionVector::EMPTY,993const bool uncontrolled = UNSPECIFIED_CONNECTION_UNCONTROLLED,994SVCPermissions permissions = SVC_UNSPECIFIED,995bool indirectLeft = false,996const std::string& edgeType = "",997SVCPermissions changeLeft = SVC_UNSPECIFIED,998SVCPermissions changeRight = SVC_UNSPECIFIED,999bool postProcess = false);10001001/** @brief Returns connections from a given lane1002*1003* This method goes through "myConnections" and copies those which are1004* starting at the given lane.1005* @param[in] lane The lane which connections shall be returned1006* @param[in] to The target Edge (ignore nullptr)1007* @param[in] toLane The target lane (ignore if > 0)1008* @return The connections from the given lane1009* @see NBEdge::Connection1010*/1011std::vector<Connection> getConnectionsFromLane(int lane, const NBEdge* to = nullptr, int toLane = -1) const;10121013/** @brief Returns the specified connection (unmodifiable)1014* This method goes through "myConnections" and returns the specified one1015* @see NBEdge::Connection1016*/1017const Connection& getConnection(int fromLane, const NBEdge* to, int toLane) const;10181019/** @brief Returns reference to the specified connection1020* This method goes through "myConnections" and returns the specified one1021* @see NBEdge::Connection1022*/1023Connection& getConnectionRef(int fromLane, const NBEdge* to, int toLane);10241025/** @brief Retrieves info about a connection to a certain lane of a certain edge1026*1027* Turnaround edge is ignored!1028* @param[in] destEdge The connection's destination edge1029* @param[in] destLane The connection's destination lane1030* @param[in] fromLane If a value >= 0 is given, only return true if a connection from the given lane exists1031* @return whether a connection to the specified lane exists1032*/1033bool hasConnectionTo(const NBEdge* destEdge, int destLane, int fromLane = -1) const;10341035/** @brief Returns the information whethe a connection to the given edge has been added (or computed)1036*1037* @param[in] e The destination edge1038* @param[in] ignoreTurnaround flag to ignore or not Turnaround1039* @return Whether a connection to the specified edge exists1040*/1041bool isConnectedTo(const NBEdge* e, const bool ignoreTurnaround = false) const;10421043/** @brief Returns the connections1044* @return This edge's connections to following edges1045*/1046const std::vector<Connection>& getConnections() const {1047return myConnections;1048}10491050/** @brief Returns the connections1051* @return This edge's connections to following edges1052*/1053std::vector<Connection>& getConnections() {1054return myConnections;1055}10561057/** @brief Returns the list of outgoing edges without the turnaround sorted in clockwise direction1058* @return Connected edges, sorted clockwise1059*/1060const EdgeVector* getConnectedSorted();10611062/** @brief Returns the list of outgoing edges unsorted1063* @return Connected edges1064*/1065EdgeVector getConnectedEdges() const;10661067/** @brief Returns the list of incoming edges unsorted1068* @return Connected predecessor edges1069*/1070EdgeVector getIncomingEdges() const;10711072/** @brief Returns the list of lanes that may be used to reach the given edge1073* @return Lanes approaching the given edge1074*/1075std::vector<int> getConnectionLanes(NBEdge* currentOutgoing, bool withBikes = true) const;10761077/// @brief sorts the outgoing connections by their angle relative to their junction1078void sortOutgoingConnectionsByAngle();10791080/// @brief sorts the outgoing connections by their from-lane-index and their to-lane-index1081void sortOutgoingConnectionsByIndex();10821083/** @brief Remaps the connection in a way that allows the removal of it1084*1085* This edge (which is a self loop edge, in fact) connections are spread over the valid incoming edges1086* @todo recheck!1087*/1088void remapConnections(const EdgeVector& incoming);10891090/** @brief Removes the specified connection(s)1091* @param[in] toEdge The destination edge1092* @param[in] fromLane The lane from which connections shall be removed; -1 means remove all1093* @param[in] toLane The lane to which connections shall be removed; -1 means remove all1094* @param[in] tryLater If the connection does not exist, try again during recheckLanes()1095* @param[in] adaptToLaneRemoval we are in the process of removing a complete lane, adapt all connections accordingly1096*/1097void removeFromConnections(NBEdge* toEdge, int fromLane = -1, int toLane = -1, bool tryLater = false, const bool adaptToLaneRemoval = false, const bool keepPossibleTurns = false);10981099/// @brief remove an existent connection of edge1100bool removeFromConnections(const NBEdge::Connection& connectionToRemove);11011102/// @brief invalidate current connections of edge1103void invalidateConnections(bool reallowSetting = false);11041105/// @brief replace in current connections of edge1106void replaceInConnections(NBEdge* which, NBEdge* by, int laneOff);11071108/// @brief replace in current connections of edge1109void replaceInConnections(NBEdge* which, const std::vector<NBEdge::Connection>& origConns);11101111/// @brief copy connections from antoher edge1112void copyConnectionsFrom(NBEdge* src);11131114/// @brief modifify the toLane for all connections to the given edge1115void shiftToLanesToEdge(NBEdge* to, int laneOff);1116/// @}11171118/** @brief Returns whether the given edge is the opposite direction to this edge1119* @param[in] edge The edge which may be the turnaround direction1120* @return Whether the given edge is this edge's turnaround direction1121* (regardless of whether a connection exists)1122*/1123bool isTurningDirectionAt(const NBEdge* const edge) const;11241125/** @brief Sets the turing destination at the given edge1126* @param[in] e The turn destination1127* @param[in] onlyPossible If true, only sets myPossibleTurnDestination1128*/1129void setTurningDestination(NBEdge* e, bool onlyPossible = false);11301131/// @name Setting/getting special types1132/// @{1133/// @brief Marks this edge as a macroscopic connector1134void setAsMacroscopicConnector() {1135myAmMacroscopicConnector = true;1136}11371138/** @brief Returns whether this edge was marked as a macroscopic connector1139* @return Whether this edge was marked as a macroscopic connector1140*/1141bool isMacroscopicConnector() const {1142return myAmMacroscopicConnector;1143}11441145/// @brief Marks this edge being within an intersection1146void setInsideTLS(bool inside) {1147myAmInTLS = inside;1148}11491150/** @brief Returns whether this edge was marked as being within an intersection1151* @return Whether this edge was marked as being within an intersection1152*/1153bool isInsideTLS() const {1154return myAmInTLS;1155}1156/// @}11571158/** @brief Sets the junction priority of the edge1159* @param[in] node The node for which the edge's priority is given1160* @param[in] prio The edge's new priority at this node1161* @todo Maybe the edge priority whould be stored in the node1162*/1163void setJunctionPriority(const NBNode* const node, int prio);11641165/** @brief Returns the junction priority (normalised for the node currently build)1166*1167* If the given node is neither the edge's start nor the edge's ending node, the behaviour1168* is undefined.1169*1170* @param[in] node The node for which the edge's priority shall be returned1171* @return The edge's priority at the given node1172* @todo Maybe the edge priority whould be stored in the node1173*/1174int getJunctionPriority(const NBNode* const node) const;11751176/// @brief set loaded length1177void setLoadedLength(double val);11781179/// @brief patch average lane length in regard to the opposite edge1180void setAverageLengthWithOpposite(double val);11811182/// @brief dimiss vehicle class information1183void dismissVehicleClassInformation();11841185/// @brief get ID of type1186const std::string& getTypeID() const {1187return myType;1188}11891190/// @brief whether at least one lane has values differing from the edges values1191bool needsLaneSpecificOutput() const;11921193/// @brief whether at least one lane has restrictions1194bool hasPermissions() const;11951196/// @brief whether lanes differ in allowed vehicle classes1197bool hasLaneSpecificPermissions() const;11981199/// @brief whether lanes differ in speed1200bool hasLaneSpecificSpeed() const;12011202/// @brief whether lanes differ in friction1203bool hasLaneSpecificFriction() const;12041205/// @brief whether lanes differ in width1206bool hasLaneSpecificWidth() const;12071208/// @brief whether lanes differ in type1209bool hasLaneSpecificType() const;12101211/// @brief whether lanes differ in offset1212bool hasLaneSpecificEndOffset() const;12131214/// @brief whether lanes differ in stopOffsets1215bool hasLaneSpecificStopOffsets() const;12161217/// @brief whether one of the lanes is an acceleration lane1218bool hasAccelLane() const;12191220/// @brief whether one of the lanes has a custom shape1221bool hasCustomLaneShape() const;12221223/// @brief whether one of the lanes has parameters set1224bool hasLaneParams() const;12251226/// @brief whether one of the lanes prohibits lane changing1227bool prohibitsChanging() const;12281229/// @brief computes the edge (step1: computation of approached edges)1230bool computeEdge2Edges(bool noLeftMovers);12311232/// @brief computes the edge, step2: computation of which lanes approach the edges)1233bool computeLanes2Edges();12341235/// @brief recheck whether all lanes within the edge are all right and optimises the connections once again1236bool recheckLanes();12371238/// @brief recheck whether all opposite and bidi settings are consistent1239void recheckOpposite(const NBEdgeCont& ec, bool fixOppositeLengths);12401241/** @brief Add a connection to the previously computed turnaround, if wished1242* and a turning direction exists (myTurnDestination!=0)1243* @param[in] noTLSControlled Whether the turnaround shall not be connected if the edge is controlled by a tls1244* @param[in] noFringe Whether the turnaround shall not be connected if the junction is at the (outer) fringe1245* @param[in] onlyDeadends Whether the turnaround shall only be built at deadends1246* @param[in] onlyTurnlane Whether the turnaround shall only be built when there is an exclusive (left) turn lane1247* @param[in] noGeometryLike Whether the turnaround shall be built at geometry-like nodes1248*/1249void appendTurnaround(bool noTLSControlled, bool noFringe, bool onlyDeadends, bool onlyTurnlane, bool noGeometryLike, bool checkPermissions);12501251/** @brief Returns the node at the given edges length (using an epsilon)1252@note When no node is existing at the given position, 0 is returned1253The epsilon is a static member of NBEdge, should be setable via program options */1254NBNode* tryGetNodeAtPosition(double pos, double tolerance = 5.0) const;12551256/// @brief get max lane offset1257double getMaxLaneOffset();12581259/// @brief Check if lanes were assigned1260bool lanesWereAssigned() const;12611262/// @brief return true if certain connection must be controlled by TLS1263bool mayBeTLSControlled(int fromLane, NBEdge* toEdge, int toLane) const;12641265/// @brief Returns if the link could be set as to be controlled1266bool setControllingTLInformation(const NBConnection& c, const std::string& tlID);12671268/// @brief clears tlID for all connections1269void clearControllingTLInformation();12701271/// @brief get the outer boundary of this edge when going clock-wise around the given node1272PositionVector getCWBoundaryLine(const NBNode& n) const;12731274/// @brief get the outer boundary of this edge when going counter-clock-wise around the given node1275PositionVector getCCWBoundaryLine(const NBNode& n) const;12761277/// @brief Check if Node is expandable1278bool expandableBy(NBEdge* possContinuation, std::string& reason) const;12791280/// @brief append another edge1281void append(NBEdge* continuation);12821283/// @brief update parameter with removed nodes1284void updateRemovedNodes(const std::string& removed);12851286/// @brief Check if edge has signalised connections1287bool hasSignalisedConnectionTo(const NBEdge* const e) const;12881289/// @brief move outgoing connection1290void moveOutgoingConnectionsFrom(NBEdge* e, int laneOff);12911292/* @brief return the turn destination if it exists1293* @param[in] possibleDestination Wether myPossibleTurnDestination should be returned if no turnaround connection1294* exists1295*/1296NBEdge* getTurnDestination(bool possibleDestination = false) const;12971298/// @brief get lane ID1299std::string getLaneID(int lane) const;13001301/// @brief get lane speed1302double getLaneSpeed(int lane) const;13031304/// @brief get lane friction of specified lane1305double getLaneFriction(int lane) const;13061307/// @brief Check if edge is near enought to be joined to another edge1308bool isNearEnough2BeJoined2(NBEdge* e, double threshold) const;13091310/** @brief Returns the angle of the edge's geometry at the given node1311*1312* The angle is in degrees between -180 and 180.1313* @param[in] node The node for which the edge's angle shall be returned1314* @return This edge's angle at the given node1315*/1316double getAngleAtNode(const NBNode* const node) const;13171318/** @brief Returns the angle of the edge's geometry at the given node1319* and disregards edge direction1320* @param[in] node The node for which the edge's angle shall be returned1321* @return This edge's angle at the given node (normalized to point towards the node)1322*/1323double getAngleAtNodeNormalized(const NBNode* const node) const;13241325/** @brief Returns the angle of from the node shape center to where the edge meets1326* the node shape1327*1328* The angle is signed, disregards direction, and starts at 12 o'clock1329* (north->south), proceeds positive clockwise.1330* @param[in] node The node for which the edge's angle shall be returned1331* @return This edge's angle at the given node shape1332*/1333double getAngleAtNodeToCenter(const NBNode* const node) const;13341335/// @brief increment lane1336void incLaneNo(int by);13371338/// @brief decrement lane1339void decLaneNo(int by);13401341/// @brief delete lane1342void deleteLane(int index, bool recompute, bool shiftIndices);13431344/// @brief add lane1345void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices);13461347/// @brief mark edge as in lane to state lane1348void markAsInLane2LaneState();13491350/// @brief add a pedestrian sidewalk of the given width and shift existing connctions1351void addSidewalk(double width);13521353/// @brief restore an previously added sidewalk1354void restoreSidewalk(std::vector<NBEdge::Lane> oldLanes, PositionVector oldGeometry, std::vector<NBEdge::Connection> oldConnections);13551356/// add a bicycle lane of the given width and shift existing connctions1357void addBikeLane(double width);13581359/// @brief restore an previously added BikeLane1360void restoreBikelane(std::vector<NBEdge::Lane> oldLanes, PositionVector oldGeometry, std::vector<NBEdge::Connection> oldConnections);13611362/// @brief add a lane of the given width, restricted to the given class and shift existing connections1363void addRestrictedLane(double width, SUMOVehicleClass vclass);13641365/// @brief set allowed/disallowed classes for the given lane or for all lanes if -1 is given1366void setPermissions(SVCPermissions permissions, int lane = -1);13671368/// @brief set preferred Vehicle Class1369void setPreferredVehicleClass(SVCPermissions permissions, int lane = -1);13701371/// @brief set allowed classes for changing to the left and right from the given lane1372void setPermittedChanging(int lane, SVCPermissions changeLeft, SVCPermissions changeRight);13731374/// @brief set allowed class for the given lane or for all lanes if -1 is given1375void allowVehicleClass(int lane, SUMOVehicleClass vclass);13761377/// @brief set disallowed class for the given lane or for all lanes if -1 is given1378void disallowVehicleClass(int lane, SUMOVehicleClass vclass);13791380/// @brief prefer certain vehicle classes for the given lane or for all lanes if -1 is given (ensures also permissions)1381void preferVehicleClass(int lane, SVCPermissions vclasses);13821383/// @brief set lane specific width (negative lane implies set for all lanes)1384void setLaneWidth(int lane, double width);13851386/// @brief set lane specific type (negative lane implies set for all lanes)1387void setLaneType(int lane, const std::string& type);13881389/// @brief set lane specific end-offset (negative lane implies set for all lanes)1390void setEndOffset(int lane, double offset);13911392/// @brief set lane specific speed (negative lane implies set for all lanes)1393void setSpeed(int lane, double speed);13941395/// @brief set lane specific friction (negative lane implies set for all lanes)1396void setFriction(int lane, double friction);13971398/// @brief set lane and vehicle class specific stopOffset (negative lane implies set for all lanes)1399/// @return Whether given stop offset was applied.1400bool setEdgeStopOffset(int lane, const StopOffset& offset, bool overwrite = false);14011402/// @brief marks one lane as acceleration lane1403void setAcceleration(int lane, bool accelRamp);14041405/// @brief marks this edge has being an offRamp or leading to one (used for connection computation)1406void markOffRamp(bool isOffRamp) {1407myIsOffRamp = isOffRamp;1408}14091410bool isOffRamp() const {1411return myIsOffRamp;1412}14131414/// @brief sets a custom lane shape1415void setLaneShape(int lane, const PositionVector& shape);14161417/// @brief get the union of allowed classes over all lanes or for a specific lane1418SVCPermissions getPermissions(int lane = -1) const;14191420/// @brief set origID for all lanes or for a specific lane1421void setOrigID(const std::string origID, const bool append, const int laneIdx = -1);14221423/// @brief set kilometrage at start of edge (negative value implies couting down along the edge)1424void setDistance(double distance) {1425myDistance = distance;1426}14271428/// @brief mark this edge as a bidi edge1429void setBidi(bool isBidi) {1430myIsBidi = isBidi;1431}14321433/// @brief return whether this edge should be a bidi edge1434bool isBidi() {1435return myIsBidi;1436}14371438// @brief returns a reference to the internal structure for the convenience of netedit1439Lane& getLaneStruct(int lane) {1440assert(lane >= 0);1441assert(lane < (int)myLanes.size());1442return myLanes[lane];1443}14441445// @brief returns a reference to the internal structure for the convenience of netedit1446const Lane& getLaneStruct(int lane) const {1447assert(lane >= 0);1448assert(lane < (int)myLanes.size());1449return myLanes[lane];1450}14511452/// @brief declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has no connections intentionally.1453void declareConnectionsAsLoaded(EdgeBuildingStep step = EdgeBuildingStep::LANES2LANES_USER) {1454myStep = step;1455}14561457/* @brief fill connection attributes shape, viaShape, ...1458*1459* @param[in,out] edgeIndex The number of connections already handled1460* @param[in,out] splitIndex The number of via edges already built1461* @param[in] tryIgnoreNodePositions Does not add node geometries if geom.size()>=21462*/1463double buildInnerEdges(const NBNode& n, int noInternalNoSplits, int& linkIndex, int& splitIndex);14641465/// @brief get Signs1466inline const std::vector<NBSign>& getSigns() const {1467return mySigns;1468}14691470/// @brief add Sign1471inline void addSign(NBSign sign) {1472mySigns.push_back(sign);1473}14741475/// @brief cut shape at the intersection shapes1476PositionVector cutAtIntersection(const PositionVector& old) const;14771478/// @brief Set Node border1479void setNodeBorder(const NBNode* node, const Position& p, const Position& p2, bool rectangularCut);1480const PositionVector& getNodeBorder(const NBNode* node) const;1481void resetNodeBorder(const NBNode* node);14821483/// @brief whether this edge is part of a bidirectional railway1484bool isBidiRail(bool ignoreSpread = false) const;14851486/// @brief whether this edge is part of a bidirectional edge pair1487bool isBidiEdge(bool checkPotential = false) const;14881489/// @brief whether this edge is a railway edge that does not continue1490bool isRailDeadEnd() const;14911492/// @brief debugging helper to print all connections1493void debugPrintConnections(bool outgoing = true, bool incoming = false) const;14941495/// @brief compute the first intersection point between the given lane geometries considering their rspective widths1496static double firstIntersection(const PositionVector& v1, const PositionVector& v2, double width1, double width2, const std::string& error = "", bool secondIntersection = false);14971498/** returns a modified version of laneShape which starts at the outside of startNode. laneShape may be shorted or extended1499* @note see [wiki:Developer/Network_Building_Process]1500*/1501static PositionVector startShapeAt(const PositionVector& laneShape, const NBNode* startNode, PositionVector nodeShape);15021503/// @name functions for router usage1504//@{15051506static inline double getTravelTimeStatic(const NBEdge* const edge, const NBVehicle* const /*veh*/, double /*time*/) {1507return edge->getLength() / edge->getSpeed();1508}15091510static int getLaneIndexFromLaneID(const std::string laneID);15111512/// @brief sets the index of the edge in the list of all network edges1513void setNumericalID(int index) {1514myIndex = index;1515}15161517/** @brief Returns the index (numeric id) of the edge1518* @note This is only used in the context of routing1519* @return This edge's numerical id1520*/1521int getNumericalID() const {1522return myIndex;1523}15241525const NBEdge* getBidiEdge() const {1526return isBidiRail() || isBidiEdge() ? myPossibleTurnDestination : nullptr;1527}15281529/** @brief Returns the following edges for the given vClass1530*/1531const EdgeVector& getSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;153215331534/** @brief Returns the following edges for the given vClass1535*/1536const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;15371538//@}1539const std::string& getID() const {1540return Named::getID();1541}15421543/// @brief join adjacent lanes with the given permissions1544bool joinLanes(SVCPermissions perms);15451546/// @brief reset lane shapes to what they would be before cutting with the junction shapes1547void resetLaneShapes();15481549/// @brief modify all existing restrictions on lane changing1550void updateChangeRestrictions(SVCPermissions ignoring);15511552/// @brief return the straightest follower edge for the given permissions or nullptr (never returns turn-arounds)1553/// @note: this method is called before connections are built and simply goes by node graph topology1554NBEdge* getStraightContinuation(SVCPermissions permissions) const;15551556/// @brief return the straightest predecessor edge for the given permissions or nullptr (never returns turn-arounds)1557/// @note: this method is called before connections are built and simply goes by node graph topology1558NBEdge* getStraightPredecessor(SVCPermissions permissions) const;15591560/// @brief set oppositeID and return opposite edge if found1561NBEdge* guessOpposite(bool reguess = false);156215631564const std::string& getTurnSignTarget() const {1565return myTurnSignTarget;1566}15671568void setTurnSignTarget(const std::string& target) {1569myTurnSignTarget = target;1570}15711572/// @brief return only those edges that permit at least one of the give permissions1573static EdgeVector filterByPermissions(const EdgeVector& edges, SVCPermissions permissions);15741575private:1576/** @class ToEdgeConnectionsAdder1577* @brief A class that being a bresenham-callback assigns the incoming lanes to the edges1578*/1579class ToEdgeConnectionsAdder : public Bresenham::BresenhamCallBack {1580private:1581/// @brief map of edges to this edge's lanes that reach them1582std::map<NBEdge*, std::vector<int> > myConnections;15831584/// @brief the transition from the virtual lane to the edge it belongs to1585const EdgeVector& myTransitions;15861587public:1588/// @brief constructor1589ToEdgeConnectionsAdder(const EdgeVector& transitions)1590: myTransitions(transitions) { }15911592/// @brief destructor1593~ToEdgeConnectionsAdder() { }15941595/// @brief executes a bresenham - step1596void execute(const int lane, const int virtEdge);15971598/// @brief get built connections1599const std::map<NBEdge*, std::vector<int> >& getBuiltConnections() const {1600return myConnections;1601}16021603private:1604/// @brief Invalidated copy constructor.1605ToEdgeConnectionsAdder(const ToEdgeConnectionsAdder&) = delete;16061607/// @brief Invalidated assignment operator.1608ToEdgeConnectionsAdder& operator=(const ToEdgeConnectionsAdder&) = delete;1609};161016111612/**1613* @class MainDirections1614* @brief Holds (- relative to the edge it is build from -!!!) the list of1615* main directions a vehicle that drives on this street may take on1616* the junction the edge ends in1617* The back direction is not regarded1618*/1619class MainDirections {1620public:1621/// @brief enum of possible directions1622enum class Direction {1623RIGHTMOST,1624LEFTMOST,1625FORWARD1626};16271628public:1629/// @brief constructor1630MainDirections(const EdgeVector& outgoing, NBEdge* parent, NBNode* to, const std::vector<int>& availableLanes);16311632/// @brief destructor1633~MainDirections();16341635/// @brief returns the index of the straightmost among the given outgoing edges1636int getStraightest() const {1637return myStraightest;1638}16391640/// @brief returns the information whether no following street has a higher priority1641bool empty() const;16421643/// @brief returns the information whether the street in the given direction has a higher priority1644bool includes(Direction d) const;16451646private:1647/// @brief the index of the straightmost among the given outgoing edges1648int myStraightest;16491650/// @brief list of the main direction within the following junction relative to the edge1651std::vector<Direction> myDirs;16521653/// @brief Invalidated copy constructor.1654MainDirections(const MainDirections&) = delete;16551656/// @brief Invalidated assignment operator.1657MainDirections& operator=(const MainDirections&) = delete;1658};16591660/// @brief Computes the shape for the given lane1661PositionVector computeLaneShape(int lane, double offset) const;16621663/// @brief compute lane shapes1664void computeLaneShapes();16651666private:1667/** @brief Initialization routines common to all constructors1668*1669* Checks whether the number of lanes>0, whether the junction's from-1670* and to-nodes are given (!=0) and whether they are distict. Throws1671* a ProcessError if any of these checks fails.1672*1673* Adds the nodes positions to geometry if it shall not be ignored or1674* if the geometry is empty.1675*1676* Computes the angle and length, and adds this edge to its node as1677* outgoing/incoming. Builds lane informations.1678*1679* @param[in] noLanes The number of lanes this edge has1680* @param[in] tryIgnoreNodePositions Does not add node geometries if geom.size()>=21681* @param[in] origID The original ID this edge had1682*/1683void init(int noLanes, bool tryIgnoreNodePositions, const std::string& origID);16841685/// @brief divides the lanes on the outgoing edges1686void divideOnEdges(const EdgeVector* outgoing);16871688/// @brief divide selected lanes on edges1689void divideSelectedLanesOnEdges(const EdgeVector* outgoing, const std::vector<int>& availableLanes);16901691/// @brief add some straight connections1692void addStraightConnections(const EdgeVector* outgoing, const std::vector<int>& availableLanes, const std::vector<int>& priorities);16931694/// @brief recomputes the edge priorities and manipulates them for a distribution of lanes on edges which is more like in real-life1695const std::vector<int> prepareEdgePriorities(const EdgeVector* outgoing, const std::vector<int>& availableLanes);16961697/// @name Setting and getting connections1698/// @{1699/** @brief moves a connection one place to the left;1700* @note Attention! no checking for field validity1701*/1702void moveConnectionToLeft(int lane);17031704/** @brief moves a connection one place to the right;1705* @noteAttention! no checking for field validity1706*/1707void moveConnectionToRight(int lane);17081709/// @brief whether the connection can originate on newFromLane1710bool canMoveConnection(const Connection& con, int newFromLane) const;1711/// @}17121713/// @brief computes the angle of this edge and stores it in myAngle1714void computeAngle();17151716/// @brief determine conflict between opposite left turns1717bool bothLeftTurns(LinkDirection dir, const NBEdge* otherFrom, LinkDirection dir2) const;1718bool haveIntersection(const NBNode& n, const PositionVector& shape, const NBEdge* otherFrom, const NBEdge::Connection& otherCon,1719int numPoints, double width1, double width2, int shapeFlag = 0) const;17201721/// @brief returns whether any lane already allows the given vclass exclusively1722bool hasRestrictedLane(SUMOVehicleClass vclass) const;17231724/// @brief restore a restricted lane1725void restoreRestrictedLane(SUMOVehicleClass vclass, std::vector<NBEdge::Lane> oldLanes, PositionVector oldGeometry, std::vector<NBEdge::Connection> oldConnections);17261727/// @brief assign length to all lanes of an internal edge1728double assignInternalLaneLength(std::vector<Connection>::iterator i, int numLanes, double lengthSum, bool averageLength);17291730/// @brief decode bitset1731static std::vector<LinkDirection> decodeTurnSigns(int turnSigns, int shift = 0);1732static void updateTurnPermissions(SVCPermissions& perm, LinkDirection dir, SVCPermissions spec, std::vector<LinkDirection> dirs);17331734/// @brief apply loaded turn sign information1735bool applyTurnSigns();17361737/* @brief remove connections with incompatible permissions (should only be1738* called for guessed connections) */1739void removeInvalidConnections();17401741private:1742/** @brief The building step1743* @see EdgeBuildingStep1744*/1745EdgeBuildingStep myStep;17461747/// @brief The type of the edge1748std::string myType;17491750/// @brief The source and the destination node1751NBNode* myFrom, *myTo;17521753/// @brief node for which turnSign information applies1754std::string myTurnSignTarget;17551756/// @brief The length of the edge1757double myLength;17581759/// @brief The angles of the edge1760/// @{1761double myStartAngle;1762double myEndAngle;1763double myTotalAngle;1764/// @}17651766/// @brief The priority of the edge1767int myPriority;17681769/// @brief The maximal speed1770double mySpeed;17711772/// @brief The current friction1773double myFriction;17741775/// @brief The mileage/kilometrage at the start of this edge in a linear coordination system1776double myDistance;17771778/** @brief List of connections to following edges1779* @see Connection1780*/1781std::vector<Connection> myConnections;17821783/// @brief List of connections marked for delayed removal1784std::vector<Connection> myConnectionsToDelete;17851786/// @brief The turn destination edge (if a connection exists)1787NBEdge* myTurnDestination;17881789/// @brief The edge that would be the turn destination if there was one1790NBEdge* myPossibleTurnDestination;17911792/// @brief The priority normalised for the node the edge is outgoing of1793int myFromJunctionPriority;17941795/// @brief The priority normalised for the node the edge is incoming in1796int myToJunctionPriority;17971798/// @brief The geometry for the edge1799PositionVector myGeom;18001801/// @brief The information about how to spread the lanes1802LaneSpreadFunction myLaneSpreadFunction;18031804/// @brief This edges's offset to the intersection begin (will be applied to all lanes)1805double myEndOffset;18061807/// @brief A vClass specific stop offset - assumed of length 0 (unspecified) or 1.1808/// For the latter case the int is a bit set specifying the vClasses,1809/// the offset applies to (see SUMOVehicleClass.h), and the double is the1810/// stopping offset in meters from the lane end1811StopOffset myEdgeStopOffset;18121813/// @brief This width of this edge's lanes1814double myLaneWidth;18151816/** @brief Lane information1817* @see Lane1818*/1819std::vector<Lane> myLanes;18201821/// @brief An optional length to use (-1 if not valid)1822double myLoadedLength;18231824/// @brief Information whether this is lies within a joined tls1825bool myAmInTLS;18261827/// @brief Information whether this edge is a (macroscopic) connector1828bool myAmMacroscopicConnector;18291830/// @brief The street name (or whatever arbitrary string you wish to attach)1831std::string myStreetName;18321833/// @brief the street signs along this edge1834std::vector<NBSign> mySigns;18351836/// @brief the position of a traffic light signal on this edge1837Position mySignalPosition;1838const NBNode* mySignalNode;18391840/// @brief intersection borders (because the node shape might be invalid)1841/// @{1842PositionVector myFromBorder;1843PositionVector myToBorder;1844/// @}18451846/// @brief whether this edge is an Off-Ramp or leads to one1847bool myIsOffRamp;18481849/// @brief whether this edge is part of a non-rail bidi edge pair1850bool myIsBidi;18511852/// @brief the index of the edge in the list of all edges. Set by NBEdgeCont and requires re-set whenever the list of edges changes1853int myIndex;18541855// @brief a static list of successor edges. Set by NBEdgeCont and requires reset when the network changes1856mutable EdgeVector mySuccessors;18571858// @brief a static list of successor edges. Set by NBEdgeCont and requires reset when the network changes1859mutable ConstRouterEdgePairVector myViaSuccessors;18601861// @brief default length for overriding connection lengths1862static double myDefaultConnectionLength;18631864public:18651866/// @class connections_toedge_finder1867class connections_toedge_finder {1868public:1869/// @brief constructor1870connections_toedge_finder(const NBEdge* const edge2find, bool hasFromLane = false) :1871myHasFromLane(hasFromLane),1872myEdge2Find(edge2find) { }18731874/// @brief operator ()1875bool operator()(const Connection& c) const {1876return c.toEdge == myEdge2Find && (!myHasFromLane || c.fromLane != -1);1877}18781879private:1880/// @brief check if has from lane1881const bool myHasFromLane;18821883/// @brief edge to find1884const NBEdge* const myEdge2Find;1885};18861887/// @class connections_toedgelane_finder1888class connections_toedgelane_finder {1889public:1890/// @brief constructor1891connections_toedgelane_finder(const NBEdge* const edge2find, int lane2find, int fromLane2find) :1892myEdge2Find(edge2find),1893myLane2Find(lane2find),1894myFromLane2Find(fromLane2find) { }18951896/// @brief operator ()1897bool operator()(const Connection& c) const {1898return c.toEdge == myEdge2Find && c.toLane == myLane2Find && (myFromLane2Find < 0 || c.fromLane == myFromLane2Find);1899}19001901private:1902/// @brief edge to find1903const NBEdge* const myEdge2Find;19041905/// @brief lane to find1906int myLane2Find;19071908/// @brief from lane to find1909int myFromLane2Find;1910};19111912/// @class connections_finder1913class connections_finder {1914public:1915/// @brief constructor1916connections_finder(int fromLane, NBEdge* const edge2find, int lane2find, bool invertEdge2find = false) :1917myFromLane(fromLane), myEdge2Find(edge2find), myLane2Find(lane2find), myInvertEdge2find(invertEdge2find) { }19181919/// @brief operator ()1920bool operator()(const Connection& c) const {1921return ((c.fromLane == myFromLane || myFromLane == -1)1922&& ((!myInvertEdge2find && c.toEdge == myEdge2Find) || (myInvertEdge2find && c.toEdge != myEdge2Find))1923&& (c.toLane == myLane2Find || myLane2Find == -1));1924}19251926private:1927/// @brief index of from lane1928int myFromLane;19291930/// @brief edge to find1931NBEdge* const myEdge2Find;19321933/// @brief lane to find1934int myLane2Find;19351936/// @brief invert edge to find1937bool myInvertEdge2find;1938};19391940/// @class connections_conflict_finder1941class connections_conflict_finder {1942public:1943/// @brief constructor1944connections_conflict_finder(int fromLane, NBEdge* const edge2find, bool checkRight) :1945myFromLane(fromLane), myEdge2Find(edge2find), myCheckRight(checkRight) { }19461947/// @brief operator ()1948bool operator()(const Connection& c) const {1949return (((myCheckRight && c.fromLane < myFromLane) || (!myCheckRight && c.fromLane > myFromLane))1950&& c.fromLane >= 0 // already assigned1951&& c.toEdge == myEdge2Find);1952}19531954private:1955/// @brief index of from lane1956int myFromLane;19571958/// @brief edge to find1959NBEdge* const myEdge2Find;19601961/// @brief check if is right1962bool myCheckRight;1963};19641965/// @class connections_fromlane_finder1966class connections_fromlane_finder {1967public:1968/// @briefconstructor1969connections_fromlane_finder(int lane2find) : myLane2Find(lane2find) { }19701971/// @brief operator ()1972bool operator()(const Connection& c) const {1973return c.fromLane == myLane2Find;1974}19751976private:1977/// @brief index of lane to find1978int myLane2Find;19791980private:1981/// @brief invalidated assignment operator1982connections_fromlane_finder& operator=(const connections_fromlane_finder& s) = delete;1983};19841985/// @brief connections_sorter sort by fromLane, toEdge and toLane1986static bool connections_sorter(const Connection& c1, const Connection& c2);19871988/**1989* @class connections_relative_edgelane_sorter1990* @brief Class to sort edges by their angle1991*/1992class connections_relative_edgelane_sorter {1993public:1994/// @brief constructor1995explicit connections_relative_edgelane_sorter(NBEdge* e) : myEdge(e) {}19961997public:1998/// @brief comparing operation1999int operator()(const Connection& c1, const Connection& c2) const;20002001private:2002/// @brief the edge to compute the relative angle of2003NBEdge* myEdge;2004};20052006private:2007/// @brief invalidated copy constructor2008NBEdge(const NBEdge& s) = delete;20092010/// @brief invalidated assignment operator2011NBEdge& operator=(const NBEdge& s) = delete;20122013/// @brief constructor for dummy edge2014NBEdge();2015};201620172018