1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    NBNode.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Yun-Pang Floetteroed
14 /// @author  Michael Behrisch
15 /// @date    Tue, 20 Nov 2001
16 /// @version $Id$
17 ///
18 // The representation of a single node
19 /****************************************************************************/
20 #ifndef NBNode_h
21 #define NBNode_h
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #include <config.h>
28 
29 #include <vector>
30 #include <deque>
31 #include <utility>
32 #include <string>
33 #include <set>
34 #include <utils/common/StdDefs.h>
35 #include <utils/common/Named.h>
36 #include <utils/geom/Bresenham.h>
37 #include <utils/geom/GeomHelper.h>
38 #include <utils/common/VectorHelper.h>
39 #include <utils/geom/Position.h>
40 #include <utils/geom/PositionVector.h>
41 #include <utils/xml/SUMOXMLDefinitions.h>
42 #include "NBEdge.h"
43 #include "NBConnection.h"
44 #include "NBConnectionDefs.h"
45 #include "NBContHelper.h"
46 
47 
48 // ===========================================================================
49 // class declarations
50 // ===========================================================================
51 class NBRequest;
52 class NBDistrict;
53 class OptionsCont;
54 class NBTrafficLightDefinition;
55 class NBTypeCont;
56 class NBTrafficLightLogicCont;
57 class NBDistrictCont;
58 class OutputDevice;
59 
60 
61 // ===========================================================================
62 // class definitions
63 // ===========================================================================
64 /**
65  * @class NBNode
66  * @brief Represents a single node (junction) during network building
67  */
68 class NBNode : public Named, public Parameterised {
69     friend class NBNodeCont;
70     friend class GNEJunction;            // < used for visualization (NETEDIT)
71     friend class NBNodesEdgesSorter;     // < sorts the edges
72     friend class NBNodeTypeComputer;     // < computes type
73     friend class NBEdgePriorityComputer; // < computes priorities of edges per intersection
74     friend class NBNodeShapeComputer;    // < computes node's shape
75 
76 public:
77     /**
78      * @class ApproachingDivider
79      * @brief Computes lane-2-lane connections
80      *
81      * Being a bresenham-callback, this class computes which lanes
82      *  are approached by the current lane (first callback parameter).
83      * The second callback parameter is the destination lane that is the
84      *  middle of the computed lanes.
85      * The lanes are spreaded from this middle position both to left and right
86      *  but may also be transposed in full when there is not enough space.
87      */
88     class ApproachingDivider : public Bresenham::BresenhamCallBack {
89     public:
90         /**@brief Constructor
91          * @param[in] approaching The list of the edges that approach the outgoing edge
92          * @param[in] currentOutgoing The outgoing edge
93          */
94         ApproachingDivider(const EdgeVector& approaching, NBEdge* currentOutgoing);
95 
96         /// @brief Destructor
97         ~ApproachingDivider();
98 
99         /// @ get number of avaliable lanes
numAvailableLanes()100         int numAvailableLanes() const {
101             return (int)myAvailableLanes.size();
102         }
103 
104         /// @brief the bresenham-callback
105         void execute(const int src, const int dest);
106 
107         /// @brief the method that spreads the wished number of lanes from the the lane given by the bresenham-call to both left and right
108         std::deque<int>* spread(const std::vector<int>& approachingLanes, int dest) const;
109 
110     private:
111         /// @brief The list of edges that approach the current edge
112         const EdgeVector& myApproaching;
113 
114         /// @brief The approached current edge
115         NBEdge* myCurrentOutgoing;
116 
117         /// @brief The available lanes to which connections shall be built
118         std::vector<int> myAvailableLanes;
119 
120         /// @brief whether the outgoing edge is exclusively used by bikes
121         bool myIsBikeEdge;
122 
123     private:
124         /// @brief Invalidated assignment operator.
125         ApproachingDivider& operator=(const ApproachingDivider&) = delete;
126 
127     };
128 
129     /** @struct Crossing
130      * @brief A definition of a pedestrian crossing
131      */
132     struct Crossing : public Parameterised {
133         /// @brief constructor
134         Crossing(const NBNode* _node, const EdgeVector& _edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector& _customShape);
135         /// @brief The parent node of this crossing
136         const NBNode* node;
137         /// @brief The edges being crossed
138         EdgeVector edges;
139         /// @brief The crossing's shape
140         PositionVector shape;
141         /// @brief This crossing's width
142         double customWidth;
143         /// @brief This crossing's width
144         double width;
145         /// @brief the (edge)-id of this crossing
146         std::string id;
147         /// @brief the lane-id of the previous walkingArea
148         std::string prevWalkingArea;
149         /// @brief the lane-id of the next walkingArea
150         std::string nextWalkingArea;
151         /// @brief whether the pedestrians have priority
152         bool priority;
153         /// @brief optional customShape for this crossing
154         PositionVector customShape;
155         /// @brief the traffic light index of this crossing (if controlled)
156         int tlLinkIndex;
157         int tlLinkIndex2;
158         /// @brief the custom traffic light index of this crossing (if controlled)
159         int customTLIndex;
160         int customTLIndex2;
161         /// @brief The id of the traffic light that controls this connection
162         std::string tlID;
163         /// @brief whether this crossing is valid (and can be written to the net.xml). This is needed for netedit because validity can only be checked during junction computation
164         bool valid;
165     };
166 
167 
168     /** @struct WalkingArea
169      * @brief A definition of a pedestrian walking area
170      */
171     struct WalkingArea {
172         /// @brief constructor
WalkingAreaWalkingArea173         WalkingArea(const std::string& _id, double _width) :
174             id(_id),
175             width(_width),
176             hasCustomShape(false),
177             minNextCrossingEdges(std::numeric_limits<int>::max()),
178             minPrevCrossingEdges(std::numeric_limits<int>::max()) {
179         }
180         /// @brief the (edge)-id of this walkingArea
181         std::string id;
182         /// @brief This lane's width
183         double width;
184         /// @brief This lane's width
185         double length;
186         /// @brief The polygonal shape
187         PositionVector shape;
188         /// @brief the lane-id of the next crossing(s)
189         std::vector<std::string> nextCrossings;
190         /// @brief the lane-id of the next sidewalk lane or ""
191         std::vector<std::string> nextSidewalks;
192         /// @brief the lane-id of the previous sidewalk lane or ""
193         std::vector<std::string> prevSidewalks;
194         /// @brief whether this walkingArea has a custom shape
195         bool hasCustomShape;
196         /// @brief minimum number of edges crossed by nextCrossings
197         int minNextCrossingEdges;
198         /// @brief minimum number of edges crossed by incoming crossings
199         int minPrevCrossingEdges;
200     };
201 
202     struct WalkingAreaCustomShape {
203         std::set<const NBEdge*, ComparatorIdLess> edges;
204         PositionVector shape;
205     };
206 
207     /// @brief edge directions (for pedestrian related stuff)
208     static const int FORWARD;
209     static const int BACKWARD;
210 
211     /// @brief unspecified lane width
212     static const double UNSPECIFIED_RADIUS;
213 
214     /// @brief flags for controlling shape generation
215     static const int AVOID_WIDE_RIGHT_TURN;
216     static const int AVOID_WIDE_LEFT_TURN;
217     static const int FOUR_CONTROL_POINTS;
218     static const int AVOID_INTERSECTING_LEFT_TURNS;
219 
220 public:
221     /**@brief Constructor
222      * @param[in] id The id of the node
223      * @param[in] position The position of the node
224      * @param[in] type The type of the node
225      */
226     NBNode(const std::string& id, const Position& position, SumoXMLNodeType type);
227 
228     /**@brief Constructor
229      * @param[in] id The id of the node
230      * @param[in] position The position of the node
231      * @param[in] district The district this district node represents, 0 means no district node
232      */
233     NBNode(const std::string& id, const Position& position, NBDistrict* district = 0);
234 
235     /// @brief Destructor
236     ~NBNode();
237 
238     /**@brief Resets initial values
239      * @param[in] position The position of the node
240      * @param[in] type The type of the node
241      * @param[in] updateEdgeGeometries Whether the geometires of all
242      *    connected edges shall be updated
243      */
244     void reinit(const Position& position, SumoXMLNodeType type,
245                 bool updateEdgeGeometries = false);
246 
247     /// @name Atomar getter methods
248     /// @{
249     /// @brief Returns the position of this node
getPosition()250     const Position& getPosition() const {
251         return myPosition;
252     }
253 
254     /// @brief Returns a position that is guaranteed to lie within the node shape
255     Position getCenter() const;
256 
257     /// @brief Returns this node's incoming edges (The edges which yield in this node)
getIncomingEdges()258     const EdgeVector& getIncomingEdges() const {
259         return myIncomingEdges;
260     }
261 
262     /// @brief Returns this node's outgoing edges (The edges which start at this node)
getOutgoingEdges()263     const EdgeVector& getOutgoingEdges() const {
264         return myOutgoingEdges;
265     }
266 
267     /// @brief Returns all edges which participate in this node (Edges that start or end at this node)
getEdges()268     const EdgeVector& getEdges() const {
269         return myAllEdges;
270     }
271 
272     /**@brief Returns the type of this node
273      * @see SumoXMLNodeType
274      */
getType()275     SumoXMLNodeType getType() const {
276         return myType;
277     }
278 
279     /// @brief Returns the turning radius of this node
getRadius()280     double getRadius() const {
281         return myRadius;
282     }
283 
284     /// @brief Returns the keepClear flag
getKeepClear()285     bool getKeepClear() const {
286         return myKeepClear;
287     }
288 
289     /// @brief Returns hint on how to compute right of way
getRightOfWay()290     RightOfWay getRightOfWay() const {
291         return myRightOfWay;
292     }
293 
294     /// @brief Returns fringe type
getFringeType()295     FringeType getFringeType() const {
296         return myFringeType;
297     }
298     /// @}
299 
300     /// @name Methods for dealing with assigned traffic lights
301     /// @{
302     /**@brief Adds a traffic light to the list of traffic lights that control this node
303      * @param[in] tld The traffic light that controls this node
304      */
305     void addTrafficLight(NBTrafficLightDefinition* tlDef);
306 
307     /// @brief Removes the given traffic light from this node
308     void removeTrafficLight(NBTrafficLightDefinition* tlDef);
309 
310     /// @brief Removes all references to traffic lights that control this tls
311     void removeTrafficLights();
312 
313     /**@brief Returns whether this node is controlled by any tls
314      * @return Whether a traffic light was assigned to this node
315      */
isTLControlled()316     bool isTLControlled() const {
317         return myTrafficLights.size() != 0;
318     }
319 
320     /// @brief Returns the traffic lights that were assigned to this node (The set of tls that control this node)
getControllingTLS()321     const std::set<NBTrafficLightDefinition*>& getControllingTLS() const {
322         return myTrafficLights;
323     }
324 
325     /// @brief causes the traffic light to be computed anew
326     void invalidateTLS(NBTrafficLightLogicCont& tlCont, bool removedConnections, bool addedConnections);
327 
328     /// @brief patches loaded signal plans by modifying lane indices above threshold by the given offset
329     void shiftTLConnectionLaneIndex(NBEdge* edge, int offset, int threshold = -1);
330     /// @}
331 
332 
333     /// @name Prunning the input
334     /// @{
335 
336     /**@brief Removes edges which are both incoming and outgoing into this node
337      *
338      * If given, the connections to other edges participating in this node are updated
339      *
340      * @param[in, opt. changed] dc The districts container to update
341      * @param[in, opt. changed] ec The edge container to remove the edges from
342      * @param[in, opt. changed] tc The traffic lights container to update
343      * @return The number of removed edges
344      */
345     int removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc);
346     /// @}
347 
348 
349     /// @name Applying offset
350     /// @{
351     /**@brief Applies an offset to the node
352      * @param[in] xoff The x-offset to apply
353      * @param[in] yoff The y-offset to apply
354      */
355     void reshiftPosition(double xoff, double yoff);
356 
357     /// @brief mirror coordinates along the x-axis
358     void mirrorX();
359     /// @}
360 
361     /// @brief adds an incoming edge
362     void addIncomingEdge(NBEdge* edge);
363 
364     /// @brief adds an outgoing edge
365     void addOutgoingEdge(NBEdge* edge);
366 
367     /// @brief computes the connections of lanes to edges
368     void computeLanes2Lanes();
369 
370     /// @brief computes the node's type, logic and traffic light
371     void computeLogic(const NBEdgeCont& ec, OptionsCont& oc);
372 
373     /// @brief compute right-of-way logic for all lane-to-lane connections
374     void computeLogic2(bool checkLaneFoes);
375 
376     /// @brief writes the XML-representation of the logic as a bitset-logic XML representation
377     bool writeLogic(OutputDevice& into) const;
378 
379     const std::string getFoes(int linkIndex) const;
380     const std::string getResponse(int linkIndex) const;
381 
382     /// @brief Returns something like the most unused direction Should only be used to add source or sink nodes
383     Position getEmptyDir() const;
384 
385     /**@brief Returns whether the given edge ends at this node
386      * @param[in] e The edge
387      * @return Whether the given edge is one of this node's incoming edges
388      */
389     bool hasIncoming(const NBEdge* const e) const;
390 
391     /**@brief Returns whether the given edge starts at this node
392      * @param[in] e The edge
393      * @return Whether the given edge is one of this node's outgoing edges
394      */
395     bool hasOutgoing(const NBEdge* const e) const;
396 
397     /// @brief returns the opposite incoming edge of certain edge
398     NBEdge* getOppositeIncoming(NBEdge* e) const;
399 
400     /// @brief invalidate incoming connections
401     void invalidateIncomingConnections();
402 
403     /// @brief invalidate outgoing connections
404     void invalidateOutgoingConnections();
405 
406     /// @brief remove duble edges
407     void removeDoubleEdges();
408 
409     /// @brief get connection to certain node
410     NBEdge* getConnectionTo(NBNode* n) const;
411 
412     /// @brief add shorted link FOES
413     void addSortedLinkFoes(const NBConnection& mayDrive, const NBConnection& mustStop);
414 
415     /// @brief get possibly splitted incoming  edge
416     NBEdge* getPossiblySplittedIncoming(const std::string& edgeid);
417 
418     /// @brief get possibly splitted outgoing edge
419     NBEdge* getPossiblySplittedOutgoing(const std::string& edgeid);
420 
421     /// @brief Removes edge from this node and optionally removes connections as well
422     void removeEdge(NBEdge* edge, bool removeFromConnections = true);
423 
424     /**@brief Computes whether the given connection is a left mover across the junction
425      *
426      * It is assumed, that it is a left-mover if the clockwise angle is lower
427      *  than the counter-clockwise angle.
428      *
429      * @param[in] from The incoming edge (the begin of the connection)
430      * @param[in] from The outgoing edge (the end of the connection)
431      * @return Whether the described connection is a left-mover
432      */
433     bool isLeftMover(const NBEdge* const from, const NBEdge* const to) const;
434 
435     /**@brief Returns the information whether the described flow must let any other flow pass
436      * @param[in] from The connection's start edge
437      * @param[in] to The connection's end edge
438      * @param[in] fromLane The lane the connection start at
439      * @param[in] toLane The lane the connection ends at
440      * @param[in] includePedCrossings Whether braking due to a pedestrian crossing counts
441      * @return Whether the described connection must brake (has higher priorised foes)
442      */
443     bool mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const;
444 
445     /**@brief Returns the information whether the described flow must brake for the given crossing
446      * @param[in] from The connection's start edge
447      * @param[in] to The connection's end edge
448      * @param[in] crossing The pedestrian crossing to check
449      * @return Whether the described connection must brake (has higher priorised foes)
450      */
451     bool mustBrakeForCrossing(const NBEdge* const from, const NBEdge* const to, const Crossing& crossing) const;
452 
453     /// @brief return whether the given laneToLane connection is a right turn which must yield to a bicycle crossings
454     static bool rightTurnConflict(const NBEdge* from, const NBEdge* to, int fromLane,
455                                   const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorFromLane,
456                                   bool lefthand = false);
457 
458     /// @brief return whether the given laneToLane connection originate from the same edge and are in conflict due to turning across each other
459     bool turnFoes(const NBEdge* from, const NBEdge* to, int fromLane,
460                   const NBEdge* from2, const NBEdge* to2, int fromLane2,
461                   bool lefthand = false) const;
462 
463     /**@brief Returns the information whether "prohibited" flow must let "prohibitor" flow pass
464      * @param[in] possProhibitedFrom The maybe prohibited connection's begin
465      * @param[in] possProhibitedTo The maybe prohibited connection's end
466      * @param[in] possProhibitorFrom The maybe prohibiting connection's begin
467      * @param[in] possProhibitorTo The maybe prohibiting connection's end
468      * @param[in] regardNonSignalisedLowerPriority Whether the right of way rules without traffic lights shall be regarded
469      * @return Whether the second flow prohibits the first one
470      */
471     bool forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
472                  const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
473                  bool regardNonSignalisedLowerPriority) const;
474 
475     /**@brief Returns the information whether the given flows cross
476      * @param[in] from1 The starting edge of the first stream
477      * @param[in] to1 The ending edge of the first stream
478      * @param[in] from2 The starting edge of the second stream
479      * @param[in] to2 The ending edge of the second stream
480      * @return Whether both stream are foes (cross)
481      */
482     bool foes(const NBEdge* const from1, const NBEdge* const to1,
483               const NBEdge* const from2, const NBEdge* const to2) const;
484 
485     /**@brief Returns the representation of the described stream's direction
486      * @param[in] incoming The edge the stream starts at
487      * @param[in] outgoing The edge the stream ends at
488      * @param[in] leftHand Whether a lefthand network is being built. Should only be set at writing time
489      * @return The direction of the stream
490      */
491     LinkDirection getDirection(const NBEdge* const incoming, const NBEdge* const outgoing, bool leftHand = false) const;
492 
493     /// @brief get link state
494     LinkState getLinkState(const NBEdge* incoming, NBEdge* outgoing,
495                            int fromLane, int toLane, bool mayDefinitelyPass, const std::string& tlID) const;
496 
497     /**@brief Compute the junction shape for this node
498      * @param[in] mismatchThreshold The threshold for warning about shapes which are away from myPosition
499      */
500     void computeNodeShape(double mismatchThreshold);
501 
502     /// @brief retrieve the junction shape
503     const PositionVector& getShape() const;
504 
505     /// @brief set the junction shape
506     void setCustomShape(const PositionVector& shape);
507 
508     /// @brief set the turning radius
setRadius(double radius)509     void setRadius(double radius) {
510         myRadius = radius;
511     }
512 
513     /// @brief set the keepClear flag
setKeepClear(bool keepClear)514     void setKeepClear(bool keepClear) {
515         myKeepClear = keepClear;
516     }
517 
518     /// @brief set method for computing right-of-way
setRightOfWay(RightOfWay rightOfWay)519     void setRightOfWay(RightOfWay rightOfWay) {
520         myRightOfWay = rightOfWay;
521     }
522 
523     /// @brief set method for computing right-of-way
setFringeType(FringeType fringeType)524     void setFringeType(FringeType fringeType) {
525         myFringeType = fringeType;
526     }
527 
528     /// @brief return whether the shape was set by the user
hasCustomShape()529     bool hasCustomShape() const {
530         return myHaveCustomPoly;
531     }
532 
533     /// @brief check if node is removable
534     bool checkIsRemovable() const;
535 
536     /// @brief check if node is removable and return reason if not
537     bool checkIsRemovableReporting(std::string& reason) const;
538 
539     /// @brief get edges to join
540     std::vector<std::pair<NBEdge*, NBEdge*> > getEdgesToJoin() const;
541 
542     /// @chech if node is near district
543     bool isNearDistrict() const;
544 
545     /// @brief check if node is a district
546     bool isDistrict() const;
547 
548     /// @brief whether an internal junction should be built at from and respect other
549     bool needsCont(const NBEdge* fromE, const NBEdge* otherFromE,
550                    const NBEdge::Connection& c, const NBEdge::Connection& otherC) const;
551 
552     /// @brief whether the connection must yield if the foe remains on the intersection after its phase ends
553     bool tlsContConflict(const NBEdge* from, const NBEdge::Connection& c,
554                          const NBEdge* foeFrom, const NBEdge::Connection& foe) const;
555 
556 
557     /**@brief Compute the shape for an internal lane
558      * @param[in] fromE The starting edge
559      * @param[in] con The connection for this internal lane
560      * @param[in] numPoints The number of geometry points for the internal lane
561      * @param[in] recordError The node itself if the displacement error during shape computation shall be recorded
562      * @return The shape of the internal lane
563      */
564     PositionVector computeInternalLaneShape(NBEdge* fromE, const NBEdge::Connection& con, int numPoints, NBNode* recordError = 0, int shapeFlag = 0) const;
565 
566     /**@brief Compute a smooth curve between the given geometries
567      * @param[in] begShape The geometry at the start
568      * @param[in] endShape The geometry at the end
569      * @param[in] numPoints The number of geometry points for the internal lane
570      * @param[in] isTurnaround Whether this shall be the shape for a turnaround
571      * @param[in] extrapolateBeg Extrapolation distance at the beginning
572      * @param[in] extrapolateEnd Extrapolation distance at the end
573      * @param[in] recordError The node itself if the displacement error during shape computation shall be recorded
574      * @return The shape of the internal lane
575      */
576     PositionVector computeSmoothShape(const PositionVector& begShape, const PositionVector& endShape, int numPoints,
577                                       bool isTurnaround, double extrapolateBeg, double extrapolateEnd,
578                                       NBNode* recordError = 0, int shapeFlag = 0) const;
579     /// @brief get bezier control points
580     static PositionVector bezierControlPoints(const PositionVector& begShape, const PositionVector& endShape,
581             bool isTurnaround, double extrapolateBeg, double extrapolateEnd,
582             bool& ok, NBNode* recordError = 0, double straightThresh = DEG2RAD(5),
583             int shapeFlag = 0);
584 
585 
586     /// @brief compute the displacement error during s-curve computation
getDisplacementError()587     double getDisplacementError() const {
588         return myDisplacementError;
589     }
590 
591     /// @brief Replaces occurences of the first edge within the list of incoming by the second Connections are remapped, too
592     void replaceIncoming(NBEdge* which, NBEdge* by, int laneOff);
593 
594     /// @brief Replaces occurences of every edge from the given list within the list of incoming by the second Connections are remapped, too
595     void replaceIncoming(const EdgeVector& which, NBEdge* by);
596 
597     /// @brief Replaces occurences of the first edge within the list of outgoing by the second Connections are remapped, too
598     void replaceOutgoing(NBEdge* which, NBEdge* by, int laneOff);
599 
600     /// @brief Replaces occurences of every edge from the given list within the list of outgoing by the second Connections are remapped, too
601     void replaceOutgoing(const EdgeVector& which, NBEdge* by);
602 
603     /// @brief guess pedestrian crossings and return how many were guessed
604     int guessCrossings();
605 
606     /* @brief check whether a crossing should be build for the candiate edges and build 0 to n crossings
607      * @param[in] candidates The candidate vector of edges to be crossed
608      * @return The number of crossings built
609      * */
610     int checkCrossing(EdgeVector candidates);
611 
612     /// @brief return true if there already exist a crossing with the same edges as the input
613     bool checkCrossingDuplicated(EdgeVector edges);
614 
615     /// @brief build internal lanes, pedestrian crossings and walking areas
616     void buildInnerEdges();
617 
618     /**@brief build pedestrian crossings
619      * @return The next index for creating internal lanes
620      **/
621     int buildCrossings();
622 
623     /**@brief build pedestrian walking areas and set connections from/to walkingAreas
624      * @param[in] cornerDetail The detail level when generating the inner curve
625      */
626     void buildWalkingAreas(int cornerDetail);
627 
628     /// @brief build crossings, and walkingareas. Also removes invalid loaded crossings if wished
629     void buildCrossingsAndWalkingAreas();
630 
631     /// @brief return all edges that lie clockwise between the given edges
632     EdgeVector edgesBetween(const NBEdge* e1, const NBEdge* e2) const;
633 
634     /// @brief return true if the given edges are connected by a crossing
635     bool crossingBetween(const NBEdge* e1, const NBEdge* e2) const;
636 
637     /// @brief get prohibitions (BLocked connections)
getProhibitions()638     const NBConnectionProhibits& getProhibitions() {
639         return myBlockedConnections;
640     }
641 
642     /// @brief whether this is structurally similar to a geometry node
643     bool geometryLike() const;
644     bool geometryLike(const EdgeVector& incoming, const EdgeVector& outgoing) const;
645 
646     /// @brief update the type of this node as a roundabout
647     void setRoundabout();
648 
649     /// @brief add a pedestrian crossing to this node
650     NBNode::Crossing* addCrossing(EdgeVector edges, double width, bool priority, int tlIndex = -1, int tlIndex2 = -1,
651                                   const PositionVector& customShape = PositionVector::EMPTY, bool fromSumoNet = false);
652 
653     /// @brief add custom shape for walkingArea
654     void addWalkingAreaShape(EdgeVector edges, const PositionVector& shape);
655 
656     /// @brief remove a pedestrian crossing from this node (identified by its edges)
657     void removeCrossing(const EdgeVector& edges);
658 
659     /// @brief discard all current (and optionally future) crossings
660     void discardAllCrossings(bool rejectAll);
661 
662     /// @brief discard previously built walkingareas (required for repeated computation by netedit)
663     void discardWalkingareas();
664 
665     /// @brief get num of crossings from sumo net
numCrossingsFromSumoNet()666     int numCrossingsFromSumoNet() const {
667         return myCrossingsLoadedFromSumoNet;
668     }
669 
670     /// @brief return this junctions pedestrian crossings
671     std::vector<Crossing*> getCrossings() const;
getCrossingsIncludingInvalid()672     inline const std::vector<Crossing*>& getCrossingsIncludingInvalid() const {
673         return myCrossings;
674     }
675 
676     /// @brief return this junctions pedestrian walking areas
getWalkingAreas()677     inline const std::vector<WalkingArea>& getWalkingAreas() const {
678         return myWalkingAreas;
679     }
680 
getWalkingAreaCustomShapes()681     const std::vector<WalkingAreaCustomShape>& getWalkingAreaCustomShapes() const {
682         return myWalkingAreaCustomShapes;
683     }
684 
685     /// @brief return the crossing with the given id
686     Crossing* getCrossing(const std::string& id) const;
687 
688     /// @brief return the crossing with the given Edges
689     Crossing* getCrossing(const EdgeVector& edges, bool hardFail = true) const;
690 
691     /* @brief set tl indices of this nodes crossing starting at the given index
692      * @return Whether a custom index was used
693      */
694     bool setCrossingTLIndices(const std::string& tlID, int startIndex);
695 
696     /// @brief return the number of lane-to-lane connections at this junction (excluding crossings)
697     int numNormalConnections() const;
698 
699     /// @brief fix overlap
700     void avoidOverlap();
701 
702     /// @brief whether the given index must yield to the foeIndex while turing right on a red light
703     bool rightOnRedConflict(int index, int foeIndex) const;
704 
705     /// @brief sort all edge containers for this node
706     void sortEdges(bool useNodeShape);
707 
708     /// @brief return the index of the given connection
709     int getConnectionIndex(const NBEdge* from, const NBEdge::Connection& con) const;
710 
711     /**
712      * @class nodes_by_id_sorter
713      * @brief Used for sorting the cells by the begin time they describe
714      */
715     class nodes_by_id_sorter {
716     public:
717         /// @brief Constructor
nodes_by_id_sorter()718         explicit nodes_by_id_sorter() { }
719 
720         /// @brief Comparing operator
operator()721         int operator()(NBNode* n1, NBNode* n2) const {
722             return n1->getID() < n2->getID();
723         }
724     };
725 
726     /** @class edge_by_direction_sorter
727      * @brief Sorts outgoing before incoming edges
728      */
729     class edge_by_direction_sorter {
730     public:
731         /// @brief constructor
edge_by_direction_sorter(NBNode * n)732         explicit edge_by_direction_sorter(NBNode* n) : myNode(n) {}
733 
734         /// @brief operator of selection
operator()735         int operator()(NBEdge* e1, NBEdge* e2) const {
736             UNUSED_PARAMETER(e2);
737             return e1->getFromNode() == myNode;
738         }
739 
740     private:
741         /// @brief The node to compute the relative angle of
742         NBNode* myNode;
743 
744     };
745 
746     /// @brief returns the node id for internal lanes, crossings and walkingareas
747     static std::string getNodeIDFromInternalLane(const std::string id);
748 
749 
750     /// @brief return whether the given type is a traffic light
751     static bool isTrafficLight(SumoXMLNodeType type);
752 
753     /// @brief check if node is a simple continuation
754     bool isSimpleContinuation(bool checkLaneNumbers = true) const;
755 
756     /// @brief mark whether a priority road turns at this node
markBentPriority(bool isBent)757     void markBentPriority(bool isBent) {
758         myIsBentPriority = isBent;
759     }
760 
761     /// @brief return whether a priority road turns at this node
isBentPriority()762     bool isBentPriority() const {
763         return myIsBentPriority;
764     }
765 
766     /// @brief return whether a priority road turns at this node
typeWasGuessed()767     bool typeWasGuessed() const {
768         return myTypeWasGuessed;
769     }
770 
771     /// @brief detects whether a given junction splits or merges lanes while keeping constant road width
772     bool isConstantWidthTransition() const;
773 
774     /// @brief return list of unique endpoint coordinates of all edges at this node
775     std::vector<std::pair<Position, std::string> > getEndPoints() const;
776 
777 private:
778     /// @brief sets the priorites in case of a priority junction
779     void setPriorityJunctionPriorities();
780 
781     /// @brief returns a list of edges which are connected to the given outgoing edge
782     void getEdgesThatApproach(NBEdge* currentOutgoing, EdgeVector& approaching);
783 
784     /// @brief replace incoming connections prohibitions
785     void replaceInConnectionProhibitions(NBEdge* which, NBEdge* by, int whichLaneOff, int byLaneOff);
786 
787     /// @brief remap removed
788     void remapRemoved(NBTrafficLightLogicCont& tc, NBEdge* removed, const EdgeVector& incoming, const EdgeVector& outgoing);
789 
790     /// @brief return whether there is a non-sidewalk lane after the given index;
791     bool forbidsPedestriansAfter(std::vector<std::pair<NBEdge*, bool> > normalizedLanes, int startIndex);
792 
793     /// @brief returns the list of all edges sorted clockwise by getAngleAtNodeToCenter
794     EdgeVector getEdgesSortedByAngleAtNodeCenter() const;
795 
796     /// @brief check if is long enough
797     static bool isLongEnough(NBEdge* out, double minLength);
798 
799     /// @brief remove all traffic light definitions that are part of a joined tls
800     void removeJoinedTrafficLights();
801 
802     /// @brief displace lane shapes to account for change in lane width at this node
803     void displaceShapeAtWidthChange(const NBEdge* from, const NBEdge::Connection& con, PositionVector& fromShape, PositionVector& toShape) const;
804 
805     /// @brief returns whether sub is a subset of super
806     static bool includes(const std::set<NBEdge*, ComparatorIdLess>& super,
807                          const std::set<const NBEdge*, ComparatorIdLess>& sub);
808 
809 private:
810     /// @brief The position the node lies at
811     Position myPosition;
812 
813     /// @brief Vector of incoming edges
814     EdgeVector myIncomingEdges;
815 
816     /// @brief Vector of outgoing edges
817     EdgeVector myOutgoingEdges;
818 
819     /// @brief Vector of incoming and outgoing edges
820     EdgeVector myAllEdges;
821 
822     /// @brief Vector of crossings
823     std::vector<Crossing*> myCrossings;
824 
825     /// @brief Vector of walking areas
826     std::vector<WalkingArea> myWalkingAreas;
827 
828     /// @brief Vector of custom walking areas shapes
829     std::vector<WalkingAreaCustomShape> myWalkingAreaCustomShapes;
830 
831     /// @brief The type of the junction
832     SumoXMLNodeType myType;
833 
834     /// @brief The container for connection block dependencies
835     NBConnectionProhibits myBlockedConnections;
836 
837     /// @brief The district the node is the centre of
838     NBDistrict* myDistrict;
839 
840     /// @brief the (outer) shape of the junction
841     PositionVector myPoly;
842 
843     /// @brief whether this nodes shape was set by the user
844     bool myHaveCustomPoly;
845 
846     /// @brief Node requests
847     NBRequest* myRequest;
848 
849     /// @brief traffic lights of node
850     std::set<NBTrafficLightDefinition*> myTrafficLights;
851 
852     /// @brief the turning radius (for all corners) at this node in m.
853     double myRadius;
854 
855     /// @brief whether the junction area must be kept clear
856     bool myKeepClear;
857 
858     /// @brief how to compute right of way for this node
859     RightOfWay myRightOfWay;
860 
861     /// @brief fringe type of this node
862     FringeType myFringeType;
863 
864     /// @brief whether to discard all pedestrian crossings
865     bool myDiscardAllCrossings;
866 
867     /// @brief number of crossings loaded from a sumo net
868     int myCrossingsLoadedFromSumoNet;
869 
870     /// @brief geometry error after computation of internal lane shapes
871     double myDisplacementError;
872 
873     /* @brief whether this junction is a bent priority junction (main direction turns)
874      * @note see NBEdgePriorityComputer
875      */
876     bool myIsBentPriority;
877 
878     /// @brief whether the node type was guessed rather than loaded
879     bool myTypeWasGuessed;
880 
881 
882 private:
883     /// @brief invalidated copy constructor
884     NBNode(const NBNode& s);
885 
886     /// @brief invalidated assignment operator
887     NBNode& operator=(const NBNode& s);
888 };
889 
890 
891 #endif
892 
893 /****************************************************************************/
894 
895