Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netbuild/NBNodeCont.h
169666 views
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 NBNodeCont.h
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Yun-Pang Floetteroed
18
/// @author Michael Behrisch
19
/// @author Walter Bamberger
20
/// @date Tue, 20 Nov 2001
21
///
22
// Container for nodes during the netbuilding process
23
/****************************************************************************/
24
#pragma once
25
#include <config.h>
26
27
#include <string>
28
#include <map>
29
#include <vector>
30
#include <set>
31
#include <utils/common/NamedRTree.h>
32
#include <utils/geom/Position.h>
33
#include "NBCont.h"
34
#include "NBEdgeCont.h"
35
#include "NBNode.h"
36
#include <utils/common/UtilExceptions.h>
37
38
39
// ===========================================================================
40
// class declarations
41
// ===========================================================================
42
class NBDistrict;
43
class OptionsCont;
44
class OutputDevice;
45
class NBParkingCont;
46
class NBPTLineCont;
47
class NBPTStopCont;
48
49
50
// ===========================================================================
51
// class definitions
52
// ===========================================================================
53
/**
54
* @class NBNodeCont
55
* @brief Container for nodes during the netbuilding process
56
*/
57
class NBNodeCont {
58
59
public:
60
/// @brief Definition of a node cluster container
61
typedef std::vector<NodeSet> NodeClusters;
62
typedef std::pair<NBNode*, double> NodeAndDist;
63
64
/// @brief Constructor
65
NBNodeCont() {}
66
67
/// @brief Destructor
68
~NBNodeCont();
69
70
/// @name Insertion/removal/retrieval of nodes
71
/// @{
72
/** @brief Inserts a node into the map
73
* @param[in] id The node's id
74
* @param[in] position The node's position
75
* @param[in] A district assigned to the node
76
* @return Whether the node could be added (no other with the same id or position is stored)
77
*/
78
bool insert(const std::string& id, const Position& position, NBDistrict* district = 0);
79
80
/** @brief Inserts a node into the map
81
* @param[in] node The node to insert
82
* @return Whether the node could be added (no other with the same id or position is stored)
83
*/
84
bool insert(NBNode* node);
85
86
/** @brief Removes the given node, deleting it
87
* @param[in] node The node to delete and remove
88
* @return Whether the node could be removed (existed)
89
*/
90
bool erase(NBNode* node);
91
92
/** @brief Removes the given node but does not delete it
93
* @param[in] node The node to delete and remove
94
* @param[in] remember Whether to keep the node for future reference
95
* @return Whether the node could be removed (existed)
96
*/
97
bool extract(NBNode* node, bool remember = false);
98
99
/** @brief Returns the node with the given name
100
* @param[in] id The id of the node to retrieve
101
* @return The node with the given id, or 0 if no such node exists
102
*/
103
NBNode* retrieve(const std::string& id) const;
104
105
/** @brief Returns the node with the given coordinates
106
* @param[in] position The position at which the node to retrieve lies
107
* @param[in] offset An offset which can be applied in the case positions are blurred
108
* @return The node at the given position, or 0 if no such node exists
109
*/
110
std::vector<NBNode*> retrieveByPos(const Position& position, const double offset = 0.) const;
111
112
/// @brief Returns the pointer to the begin of the stored nodes
113
std::map<std::string, NBNode*>::const_iterator begin() const {
114
return myNodes.begin();
115
}
116
117
/// @brief Returns the pointer to the end of the stored nodes
118
std::map<std::string, NBNode*>::const_iterator end() const {
119
return myNodes.end();
120
}
121
/// @}
122
123
/// @name Methods for joining nodes
124
/// @{
125
/* @brief add ids of nodes wich shall not be joined
126
* @param[in] ids A list of ids to exclude from joining
127
* @note it does not check whether the nodes exist because all nodes may not have been loaded yet
128
*/
129
void addJoinExclusion(const std::vector<std::string>& ids);
130
131
/** @brief generate id from cluster node ids
132
* @param[in] cluster The cluster ids
133
* @param[in] prefix The cluster prefix
134
* @return the generated id
135
*/
136
std::string createClusterId(const NodeSet& cluster, const std::string& prefix = "cluster_") {
137
std::set<std::string> clusterIds;
138
for (NBNode* j : cluster) {
139
clusterIds.insert(j->getID());
140
}
141
return createClusterId(clusterIds, prefix);
142
}
143
144
/** @brief generate id from cluster node ids
145
* @param[in] cluster The cluster ids
146
* @param[in] prefix The cluster prefix
147
* @return the generated id
148
*/
149
std::string createClusterId(const std::set<std::string>& cluster, const std::string& prefix = "cluster_");
150
151
/** @brief add ids of nodes which shall be joined into a single node
152
* @param[in] cluster The cluster to add
153
*/
154
void addCluster2Join(const std::set<std::string>& cluster, NBNode* node);
155
156
/// @brief Joins loaded junction clusters (see NIXMLNodesHandler)
157
int joinLoadedClusters(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
158
159
/// @brief Joins junctions that are very close together
160
int joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, NBPTStopCont& sc);
161
162
/// @brief Joins junctions with similar coordinates regardless of topology
163
int joinSameJunctions(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, double maxDist);
164
165
/// @brief return all cluster neighbors for the given node
166
static NodeSet getClusterNeighbors(const NBNode* n, double longThreshold, NodeSet& cluster);
167
168
/// @brief whether the given node may continue a slip lane
169
static bool isSlipLaneContinuation(const NBNode* cont);
170
171
/// @brief check whether the given node maybe the start of a slip lane
172
bool maybeSlipLaneStart(const NBNode* n, EdgeVector& outgoing, double& inAngle) const;
173
/// @brief check whether the given node maybe the end of a slip lane
174
bool maybeSlipLaneEnd(const NBNode* n, EdgeVector& incoming, double& outAngle) const;
175
176
/// @brief try to find a joinable subset (recursively)
177
bool reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, double maxDist, std::vector<NBNode*> cands = std::vector<NBNode*>()) const;
178
179
/// @brief find closest neighbor for building circle
180
NBEdge* shortestEdge(const NodeSet& cluster, const NodeSet& startNodes, const std::vector<NBNode*>& exclude) const;
181
/// @}
182
183
/// @name Adapting the input
184
/// @{
185
/** @brief Removes self-loop edges (edges where the source and the destination node are the same)
186
* @param[in, opt. changed] dc The districts container to update
187
* @param[in, opt. changed] ec The edge container to remove the edges from
188
* @param[in, opt. changed] tc The traffic lights container to update
189
* @post Each edge is a uni-directional connection between two different nodes
190
* @return The number of removed edges
191
*/
192
int removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc);
193
194
/** @brief Joins edges connecting the same nodes
195
* @param[in, opt. changed] dc The districts container to update
196
* @param[in, opt. changed] ec The edge container to remove the edges from
197
* @param[in, opt. changed] tc The traffic lights container to update
198
* @post No two edges with same geometry connecting same nodes exist
199
*/
200
void joinSimilarEdges(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, bool removeDuplicates);
201
202
/// @brief fix overlap
203
void avoidOverlap();
204
205
/** @brief Removes sequences of edges that are not connected with a junction.
206
* Simple roads without junctions sometimes remain when converting from OpenStreetMap,
207
* but they make no sense. Remaining empty nodes are also deleted.
208
*
209
* @param[in, opt. changed] dc The district container needed if edges shall be removed
210
* @param[in, opt. changed] ec The container with the edge to be tested
211
* @return The number of removed edges
212
*/
213
int removeIsolatedRoads(NBDistrictCont& dc, NBEdgeCont& ec);
214
215
/** @brief Checks the network for weak connectivity and removes all but the largest components.
216
* The connectivity check is done regardless of edge direction and vclass.
217
*
218
* @param[in, opt. changed] dc The district container needed if edges shall be removed
219
* @param[in, opt. changed] ec The container with the edge to be tested
220
* @param[in] numKeep The number of components to keep
221
* @return The number of removed edges
222
*/
223
int removeComponents(NBDistrictCont& dc, NBEdgeCont& ec, const int numKeep, bool hasPTStops);
224
225
/* @brief remove rail components after ptstops are built
226
* @return The number of removed edges
227
*/
228
int removeRailComponents(NBDistrictCont& dc, NBEdgeCont& ec, NBPTStopCont& sc);
229
230
/** @brief Removes "unwished" nodes
231
*
232
* Removes nodes if a) no incoming/outgoing edges exist or
233
* b) if the node is a "geometry" node. In the second case,
234
* edges that participate at the node will be joined.
235
* Whether the node is a geometry node or not, is determined
236
* by a call to NBNode::checkIsRemovable.
237
* The node is removed from the list of tls-controlled nodes.
238
* @param[in, opt. changed] dc The district container needed if a node shall be removed
239
* @param[in, opt. changed] ec The edge container needed for joining edges
240
* @param[in, opt. changed] tlc The traffic lights container to remove nodes from
241
* @param[in, opt. changed] sc The pt stops container to update stop edges
242
* @param[in, opt. changed] pc The pt stops container to update stop edges
243
* @param[in] removeGeometryNodes Whether geometry nodes shall also be removed
244
* @return The number of removed nodes
245
*/
246
int removeUnwishedNodes(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc,
247
NBPTStopCont& sc, NBPTLineCont& lc, NBParkingCont& pc,
248
bool removeGeometryNodes);
249
/// @}
250
251
/// @name Methods for guessing/computing traffic lights
252
/// @{
253
/** @brief Guesses which junctions or junction clusters shall be controlled by tls
254
* @param[in] oc The options that steer the guessing process
255
* @param[filled] tlc The traffic lights control into which new traffic light definitions shall be stored
256
* @todo Recheck exception handling
257
*/
258
void guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc);
259
260
/// @brief recheck myGuessedTLS after node logics are computed
261
void recheckGuessedTLS(NBTrafficLightLogicCont& tlc);
262
263
/// @brief check whether a specific guessed tls should keep its type
264
bool recheckTLSThreshold(NBNode* node);
265
266
/// @brief compute keepClear status for all connections
267
void computeKeepClear();
268
269
/** @brief Builds clusters of tls-controlled junctions and joins the control if possible
270
* @param[changed] tlc The traffic lights control for adding/removing new/prior tls
271
* @param[in] maxdist The maximum distance between nodes for clustering
272
* @todo Recheck exception handling
273
*/
274
void joinTLS(NBTrafficLightLogicCont& tlc, double maxdist);
275
276
/** @brief Sets the given node as being controlled by a tls
277
* @param[in] node The node that shall be controlled by a tls
278
* @param[in] tlc The traffic lights control into which the new traffic light definition shall be stored
279
* @param[in] type The type of the new tls
280
* @param[in] id The id of the tls to add
281
* @todo Recheck exception handling
282
*/
283
void setAsTLControlled(NBNode* node, NBTrafficLightLogicCont& tlc, TrafficLightType type, std::string id = "");
284
/// @}
285
286
/// @brief Returns whether the node with the id was deleted explicitly
287
bool wasRemoved(std::string id) const {
288
return myExtractedNodes.count(id) != 0;
289
}
290
291
/// @brief add prefix to all nodes
292
void addPrefix(const std::string& prefix);
293
294
/// @brief Renames the node. Throws exception if newID already exists
295
void rename(NBNode* node, const std::string& newID);
296
297
/// divides the incoming lanes on outgoing lanes
298
void computeLanes2Lanes();
299
300
/// @brief build the list of outgoing edges and lanes
301
void computeLogics(const NBEdgeCont& ec);
302
303
/// @brief compute right-of-way logic for all lane-to-lane connections
304
void computeLogics2(const NBEdgeCont& ec, OptionsCont& oc);
305
306
/// @brief Returns the number of nodes stored in this container
307
int size() const {
308
return (int) myNodes.size();
309
}
310
311
/// @brief deletes all nodes
312
void clear();
313
314
/// @brief generates a new node ID
315
std::string getFreeID();
316
317
/** @brief Compute the junction shape for this node
318
* @param[in] mismatchThreshold The threshold for warning about shapes which are away from myPosition
319
*/
320
void computeNodeShapes(double mismatchThreshold = -1);
321
322
/** @brief Prints statistics about built nodes
323
*
324
* Goes through stored nodes, computes the numbers of unregulated, priority and right-before-left
325
* junctions and prints them.
326
*/
327
void printBuiltNodesStatistics() const;
328
329
/// @brief get all node names
330
std::vector<std::string> getAllNames() const;
331
332
/* @brief analyzes a cluster of nodes which shall be joined
333
* @param[in] cluster The nodes to be joined
334
* @param[out] id The name for the new node
335
* @param[out] pos The position of the new node
336
* @param[out] hasTLS Whether the new node has a traffic light
337
* @param[out] tlType The type of traffic light (if any)
338
*/
339
void analyzeCluster(NodeSet cluster, std::string& id, Position& pos,
340
bool& hasTLS, TrafficLightType& type, SumoXMLNodeType& nodeType);
341
342
/// @brief gets all joined clusters (see doc for myClusters2Join)
343
void registerJoinedCluster(const NodeSet& cluster);
344
void registerJoinedCluster(const std::set<std::string>& cluster);
345
346
/// @brief remove cluster from list (on netedit-undo)
347
void unregisterJoinedCluster(const std::set<std::string>& cluster);
348
349
/// @brief gets all joined clusters (see doc for myClusters2Join)
350
const std::vector<std::set<std::string> >& getJoinedClusters() const {
351
return myJoinedClusters;
352
}
353
354
/* @brief discards traffic lights
355
* @param[in] geometryLike Whether only tls at geometry-like nodes shall be discarded
356
*/
357
void discardTrafficLights(NBTrafficLightLogicCont& tlc, bool geometryLike);
358
359
/// @brief discards rail signals
360
void discardRailSignals();
361
362
/// @brief mark a node as being created form a split
363
void markAsSplit(const NBNode* node) {
364
mySplit.insert(node);
365
}
366
367
/// @brief mark a node as explicitly not controlled by a TLS
368
void markAsNotTLS(const NBNode* node) {
369
myUnsetTLS.insert(node);
370
}
371
372
/// @brief remap node IDs according to options --numerical-ids and --reserved-ids
373
int remapIDs(bool numericaIDs, bool reservedIDs, bool keptIDs, const std::string& prefix, NBTrafficLightLogicCont& tlc);
374
375
/// @brief guess and mark fringe nodes
376
int guessFringe();
377
378
/// @brief apply default values after loading
379
void applyConditionalDefaults();
380
381
/// @brief reset all node shapes
382
bool resetNodeShapes();
383
384
private:
385
386
/// @name Helper methods for for joining nodes
387
/// @{
388
/** @brief Builds node clusters
389
*
390
* A node cluster is made up from nodes which are near by (distance<maxDist) and connected.
391
*
392
* @param[in] maxDist The maximum distance between two nodes for clustering
393
* @param[in, filled] into The container to store the clusters in
394
*/
395
void generateNodeClusters(double maxDist, NodeClusters& into) const;
396
397
/// @brief remove geometry-like fringe nodes from cluster
398
void pruneClusterFringe(NodeSet& cluster, double maxDist, bool remove2TLS = false) const;
399
400
/// @brief avoid removal of long edges when joining junction clusters
401
static int pruneLongEdges(NodeSet& cluster, double maxDist, const bool dryRun = false);
402
403
/// @brief compute the maximum distance between any two cluster nodes
404
static double getDiameter(const NodeSet& cluster);
405
406
/// @brief check whether the node is geometryLike when only considering edges that support the given permissions
407
static bool geometryLikeForClass(const NBNode* n, SVCPermissions permissions);
408
409
/// @brief remove nodes that form a slip lane from cluster
410
void pruneSlipLaneNodes(NodeSet& cluster, double maxDist) const;
411
412
/// @brief determine wether the cluster is not too complex for joining
413
bool feasibleCluster(const NodeSet& cluster, const std::map<const NBNode*, std::vector<NBNode*> >& ptStopEnds,
414
double maxDist, std::string& reason, NBNode*& tryRemove) const;
415
416
/// @brief joins the given node clusters
417
void joinNodeClusters(NodeClusters clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, bool resetConnections = false);
418
void joinNodeCluster(NodeSet clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc,
419
NBNode* predefined = nullptr, bool resetConnections = false);
420
421
/// @}
422
423
/// @name Helper methods for guessing/computing traffic lights
424
/// @{
425
/** @brief Returns whethe the given node cluster should be controlled by a tls
426
* @param[in] c The node cluster
427
* @param[in] laneSpeedThreshold threshold for determining whether a node or cluster should be tls controlled
428
* @return Whether this node cluster shall be controlled by a tls
429
*/
430
bool shouldBeTLSControlled(const NodeSet& c, double laneSpeedThreshold, bool recheck = false) const;
431
432
/// @brief check wheter the set of nodes only contains pedestrian crossings
433
bool onlyCrossings(const NodeSet& c) const;
434
435
/// @brief check wheter the set of nodes contains traffic lights with custom id
436
bool customTLID(const NodeSet& c) const;
437
/// @}
438
439
/// @brief update pareto frontier with the given node
440
void paretoCheck(NBNode* node, NodeSet& frontier, int xSign, int ySign);
441
442
/// @brief Definition of the map of names to nodes
443
typedef std::map<std::string, NBNode*> NodeCont;
444
445
/// @brief The map of names to nodes
446
NodeCont myNodes;
447
448
/// @brief The extracted nodes which are kept for reference
449
NodeCont myExtractedNodes;
450
451
/// @brief set of node ids which should not be joined
452
std::set<std::string> myJoinExclusions;
453
454
/// @brief loaded sets of node ids to join (cleared after use)
455
std::vector<std::pair<std::set<std::string>, NBNode*> > myClusters2Join;
456
457
/// @brief sets of node ids which were joined
458
std::vector<std::set<std::string> > myJoinedClusters;
459
460
/// @brief ids found in loaded join clusters used for error checking
461
std::set<std::string> myJoined;
462
463
/// @brief nodes that were created when splitting an edge
464
std::set<const NBNode*> mySplit;
465
466
/// @brief nodes that received a traffic light due to guessing (--tls.guess)
467
std::set<NBNode*, ComparatorIdLess> myGuessedTLS;
468
469
/// @brief nodes that are excluded from tls-guessing
470
std::set<const NBNode*> myUnsetTLS;
471
472
/// @brief node positions for faster lookup
473
NamedRTree myRTree;
474
475
/// @brief network components that must be removed if not connected to the road network via stop access
476
std::vector<std::vector<std::string> > myRailComponents;
477
478
/// @brief invalidated copy constructor
479
NBNodeCont(const NBNodeCont& s) = delete;
480
481
/// @brief invalidated assignment operator
482
NBNodeCont& operator=(const NBNodeCont& s) = delete;
483
};
484
485