/****************************************************************************/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 GNEEdge.h14/// @author Jakob Erdmann15/// @date Feb 201116///17// A road/street connecting two junctions (netedit-version, adapted from GUIEdge)18// Basically a container for an NBEdge with drawing and editing capabilities19/****************************************************************************/20#pragma once21#include <config.h>2223#include <netbuild/NBEdge.h>24#include <netedit/elements/GNECandidateElement.h>25#include <netedit/elements/moving/GNEMoveResult.h>26#include <utils/gui/div/GUIDottedGeometry.h>27#include <utils/gui/div/GUIGeometry.h>2829#include "GNENetworkElement.h"3031// ===========================================================================32// class declarations33// ===========================================================================3435class GNEConnection;36class GNECrossing;37class GNEEdgeTemplate;38class GNEEdgeType;39class GNEJunction;40class GNELane;41class GNEMoveElementEdge;42class GNEMoveOperation;43class GNENet;44class GNERouteProbe;4546// ===========================================================================47// class definitions48// ===========================================================================4950class GNEEdge : public GNENetworkElement, public GNECandidateElement {5152/// @brief Friend class53friend class GNEChange_Lane;54friend class GNEChange_Connection;55friend class GNEMoveElementEdge;5657public:58/// @brief Definition of the connection's vector59typedef std::vector<GNEConnection*> ConnectionVector;6061/**@brief Constructor62* @param[in] net The net to inform about gui updates63* @param[in] nbe The represented edge64* @param[in] loaded Whether the edge was loaded from a file65*/66GNEEdge(GNENet* net, NBEdge* nbe, bool wasSplit = false, bool loaded = false);6768/// @brief Destructor.69~GNEEdge();7071/// @brief methods to retrieve the elements linked to this edge72/// @{7374/// @brief get GNEMoveElement associated with this edge75GNEMoveElement* getMoveElement() const override;7677/// @brief get parameters associated with this edge78Parameterised* getParameters() override;7980/// @brief get parameters associated with this edge (constant)81const Parameterised* getParameters() const override;8283/// @}8485/// @brief get from Junction (only used to increase readability)86inline GNEJunction* getFromJunction() const {87return getParentJunctions().front();88}8990/// @brief get from Junction (only used to increase readability)91inline GNEJunction* getToJunction() const {92return getParentJunctions().back();93}9495/// @brief check if current network element is valid to be written into XML96bool isNetworkElementValid() const override;9798/// @brief return a string with the current network element problem99std::string getNetworkElementProblem() const override;100101/// @name Functions related with geometry of element102/// @{103104/// @brief update pre-computed geometry information105void updateGeometry() override;106107/// @brief Returns position of hierarchical element in view108Position getPositionInView() const;109110/// @}111112/// @name Function related with contour drawing113/// @{114115/// @brief check if draw from contour (green)116bool checkDrawFromContour() const override;117118/// @brief check if draw from contour (magenta)119bool checkDrawToContour() const override;120121/// @brief check if draw related contour (cyan)122bool checkDrawRelatedContour() const override;123124/// @brief check if draw over contour (orange)125bool checkDrawOverContour() const override;126127/// @brief check if draw delete contour (pink/white)128bool checkDrawDeleteContour() const override;129130/// @brief check if draw delete contour small (pink/white)131bool checkDrawDeleteContourSmall() const override;132133/// @brief check if draw select contour (blue)134bool checkDrawSelectContour() const override;135136/// @brief check if draw move contour (red)137bool checkDrawMoveContour() const override;138139/// @}140141/// @name functions for geometry points142/// @{143/// @brief check if current edge has custom end points144bool hasCustomEndPoints() const;145146/// @brief return true if user clicked over ShapeStart147bool clickedOverShapeStart(const Position& pos) const;148149/// @brief return true if user clicked over ShapeEnd150bool clickedOverShapeEnd(const Position& pos) const;151152/// @brief return true if user clicked over a Geometry Point153bool clickedOverGeometryPoint(const Position& pos) const;154/// @}155156/// @brief update edge geometry after junction move157void updateJunctionPosition(GNEJunction* junction, const Position& origPos);158159/// @name inherited from GUIGlObject160/// @{161/**@brief Returns an own popup-menu162*163* @param[in] app The application needed to build the popup-menu164* @param[in] parent The parent window needed to build the popup-menu165* @return The built popup-menu166* @see GUIGlObject::getPopUpMenu167*/168GUIGLObjectPopupMenu* getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) override;169170/// @brief return exaggeration associated with this GLObject171double getExaggeration(const GUIVisualizationSettings& s) const override;172173/// @brief Returns the boundary to which the view shall be centered in order to show the object174Boundary getCenteringBoundary() const override;175176/// @brief update centering boundary (implies change in RTREE)177void updateCenteringBoundary(const bool updateGrid);178179/// @brief Returns the street name180const std::string getOptionalName() const override;181182/**@brief Draws the object183* @param[in] s The settings for the current view (may influence drawing)184* @see GUIGlObject::drawGL185*/186void drawGL(const GUIVisualizationSettings& s) const override;187188/// @brief delete element189void deleteGLObject() override;190191/// @brief update GLObject (geometry, ID, etc.)192void updateGLObject() override;193194/// @}195196/// @brief returns the internal NBEdge197NBEdge* getNBEdge() const;198199/// @brief get opposite edges200std::vector<GNEEdge*> getOppositeEdges() const;201202/// @brief makes pos the new geometry endpoint at the appropriate end, or remove current existent endpoint203void editEndpoint(Position pos, GNEUndoList* undoList);204205/// @brief restores the endpoint to the junction position at the appropriate end206void resetEndpoint(const Position& pos, GNEUndoList* undoList);207208/// @brief restores both endpoint to the junction position at the appropriate end209void resetBothEndpoint(GNEUndoList* undoList);210211/// @name inherited from GNEAttributeCarrier212/// @{213/* @brief method for getting the Attribute of an XML key214* @param[in] key The attribute key215* @return string with the value associated to key216*/217std::string getAttribute(SumoXMLAttr key) const override;218std::string getAttributeForSelection(SumoXMLAttr key) const override;219220/* @brief method for getting the Attribute of an XML key in double format221* @param[in] key The attribute key222* @return double with the value associated to key223*/224double getAttributeDouble(SumoXMLAttr key) const override;225226/* @brief method for getting the Attribute of an XML key in position format227* @param[in] key The attribute key228* @return position with the value associated to key229*/230Position getAttributePosition(SumoXMLAttr key) const override;231232/* @brief method for getting the Attribute of an XML key in Position format233* @param[in] key The attribute key234* @return position with the value associated to key235*/236PositionVector getAttributePositionVector(SumoXMLAttr key) const override;237238/* @brief method for setting the attribute and letting the object perform additional changes239* @param[in] key The attribute key240* @param[in] value The new value241* @param[in] undoList The undoList on which to register changes242*/243void setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) override;244245/* @brief method for setting the attribute and letting the object perform additional changes246* @param[in] key The attribute key247* @param[in] value The new value248* @param[in] undoList The undoList on which to register changes249*/250bool isValid(SumoXMLAttr key, const std::string& value) override;251252/* @brief method for check if the value for certain attribute is set253* @param[in] key The attribute key254*/255bool isAttributeEnabled(SumoXMLAttr key) const override;256257/* @brief method for check if the value for certain attribute is computed (for example, due a network recomputing)258* @param[in] key The attribute key259*/260bool isAttributeComputed(SumoXMLAttr key) const override;261262/// @}263264/// @brief set responsibility for deleting internal structures265void setResponsible(bool newVal);266267/**@brief update edge geometry and inform the lanes268* @param[in] geom The new geometry269* @param[in] inner Whether geom is only the inner points270*/271void setGeometry(PositionVector geom, bool inner);272273/// @brief get front up shape position274const Position getFrontUpShapePosition() const;275276/// @brief get front down shape position277const Position getFrontDownShapePosition() const;278279/// @brief get back up shape position280const Position getBackUpShapePosition() const;281282/// @brief get back down shape position283const Position getBackDownShapePosition() const;284285/// @brief remake connections286void remakeGNEConnections(bool junctionsReady = false);287288/// @brief copy edge attributes from edgetemplate289void copyTemplate(const GNEEdgeTemplate* edgeTemplate, GNEUndoList* undoList);290291/// @brief copy edge attributes from edgeType292void copyEdgeType(const GNEEdgeType* edgeType, GNEUndoList* undoList);293294/// @brief returns GLIDs of all lanes295std::set<GUIGlID> getLaneGlIDs() const;296297/// @brief returns a reference to the GNEConnection vector298const std::vector<GNEConnection*>& getGNEConnections() const;299300/// @brief get GNEConnection if exist, and if not create it if create is enabled301GNEConnection* retrieveGNEConnection(int fromLane, NBEdge* to, int toLane, bool createIfNoExist = true);302303/// @brief whether this edge was created from a split304bool wasSplit();305306/* @brief compute a splitting position which keeps the resulting edges307* straight unless the user clicked near a geometry point */308Position getSplitPos(const Position& clickPos);309310/// @brief set edge ID311void setEdgeID(const std::string& newID);312313/// @brief check if edge has a restricted lane314bool hasRestrictedLane(SUMOVehicleClass vclass) const;315316// @brief the radius in which to register clicks for geometry nodes317static const double SNAP_RADIUS;318319// @brief the radius in which to register clicks for geometry nodes (Squared)320static const double SNAP_RADIUS_SQUARED;321322/// @brief clear current connections323void clearGNEConnections();324325/// @brief obtain relative positions of RouteProbes326int getRouteProbeRelativePosition(GNERouteProbe* routeProbe) const;327328/// @brief get GNECrossings vinculated with this Edge329std::vector<GNECrossing*> getGNECrossings();330331/// @brief make geometry smooth332void smooth(GNEUndoList* undoList);333334/// @brief interpolate z values linear between junctions335void straightenElevation(GNEUndoList* undoList);336337/// @brief smooth elevation with regard to adjoining edges338void smoothElevation(GNEUndoList* undoList);339340/// @brief return smoothed shape341PositionVector smoothShape(const PositionVector& shape, bool forElevation);342343/// @brief return the first lane that allow a vehicle of type vClass (or the first lane, if none was found)344GNELane* getLaneByAllowedVClass(const SUMOVehicleClass vClass) const;345346/// @brief return the first lane that disallow a vehicle of type vClass (or the first lane, if none was found)347GNELane* getLaneByDisallowedVClass(const SUMOVehicleClass vClass) const;348349// @brief update vehicle spread geometries350void updateVehicleSpreadGeometries();351352// @brief update vehicle geometries353void updateVehicleStackLabels();354355// @brief update person geometries356void updatePersonStackLabels();357358// @brief update vehicle geometries359void updateContainerStackLabels();360361/// @brief check if edge makes a convex angle [0 - 180) degrees362bool isConvexAngle() const;363364/// @brief check if this edge has predecessors (note: only for vehicles, this function ignore walking areas!)365bool hasPredecessors() const;366367/// @brief check if this edge has successors (note: only for vehicles, this function ignore walking areas!)368bool hasSuccessors() const;369370/// @brief get reverse edge (if exist)371GNEEdge* getReverseEdge() const;372373protected:374/// @brief the underlying NBEdge375NBEdge* myNBEdge;376377/// @brief vector with the connections of this edge378ConnectionVector myGNEConnections;379380/// @brief position used for move Lanes381Position myPositionBeforeMoving;382383/// @brief whether we are responsible for deleting myNBNode384bool myAmResponsible;385386/// @brief whether this edge was created from a split387bool myWasSplit;388389/// @brief modification status of the connections390std::string myConnectionStatus;391392private:393/// @brief Stack position (used to stack demand elements over edges)394class StackPosition : public std::pair<double, double> {395396public:397/// @brief constructor398StackPosition(const double departPos, const double length);399400/// @brief get begin position401double beginPosition() const;402403/// @brief get end position404double endPosition() const;405};406407/// @brief Stack demand elements408class StackDemandElements : public std::pair<StackPosition, std::vector<GNEDemandElement*> > {409410public:411/// @brief constructor412StackDemandElements(const StackPosition stackedPosition, GNEDemandElement* demandElement);413414/// @brief add demand elment to current StackDemandElements415void addDemandElements(GNEDemandElement* demandElement);416417/// @brief get stack position418const StackPosition& getStackPosition() const;419420/// @brief get demand elements421const std::vector<GNEDemandElement*>& getDemandElements() const;422};423424/// @brief move element edge425GNEMoveElementEdge* myMoveElementEdge = nullptr;426427/// @brief edge boundary428Boundary myEdgeBoundary;429430/// @brief flag to enable/disable update geometry of lanes (used mainly by setNumLanes)431bool myUpdateGeometry;432433/// @brief set attribute after validation434void setAttribute(SumoXMLAttr key, const std::string& value) override;435436/**@brief changes the number of lanes.437* When reducing the number of lanes, higher-numbered lanes are removed first.438* When increasing the number of lanes, the last known attributes for a lane439* with this number are restored. If none are found the attributes for the440* leftmost lane are copied441*/442void setNumLanes(int numLanes, GNEUndoList* undoList);443444/// @brief update front parent junction445void updateFirstParentJunction(const std::string& value);446447/// @brief update last parent junction448void updateSecondParentJunction(const std::string& value);449450/// @brief@brief increase number of lanes by one use the given attributes and restore the GNELane451void addLane(GNELane* lane, const NBEdge::Lane& laneAttrs, bool recomputeConnections);452453/// @briefdecrease the number of lanes by one. argument is only used to increase robustness (assertions)454void removeLane(GNELane* lane, bool recomputeConnections);455456/// @brief adds a connection457void addConnection(NBEdge::Connection nbCon, bool selectAfterCreation = false);458459/// @brief removes a connection460void removeConnection(NBEdge::Connection nbCon);461462/// @brief remove crossing of junction463void removeEdgeFromCrossings(GNEJunction* junction, GNEUndoList* undoList);464465/// @brief change Shape StartPos466void setShapeStartPos(const Position& pos);467468/// @brief change Shape EndPos469void setShapeEndPos(const Position& pos);470471/// @brief get vehicles a that start over this edge472const std::map<const GNELane*, std::vector<GNEDemandElement*> > getVehiclesOverEdgeMap() const;473474/// @brief get persons a that start over this edge475const std::map<const GNELane*, std::vector<GNEDemandElement*> > getPersonsOverEdgeMap() const;476477/// @brief get containers a that start over this edge478const std::map<const GNELane*, std::vector<GNEDemandElement*> > getContainersOverEdgeMap() const;479480/// @brief draw edge geometry points (note: This function is called by GNELane::drawGL(...)481void drawEdgeGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,482const double layer) const;483484/// @brief draw start extreme geometry point485void drawStartGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,486const double geometryPointRadius, const double layer, const double exaggeration) const;487488/// @brief draw end extreme geometry point489void drawEndGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,490const double geometryPointRadius, const double layer, const double exaggeration) const;491492/// @brief draw edge name493void drawEdgeName(const GUIVisualizationSettings& s) const;494495/// @brief draw edgeStopOffset496void drawLaneStopOffset(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,497const double layer) const;498499/// @brief draw edge shape (only one line)500void drawEdgeShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,501const double layer) const;502503/// @brief draw children504void drawChildrens(const GUIVisualizationSettings& s) const;505506/// @brief calculate contours507void calculateEdgeContour(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,508const double layer) const;509510/// @brief draw TAZElements511void drawTAZElements(const GUIVisualizationSettings& s) const;512513/// @brief check if draw big geometry points514bool drawBigGeometryPoints() const;515516/// @brief check if given stacked positions are overlapped517bool areStackPositionOverlapped(const GNEEdge::StackPosition& vehicleA, const GNEEdge::StackPosition& vehicleB) const;518519/// @brief get geometry point radius520double getGeometryPointRadius() const;521522/// @brief invalidated copy constructor523GNEEdge(const GNEEdge& s) = delete;524525/// @brief invalidated assignment operator526GNEEdge& operator=(const GNEEdge& s) = delete;527};528529530