1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    NBNodeCont.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Yun-Pang Floetteroed
14 /// @author  Michael Behrisch
15 /// @author  Walter Bamberger
16 /// @date    Tue, 20 Nov 2001
17 /// @version $Id$
18 ///
19 // Container for nodes during the netbuilding process
20 /****************************************************************************/
21 #ifndef NBNodeCont_h
22 #define NBNodeCont_h
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #include <config.h>
29 
30 #include <string>
31 #include <map>
32 #include <vector>
33 #include <set>
34 #include <utils/common/NamedRTree.h>
35 #include <utils/geom/Position.h>
36 #include "NBEdgeCont.h"
37 #include "NBNode.h"
38 #include <utils/common/UtilExceptions.h>
39 
40 
41 // ===========================================================================
42 // class declarations
43 // ===========================================================================
44 class NBDistrict;
45 class OptionsCont;
46 class OutputDevice;
47 class NBParkingCont;
48 class NBPTLineCont;
49 class NBPTStopCont;
50 
51 
52 
53 // ===========================================================================
54 // class definitions
55 // ===========================================================================
56 /**
57  * @class NBNodeCont
58  * @brief Container for nodes during the netbuilding process
59  */
60 class NBNodeCont {
61 public:
62     /// @brief Definition of a node cluster container
63     typedef std::set<NBNode*, ComparatorIdLess> NodeSet;
64     typedef std::vector<NodeSet> NodeClusters;
65     typedef std::pair<NBNode*, double> NodeAndDist;
66 
67     /// @brief Constructor
68     NBNodeCont();
69 
70     /// @brief Destructor
71     ~NBNodeCont();
72 
73     /// @name Insertion/removal/retrieval of nodes
74     /// @{
75     /** @brief Inserts a node into the map
76      * @param[in] id The node's id
77      * @param[in] position The node's position
78      * @param[in] A district assigned to the node
79      * @return Whether the node could be added (no other with the same id or position is stored)
80      */
81     bool insert(const std::string& id, const Position& position, NBDistrict* district = 0);
82 
83     /** @brief Inserts a node into the map
84      * @param[in] node The node to insert
85      * @return Whether the node could be added (no other with the same id or position is stored)
86      */
87     bool insert(NBNode* node);
88 
89     /** @brief Removes the given node, deleting it
90      * @param[in] node The node to delete and remove
91      * @return Whether the node could be removed (existed)
92      */
93     bool erase(NBNode* node);
94 
95     /** @brief Removes the given node but does not delete it
96      * @param[in] node The node to delete and remove
97      * @param[in] remember Whether to keep the node for future reference
98      * @return Whether the node could be removed (existed)
99      */
100     bool extract(NBNode* node, bool remember = false);
101 
102     /** @brief Returns the node with the given name
103      * @param[in] id The id of the node to retrieve
104      * @return The node with the given id, or 0 if no such node exists
105      */
106     NBNode* retrieve(const std::string& id) const;
107 
108     /** @brief Returns the node with the given coordinates
109      * @param[in] position The position at which the node to retrieve lies
110      * @param[in] offset An offset which can be applied in the case positions are blurred
111      * @return The node at the given position, or 0 if no such node exists
112      */
113     NBNode* retrieve(const Position& position, const double offset = 0.) const;
114 
115     /// @brief Returns the pointer to the begin of the stored nodes
begin()116     std::map<std::string, NBNode*>::const_iterator begin() const {
117         return myNodes.begin();
118     }
119 
120     /// @brief Returns the pointer to the end of the stored nodes
end()121     std::map<std::string, NBNode*>::const_iterator end() const {
122         return myNodes.end();
123     }
124     /// @}
125 
126     /// @name Methods for for joining nodes
127     /// @{
128     /* @brief add ids of nodes wich shall not be joined
129      * @param[in] ids A list of ids to exclude from joining
130      * @param[in] check Whether to check if these nodes are known
131      * @note checking is off by default because all nodes may not have been loaded yet
132      */
133     void addJoinExclusion(const std::vector<std::string>& ids, bool check = false);
134 
135     /** @brief add ids of nodes which shall be joined into a single node
136      * @param[in] cluster The cluster to add
137      */
138     void addCluster2Join(std::set<std::string> cluster, NBNode* node);
139 
140     /// @brief Joins loaded junction clusters (see NIXMLNodesHandler)
141     int joinLoadedClusters(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
142 
143     /// @brief Joins junctions that are very close together
144     int joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, NBPTStopCont& sc);
145 
146     /// @brief remove geometry-like fringe nodes from cluster
147     void pruneClusterFringe(NodeSet& cluster) const;
148 
149     /// @brief determine wether the cluster is not too complex for joining
150     bool feasibleCluster(const NodeSet& cluster, const NBEdgeCont& ec, const NBPTStopCont& sc, std::string& reason) const;
151 
152     /// @brief try to find a joinable subset (recursively)
153     bool reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, std::vector<NBNode*> cands = std::vector<NBNode*>()) const;
154 
155     /// @brief find closest neighbor for building circle
156     NBEdge* shortestEdge(const NodeSet& cluster, const NodeSet& startNodes, const std::vector<NBNode*>& exclude) const;
157     /// @}
158 
159     /// @name Adapting the input
160     /// @{
161     /** @brief Removes self-loop edges (edges where the source and the destination node are the same)
162      * @param[in, opt. changed] dc The districts container to update
163      * @param[in, opt. changed] ec The edge container to remove the edges from
164      * @param[in, opt. changed] tc The traffic lights container to update
165      * @post Each edge is a uni-directional connection between two different nodes
166      */
167     void removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc);
168 
169     /** @brief Joins edges connecting the same nodes
170      * @param[in, opt. changed] dc The districts container to update
171      * @param[in, opt. changed] ec The edge container to remove the edges from
172      * @param[in, opt. changed] tc The traffic lights container to update
173      * @post No two edges with same geometry connecting same nodes exist
174      */
175     void joinSimilarEdges(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
176 
177     /// @brief fix overlap
178     void avoidOverlap();
179 
180     /** @brief Removes sequences of edges that are not connected with a junction.
181      * Simple roads without junctions sometimes remain when converting from OpenStreetMap,
182      * but they make no sense. Remaining empty nodes are also deleted.
183      *
184      * @param[in, opt. changed] dc The district container needed if edges shall be removed
185      * @param[in, opt. changed] ec The container with the edge to be tested
186      */
187     void removeIsolatedRoads(NBDistrictCont& dc, NBEdgeCont& ec);
188 
189     /** @brief Checks the network for weak connectivity and removes all but the largest components.
190      * The connectivity check is done regardless of edge direction and vclass.
191      *
192      * @param[in, opt. changed] dc The district container needed if edges shall be removed
193      * @param[in, opt. changed] ec The container with the edge to be tested
194      * @param[in] numKeep The number of components to keep
195      */
196     void removeComponents(NBDistrictCont& dc, NBEdgeCont& ec, const int numKeep);
197 
198     /** @brief Removes "unwished" nodes
199      *
200      * Removes nodes if a) no incoming/outgoing edges exist or
201      *  b) if the node is a "geometry" node. In the second case,
202      *  edges that participate at the node will be joined.
203      * Whether the node is a geometry node or not, is determined
204      *  by a call to NBNode::checkIsRemovable.
205      * The node is removed from the list of tls-controlled nodes.
206      * @param[in, opt. changed] dc The district container needed if a node shall be removed
207      * @param[in, opt. changed] ec The edge container needed for joining edges
208      * @param[in, opt. changed] tlc The traffic lights container to remove nodes from
209      * @param[in] removeGeometryNodes Whether geometry nodes shall also be removed
210      * @return The number of removed nodes
211      */
212     int removeUnwishedNodes(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc,
213                             NBPTStopCont& sc, NBPTLineCont& lc,
214                             NBParkingCont& pc,
215                             bool removeGeometryNodes);
216     /// @}
217 
218     /// @name Methods for guessing/computing traffic lights
219     /// @{
220     /** @brief Guesses which junctions or junction clusters shall be controlled by tls
221      * @param[in] oc The options that steer the guessing process
222      * @param[filled] tlc The traffic lights control into which new traffic light definitions shall be stored
223      * @todo Recheck exception handling
224      */
225     void guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc);
226 
227     /** @brief Builds clusters of tls-controlled junctions and joins the control if possible
228      * @param[changed] tlc The traffic lights control for adding/removing new/prior tls
229      * @param[in] maxdist The maximum distance between nodes for clustering
230      * @todo Recheck exception handling
231      */
232     void joinTLS(NBTrafficLightLogicCont& tlc, double maxdist);
233 
234     /** @brief Sets the given node as being controlled by a tls
235      * @param[in] node The node that shall be controlled by a tls
236      * @param[in] tlc The traffic lights control into which the new traffic light definition shall be stored
237      * @param[in] type The type of the new tls
238      * @param[in] id The id of the tls to add
239      * @todo Recheck exception handling
240      */
241     void setAsTLControlled(NBNode* node, NBTrafficLightLogicCont& tlc, TrafficLightType type, std::string id = "");
242     /// @}
243 
244     /** @brief Returns whether the node with the id was deleted explicitly
245      */
wasRemoved(std::string id)246     bool wasRemoved(std::string id) const {
247         return myExtractedNodes.count(id) != 0;
248     }
249 
250 
251     /// @brief Renames the node. Throws exception if newID already exists
252     void rename(NBNode* node, const std::string& newID);
253 
254     /// divides the incoming lanes on outgoing lanes
255     void computeLanes2Lanes();
256 
257     /// @brief build the list of outgoing edges and lanes
258     void computeLogics(const NBEdgeCont& ec, OptionsCont& oc);
259 
260     /// @brief compute right-of-way logic for all lane-to-lane connections
261     void computeLogics2(const NBEdgeCont& ec, OptionsCont& oc);
262 
263     /// @brief Returns the number of nodes stored in this container
size()264     int size() const {
265         return (int) myNodes.size();
266     }
267 
268     /// @brief deletes all nodes
269     void clear();
270 
271     /// @brief generates a new node ID
272     std::string getFreeID();
273 
274     /** @brief Compute the junction shape for this node
275      * @param[in] mismatchThreshold The threshold for warning about shapes which are away from myPosition
276      */
277     void computeNodeShapes(double mismatchThreshold = -1);
278 
279     /** @brief Prints statistics about built nodes
280      *
281      * Goes through stored nodes, computes the numbers of unregulated, priority and right-before-left
282      *  junctions and prints them.
283      */
284     void printBuiltNodesStatistics() const;
285 
286     /// @brief get all node names
287     std::vector<std::string> getAllNames() const;
288 
289     /* @brief analyzes a cluster of nodes which shall be joined
290      * @param[in] cluster The nodes to be joined
291      * @param[out] id The name for the new node
292      * @param[out] pos The position of the new node
293      * @param[out] hasTLS Whether the new node has a traffic light
294      * @param[out] tlType The type of traffic light (if any)
295      */
296     void analyzeCluster(NodeSet cluster, std::string& id, Position& pos,
297                         bool& hasTLS, TrafficLightType& type, SumoXMLNodeType& nodeType);
298 
299     /// @brief gets all joined clusters (see doc for myClusters2Join)
300     void registerJoinedCluster(const NodeSet& cluster);
301 
302     /// @brief gets all joined clusters (see doc for myClusters2Join)
getJoinedClusters()303     const std::vector<std::set<std::string> >& getJoinedClusters() const {
304         return myJoinedClusters;
305     }
306 
307     /* @brief discards traffic lights
308      * @param[in] geometryLike Whether only tls at geometry-like nodes shall be discarded
309      */
310     void discardTrafficLights(NBTrafficLightLogicCont& tlc, bool geometryLike, bool guessSignals);
311 
312     /* @brief discards rail signals
313      */
314     void discardRailSignals();
315 
316     /// @brief mark a node as being created form a split
markAsSplit(const NBNode * node)317     void markAsSplit(const NBNode* node) {
318         mySplit.insert(node);
319     }
320 
321     /// @brief remap node IDs accoring to options --numerical-ids and --reserved-ids
322     int remapIDs(bool numericaIDs, bool reservedIDs, const std::string& prefix);
323 
324 private:
325 
326     /// @name Helper methods for for joining nodes
327     /// @{
328     /** @brief Builds node clusters
329      *
330      * A node cluster is made up from nodes which are near by (distance<maxDist) and connected.
331      *
332      * @param[in] maxDist The maximum distance between two nodes for clustering
333      * @param[in, filled] into The container to store the clusters in
334      */
335     void generateNodeClusters(double maxDist, NodeClusters& into) const;
336 
337     /// @brief joins the given node clusters
338     void joinNodeClusters(NodeClusters clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
339     void joinNodeCluster(NodeSet clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, NBNode* predefined = nullptr);
340 
341     /// @}
342 
343     /// @name Helper methods for guessing/computing traffic lights
344     /// @{
345     /** @brief Returns whethe the given node cluster should be controlled by a tls
346      * @param[in] c The node cluster
347      * @param[in] laneSpeedThreshold threshold for determining whether a node or cluster should be tls controlled
348      * @return Whether this node cluster shall be controlled by a tls
349      */
350     bool shouldBeTLSControlled(const NodeSet& c, double laneSpeedThreshold) const;
351 
352     /// @brief check wheter the set of nodes only contains pedestrian crossings
353     bool onlyCrossings(const NodeSet& c) const;
354 
355     /// @brief check wheter the set of nodes contains traffic lights with custom id
356     bool customTLID(const NodeSet& c) const;
357     /// @}
358 
359 
360 private:
361     /// @brief The running internal id
362     int myInternalID;
363 
364     /// @brief Definition of the map of names to nodes
365     typedef std::map<std::string, NBNode*> NodeCont;
366 
367     /// @brief The map of names to nodes
368     NodeCont myNodes;
369 
370     /// @brief The extracted nodes which are kept for reference
371     NodeCont myExtractedNodes;
372 
373     /// @brief set of node ids which should not be joined
374     std::set<std::string> myJoinExclusions;
375 
376     /// @brief loaded sets of node ids to join (cleared after use)
377     std::vector<std::pair<std::set<std::string>, NBNode*> > myClusters2Join;
378 
379     /// @brief sets of node ids which were joined
380     std::vector<std::set<std::string> > myJoinedClusters;
381 
382     /// @brief ids found in loaded join clusters used for error checking
383     std::set<std::string> myJoined;
384 
385     /// @brief nodes that were created when splitting an edge
386     std::set<const NBNode*> mySplit;
387 
388     /// @brief node positions for faster lookup
389     NamedRTree myRTree;
390 
391 private:
392     /// @brief invalidated copy constructor
393     NBNodeCont(const NBNodeCont& s);
394 
395     /// @brief invalidated assignment operator
396     NBNodeCont& operator=(const NBNodeCont& s);
397 
398 };
399 
400 
401 #endif
402 
403 /****************************************************************************/
404 
405