43 #define DEBUGNODEID "gneJ34"
44 #define DEBUGNODEID2 "28842974"
45 #define DEBUGEDGEID "22820560#0"
46 #define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
48 #define SHARP_THRESHOLD_SAMEDIR 100
49 #define SHARP_THRESHOLD 80
66 const std::vector<NBRailwayTopologyAnalyzer::Track*>&
68 if ((minPermissions & svc) != 0) {
71 if (svcSuccessors.count(svc) == 0) {
72 std::vector<Track*> succ;
73 for (
Track* t : successors) {
74 if ((t->edge->getPermissions() & svc) != 0) {
78 svcSuccessors[svc] = succ;
80 return svcSuccessors[svc];
84 const std::vector<std::pair<const NBRailwayTopologyAnalyzer::Track*, const NBRailwayTopologyAnalyzer::Track*> >&
86 if ((minPermissions & svc) != 0) {
89 if (svcViaSuccessors.count(svc) == 0) {
90 std::vector<std::pair<const Track*, const Track*> >& succ = svcViaSuccessors[svc];
91 for (
const Track*
const t : successors) {
92 if ((t->edge->getPermissions() & svc) != 0) {
93 succ.push_back(std::make_pair(t,
nullptr));
97 return svcViaSuccessors[svc];
127 int numRailEdges = 0;
128 int numBidiEdges = 0;
129 int numNotCenterEdges = 0;
130 int numAddedBidiEdges = 0;
132 std::vector<NBEdge*> edges;
133 if (inputfile ==
"") {
135 edges.push_back(edge);
138 std::set<std::string> edgeIDs;
140 for (
const std::string& edgeID : edgeIDs) {
142 if (edge !=
nullptr) {
143 edges.push_back(edge);
147 for (
NBEdge* edge : edges) {
152 if (!edge->isBidiRail()) {
166 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiEdges) +
" bidi-edges to ensure that all tracks are usable in both directions.");
167 if (numNotCenterEdges) {
168 WRITE_WARNING(
"Ignore " +
toString(numNotCenterEdges) +
" edges because they have the wrong spreadType");
176 const std::string id2 = (edge->
getID()[0] ==
'-'
177 ? edge->
getID().substr(1)
178 :
"-" + edge->
getID());
200 inEdges.push_back(e);
205 outEdges.push_back(e);
214 std::set<NBNode*> brokenNodes;
220 std::set<NBNode*> railNodes =
getRailNodes(nb, verbose);
221 std::map<std::pair<int, int>, std::set<NBNode*, ComparatorIdLess> > types;
222 std::set<NBEdge*, ComparatorIdLess> bidiEdges;
223 std::set<NBEdge*, ComparatorIdLess> bufferStops;
224 for (
NBNode* node : railNodes) {
227 types[std::make_pair((
int)inEdges.size(), (
int)outEdges.size())].insert(node);
228 for (
NBEdge* e : outEdges) {
229 if (e->isBidiRail() && bidiEdges.count(e->getTurnDestination(
true)) == 0) {
232 if (e->getID()[0] ==
'-') {
233 std::swap(primary, secondary);
234 }
else if (primary->
getID()[0] !=
'-' && secondary->
getID()[0] !=
'-' && secondary->
getID() < primary->
getID()) {
235 std::swap(primary, secondary);
237 if (bidiEdges.count(secondary) == 0) {
239 bidiEdges.insert(primary);
249 int numBufferStops = 0;
250 if (verbose && types.size() > 0) {
251 WRITE_MESSAGE(
"Railway nodes by number of incoming,outgoing edges:")
256 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are outgoing");
260 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are incoming");
264 device.
writeAttr(
"meaning",
"an incoming edge has a sharp angle to all outgoing edges");
268 device.
writeAttr(
"meaning",
"an outgoing edge has a sharp angle from all incoming edges");
272 for (
auto it : types) {
273 int numBrokenType = 0;
274 device.
openTag(
"railNodeType");
275 int in = it.first.first;
276 int out = it.first.second;
279 for (
NBNode* n : it.second) {
287 std::string broken =
"";
297 for (
NBEdge* e : inRail) {
308 for (
NBEdge* e : outRail) {
319 if (((in == 1 && out == 1) || (in == 2 && out == 2))
324 if (broken.size() > 0) {
326 brokenNodes.insert(n);
338 +
" count: " +
toString(it.second.size()) +
" broken: " +
toString(numBrokenType));
352 for (
NBEdge* e : bidiEdges) {
355 device.
writeAttr(
"bidi", e->getTurnDestination(
true)->getID());
369 std::set<NBNode*> railNodes;
372 int numRailEdges = 0;
373 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
374 if (
isRailway(it->second->getPermissions())) {
376 railNodes.
insert(it->second->getFromNode());
377 railNodes.insert(it->second->getToNode());
381 std::set<NBNode*> railSignals;
382 for (
NBNode* node : railNodes) {
384 railSignals.insert(node);
420 #ifdef DEBUG_SEQSTOREVERSE
425 for (
NBEdge* e1 : edges) {
426 for (
NBEdge* e2 : edges2) {
446 if (e != candOut &&
isStraight(node, e, candOut)) {
448 std::cout <<
" isStraight e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
454 if (e != candOut && !
isStraight(node, e, candOut)) {
456 std::cout <<
" isSharp e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
473 if (!e1->isBidiRail(
true)) {
479 return !
allBidi || countBidiAsSharp;
486 if (!e->isBidiRail()) {
498 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
516 if (bidiOut ==
nullptr) {
521 tmpBidiOut.push_back(bidiOut);
523 tmpBidiIn.push_back(bidiIn);
527 for (
NBEdge* cand : outRail) {
529 if (!cand->isBidiRail() &&
isStraight(node, bidiIn, cand)
531 &&
allSharp(node, inRail, tmpBidiOut,
true)) {
538 for (
NBEdge* cand : inRail) {
540 if (!cand->isBidiRail() &&
isStraight(node, cand, bidiOut)
542 &&
allSharp(node, outRail, tmpBidiIn,
true)) {
557 std::vector<EdgeVector> seqsToReverse;
558 for (
NBNode* n : brokenNodes) {
561 for (
NBEdge* start : outRail) {
563 tmp.push_back(start);
565 if (!
allBroken(n, start, inRail, outRail)
566 || (inRail.size() == 1 && outRail.size() == 1)) {
567 #ifdef DEBUG_SEQSTOREVERSE
569 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
578 seq.push_back(start);
580 NBNode* n2 = start->getToNode();
583 if (brokenNodes.count(n2) != 0) {
585 tmp2.push_back(start);
586 if (
allBroken(n2, start, outRail2, inRail2)) {
587 seqsToReverse.push_back(seq);
589 #ifdef DEBUG_SEQSTOREVERSE
591 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
597 if (outRail2.size() == 0) {
600 #ifdef DEBUG_SEQSTOREVERSE
602 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
605 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
608 #ifdef DEBUG_SEQSTOREVERSE
610 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
614 start = outRail2.front();
621 if (seqsToReverse.size() > 0) {
622 WRITE_MESSAGE(
"Found " +
toString(seqsToReverse.size()) +
" reversible edge sequences between broken rail nodes");
624 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
626 return a.size() < b.size();
629 std::set<NBNode*> affectedEndpoints;
630 std::set<std::string> reversedIDs;
631 std::map<int, int> seqLengths;
633 NBNode* seqStart = seq.front()->getFromNode();
634 NBNode* seqEnd = seq.back()->getToNode();
636 if (affectedEndpoints.count(seqStart) == 0
637 && affectedEndpoints.count(seqEnd) == 0) {
638 affectedEndpoints.insert(seqStart);
639 affectedEndpoints.insert(seqEnd);
642 e->reinitNodes(e->getToNode(), e->getFromNode());
643 e->setGeometry(e->getGeometry().reverse());
644 reversedIDs.insert(e->getID());
646 seqLengths[(int)seq.size()]++;
650 if (numReversed > 0) {
653 if (reversedIDs.count(item.second->getEdgeId())) {
654 item.second->findLaneAndComputeBusStopExtent(nb.
getEdgeCont());
666 int numBufferStops = 0;
667 int numAddedBidiTotal = 0;
668 for (
NBNode* node : railNodes) {
670 if (node->getEdges().size() != 1) {
671 WRITE_WARNING(
"Ignoring buffer stop junction '" + node->getID() +
"' with " +
toString(node->getEdges().size()) +
" edges\n");
674 int numAddedBidi = 0;
681 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
683 if (prev ==
nullptr) {
684 assert(node->getEdges().size() == 1);
685 e = node->getEdges().front();
690 assert(inRail.size() == 2);
691 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
694 assert(outRail.size() == 2);
695 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
727 if (numAddedBidiTotal > 0) {
728 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiTotal) +
" edges to connect " +
toString(numBufferStops) +
" buffer stops in both directions.");
736 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
737 if (
isStraight(n, inRail.front(), outRail.front())) {
738 return inRail.front();
739 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
740 return inRail.back();
743 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
744 if (
isStraight(n, outRail.front(), inRail.front())) {
745 return outRail.front();
746 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
747 return outRail.back();
757 std::map<int, int> seqLengths;
760 for (
NBNode* n : brokenNodes) {
762 if (edge !=
nullptr) {
763 std::vector<NBNode*> nodeSeq;
766 nodeSeq.push_back(prev);
767 edgeSeq.push_back(edge);
775 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
777 edge = allRail.front() == edge ? allRail.back() : allRail.front();
778 nodeSeq.push_back(prev);
779 edgeSeq.push_back(edge);
788 for (
NBEdge* e : edgeSeq) {
791 seqLengths[(int)edgeSeq.size()]++;
793 numAdded += (int)edgeSeq.size();
807 if (seqLengths.size() > 0) {
817 std::vector<Track*> tracks;
819 tracks.push_back(
new Track(edge));
821 const int numEdges = (int)tracks.
size();
823 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse"));
826 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
829 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
830 tracks.push_back(start);
831 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
832 tracks.push_back(end);
833 stopTracks[edge] = std::make_pair(start, end);
840 for (
NBEdge* e1 : railEdges) {
841 for (
NBEdge* e2 : railEdges) {
843 int i = e1->getNumericalID();
844 int i2 = e2->getNumericalID();
845 if (e1->getToNode() == node) {
846 if (e2->getFromNode() == node) {
848 tracks[i]->addSuccessor(tracks[i2]);
850 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
853 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
854 tracks[i2]->addSuccessor(tracks[i + numEdges]);
857 if (e2->getFromNode() == node) {
859 tracks[i + numEdges]->addSuccessor(tracks[i2]);
860 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
871 for (
auto& item : stopTracks) {
872 const int index = item.first->getNumericalID();
874 item.second.first->addSuccessor(tracks[index]);
875 item.second.first->addSuccessor(tracks[index + numEdges]);
877 tracks[index]->addSuccessor(item.second.second);
878 tracks[index + numEdges]->addSuccessor(item.second.second);
894 int numDisconnected = 0;
895 std::set<NBEdge*, ComparatorIdLess> addBidiStops;
896 std::set<NBEdge*, ComparatorIdLess> addBidiEdges;
897 std::set<std::pair<NBEdge*, NBEdge*> > visited;
903 if (routeStart !=
nullptr) {
904 stops.insert(stops.begin(), routeStart);
906 if (routeEnd !=
nullptr) {
907 stops.push_back(routeEnd);
909 if (stops.size() < 2) {
912 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
914 NBEdge* toEdge = *(it + 1);
915 std::pair<NBEdge*, NBEdge*> trip(fromEdge, toEdge);
917 if (visited.count(trip) != 0) {
920 visited.insert(trip);
922 if (stopTracks.count(fromEdge) == 0
923 || stopTracks.count(toEdge) == 0) {
927 std::vector<const Track*> route;
928 router->
compute(stopTracks[fromEdge].first, stopTracks[toEdge].second, &veh, 0, route);
932 if (route.size() > 0) {
933 assert(route.size() > 2);
934 for (
int i = 1; i < (int)route.size() - 1; ++i) {
935 if (route[i]->getNumericalID() >= numEdges) {
936 NBEdge* edge = route[i]->edge;
937 if (addBidiEdges.count(edge) == 0) {
939 bool isStop = i == 1 || i == (int)route.size() - 2;
941 addBidiEdges.insert(edge);
943 addBidiStops.insert(edge);
947 WRITE_WARNING(
"Stop on edge " + fromEdge->
getID() +
" can only be reached in reverse but edge has the wrong spreadType");
955 WRITE_WARNING(
"No connection found between stops on edge '" + fromEdge->
getID() +
"' and edge '" + toEdge->
getID() +
"'");
960 for (
NBEdge* edge : addBidiEdges) {
961 if (!edge->isBidiRail()) {
972 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
973 WRITE_MESSAGE(
"Added " +
toString(addBidiStops.size()) +
" bidi-edges for public transport stops and a total of "
974 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
975 +
toString(numDisconnected) +
" stops remain disconnected)");
979 for (
Track* t : tracks) {
991 if (!
isRailway(e.second->getPermissions())) {
994 NBNode*
const from = e.second->getFromNode();
995 NBNode*
const to = e.second->getToNode();
996 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
999 if (e.second->isBidiRail()) {
1002 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
1007 bool haveStraight =
false;
1008 bool haveStraightReverse =
false;
1009 if (!geometryLike || outRailFrom.size() + inRailFrom.size() == 2) {
1010 for (
const NBEdge* fromStraightCand : outRailFrom) {
1011 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1012 haveStraightReverse =
true;
1017 if (haveStraightReverse) {
1018 for (
const NBEdge* fromStraightCand : inRailFrom) {
1019 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1020 haveStraight =
true;
1027 if ((!haveStraightReverse || haveStraight) && (!geometryLike || outRailTo.size() + inRailTo.size() == 2)) {
1030 haveStraight =
false;
1031 haveStraightReverse =
false;
1032 for (
const NBEdge* toStraightCand : inRailTo) {
1033 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1034 haveStraightReverse =
true;
1039 if (haveStraightReverse) {
1040 for (
const NBEdge* toStraightCand : outRailTo) {
1041 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1042 haveStraight =
true;
1050 if (haveStraightReverse && !haveStraight) {
1053 if (e2 !=
nullptr) {
1062 WRITE_MESSAGE(
"Added " +
toString(added) +
" bidi-edges to ensure connectivity of straight tracks at geometry-like nodes.");
1064 WRITE_MESSAGE(
"Added " +
toString(added) +
" bidi-edges to ensure connectivity of straight tracks at switches.");
1094 if (
isRailway(edge->getPermissions())) {
1095 if (!edge->isBidiRail()) {
1096 edge->setPriority(4);
1103 if (uni.size() == 0) {
1104 if (bidi.size() != 0) {
1105 WRITE_WARNING(
"Cannot assign track direction priority because there are no unidirectional tracks");
1112 while (!check.empty()) {
1113 NBEdge* edge = *check.begin();
1115 if (seen.count(edge) != 0) {
1121 forward.insert(straightOut);
1122 check.insert(straightOut);
1126 forward.insert(straightIn);
1127 check.insert(straightIn);
1129 #ifdef DEBUG_DIRECTION_PRIORITY
1137 for (
NBEdge* edge : bidi) {
1138 NBEdge* bidiEdge =
const_cast<NBEdge*
>(edge->getBidiEdge());
1139 if (forward.count(edge) != 0) {
1140 if (forward.count(bidiEdge) == 0) {
1145 edge->setPriority(2);
1149 if (forward.count(bidiEdge) != 0) {
1150 edge->setPriority(0);
1154 edge->setPriority(1);
1159 std::map<int, int> numPrios;
1160 for (
NBEdge* edge : bidi) {
1161 numPrios[edge->getPriority()]++;
#define WRITE_MESSAGE(msg)
#define WRITE_WARNING(msg)
#define SHARP_THRESHOLD_SAMEDIR
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SUMO_TAG_NODE
alternative definition for junction
bool gDebugFlag1
global utility flags for debugging
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Computes the shortest path through a network using the Dijkstra algorithm.
Storage for edges, including some functionality operating on multiple edges.
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
int size() const
Returns the number of edges.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
EdgeVector getAllEdges() const
return all edges
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
The representation of a single edge during network building.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
NBEdge * getStraightContinuation(SVCPermissions permissions) const
return the straightest follower edge for the given permissions or nullptr (never returns turn-arounds...
static double getTravelTimeStatic(const NBEdge *const edge, const NBVehicle *const, double)
const std::string & getID() const
NBNode * getToNode() const
Returns the destination node of the edge.
NBEdge * getStraightPredecessor(SVCPermissions permissions) const
return the straightest predecessor edge for the given permissions or nullptr (never returns turn-arou...
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
const PositionVector & getGeometry() const
Returns the geometry of the edge.
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
NBEdge * getTurnDestination(bool possibleDestination=false) const
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
void setPriority(int priority)
Sets the priority of the edge.
NBNode * getFromNode() const
Returns the origin node of the edge.
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
static void loadEdgesFromFile(const std::string &file, std::set< std::string > &into)
Add edge ids defined in file (either ID or edge:ID per line) into the given set.
Instance responsible for building networks.
NBPTLineCont & getPTLineCont()
Returns a reference to the pt line container.
NBEdgeCont & getEdgeCont()
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
Represents a single node (junction) during network building.
void invalidateIncomingConnections()
invalidate incoming connections
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const std::map< std::string, NBPTLine * > & getLines() const
NBEdge * getRouteEnd(const NBEdgeCont &ec) const
return last valid edge of myRoute (if it doest not lie before the last stop)
const std::string & getRef() const
get line reference (not unique)
NBEdge * getRouteStart(const NBEdgeCont &ec) const
return first valid edge of myRoute (if it doest not lie after the first stop)
std::vector< NBEdge * > getStopEdges(const NBEdgeCont &ec) const
get stop edges
const std::map< std::string, NBPTStop * > & getStops() const
SVCPermissions minPermissions
const std::vector< std::pair< const Track *, const Track * > > & getViaSuccessors(SUMOVehicleClass svc=SVC_IGNORING) const
const std::vector< Track * > & getSuccessors(SUMOVehicleClass svc=SVC_IGNORING) const
std::vector< Track * > successors
void addSuccessor(Track *track)
std::vector< std::pair< const Track *, const Track * > > viaSuccessors
static NBEdge * isBidiSwitch(const NBNode *n)
static void getRailEdges(const NBNode *node, EdgeVector &inEdges, EdgeVector &outEdges)
filter out rail edges among all edges of a the given node
static void updateTurns(NBEdge *edge)
recompute turning directions for both nodes of the given edge
static void addBidiEdgesForStops(NBNetBuilder &nb)
add bidi-edges to connect successive public transport stops
static bool isStraight(const NBNode *node, const NBEdge *e1, const NBEdge *e2)
static void addBidiEdgesForStraightConnectivity(NBNetBuilder &nb, bool geometryLike)
add bidi-edges to connect straight tracks
static NBEdge * addBidiEdge(NBNetBuilder &nb, NBEdge *edge, bool update=true)
add bidi-edge for the given edge
static std::set< NBNode * > getBrokenRailNodes(NBNetBuilder &nb, bool verbose=false)
static void analyzeTopology(NBNetBuilder &nb)
Computes highway on-/off-ramps (if wished)
static int extendBidiEdges(NBNetBuilder &nb)
add further bidi-edges near existing bidi-edges
static bool allSharp(const NBNode *node, const EdgeVector &in, const EdgeVector &out, bool countBidiAsSharp=false)
static void addBidiEdgesForBufferStops(NBNetBuilder &nb)
add bidi-edges to connect buffers stops in both directions
static bool allBroken(const NBNode *node, NBEdge *candOut, const EdgeVector &in, const EdgeVector &out)
static bool allBidi(const EdgeVector &edges)
static void reverseEdges(NBNetBuilder &nb)
reverse edges sequences that are to broken nodes on both sides
static void repairTopology(NBNetBuilder &nb)
static double getTravelTimeStatic(const Track *const track, const NBVehicle *const veh, double time)
static std::set< NBNode * > getRailNodes(NBNetBuilder &nb, bool verbose=false)
static bool hasStraightPair(const NBNode *node, const EdgeVector &edges, const EdgeVector &edges2)
static void addBidiEdgesBetweenSwitches(NBNetBuilder &nb)
add bidi-edges to connect switches that are approached in both directions
static void assignDirectionPriority(NBNetBuilder &nb)
static void makeAllBidi(NBNetBuilder &nb)
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
A vehicle as used by router.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
PositionVector reverse() const
reverse position vector
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter