Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file NBEdgeCont.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Tue, 20 Nov 2001
19 : ///
20 : // Storage for edges, including some functionality operating on multiple edges
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <map>
26 : #include <iostream>
27 : #include <string>
28 : #include <vector>
29 : #include <set>
30 : #include "NBCont.h"
31 : #include <utils/common/SUMOVehicleClass.h>
32 : #include <utils/common/UtilExceptions.h>
33 : #include <utils/geom/PositionVector.h>
34 : #include <utils/common/NamedRTree.h>
35 :
36 :
37 : // ===========================================================================
38 : // class declarations
39 : // ===========================================================================
40 : class OptionsCont;
41 : class OutputDevice;
42 : class NBNodeCont;
43 : class NBTypeCont;
44 : class NBEdge;
45 : class NBNode;
46 : class NBDistrictCont;
47 : class NBTrafficLightLogicCont;
48 : class NBPTStopCont;
49 : class NBPTLineCont;
50 :
51 :
52 : // ===========================================================================
53 : // class definitions
54 : // ===========================================================================
55 : /**
56 : * @class NBEdgeCont
57 : * @brief Storage for edges, including some functionality operating on multiple edges
58 : */
59 : class NBEdgeCont {
60 :
61 : public:
62 : /** @brief Constructor
63 : * @param[in] tc The net builded; used to obtain types
64 : */
65 : NBEdgeCont(NBTypeCont& tc);
66 :
67 : /// @brief Destructor
68 : ~NBEdgeCont();
69 :
70 : /** @brief Initialises the storage by applying given options
71 : *
72 : * Options, mainly steering the acceptance of edges, are parsed
73 : * and the according internal variables are set.
74 : *
75 : * @param[in] oc The options container to read options from
76 : * @todo Recheck exceptions
77 : */
78 : void applyOptions(OptionsCont& oc);
79 :
80 : /** @brief Deletes all edges */
81 : void clear();
82 :
83 : /// @name edge access methods
84 : /// @{
85 :
86 : /** @brief Adds an edge to the dictionary
87 : *
88 : * First, it is determined whether the edge shall not be discarded due to any
89 : * reasons (being outside a boundary, or not in the optional list of edges to
90 : * import, etc.). If so, the edge is deleted and "true" is returned.
91 : * "true" is also returned if the edge is accepted - no edge with the same
92 : * name exists within this container. If another edge with the same name
93 : * exists, false is returned.
94 : *
95 : * @param[in] edge The edge to add
96 : * @param[in] ignorePrunning Whether this edge must not be prunned
97 : * @return Whether the edge was valid (no edge with the same id is already known)
98 : */
99 : bool insert(NBEdge* edge, bool ignorePrunning = false);
100 :
101 : /** @brief Returns the edge that has the given id
102 : *
103 : * If no edge that has the given id is known, 0 is returned.
104 : *
105 : * @param[in] id The id of the edge to retrieve
106 : * @param[in] bool Whether extracted edges shall be retrieved as well
107 : * @return The edge with the given id, 0 if no such edge exists
108 : */
109 : NBEdge* retrieve(const std::string& id, bool retrieveExtracted = false) const;
110 :
111 : /** @brief Tries to retrieve an edge, even if it is splitted
112 : *
113 : * The edge given with the id should exist and is followed downstream or upstream,
114 : * depending on the parameter to the last edge still starting with the id.
115 : *
116 : * @param[in] id The id of the edge to retrieve
117 : * @param[in] downstream search direction
118 : * @return The searched edge
119 : * @todo Recheck usage
120 : */
121 : NBEdge* retrievePossiblySplit(const std::string& id, bool downstream) const;
122 :
123 : /** @brief Tries to retrieve an edge, even if it is splitted
124 : *
125 : * To describe which part of the edge shall be returned, the
126 : * id of a second edge, participating at the node and the information
127 : * whether to return the outgoing or the incoming is needed.
128 : *
129 : * @param[in] id The id of the edge to retrieve
130 : * @param[in] hint An additional information which helps to retrieve the correct edge
131 : * @param[in] incoming Whether the edge to find is an incoming edge at the node "hint" participates
132 : * @return The searched edge
133 : * @todo Recheck usage
134 : */
135 : NBEdge* retrievePossiblySplit(const std::string& id, const std::string& hint, bool incoming) const;
136 :
137 : /** @brief Tries to retrieve an edge, even if it is splitted
138 : *
139 : * To describe which part of the edge shall be returned, a
140 : * position hint is supplied.
141 : *
142 : * @param[in] id The id of the edge to retrieve
143 : * @param[in] pos An additional about the position of the basic edge's subpart
144 : * @return The searched edge
145 : * @todo Recheck usage
146 : */
147 : NBEdge* retrievePossiblySplit(const std::string& id, double pos) const;
148 :
149 : /** @brief Removes the given edge from the container (deleting it)
150 : *
151 : * @param[in] dc The district container, in order to remove the edge from sources/sinks
152 : * @param[in] edge The edge to remove
153 : * @todo Recheck whether the district cont is needed - if districts are processed using an external tool
154 : */
155 : void erase(NBDistrictCont& dc, NBEdge* edge);
156 :
157 : /** @brief Removes the given edge from the container like erase but does not
158 : * delete it
159 : *
160 : * @param[in] dc The district container, in order to remove the edge from sources/sinks
161 : * @param[in] edge The edge to remove
162 : * @param[in] remember Whether to keep this edge for future reference
163 : * @todo Recheck whether the district cont is needed - if districts are processed using an external tool
164 : * @todo Recheck whether this is used at all and why
165 : */
166 : void extract(NBDistrictCont& dc, NBEdge* edge, bool remember = false);
167 :
168 : /** @brief Returns the pointer to the begin of the stored edges
169 : * @return The iterator to the beginning of stored edges
170 : */
171 : std::map<std::string, NBEdge*>::const_iterator begin() const {
172 : return myEdges.begin();
173 : }
174 :
175 : /** @brief Returns the pointer to the end of the stored edges
176 : * @return The iterator to the end of stored edges
177 : */
178 : std::map<std::string, NBEdge*>::const_iterator end() const {
179 : return myEdges.end();
180 : }
181 : /// @}
182 :
183 : /// @name explicit edge manipulation methods
184 : /// @{
185 :
186 : /** @struct Split
187 : * @brief A structure which describes changes of lane number or speed along the road
188 : */
189 524 : struct Split {
190 : /// @brief The lanes after this change
191 : std::vector<int> lanes;
192 : /// @brief The position of this change
193 : double pos = INVALID_DOUBLE;
194 : /// @brief The speed after this change
195 : double speed = INVALID_DOUBLE;
196 : /// @brief The friction after this change
197 : double friction = INVALID_DOUBLE;
198 : /// @brief The new node that is created for this split
199 : NBNode* node = nullptr;
200 : /// @brief The id for the edge before the split
201 : std::string idBefore;
202 : /// @brief The id for the edge after the split
203 : std::string idAfter;
204 : /// @brief the default node id
205 : std::string nameID;
206 : /// @brief lateral offset to edge geometry
207 : double offset = 0.;
208 : /// @brief direction in which to apply the offset (used by netgenerate for lefthand networks)
209 : int offsetFactor = 1;
210 : };
211 :
212 : /// @brief process splits
213 : void processSplits(NBEdge* e, std::vector<Split> splits,
214 : NBNodeCont& nc, NBDistrictCont& dc, NBTrafficLightLogicCont& tlc);
215 :
216 : /** @brief Splits the edge at the position nearest to the given node
217 : *
218 : * Uses "splitAt(NBDistrictCont &, NBEdge *, NBNode *, const std::string &, const std::string &, int , int)"
219 : * to perform the split; the edge names are built by appending "[0]" and "[1]",
220 : * respectively. Both edges will have the same number of lanes.
221 : *
222 : * @param[in] dc The district container, in order to remove/add the edge from/to sources/sinks
223 : * @param[in] edge The edge to split
224 : * @param[in] node The node to split the edge at
225 : * @return Whether the edge could be split
226 : * @exception ProcessError If connections between the edges can not be built
227 : * @see NBEdge::splitAt(NBDistrictCont &, NBEdge *, NBNode *, const std::string &, const std::string &, int , int)
228 : */
229 : bool splitAt(NBDistrictCont& dc, NBEdge* edge, NBNode* node);
230 :
231 : /** @brief Splits the edge at the position nearest to the given node using the given modifications
232 : *
233 : * Determines the position of the split by finding the nearest position on the
234 : * edge to the given node. If this position is too near to the edges begin/end,
235 : * false is returned.
236 : *
237 : * Otherwise, "splitAt(NBDistrictCont &, NBEdge *, double, NBNode *, const std::string &, const std::string &, int , int)"
238 : * is used to perform the split.
239 : *
240 : * @param[in] nb The net builder containing all nodes, edges etc.
241 : * @param[in] edge The edge to split
242 : * @param[in] node The node to split the edge at
243 : * @param[in] firstEdgeName The id the first part of the split edge shall have
244 : * @param[in] secondEdgeName The id the second part of the split edge shall have
245 : * @param[in] noLanesFirstEdge The number of lanes the second part of the split edge shall have
246 : * @param[in] noLanesSecondEdge The number of lanes the second part of the split edge shall have
247 : * @param[in] speed The speed for the edge after the split
248 : * @param[in] friction The friction for the edge after the split
249 : * @param[in] changedLeft The number of lanes that is added or removed on the left side of the edge
250 : * (By default all added/removed lanes are assumed to be on the right when computing connections)
251 : * @return Whether the edge could be split
252 : * @exception ProcessError If connections between the edges can not be built
253 : * @see NBEdge::splitAt(NBDistrictCont &, NBEdge *, double, NBNode *, const std::string &, const std::string &, int , int)
254 : */
255 : bool splitAt(NBDistrictCont& dc, NBEdge* edge, NBNode* node,
256 : const std::string& firstEdgeName, const std::string& secondEdgeName,
257 : int noLanesFirstEdge, int noLanesSecondEdge,
258 : const double speed = -1., const double friction = 1., const int changedLeft = 0);
259 :
260 : /** @brief Splits the edge at the position nearest to the given node using the given modifications
261 : *
262 : * @param[in] dc The district container, in order to remove/add the edge from/to sources/sinks
263 : * @param[in] edge The edge to split
264 : * @param[in] node The node to split the edge at
265 : * @param[in] firstEdgeName The id the first part of the split edge shall have
266 : * @param[in] secondEdgeName The id the second part of the split edge shall have
267 : * @param[in] noLanesFirstEdge The number of lanes the second part of the split edge shall have
268 : * @param[in] noLanesSecondEdge The number of lanes the second part of the split edge shall have
269 : * @param[in] speed The speed for the edge after the split
270 : * @param[in] changedLeft The number of lanes that is added or removed on the left side of the edge
271 : * (By default all added/removed lanes are assumed to be on the right when computing connections)
272 : * @return Whether the edge could be split
273 : * @exception ProcessError If connections between the edges can not be built
274 : */
275 : bool splitAt(NBDistrictCont& dc, NBEdge* edge, double edgepos, NBNode* node,
276 : const std::string& firstEdgeName, const std::string& secondEdgeName,
277 : int noLanesFirstEdge, int noLanesSecondEdge,
278 : const double speed = -1., const double friction = 1., const int changedLeft = 0);
279 : /// @}
280 :
281 : /// @brief if base is an existing edge id, find a unused id of the form base + sep + INT
282 : std::string createUnusedID(const std::string& base, const std::string& sep);
283 :
284 : /// @name container access methods
285 : /// @{
286 :
287 : /** @brief Returns the number of edges
288 : * @return The number of edges stored in this container
289 : */
290 : int size() const {
291 4649 : return (int) myEdges.size();
292 : }
293 :
294 : /** @brief Returns all ids of known edges
295 : * @return All ids of known edges
296 : * @todo Recheck usage, probably, filling a given vector would be better...
297 : */
298 : std::vector<std::string> getAllNames() const;
299 :
300 : /** @brief Returns the edge split if the edge has been split, nullptr otherwise
301 : * @return the pair of edges after the split
302 : */
303 : const std::pair<NBEdge*, NBEdge*>* getSplit(const NBEdge* const origEdge) const {
304 : const auto& split = myEdgesSplit.find(origEdge);
305 19459 : if (split == myEdgesSplit.end()) {
306 : return nullptr;
307 : }
308 5 : return &split->second;
309 : }
310 :
311 : NBEdge* getSplitBase(const std::string& edgeID) const;
312 :
313 : /** @brief Returns the number of edge splits
314 : * @return How often an edge was split
315 : */
316 : int getNumEdgeSplits() const {
317 4548 : return (int)myEdgesSplit.size();
318 : }
319 : /// @}
320 :
321 : /// @name Adapting the input
322 : /// @{
323 :
324 : /** @brief Removes unwished edges (not in keep-edges)
325 : * @param[in, opt. changed] dc The district container needed to remove edges
326 : * @todo Recheck usage; check whether keep-edges.postload is really useful
327 : * @return The number of removed edges
328 : */
329 : int removeUnwishedEdges(NBDistrictCont& dc);
330 :
331 : /** @brief Splits edges into multiple if they have a complex geometry
332 : *
333 : * Calls "NBEdge::splitGeometry" for all edges within the container which
334 : * have more than three positions in their geometry.
335 : *
336 : * @param[in] nc The node container needed to build (geometry) nodes
337 : * @see NBEdge::splitGeometry
338 : */
339 : void splitGeometry(NBDistrictCont& dc, NBNodeCont& nc);
340 :
341 : /** @brief
342 : * @param[in] nc The node container needed to build (geometry) nodes
343 : * @see NBEdge::reduceGeometry
344 : */
345 : void reduceGeometries(const double minDist);
346 :
347 : /** @brief
348 : * @param[in] maxAngle The maximum geometry angle allowed
349 : * @param[in] minRadius The minimum turning radius allowed at the start and end
350 : * @param[in] fix Whether to prune geometry points to avoid sharp turns at start and end
351 : * @see NBEdge::checkGeometry
352 : */
353 : void checkGeometries(const double maxAngle, bool fixAngle, const double minRadius, bool fix, bool fixRailways, bool silent = false);
354 : /// @}
355 :
356 : /// @name processing methods
357 : /// @{
358 :
359 : /** @brief Sorts all lanes of all edges within the container by their direction
360 : *
361 : * Calls "NBEdge::sortOutgoingLanesConnections" for all edges within the container.
362 : *
363 : * @todo Recheck whether a visitor-pattern should be used herefor
364 : * @see NBEdge::sortOutgoingLanesConnections
365 : */
366 : void sortOutgoingLanesConnections();
367 :
368 : /** @brief Computes for each edge the approached edges
369 : *
370 : * Calls "NBEdge::computeEdge2Edges" for all edges within the container.
371 : *
372 : * @param[in] noLeftMovers Whether left-moving connections shall be omitted
373 : * @todo Recheck whether a visitor-pattern should be used herefor
374 : * @see NBEdge::computeEdge2Edges
375 : */
376 : void computeEdge2Edges(bool noLeftMovers);
377 :
378 : /** @brief Computes for each edge which lanes approach the next edges
379 : *
380 : * Calls "NBEdge::computeLanes2Edges" for all edges within the container.
381 : *
382 : * @todo Recheck whether a visitor-pattern should be used herefor
383 : * @see NBEdge::computeLanes2Edges
384 : */
385 : void computeLanes2Edges();
386 :
387 : /** @brief Rechecks whether all lanes have a successor for each of the stored edges
388 : *
389 : * Calls "NBEdge::recheckLanes" for all edges within the container.
390 : *
391 : * @todo Recheck whether a visitor-pattern should be used herefor
392 : * @see NBEdge::recheckLanes
393 : */
394 : void recheckLanes();
395 :
396 : /** @brief Appends turnarounds to all edges stored in the container
397 : *
398 : * Calls "NBEdge::appendTurnaround" for all edges within the container.
399 : *
400 : * @param[in] noTLSControlled Whether the turnaround shall not be connected if the edge is controlled by a tls
401 : * @param[in] noFringe Whether the turnaround shall not be connected if the junction is at the (outer) fringe
402 : * @param[in] onlyDeadends Whether the turnaround shall only be built at deadends
403 : * @param[in] onlyTurnlane Whether the turnaround shall only be built when there is an exclusive (left) turn lane
404 : * @param[in] noGeometryLike Whether the turnaround shall be built at geometry-like nodes
405 : * @see NBEdge::appendTurnaround
406 : */
407 : void appendTurnarounds(bool noTLSControlled, bool noFringe, bool onlyDeadends, bool onlyTurnlane, bool noGeometryLike);
408 :
409 : /** @brief Appends turnarounds to all edges stored in the container
410 : * Calls "NBEdge::appendTurnaround" for edges with the given ids
411 : * @param[in] ids The list of ids for which to append a turnaround
412 : * @param[in] noTLSControlled Whether the turnaround shall not be connected if the edge is controlled by a tls
413 : * @see NBEdge::appendTurnaround
414 : */
415 : void appendTurnarounds(const std::set<std::string>& ids, bool noTLSControlled);
416 :
417 : /// @brief Appends turnarounds to all bidiRail edges with stops
418 : void appendRailwayTurnarounds(const NBPTStopCont& sc);
419 :
420 : /** @brief Computes the shapes of all edges stored in the container
421 : *
422 : * Calls "NBEdge::computeEdgeShape" for all edges within the container.
423 : *
424 : * @todo Recheck whether a visitor-pattern should be used herefor
425 : * @todo Recheck usage
426 : * @see NBEdge::computeEdgeShape
427 : */
428 : void computeEdgeShapes(double smoothElevationThreshold = -1);
429 :
430 : /** @brief Computes the shapes of all lanes of all edges stored in the container
431 : *
432 : * Calls "NBEdge::computeLaneShapes" for all edges within the container.
433 : *
434 : * @todo Recheck whether a visitor-pattern should be used herefor
435 : * @todo Recheck usage
436 : * @see NBEdge::computeLaneShapes
437 : */
438 : void computeLaneShapes();
439 :
440 : /// @brief Clears information about controlling traffic lights for all connenections of all edges
441 : void clearControllingTLInformation() const;
442 :
443 : /** @brief Joins the given edges because they connect the same nodes
444 : *
445 : * @param[in] dc The district container needed to remove edges
446 : * @param[in] tlc The tls container needed to remove edges
447 : * @param[in] edges The edges to join
448 : * @todo Recheck and describe usage
449 : */
450 : void joinSameNodeConnectingEdges(NBDistrictCont& dc,
451 : NBTrafficLightLogicCont& tlc, EdgeVector edges);
452 :
453 : /// @brief Sets opposite lane information for geometrically close edges
454 : void guessOpposites();
455 :
456 : /** @brief Rechecks whether the lane spread is proper
457 : *
458 : * @todo Recheck usage; check whether this is really needed and whether it works at all
459 : */
460 : void recheckLaneSpread();
461 :
462 : /// @}
463 :
464 : /// @brief Returns the edge with negated id if it exists
465 : NBEdge* getOppositeByID(const std::string& edgeID) const;
466 :
467 : /// @brief Returns the edge with id if it exists
468 : NBEdge* getByID(const std::string& edgeID) const;
469 :
470 : /** @brief Determines which edges belong to roundabouts and increases their priority
471 : * @return The number of guessed roundabouts
472 : */
473 : int guessRoundabouts();
474 :
475 : /** @brief Determines which edges have been marked as roundabouts and stores them internally
476 : * @return The number of found roundabouts
477 : */
478 : int extractRoundabouts();
479 :
480 : // brief ensure myRoundabouts only holds valid edges
481 : void cleanupRoundabouts();
482 :
483 : /** @brief Returns whether the edge with the id was ignored during parsing
484 : * @return Whether the edge with the id was ignored during parsing
485 : */
486 : bool wasIgnored(std::string id) const {
487 : return myIgnoredEdges.count(id) != 0;
488 : }
489 :
490 : /// @brief mark the given edge id as ignored
491 : void ignore(std::string id) {
492 : myIgnoredEdges.insert(id);
493 6085 : }
494 :
495 : /// @brief Returns whether the edge with the id was deleted explicitly
496 : bool wasRemoved(std::string id) const {
497 : return myExtractedEdges.count(id) != 0;
498 : }
499 :
500 : /// @brief Renames the edge. Throws exception if newID already exists
501 : void rename(NBEdge* edge, const std::string& newID);
502 :
503 : /// @name Connections handling
504 : /// @{
505 :
506 : /** @brief Adds a connection which could not be set during loading
507 : * @param[in] from The id of the edge the connection starts at
508 : * @param[in] fromLane The number of the lane the connection starts at
509 : * @param[in] to The id of the edge the connection ends at
510 : * @param[in] toLane The number of the lane the connection ends at
511 : * @param[in] mayDefinitelyPass Whether the connection may be passed without braking
512 : * @param[in] keepClear Whether the connection must check to keep the junction clear
513 : * @param[in] contPos Custom position for internal junction
514 : * @param[in] visibility Custom foe visiblity connection
515 : * @param[in] speed Custom speed
516 : * @param[in] friction Custom friction
517 : * @param[in] customShape Custom shape
518 : * @param[in] warnOnly Whether a failure to set this connection should only result in a warning
519 : */
520 : void addPostProcessConnection(const std::string& from, int fromLane, const std::string& to, int toLane, bool mayDefinitelyPass,
521 : KeepClear keepClear, double contPos, double visibility,
522 : double speed, double friction, double length,
523 : const PositionVector& customShape,
524 : bool uncontrolled,
525 : bool warnOnly,
526 : SVCPermissions permissions = SVC_UNSPECIFIED,
527 : bool indirectLeft = false,
528 : const std::string& edgeType = "",
529 : SVCPermissions changeLeft = SVC_UNSPECIFIED,
530 : SVCPermissions changeRight = SVC_UNSPECIFIED);
531 :
532 : /// @brief add post process connections
533 : bool hasPostProcessConnection(const std::string& from, const std::string& to = "");
534 :
535 : /// @brief Try to set any stored connections
536 : void recheckPostProcessConnections();
537 : /// @}
538 :
539 : /// @brief assigns street signs to edges based on toNode types
540 : void generateStreetSigns();
541 :
542 : /// @brief add sidwalks to edges within the given limits or permissions and return the number of edges affected
543 : int guessSpecialLanes(SUMOVehicleClass svc, double width, double minSpeed, double maxSpeed, bool fromPermissions, const std::string& excludeOpt,
544 : NBTrafficLightLogicCont& tlc);
545 :
546 : /** @brief Returns the determined roundabouts
547 : * @return The list of roundabout edges
548 : */
549 : const std::set<EdgeSet> getRoundabouts() const;
550 :
551 : /// @brief check if there is guessed roundabouts
552 : bool hasGuessedRoundabouts() const {
553 : return myGuessedRoundabouts.size() > 0;
554 : }
555 :
556 : /// @brief add user specified roundabout
557 : void addRoundabout(const EdgeSet& roundabout);
558 :
559 : /// @brief remove roundabout that contains the given node
560 : void removeRoundabout(const NBNode* node);
561 : /// @brief remove edges from all stored roundabouts
562 : void removeRoundaboutEdges(const EdgeSet& toRemove);
563 :
564 : /// @brief mark edge priorities and prohibit turn-arounds for all roundabout edges
565 : void markRoundabouts();
566 :
567 : /// @brief fix roundabout information after splitting an edge
568 : void patchRoundabouts(NBEdge* orig, NBEdge* part1, NBEdge* part2, std::set<EdgeSet>& roundabouts);
569 :
570 : /// @brief Returns true if this edge matches one of the removal criteria
571 : bool ignoreFilterMatch(NBEdge* edge);
572 :
573 : /// @brief remap node IDs accoring to options --numerical-ids and --reserved-ids
574 : int remapIDs(bool numericaIDs, bool reservedIDs, bool keptIDs, const std::string& prefix, NBPTStopCont& sc);
575 :
576 : /// @brief check whether edges overlap
577 : void checkOverlap(double threshold, double zThreshold) const;
578 :
579 : /// @brief check whether edges are to steep
580 : void checkGrade(double threshold) const;
581 :
582 : /** @brief Returns the edges which have been built by splitting the edge of the given id
583 : *
584 : * @param[in] id The id of the original edge
585 : * @return List of all edges which have been built by splitting the original edge
586 : * @todo Recheck usage
587 : */
588 : EdgeVector getGeneratedFrom(const std::string& id) const;
589 :
590 : /// @brief join adjacent lanes with the given permissions
591 : int joinLanes(SVCPermissions perms);
592 :
593 : /// @brief join tram edges into adjacent lanes
594 : int joinTramEdges(NBDistrictCont& dc, NBPTStopCont& sc, NBPTLineCont& lc, double maxDist);
595 :
596 : /// @brief return all edges
597 : EdgeVector getAllEdges() const;
598 :
599 : /// @brief return all router edges
600 : RouterEdgeVector getAllRouterEdges() const;
601 :
602 : /// @brief ensure that all edges have valid nodes
603 : bool checkConsistency(const NBNodeCont& nc);
604 :
605 : /// @brief modify all restrictions on lane changing for edges and connections
606 : void updateAllChangeRestrictions(SVCPermissions ignoring);
607 :
608 : /// @brief add prefix to all edges
609 : void addPrefix(const std::string& prefix);
610 :
611 : /// @brief adapt custom lengths of split edges to account for intersection size
612 : void fixSplitCustomLength();
613 :
614 : /// @brief compute all edge angles
615 : void computeAngles();
616 :
617 : /// @brief return all edge types in used
618 : std::set<std::string> getUsedTypes() const;
619 :
620 : /// @brief return number of edges removed
621 : int removeEdgesBySpeed(NBDistrictCont& dc);
622 : int removeEdgesByPermissions(NBDistrictCont& dc);
623 : int removeLanesByWidth(NBDistrictCont& dc, const double minWidth);
624 :
625 : /// @brief return number of edges split
626 : int attachRemoved(NBNodeCont& nc, NBDistrictCont& dc, const double maxDist);
627 :
628 : private:
629 : /// @brief compute the form factor for a loop of edges
630 : static double formFactor(const EdgeVector& loopEdges);
631 :
632 : /// @brief remove roundabout edges
633 : void removeRoundaboutEdges(const EdgeSet& toRemove, std::set<EdgeSet>& roundabouts);
634 :
635 : /// @brief The network builder; used to obtain type information
636 : NBTypeCont& myTypeCont;
637 :
638 : /** @struct PostProcessConnection
639 : * @brief A structure representing a connection between two lanes
640 : */
641 : struct PostProcessConnection {
642 :
643 : public:
644 : /** @brief Constructor
645 : * @param[in] from The id of the edge the connection starts at
646 : * @param[in] fromLane The number of the lane the connection starts at
647 : * @param[in] to The id of the edge the connection ends at
648 : * @param[in] toLane The number of the lane the connection ends at
649 : * @param[in] mayDefinitelyPass Whether the connection may be passed without braking
650 : */
651 18 : PostProcessConnection(const std::string& from_, int fromLane_, const std::string& to_, int toLane_,
652 : bool mayDefinitelyPass_, KeepClear keepClear_, double contPos_, double visibility_, double speed_,
653 : double friction_, double length_,
654 : const PositionVector& customShape_,
655 : bool uncontrolled_,
656 : bool warnOnly_,
657 : SVCPermissions permissions_,
658 : bool indirectLeft_,
659 : const std::string& edgeType_,
660 : SVCPermissions changeLeft_,
661 18 : SVCPermissions changeRight_) :
662 18 : from(from_), fromLane(fromLane_), to(to_), toLane(toLane_), mayDefinitelyPass(mayDefinitelyPass_), keepClear(keepClear_), contPos(contPos_),
663 18 : visibility(visibility_),
664 18 : speed(speed_),
665 18 : friction(friction_),
666 18 : customLength(length_),
667 : customShape(customShape_),
668 18 : uncontrolled(uncontrolled_),
669 18 : permissions(permissions_),
670 18 : indirectLeft(indirectLeft_),
671 18 : edgeType(edgeType_),
672 18 : changeLeft(changeLeft_),
673 18 : changeRight(changeRight_),
674 18 : warnOnly(warnOnly_)
675 18 : {}
676 :
677 : /// @brief The id of the edge the connection starts at
678 : std::string from;
679 :
680 : /// @brief The number of the lane the connection starts at
681 : int fromLane;
682 :
683 : /// @brief The id of the edge the connection ends at
684 : std::string to;
685 :
686 : /// @brief The number of the lane the connection ends at
687 : int toLane;
688 :
689 : /// @brief Whether the connection may be passed without braking
690 : bool mayDefinitelyPass;
691 :
692 : /// @brief Whether the connection may be passed without braking
693 : KeepClear keepClear;
694 :
695 : /// @brief custom position for internal junction on this connection
696 : double contPos;
697 :
698 : /// @brief custom foe visiblity for connection
699 : double visibility;
700 :
701 : /// @brief custom speed for connection
702 : double speed;
703 :
704 : /// @brief custom friction for connection
705 : double friction;
706 :
707 : /// @brief custom length for connection
708 : double customLength;
709 :
710 : /// @brief custom shape for connection
711 : PositionVector customShape;
712 :
713 : /// @brief whether this connection shall not be controlled by a traffic light
714 : bool uncontrolled;
715 :
716 : /// @brief custom permissions for connection
717 : SVCPermissions permissions;
718 :
719 : /// @brief whether this connection is an indirect left turn
720 : bool indirectLeft;
721 :
722 : /// @brief custom edge type
723 : std::string edgeType;
724 :
725 : /// @brief custom lane changing permissions for connection
726 : SVCPermissions changeLeft;
727 :
728 : /// @brief custom lane changing permissions for connection
729 : SVCPermissions changeRight;
730 :
731 : /// @brief whether a failure to set this connection is a warning or an error
732 : bool warnOnly;
733 : };
734 :
735 : struct MinLaneComparatorIdLess {
736 : bool operator()(const std::pair<NBEdge*, int>& a, const std::pair<NBEdge*, int>& b) const;
737 : };
738 :
739 : /// @brief The list of connections to recheck
740 : std::map<std::string, std::vector<PostProcessConnection> > myConnections;
741 :
742 : /// @brief The type of the dictionary where an edge may be found by its id
743 : typedef std::map<std::string, NBEdge*> EdgeCont;
744 :
745 : /// @brief The instance of the dictionary (id->edge)
746 : EdgeCont myEdges;
747 :
748 : /// @brief The extracted edges which are kept for reference
749 : EdgeCont myExtractedEdges;
750 :
751 : /// @brief The edges which got extracted twice but may still be referenced somewhere TODO smart_ptr?
752 : std::set<NBEdge*> myEdgeCemetery;
753 :
754 : /// @brief The ids of ignored edges
755 : std::set<std::string> myIgnoredEdges;
756 :
757 : /// @brief the number of splits of edges during the building
758 : std::map<const NBEdge*, std::pair<NBEdge*, NBEdge*> > myEdgesSplit;
759 : /// @brief the edges that were created as result of splitting
760 : std::set<const NBEdge*> myWasSplit;
761 :
762 : /// @name Settings for accepting/dismissing edges
763 : /// @{
764 :
765 : /// @brief The minimum speed an edge may have in order to be kept (default: -1)
766 : double myEdgesMinSpeed;
767 :
768 : /// @brief Whether edges shall be joined and patched first, then removed
769 : bool myRemoveEdgesAfterLoading;
770 :
771 : /// @brief Set of ids of edges which shall explicitly be kept
772 : std::set<std::string> myEdges2Keep;
773 :
774 : /// @brief Set of ids of edges which shall explicitly be removed
775 : std::set<std::string> myEdges2Remove;
776 :
777 : /// @brief Set of vehicle types which must be allowed on edges in order to keep them
778 : SVCPermissions myVehicleClasses2Keep;
779 :
780 : /// @brief Set of vehicle types which need not be supported (edges which allow ONLY these are removed)
781 : SVCPermissions myVehicleClasses2Remove;
782 :
783 : /// @brief Set of edges types which shall be kept
784 : std::set<std::string> myTypes2Keep;
785 :
786 : /// @brief Set of edges types which shall be removed
787 : std::set<std::string> myTypes2Remove;
788 :
789 : /// @brief Boundary within which an edge must be located in order to be kept
790 : PositionVector myPruningBoundary;
791 :
792 : /// @brief whether a geo transform has been applied to the pruning boundary
793 : bool myNeedGeoTransformedPruningBoundary;
794 : /// @}
795 :
796 : /// @brief Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout)
797 : std::set<EdgeSet> myRoundabouts;
798 :
799 : /// @brief Edges marked as belonging to a roundabout after guessing
800 : std::set<EdgeSet> myGuessedRoundabouts;
801 :
802 : /** @class split_sorter
803 : * @brief Sorts splits by their position (increasing)
804 : */
805 : class split_sorter {
806 : public:
807 : /// @brief Constructor
808 : explicit split_sorter() { }
809 :
810 : /// @brief Comparing operator
811 : int operator()(const Split& e1, const Split& e2) const {
812 168 : return e1.pos < e2.pos;
813 : }
814 : };
815 :
816 : /// @brief invalidated copy constructor
817 : NBEdgeCont(const NBEdgeCont& s) = delete;
818 :
819 : /// @brief invalidated assignment operator
820 : NBEdgeCont& operator=(const NBEdgeCont& s) = delete;
821 : };
|