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