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