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*>&
72 std::vector<Track*> succ;
74 if ((t->edge->getPermissions() & svc) != 0) {
84 const std::vector<std::pair<const NBRailwayTopologyAnalyzer::Track*, const NBRailwayTopologyAnalyzer::Track*> >&
90 std::vector<std::pair<const Track*, const Track*> >& succ =
svcViaSuccessors[svc];
92 if ((t->edge->getPermissions() & svc) != 0) {
93 succ.push_back(std::make_pair(t,
nullptr));
125 int numRailEdges = 0;
126 int numBidiEdges = 0;
127 int numNotCenterEdges = 0;
128 int numAddedBidiEdges = 0;
148 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiEdges) +
" bidi-edges to ensure that all tracks are usable in both directions.");
149 if (numNotCenterEdges) {
150 WRITE_WARNING(
"Ignore " +
toString(numNotCenterEdges) +
" edges because they have the wrong spreadType");
158 const std::string id2 = (edge->
getID()[0] ==
'-' 159 ? edge->
getID().substr(1)
160 :
"-" + edge->
getID());
182 inEdges.push_back(e);
187 outEdges.push_back(e);
196 std::set<NBNode*> brokenNodes;;
202 std::set<NBNode*> railNodes =
getRailNodes(nb, verbose);
203 std::map<std::pair<int, int>, std::set<NBNode*, ComparatorIdLess> > types;
204 std::set<NBEdge*, ComparatorIdLess> bidiEdges;
205 std::set<NBEdge*, ComparatorIdLess> bufferStops;
206 for (
NBNode* node : railNodes) {
209 types[std::make_pair((
int)inEdges.size(), (int)outEdges.size())].insert(node);
210 for (
NBEdge* e : outEdges) {
211 if (e->isBidiRail() && bidiEdges.count(e->getTurnDestination(
true)) == 0) {
214 if (e->getID()[0] ==
'-') {
215 std::swap(primary, secondary);
216 }
else if (primary->
getID()[0] !=
'-' && secondary->
getID()[0] !=
'-' && secondary->
getID() < primary->
getID()) {
217 std::swap(primary, secondary);
219 if (bidiEdges.count(secondary) == 0) {
221 bidiEdges.insert(primary);
231 int numBufferStops = 0;
232 if (verbose && types.size() > 0) {
233 WRITE_MESSAGE(
"Railway nodes by number of incoming,outgoing edges:")
235 for (
auto it : types) {
236 int numBrokenType = 0;
237 device.
openTag(
"railNodeType");
238 int in = it.first.first;
239 int out = it.first.second;
242 for (
NBNode* n : it.second) {
253 std::string broken =
"";
263 for (
NBEdge* e : inRail) {
274 for (
NBEdge* e : outRail) {
285 if (((in == 1 && out == 1) || (in == 2 && out == 2))
290 if (broken.size() > 0) {
292 brokenNodes.insert(n);
304 +
" count: " +
toString(it.second.size()) +
" broken: " +
toString(numBrokenType));
318 for (
NBEdge* e : bidiEdges) {
321 device.
writeAttr(
"bidi", e->getTurnDestination(
true)->getID());
335 std::set<NBNode*> railNodes;
338 int numRailEdges = 0;
339 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
340 if (
isRailway(it->second->getPermissions())) {
342 railNodes.
insert(it->second->getFromNode());
343 railNodes.insert(it->second->getToNode());
347 std::set<NBNode*> railSignals;
348 for (
NBNode* node : railNodes) {
350 railSignals.insert(node);
386 #ifdef DEBUG_SEQSTOREVERSE 391 for (
NBEdge* e1 : edges) {
392 for (
NBEdge* e2 : edges2) {
412 if (e != candOut &&
isStraight(node, e, candOut)) {
414 std::cout <<
" isStraight e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
420 if (e != candOut && !
isStraight(node, e, candOut)) {
422 std::cout <<
" isSharp e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
439 if (!e1->isBidiRail(
true)) {
445 return !allBidi || countBidiAsSharp;
452 if (!e->isBidiRail()) {
465 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
483 if (bidiOut ==
nullptr) {
488 tmpBidiOut.push_back(bidiOut);
490 tmpBidiIn.push_back(bidiIn);
494 for (
NBEdge* cand : outRail) {
496 if (!cand->isBidiRail() &&
isStraight(node, bidiIn, cand)
498 &&
allSharp(node, inRail, tmpBidiOut,
true)) {
505 for (
NBEdge* cand : inRail) {
507 if (!cand->isBidiRail() &&
isStraight(node, cand, bidiOut)
509 &&
allSharp(node, outRail, tmpBidiIn,
true)) {
524 std::vector<EdgeVector> seqsToReverse;
525 for (
NBNode* n : brokenNodes) {
528 for (
NBEdge* start : outRail) {
530 tmp.push_back(start);
532 if (!
allBroken(n, start, inRail, outRail)
533 || (inRail.size() == 1 && outRail.size() == 1)) {
534 #ifdef DEBUG_SEQSTOREVERSE 536 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
545 seq.push_back(start);
547 NBNode* n2 = start->getToNode();
550 if (brokenNodes.count(n2) != 0) {
552 tmp2.push_back(start);
553 if (
allBroken(n2, start, outRail2, inRail2)) {
554 seqsToReverse.push_back(seq);
556 #ifdef DEBUG_SEQSTOREVERSE 558 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
564 if (outRail2.size() == 0) {
567 #ifdef DEBUG_SEQSTOREVERSE 569 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
572 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
575 #ifdef DEBUG_SEQSTOREVERSE 577 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
581 start = outRail2.front();
588 if (seqsToReverse.size() > 0) {
589 WRITE_MESSAGE(
"Found " +
toString(seqsToReverse.size()) +
" reversible edge sequences between broken rail nodes");
591 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
593 return a.size() < b.size();
596 std::set<NBNode*> affectedEndpoints;
597 std::set<std::string> reversedIDs;
598 std::map<int, int> seqLengths;
600 NBNode* seqStart = seq.front()->getFromNode();
601 NBNode* seqEnd = seq.back()->getToNode();
603 if (affectedEndpoints.count(seqStart) == 0
604 && affectedEndpoints.count(seqEnd) == 0) {
605 affectedEndpoints.insert(seqStart);
606 affectedEndpoints.insert(seqEnd);
609 e->reinitNodes(e->getToNode(), e->getFromNode());
610 e->setGeometry(e->getGeometry().reverse());
611 reversedIDs.insert(e->getID());
613 seqLengths[(int)seq.size()]++;
617 if (numReversed > 0) {
620 if (reversedIDs.count(item.second->getEdgeId())) {
621 item.second->findLaneAndComputeBusStopExtend(nb.
getEdgeCont());
633 int numBufferStops = 0;
634 int numAddedBidiTotal = 0;
635 for (
NBNode* node : railNodes) {
637 if (node->getEdges().size() != 1) {
638 WRITE_WARNING(
"Ignoring buffer stop junction '" + node->getID() +
"' with " +
toString(node->getEdges().size()) +
" edges\n");
641 int numAddedBidi = 0;
648 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
650 if (prev ==
nullptr) {
651 assert(node->getEdges().size() == 1);
652 e = node->getEdges().front();
657 assert(inRail.size() == 2);
658 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
661 assert(outRail.size() == 2);
662 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
694 if (numAddedBidiTotal > 0) {
695 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiTotal) +
" edges to connect " +
toString(numBufferStops) +
" buffer stops in both directions.");
703 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
704 if (
isStraight(n, inRail.front(), outRail.front())) {
705 return inRail.front();
706 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
707 return inRail.back();
710 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
711 if (
isStraight(n, outRail.front(), inRail.front())) {
712 return outRail.front();
713 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
714 return outRail.back();
724 std::map<int, int> seqLengths;
727 for (
NBNode* n : brokenNodes) {
729 if (edge !=
nullptr) {
730 std::vector<NBNode*> nodeSeq;
733 nodeSeq.push_back(prev);
734 edgeSeq.push_back(edge);
742 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
744 edge = allRail.front() == edge ? allRail.back() : allRail.front();
745 nodeSeq.push_back(prev);
746 edgeSeq.push_back(edge);
755 for (
NBEdge* e : edgeSeq) {
758 seqLengths[(int)edgeSeq.size()]++;
760 numAdded += (int)edgeSeq.size();
774 if (seqLengths.size() > 0) {
784 std::vector<Track*> tracks;
788 const int numEdges = (int)tracks.
size();
793 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
797 tracks.push_back(start);
799 tracks.push_back(end);
800 stopTracks[
edge] = std::make_pair(start, end);
807 for (
NBEdge* e1 : railEdges) {
808 for (
NBEdge* e2 : railEdges) {
810 int i = e1->getNumericalID();
811 int i2 = e2->getNumericalID();
812 if (e1->getToNode() == node) {
813 if (e2->getFromNode() == node) {
815 tracks[i]->addSuccessor(tracks[i2]);
817 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
820 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
821 tracks[i2]->addSuccessor(tracks[i + numEdges]);
824 if (e2->getFromNode() == node) {
826 tracks[i + numEdges]->addSuccessor(tracks[i2]);
827 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
838 for (
auto& item : stopTracks) {
839 const int index = item.first->getNumericalID();
841 item.second.first->addSuccessor(tracks[index]);
842 item.second.first->addSuccessor(tracks[index + numEdges]);
844 tracks[
index]->addSuccessor(item.second.second);
845 tracks[index + numEdges]->addSuccessor(item.second.second);
862 int numDisconnected = 0;
863 std::set<NBEdge*> addBidiStops;
864 std::set<NBEdge*> addBidiEdges;
865 std::set<std::pair<NBPTStop*, NBPTStop*> > visited;
867 std::vector<NBPTStop*> stops = line->getStops();
868 if (stops.size() < 2) {
871 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
872 std::pair<NBPTStop*, NBPTStop*> trip(*it, *(it + 1));
873 if (visited.count(trip) != 0) {
876 visited.insert(trip);
880 if (fromEdge ==
nullptr || toEdge ==
nullptr) {
883 if (stopTracks.count(fromEdge) == 0
884 || stopTracks.count(toEdge) == 0) {
888 std::vector<const Track*> route;
889 router->
compute(stopTracks[fromEdge].first, stopTracks[toEdge].second, &veh, 0, route);
893 if (route.size() > 0) {
894 assert(route.size() > 2);
895 for (
int i = 1; i < (int)route.size() - 1; ++i) {
898 if (addBidiEdges.count(edge) == 0) {
900 bool isStop = i == 1 || i == (int)route.size() - 2;
902 addBidiEdges.insert(edge);
904 addBidiStops.insert(edge);
908 WRITE_WARNING(
"Stop on edge " + fromEdge->
getID() +
" can only be reached in reverse but edge has the wrong spreadType");
916 WRITE_WARNING(
"No connection found between stops on edge '" + fromEdge->
getID() +
"' and edge '" + toEdge->
getID() +
"'");
933 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
934 WRITE_MESSAGE(
"Added " +
toString(addBidiStops.size()) +
" bidi-edges for public transport stops and a total of " 935 +
toString(added) +
" bidi-edges to ensure connectivity of stops (" 936 +
toString(numDisconnected) +
" stops remain disconnected)");
940 for (
Track* t : tracks) {
952 if (!
isRailway(e.second->getPermissions())) {
955 NBNode*
const from = e.second->getFromNode();
956 NBNode*
const to = e.second->getToNode();
957 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
960 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
963 bool haveReverse =
false;
964 for (
const NBEdge* cand : outRailTo) {
965 if (cand->getToNode() == from) {
973 bool haveStraightFrom =
false;
974 for (
const NBEdge* fromStraightCand : outRailFrom) {
975 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
976 haveStraightFrom =
true;
980 if (!haveStraightFrom) {
983 for (
const NBEdge* toStraightCand : inRailTo) {
984 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
997 WRITE_MESSAGE(
"Added " +
toString(added) +
" bidi-edges to ensure connectivity of straight tracks.");
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
bool gDebugFlag1
global utility flags for debugging
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
#define SHARP_THRESHOLD_SAMEDIR
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
void close()
Closes the device and removes it from the dictionary.
static bool allBidi(const EdgeVector &edges)
static bool isStraight(const NBNode *node, const NBEdge *e1, const NBEdge *e2)
static NBEdge * addBidiEdge(NBNetBuilder &nb, NBEdge *edge, bool update=true)
add bidi-edge for the given edge
static std::set< NBNode * > getRailNodes(NBNetBuilder &nb, bool verbose=false)
std::vector< std::pair< const Track *, const Track * > > viaSuccessors
static bool allBroken(const NBNode *node, NBEdge *candOut, const EdgeVector &in, const EdgeVector &out)
std::vector< Track * > successors
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
static void repairTopology(NBNetBuilder &nb)
SVCPermissions minPermissions
static void addBidiEdgesForStraightConnectivity(NBNetBuilder &nb)
add bidi-edges to connect straight tracks
The representation of a single edge during network building.
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E *> &into)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
const std::vector< NBPTLine * > & getLines() const
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
NBEdge * getTurnDestination(bool possibleDestination=false) const
Track(NBEdge *e, int i=-1, const std::string &_id="")
static void updateTurns(NBEdge *edge)
recompute turning directions for both nodes of the given edge
NBPTLineCont & getPTLineCont()
Returns a reference to the pt line container.
PositionVector reverse() const
reverse position vector
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
const std::string & getID() const
Returns the id.
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
const std::vector< std::pair< const Track *, const Track * > > & getViaSuccessors(SUMOVehicleClass svc=SVC_IGNORING) const
static std::set< NBNode * > getBrokenRailNodes(NBNetBuilder &nb, bool verbose=false)
#define WRITE_WARNING(msg)
std::map< SUMOVehicleClass, std::vector< std::pair< const Track *, const Track * > > > svcViaSuccessors
static OptionsCont & getOptions()
Retrieves the options.
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter ...
void invalidateIncomingConnections()
invalidate incoming connections
static void analyzeTopology(NBNetBuilder &nb)
Computes highway on-/off-ramps (if wished)
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
static void reverseEdges(NBNetBuilder &nb)
reverse edges sequences that are to broken nodes on both sides
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Computes the shortest path through a network using the Dijkstra algorithm.
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.
static void addBidiEdgesForBufferStops(NBNetBuilder &nb)
add bidi-edges to connect buffers stops in both directions
classes which drive on tracks
int getNumericalID() const
NBEdgeCont & getEdgeCont()
static void getRailEdges(const NBNode *node, EdgeVector &inEdges, EdgeVector &outEdges)
filter out rail edges among all edges of a the given node
Storage for edges, including some functionality operating on multiple edges.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
static void makeAllBidi(NBNetBuilder &nb)
A vehicle as used by router.
static void addBidiEdgesForStops(NBNetBuilder &nb)
add bidi-edges to connect successive public transport stops
static bool allSharp(const NBNode *node, const EdgeVector &in, const EdgeVector &out, bool countBidiAsSharp=false)
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
static NBEdge * isBidiSwitch(const NBNode *n)
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any) ...
std::map< SUMOVehicleClass, std::vector< Track * > > svcSuccessors
const PositionVector & getGeometry() const
Returns the geometry of the edge.
const std::map< std::string, NBPTStop * > & getStops() const
EdgeVector getAllEdges() const
return all edges
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Instance responsible for building networks.
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
void addSuccessor(Track *track)
static void addBidiEdgesBetweenSwitches(NBNetBuilder &nb)
add bidi-edges to connect switches that are approached in both directions
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
int size() const
Returns the number of edges.
alternative definition for junction
const std::vector< Track * > & getSuccessors(SUMOVehicleClass svc=SVC_IGNORING) const
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
static double getTravelTimeStatic(const NBEdge *const edge, const NBVehicle *const, double)
Represents a single node (junction) during network building.
Static storage of an output device and its base (abstract) implementation.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static bool hasStraightPair(const NBNode *node, const EdgeVector &edges, const EdgeVector &edges2)
NBNode * getFromNode() const
Returns the origin node of the edge.
static double getTravelTimeStatic(const Track *const track, const NBVehicle *const veh, double time)
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
#define WRITE_MESSAGE(msg)
static int extendBidiEdges(NBNetBuilder &nb)
add further bidi-edges near existing bidi-edges
NBNode * getToNode() const
Returns the destination node of the edge.
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.