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