60 #define EXTEND_CROSSING_ANGLE_THRESHOLD 35.0
62 #define SPLIT_CROSSING_WIDTH_THRESHOLD 1.5
63 #define SPLIT_CROSSING_ANGLE_THRESHOLD 5
66 #define MIN_WEAVE_LENGTH 20.0
73 #define DEBUG_NODE_ID "F"
74 #define DEBUGCOND (getID() == DEBUG_NODE_ID)
75 #define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUG_NODE_ID))
97 myApproaching(approaching),
98 myCurrentOutgoing(currentOutgoing),
99 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE) {
101 std::set<int> approachedLanes;
105 approachedLanes.insert(con.toLane);
113 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
119 && approachedLanes.count(i) == 0) {
132 assert((
int)myApproaching.size() > src);
134 NBEdge* incomingEdge = myApproaching[src];
138 if (myAvailableLanes.size() == 0) {
142 if (approachingLanes.size() == 0) {
145 #ifdef DEBUG_CONNECTION_GUESSING
147 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
151 std::deque<int>* approachedLanes = spread(approachingLanes, dest);
152 assert(approachedLanes->size() <= myAvailableLanes.size());
154 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
155 assert((
int)approachingLanes.size() > i);
156 int approached = myAvailableLanes[(*approachedLanes)[i]];
159 delete approachedLanes;
165 std::deque<int>* ret =
new std::deque<int>();
166 const int numLanes = (int)approachingLanes.size();
170 ret->push_back(dest);
174 const int numOutgoingLanes = (int)myAvailableLanes.size();
176 ret->push_back(dest);
180 while (noSet < numLanes) {
186 if (numOutgoingLanes == noSet) {
195 if (dest + loffset >= numOutgoingLanes) {
198 for (
int i = 0; i < (int)ret->size(); i++) {
199 (*ret)[i] = (*ret)[i] - 1;
204 ret->push_back(dest + loffset);
209 if (numOutgoingLanes == noSet) {
214 if (noSet < numLanes) {
217 if (dest < roffset) {
220 for (
int i = 0; i < (int)ret->size(); i++) {
221 (*ret)[i] = (*ret)[i] + 1;
224 ret->push_front(dest - roffset);
243 customShape(_customShape),
244 tlLinkIndex(_customTLIndex),
245 tlLinkIndex2(_customTLIndex2),
246 customTLIndex(_customTLIndex),
247 customTLIndex2(_customTLIndex2),
280 myPosition(position),
282 myDistrict(district),
283 myHaveCustomPoly(false),
285 myRadius(UNSPECIFIED_RADIUS),
286 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
289 myDiscardAllCrossings(false),
290 myCrossingsLoadedFromSumoNet(0),
291 myDisplacementError(0),
292 myIsBentPriority(false),
293 myTypeWasGuessed(false) {
307 bool updateEdgeGeometries) {
314 if (updateEdgeGeometries) {
318 (*i)->setGeometry(geom);
323 (*i)->setGeometry(geom);
336 wacs.shape.add(xoff, yoff, 0);
339 c->customShape.add(xoff, yoff, 0);
350 c->customShape.mirrorX();
357 wacs.shape.mirrorX();
383 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
397 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
400 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
401 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
403 const std::vector<NBNode*>& nodes = orig->
getNodes();
404 while (!nodes.empty()) {
405 newDef->
addNode(nodes.front());
406 nodes.front()->removeTrafficLight(orig);
419 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
446 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
498 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
501 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
517 double extrapolateBeg,
518 double extrapolateEnd,
520 int shapeFlag)
const {
524 #ifdef DEBUG_SMOOTH_GEOM
526 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
529 if (init.size() == 0) {
531 ret.push_back(begShape.back());
532 ret.push_back(endShape.front());
544 double extrapolateBeg,
545 double extrapolateEnd,
548 double straightThresh,
551 const Position beg = begShape.back();
552 const Position end = endShape.front();
555 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
556 #ifdef DEBUG_SMOOTH_GEOM
557 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
573 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
574 init.push_back(center);
581 if (fabs(angle) <
M_PI / 4.) {
584 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
585 const double halfDistance = dist / 2;
586 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
587 #ifdef DEBUG_SMOOTH_GEOM
588 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
589 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
592 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
595 #ifdef DEBUG_SMOOTH_GEOM
596 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
597 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
598 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
599 <<
" displacementError=" << sin(displacementAngle) * dist
600 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
603 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
608 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
609 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
611 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
613 #ifdef DEBUG_SMOOTH_GEOM
614 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
615 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
616 <<
" halfDistance=" << halfDistance <<
"\n";
627 #ifdef DEBUG_SMOOTH_GEOM
629 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
630 <<
" endShapeBegLine=" << endShapeBegLine
631 <<
" begShapeEndLineRev=" << begShapeEndLineRev
636 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
642 const double minControlLength =
MIN2((
double)1.0, dist / 2);
645 const bool lengthenBeg = distBeg <= minControlLength;
646 const bool lengthenEnd = distEnd <= minControlLength;
647 if (lengthenBeg && lengthenEnd) {
648 #ifdef DEBUG_SMOOTH_GEOM
649 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
650 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
652 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
661 }
else if (lengthenBeg || lengthenEnd) {
670 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
673 :
MIN2(0.6, 16 / dist));
674 init.push_back(begShapeEndLineRev.
positionAtOffset2D(100 -
MIN2(distBeg * factor / 1.2, dist * factor / 1.8)));
675 init.push_back(endShapeBegLine.
positionAtOffset2D(100 -
MIN2(distEnd * factor / 1.2, dist * factor / 1.8)));
684 const double z3 = 0.5 * (beg.
z() + end.
z());
688 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
693 intersect.
set(intersect.
x(), intersect.
y(), z);
694 init.push_back(intersect);
716 if (useCustomShape) {
719 if (startBorder.size() == 0) {
720 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
723 if (tmp.size() < 2) {
725 useCustomShape =
false;
729 tmp[0] = fromShape.back();
730 }
else if (recordError !=
nullptr) {
731 const double offset = tmp[0].distanceTo2D(fromShape.back());
737 if (endBorder.size() == 0) {
738 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
741 if (ret.size() < 2) {
743 useCustomShape =
false;
746 ret[-1] = toShape.front();
747 }
else if (recordError !=
nullptr) {
748 const double offset = ret[-1].distanceTo2D(toShape.front());
755 if (!useCustomShape) {
763 #ifdef DEBUG_SMOOTH_GEOM
765 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
770 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
802 for (
int i = 0; i < con.
toLane; ++i) {
806 for (
int i = 0; i < con.
fromLane; ++i) {
816 fromShape.
move2side(inCenter - outCenter);
869 const bool bothLeft = thisLeft && otherLeft;
870 if (fromE == otherFromE && !thisRight) {
877 if (c.
tlID !=
"" && !bothLeft) {
880 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
905 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
907 if ((*i)->getNodes().size() > 1) {
909 (*i)->removeNode(
this);
910 (*i)->setParticipantsInformation();
911 (*i)->setTLControllingInformation();
942 WRITE_WARNINGF(
"Junction '%' is too complicated (% connections, max %); will be set to %.",
944 }
else if (numConnections == 0) {
968 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
976 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
979 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1035 edge->computeEdgeShape();
1063 if (mismatchThreshold >= 0
1090 #ifdef DEBUG_CONNECTION_GUESSING
1092 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a\n";
1095 int inOffset, outOffset, addedLanes;
1096 getReduction(out, in, outOffset, inOffset, addedLanes);
1101 const int addedLeft = addedLanes - addedRight;
1103 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1107 for (
int i = 0; i < addedRight; ++i) {
1112 const int outOffset2 = outOffset + addedRight + in->
getNumLanes() - inOffset;
1113 for (
int i = 0; i < addedLeft; ++i) {
1140 #ifdef DEBUG_CONNECTION_GUESSING
1142 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1151 std::swap(in1, in2);
1152 std::swap(in1Offset, in2Offset);
1179 #ifdef DEBUG_CONNECTION_GUESSING
1181 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1186 std::swap(out1, out2);
1187 std::swap(out1Offset, out2Offset);
1204 #ifdef DEBUG_CONNECTION_GUESSING
1206 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1215 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1231 #ifdef DEBUG_CONNECTION_GUESSING
1233 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f\n";
1236 int inOffset, outOffset, reduction;
1243 inOffset += reduction;
1244 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1260 const int numApproaching = (int)approaching.size();
1261 if (numApproaching != 0) {
1265 #ifdef DEBUG_CONNECTION_GUESSING
1267 std::cout <<
"l2l node=" <<
getID() <<
" bresenham:\n";
1269 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1270 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1271 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1276 int bikeLaneTarget = currentOutgoing->getSpecialLane(
SVC_BICYCLE);
1285 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1286 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1291 unsatisfied &= ~satisfied;
1294 if (unsatisfied != 0) {
1295 #ifdef DEBUG_CONNECTION_GUESSING
1297 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1301 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1302 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1303 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); ++toLane) {
1304 const SVCPermissions satisfied = incoming->getPermissions(fromLane) & currentOutgoing->getPermissions(toLane) & unsatisfied;
1305 if (satisfied != 0 && !incoming->getLaneStruct(fromLane).connectionsDone) {
1306 bool mayUseSameDestination = unsatisfied ==
SVC_TRAM;
1308 #ifdef DEBUG_CONNECTION_GUESSING
1310 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1313 unsatisfied &= ~satisfied;
1319 #ifdef DEBUG_CONNECTION_GUESSING
1321 if (unsatisfied != 0) {
1322 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1335 bool builtConnection =
false;
1336 for (
int i = 0; i < (int)incoming->getNumLanes(); i++) {
1338 && incoming->getConnectionsFromLane(i, currentOutgoing).size() == 0) {
1340 if (bikeLaneTarget >= 0) {
1342 builtConnection =
true;
1345 for (
int i2 = 0; i2 < (int)currentOutgoing->getNumLanes(); i2++) {
1346 if ((currentOutgoing->getPermissions(i2) &
SVC_BICYCLE) != 0) {
1348 const bool allowDouble = (incoming->getPermissions(i) ==
SVC_BICYCLE
1351 builtConnection =
true;
1358 if (!builtConnection && bikeLaneTarget >= 0
1359 && incoming->getConnectionsFromLane(-1, currentOutgoing, bikeLaneTarget).size() == 0) {
1362 int end = (int)incoming->getNumLanes();
1365 std::swap(start, end);
1368 for (
int i = start; i < end; i += inc) {
1369 if ((incoming->getPermissions(i) &
SVC_BICYCLE) != 0) {
1382 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1383 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1385 (*i)->removeFromConnections((*k).toEdge);
1396 incoming->markAsInLane2LaneState();
1400 #ifdef DEBUG_CONNECTION_GUESSING
1402 std::cout <<
"final connections at " <<
getID() <<
"\n";
1404 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1405 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1406 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1431 int inOffset, outOffset, reduction;
1433 if (reduction > 0) {
1438 int outLanesRight = 0;
1439 int outLanesLeft = 0;
1440 int outLanesStraight = 0;
1443 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianLaneIndex(
FORWARD,
true));
1444 const int usableLanes = succ->getNumLanes() - outOffset;
1447 outLanesStraight += usableLanes;
1449 outLanesRight += usableLanes;
1451 outLanesLeft += usableLanes;
1456 const int usableLanes = out->
getNumLanes() - outOffset;
1457 int addedTurnLanes =
MIN3(
1459 MAX2(0, usableLanes - outLanesStraight),
1460 outLanesRight + outLanesLeft);
1461 if (outLanesLeft == 0) {
1462 return addedTurnLanes;
1464 return MIN2(addedTurnLanes / 2, outLanesRight);
1472 while (seen < minLength) {
1489 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1494 approaching.clear();
1495 for (; *i != currentOutgoing;) {
1497 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1498 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1499 if (connLanes.size() != 0) {
1500 approaching.push_back(*i);
1530 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1532 laneOff += (*i)->getNumLanes();
1562 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1564 laneOff += (*i)->getNumLanes();
1579 int whichLaneOff,
int byLaneOff) {
1583 bool changed =
false;
1585 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1588 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1602 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1604 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1605 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1665 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1666 edges.erase(find(edges.begin(), edges.end(), e));
1668 if (edges.size() == 0) {
1683 if (mayDrive.
getFrom() ==
nullptr ||
1684 mayDrive.
getTo() ==
nullptr ||
1685 mustStop.
getFrom() ==
nullptr ||
1686 mustStop.
getTo() ==
nullptr) {
1688 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1692 conn.push_back(mayDrive);
1699 int size = (int) edgeid.length();
1701 std::string
id = (*i)->
getID();
1702 if (
id.substr(0, size) == edgeid) {
1712 int size = (int) edgeid.length();
1714 std::string
id = (*i)->
getID();
1715 if (
id.substr(0, size) == edgeid) {
1740 if (removeFromConnections) {
1742 (*i)->removeFromConnections(edge);
1746 const bool incoming = edge->
getToNode() ==
this;
1748 (*i)->replaceRemoved(edge, -1,
nullptr, -1, incoming);
1757 EdgeVector::const_iterator i;
1759 NBNode* conn = (*i)->getFromNode();
1762 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1766 NBNode* conn = (*i)->getToNode();
1769 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1773 if (pos.
x() == 0 && pos.
y() == 0) {
1785 (*i)->invalidateConnections();
1793 (*i)->invalidateConnections();
1805 if (to ==
nullptr) {
1820 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
1821 if (from != prohibitorFrom) {
1858 if ((!flip && fromLane <= prohibitorFromLane) ||
1859 (flip && fromLane >= prohibitorFromLane)) {
1862 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
1863 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
1892 bool lefthand)
const {
1894 if (from != from2 || to == to2 || fromLane == fromLane2) {
1902 bool result =
false;
1904 if (fromLane < fromLane2) {
1906 while (*it != to2) {
1914 while (*it != to2) {
1946 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
1956 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
1957 bool regardNonSignalisedLowerPriority)
const {
1959 possProhibitedFrom, possProhibitedTo,
1960 regardNonSignalisedLowerPriority);
1966 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
1975 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1976 bool changed =
true;
1982 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1987 bool blockedChanged =
false;
1989 NBConnectionVector::const_iterator j;
1990 for (j = blocked.begin(); j != blocked.end(); j++) {
1992 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
1993 blockedChanged =
true;
1997 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1999 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2003 }
else if (sblocked.
getFrom() == removed) {
2004 assert(sblocked.
getTo() != removed);
2005 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2008 }
else if (sblocked.
getTo() == removed) {
2009 assert(sblocked.
getFrom() != removed);
2010 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2017 if (blockedChanged) {
2018 blockedConnectionsNew[blocker] = newBlocked;
2023 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2028 }
else if (blocker.
getFrom() == removed) {
2029 assert(blocker.
getTo() != removed);
2031 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2034 }
else if (blocker.
getTo() == removed) {
2035 assert(blocker.
getFrom() != removed);
2037 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2041 blockedConnectionsNew[blocker] = blocked;
2054 EdgeVector::const_iterator i = itOut;
2055 while (*i != incoming) {
2061 if ((*i)->getFromNode() !=
this) {
2069 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2080 if (outgoing ==
nullptr) {
2098 if (abs((
int) angle) + 1 < 45) {
2101 if (outCW !=
nullptr) {
2103 if (fabs(angle2) < fabs(angle)) {
2104 if (fabs(angle2 - angle) > 5) {
2105 if (angle2 > angle) {
2114 if (outCCW !=
nullptr) {
2116 if (fabs(angle2) < fabs(angle)) {
2117 if (fabs(angle2 - angle) > 5) {
2118 if (angle2 > angle) {
2135 if (outCW !=
nullptr) {
2146 if (outCCW !=
nullptr) {
2157 bool mayDefinitelyPass,
const std::string& tlID)
const {
2164 if (outgoing ==
nullptr) {
2176 if (!mayDefinitelyPass
2177 &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)
2202 reason =
"rail_signal";
2206 reason =
"crossing";
2209 EdgeVector::const_iterator i;
2214 reason =
"edges incompatible: " + reason;
2218 reason =
"turnaround";
2226 std::set<NBNode*> origSet;
2228 origSet.insert((*i)->getFromNode());
2230 if (origSet.size() < 2) {
2238 if (opposite !=
nullptr) {
2242 if (!(*i)->expandableBy(continuation, reason)) {
2243 reason =
"edges incompatible: " + reason;
2249 reason =
"not opposites";
2256 reason =
"intersection";
2261 std::vector<std::pair<NBEdge*, NBEdge*> >
2264 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2268 std::pair<NBEdge*, NBEdge*>(
2276 assert(opposite != 0);
2278 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2296 (*i)->resetNodeBorder(
this);
2305 if (e->getToNode() == n && e->getPermissions() != 0) {
2319 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2321 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2338 #ifdef DEBUG_PED_STRUCTURES
2347 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
2351 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2352 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2354 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2356 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2357 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2360 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2361 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2366 int firstSidewalk = -1;
2367 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2368 if (normalizedLanes[i].second) {
2373 int hadCandidates = 0;
2374 std::vector<int> connectedCandidates;
2375 if (firstSidewalk != -1) {
2377 std::vector<std::pair<NBEdge*, bool> > tmp;
2378 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2379 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2380 normalizedLanes = tmp;
2383 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2384 NBEdge* edge = normalizedLanes[i].first;
2385 const bool allowsPed = normalizedLanes[i].second;
2387 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2389 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2390 candidates.push_back(edge);
2391 }
else if (allowsPed) {
2392 if (candidates.size() > 0) {
2398 connectedCandidates.push_back(n);
2405 if (hadCandidates > 0 && candidates.size() > 0) {
2411 connectedCandidates.push_back(n);
2417 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2419 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2421 if (connectedCandidates.back() <= connectedCandidates.front()) {
2422 numGuessed -= connectedCandidates.back();
2425 numGuessed -= connectedCandidates.front();
2431 std::cout <<
"guessedCrossings:\n";
2433 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2443 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2445 if (candidates.size() == 0) {
2447 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2452 double prevAngle = -100000;
2453 for (
int i = 0; i < (int)candidates.size(); ++i) {
2454 NBEdge* edge = candidates[i];
2459 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2465 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2474 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2479 double prevAngle = -100000;
2480 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2481 double angle = (*it)->getCrossingAngle(
this);
2482 if (it != candidates.begin()) {
2483 NBEdge* prev = *(it - 1);
2488 double intermediateWidth = 0;
2491 prevPos = prev->
getLanes()[laneI].shape[-1];
2494 prevPos = prev->
getLanes()[laneI].shape[0];
2499 currPos = curr->
getLanes()[laneI].shape[0];
2502 currPos = curr->
getLanes()[laneI].shape[-1];
2508 <<
" prevAngle=" << prevAngle
2509 <<
" angle=" << angle
2510 <<
" intermediateWidth=" << intermediateWidth
2523 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2534 std::sort(edges.begin(), edges.end());
2538 EdgeVector edgesOfCrossing = crossing->edges;
2539 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2540 if (edgesOfCrossing == edges) {
2550 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2551 if (!normalizedLanes[i].second) {
2566 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2567 if (crossing->valid) {
2568 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found).",
2572 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2573 if (it_nc != wa.nextCrossings.end()) {
2574 wa.nextCrossings.erase(it_nc);
2577 crossing->valid =
false;
2578 crossing->prevWalkingArea =
"";
2579 crossing->nextWalkingArea =
"";
2584 std::vector<NBNode::Crossing*>
2586 std::vector<Crossing*> result;
2589 result.push_back(c.get());
2623 int noInternalNoSplits = 0;
2625 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2626 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2627 if ((*k).toEdge ==
nullptr) {
2630 noInternalNoSplits++;
2636 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2643 #ifdef DEBUG_PED_STRUCTURES
2647 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2663 c->nextWalkingArea =
"";
2664 c->prevWalkingArea =
"";
2667 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2673 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2676 double maxAngleDiff = 0;
2677 int maxAngleDiffIndex = 0;
2678 for (
int i = 0; i < (int) edges.size(); i++) {
2680 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2685 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2687 if (diff > maxAngleDiff) {
2688 maxAngleDiff = diff;
2689 maxAngleDiffIndex = i;
2692 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2694 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2696 std::cout <<
" rotatedEdges=" <<
toString(edges);
2700 std::reverse(edges.begin(), edges.end());
2702 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2706 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2707 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2708 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2709 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2711 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross).", c->id,
getID(),
toString(c->edges));
2713 }
else if (c->customShape.size() != 0) {
2714 c->shape = c->customShape;
2716 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2717 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2726 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (invalid shape).", c->id,
getID(),
toString(c->edges));
2729 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2730 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2740 #ifdef DEBUG_PED_STRUCTURES
2746 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2753 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2754 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2756 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2758 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2762 normalizedLanes.push_back(std::make_pair(edge, l));
2765 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2770 normalizedLanes.push_back(std::make_pair(edge, l));
2776 std::vector<std::pair<int, int> > waIndices;
2778 NBEdge* prevEdge = normalizedLanes.back().first;
2779 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2780 NBEdge* edge = normalizedLanes[i].first;
2790 waIndices.push_back(std::make_pair(start, i - start));
2800 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2805 const int waNumLanes = (int)normalizedLanes.size() - start;
2806 if (waIndices.size() == 0) {
2807 waIndices.push_back(std::make_pair(start, waNumLanes));
2809 std::cout <<
" single wa, end at wrap-around\n";
2812 if (waIndices.front().first == 0) {
2813 NBEdge* edge = normalizedLanes.front().first;
2814 NBEdge* prevEdge = normalizedLanes.back().first;
2817 waIndices.push_back(std::make_pair(start, waNumLanes));
2819 std::cout <<
" do not wrap around, turn-around in between\n";
2823 waIndices.front().first = start;
2824 waIndices.front().second = waNumLanes + waIndices.front().second;
2826 std::cout <<
" wrapping around\n";
2831 waIndices.push_back(std::make_pair(start, waNumLanes));
2833 std::cout <<
" end at wrap-around\n";
2839 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2840 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2841 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2845 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2846 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2847 const int start = waIndices[i].first;
2848 const int prev = start > 0 ? start - 1 : (int)normalizedLanes.size() - 1;
2849 const int count = waIndices[i].second;
2850 const int end = (start + count) % normalizedLanes.size();
2854 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << start <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2856 double endCrossingWidth = 0;
2857 double startCrossingWidth = 0;
2861 bool connectsCrossing =
false;
2862 std::vector<Position> connectedPoints;
2865 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
2867 if (c->edges.back() == normalizedLanes[end].first
2868 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
2870 if (c->nextWalkingArea !=
"") {
2871 WRITE_WARNINGF(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'.",
2872 getID(), c->id, c->nextWalkingArea, wa.
id);
2875 c->nextWalkingArea = wa.
id;
2878 endCrossingWidth = c->width;
2879 endCrossingShape = c->shape;
2881 connectsCrossing =
true;
2882 connectedPoints.push_back(c->shape[-1]);
2886 std::cout <<
" crossing " << c->id <<
" ends\n";
2889 if (c->edges.front() == normalizedLanes[prev].first
2890 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
2892 if (c->prevWalkingArea !=
"") {
2893 WRITE_WARNINGF(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'.",
2894 getID(), c->id, c->prevWalkingArea, wa.
id);
2897 c->prevWalkingArea = wa.
id;
2901 startCrossingWidth = c->width;
2902 startCrossingShape = c->shape;
2904 connectsCrossing =
true;
2905 connectedPoints.push_back(c->shape[0]);
2909 std::cout <<
" crossing " << c->id <<
" starts\n";
2912 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
2913 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
2914 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[start].first->getID()
2915 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
2918 if (count < 2 && !connectsCrossing) {
2921 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
2926 std::set<NBEdge*, ComparatorIdLess> connected;
2927 for (
int j = 0; j < count; ++j) {
2928 const int nlI = (start + j) % normalizedLanes.size();
2929 NBEdge* edge = normalizedLanes[nlI].first;
2932 if (connected.count(edge) == 0) {
2940 connected.insert(edge);
2947 if (buildExtensions) {
2949 if (startCrossingShape.size() > 0) {
2951 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
2953 startCrossingShape.
move2side(startCrossingWidth / 2);
2955 startCrossingShape.
move2side(-startCrossingWidth);
2959 if (endCrossingShape.size() > 0) {
2961 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
2963 endCrossingShape.
move2side(endCrossingWidth / 2);
2965 endCrossingShape.
move2side(-endCrossingWidth);
2970 && normalizedLanes.size() == 2) {
2972 NBEdge* e1 = *connected.begin();
2973 NBEdge* e2 = *(++connected.begin());
2976 std::cout <<
" not building a walkingarea since normal connections exist\n";
2982 if (cornerDetail > 0) {
2983 int smoothEnd = end;
2984 int smoothPrev = prev;
2986 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
2987 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
2989 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
2990 if (smoothPrev == 0) {
2991 smoothPrev = (int)normalizedLanes.size() - 1;
2996 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
2997 begShape = begShape.
reverse();
2999 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3000 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3001 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3004 if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3008 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3012 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
3013 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3014 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
3015 if (curve.size() > 2) {
3016 curve.erase(curve.begin());
3018 if (endCrossingWidth > 0) {
3019 wa.
shape.pop_back();
3021 if (startCrossingWidth > 0) {
3031 if (wacs.shape.size() != 0 &&
includes(connected, wacs.edges)) {
3032 wa.
shape = wacs.shape;
3038 double lengthSum = 0;
3039 int combinations = 0;
3040 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3041 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3051 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
3053 wa.
length = POSITION_EPS;
3054 if (combinations > 0) {
3055 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3060 std::vector<Crossing*> validCrossings =
getCrossings();
3061 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3063 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3065 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
3080 wa.
shape.push_back(tmp[-1]);
3082 wa.
shape.push_back(tmp[-1]);
3086 wa.
shape.push_back(tmp[0]);
3088 wa.
shape.push_back(tmp[0]);
3091 std::set<NBEdge*, ComparatorIdLess> crossed(prev.
edges.begin(), prev.
edges.end());
3092 crossed.insert(next.
edges.begin(), next.
edges.end());
3095 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(crossed, wacs.edges)) {
3096 wa.
shape = wacs.shape;
3105 std::cout <<
" build wa=" << wa.
id <<
"\n";
3113 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3115 for (
const NBEdge* e : sub) {
3116 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3135 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3136 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3137 if (it1 != edges.end() && it2 != edges.end()) {
3162 return other1 == other2;
3174 while (it != it_end) {
3175 result.push_back(*it);
3185 wacs.
edges.insert(edges.begin(), edges.end());
3198 if (incoming.size() == 1 && outgoing.size() == 1) {
3201 if (incoming.size() == 2 && outgoing.size() == 2) {
3204 NBEdge* in0 = incoming[0];
3205 NBEdge* in1 = incoming[1];
3206 NBEdge* out0 = outgoing[0];
3207 NBEdge* out1 = outgoing[1];
3212 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
3216 if (
MAX2(angle0, angle1) <= 160) {
3236 if (out->getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
3246 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
3247 myCrossings.push_back(std::unique_ptr<Crossing>(c));
3257 EdgeSet edgeSet(edges.begin(), edges.end());
3259 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
3260 if (edgeSet == edgeSet2) {
3276 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
3282 EdgeSet edgeSet(edges.begin(), edges.end());
3284 EdgeSet edgeSet2(it->edges.begin(), it->edges.end());
3285 if (edgeSet == edgeSet2) {
3292 throw ProcessError(
"Request for unknown crossing for the given Edges");
3299 bool usedCustom =
false;
3301 c->tlLinkIndex = startIndex++;
3303 if (c->customTLIndex != -1) {
3304 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
3305 c->tlLinkIndex = c->customTLIndex;
3307 c->tlLinkIndex2 = c->customTLIndex2;
3319 result += (int)edge->getConnections().size();
3332 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
3333 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
3369 std::cout <<
" angles:\n";
3370 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3371 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3373 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3378 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
3380 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
3382 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
3393 assert(
id[0] ==
':');
3394 std::string::size_type sep_index =
id.rfind(
'_');
3395 if (sep_index == std::string::npos) {
3396 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3399 sep_index =
id.substr(0, sep_index).rfind(
'_');
3400 if (sep_index == std::string::npos) {
3401 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3404 return id.substr(1, sep_index - 1);
3414 if (turnDest !=
nullptr) {
3434 if (def->rightOnRedConflict(index, foeIndex)) {
3456 std::vector<NBEdge*>::iterator j;
3457 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3460 if (allEdges.size() > 1 && j != allEdges.end()) {
3465 NBEdge* firstOfAll = allEdges.front();
3466 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3467 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3473 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3474 if (firstOfIncoming !=
nullptr) {
3475 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3477 if (firstOfOutgoing !=
nullptr) {
3478 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3480 #ifdef DEBUG_EDGE_SORTING
3482 std::cout <<
"sortedEdges:\n";
3483 for (
NBEdge* e : allEdges) {
3484 std::cout <<
" " << e->getID()
3485 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3486 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3493 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3494 std::vector<NBEdge*>::const_iterator in, out;
3495 std::vector<NBEdge*> allTmp;
3496 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3497 if ((*in)->isTurningDirectionAt(*out)) {
3498 allTmp.push_back(*in);
3499 allTmp.push_back(*out);
3504 if (allTmp.size() == allEdges.size()) {
3517 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3521 e->computeEdgeShape();
3526 std::vector<std::pair<Position, std::string> >
3529 std::vector<std::pair<Position, std::string> >result;
3531 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3532 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
3534 for (
const auto& pair : result) {
3535 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
3541 result.push_back(std::make_pair(pos, origID));
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
#define EXTEND_CROSSING_ANGLE_THRESHOLD
#define SPLIT_CROSSING_WIDTH_THRESHOLD
#define SPLIT_CROSSING_ANGLE_THRESHOLD
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TRAM
vehicle is a light rail
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ DEFAULT
No information given; use default.
FringeType
algorithms for computing right of way
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ TURN_LEFTHAND
The link is a 180 degree turn (left-hand network)
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link)
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_MAJOR
This is an uncontrolled, major link, may pass.
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
@ LINKSTATE_EQUAL
This is an uncontrolled, right-before-left link.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
@ LINKSTATE_TL_OFF_BLINKING
The link is controlled by a tls which is off and blinks, has to brake.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
@ LINKSTATE_TL_OFF_NOSIGNAL
The link is controlled by a tls which is off, not blinking, may pass.
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
@ TRAFFIC_LIGHT_RIGHT_ON_RED
@ TRAFFIC_LIGHT_NOJUNCTION
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
#define UNUSED_PARAMETER(x)
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static void compute(BresenhamCallBack *callBack, const int val1, const int val2)
static double getCCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle counter-clockwise.
static double getCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle clockwise.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
bool replaceTo(NBEdge *which, NBEdge *by)
replaces the to-edge by the one given
bool replaceFrom(NBEdge *which, NBEdge *by)
replaces the from-edge by the one given
NBEdge * getTo() const
returns the to-edge (end of the connection)
Class to sort edges by their angle in relation to the given edge.
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
A container for districts.
A class representing a single district.
void replaceIncoming(const EdgeVector &which, NBEdge *const by)
Replaces incoming edges from the vector (sinks) by the given edge.
void replaceOutgoing(const EdgeVector &which, NBEdge *const by)
Replaces outgoing edges from the vector (source) by the given edge.
Storage for edges, including some functionality operating on multiple edges.
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
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
bool isInsideTLS() const
Returns whether this edge was marked as being within an intersection.
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
double getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
double getLaneWidth() const
Returns the default width of lanes of this edge.
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
EdgeBuildingStep getStep() const
The building step of this edge.
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
const std::string & getID() const
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
NBNode * getToNode() const
Returns the destination node of the edge.
@ LANES2LANES_DONE
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
@ LANES2EDGES
Lanes to edges - relationships are computed/loaded.
@ LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
double getSpeed() const
Returns the speed allowed on this edge.
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
int getNumLanes() const
Returns the number of lanes.
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
const PositionVector & getNodeBorder(const NBNode *node) const
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
@ VALIDATED
The connection was computed and validated.
@ COMPUTED
The connection was computed.
static PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode, PositionVector nodeShape)
std::string getSidewalkID()
get the lane id for the canonical sidewalk lane
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing, bool withBikes=true) const
Returns the list of lanes that may be used to reach the given edge.
double getStartAngle() const
Returns the angle at the start of the edge (relative to the node shape center) The angle is computed ...
int getSpecialLane(SVCPermissions permissions) const
return index of the first lane that allows the given permissions
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
NBEdge * getTurnDestination(bool possibleDestination=false) const
void shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
static const double UNSPECIFIED_WIDTH
unspecified lane width
double getEndAngle() const
Returns the angle at the end of the edge (relative to the node shape center) The angle is computed in...
void replaceInConnections(NBEdge *which, NBEdge *by, int laneOff)
replace in current connections of edge
bool hasConnectionTo(NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
double getEndOffset() const
Returns the offset to the destination node.
bool addLane2LaneConnections(int fromLane, NBEdge *dest, int toLane, int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Lane & getLaneStruct(int lane)
Connection getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection This method goes through "myConnections" and returns the specified o...
double getFinalLength() const
get length that will be assigned to the lanes in the final network
NBNode * getFromNode() const
Returns the origin node of the edge.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
A loaded (complete) traffic light logic.
Computes lane-2-lane connections.
bool myIsBikeEdge
whether the outgoing edge is exclusively used by bikes
ApproachingDivider(const EdgeVector &approaching, NBEdge *currentOutgoing)
Constructor.
~ApproachingDivider()
Destructor.
const EdgeVector & myApproaching
The list of edges that approach the current edge.
int numAvailableLanes() const
@ get number of avaliable lanes
std::deque< int > * spread(const std::vector< int > &approachingLanes, int dest) const
the method that spreads the wished number of lanes from the the lane given by the bresenham-call to b...
NBEdge * myCurrentOutgoing
The approached current edge.
void execute(const int src, const int dest)
the bresenham-callback
std::vector< int > myAvailableLanes
The available lanes to which connections shall be built.
A definition of a pedestrian crossing.
Crossing(const NBNode *_node, const EdgeVector &_edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector &_customShape)
constructor
std::string id
the (edge)-id of this crossing
std::string prevWalkingArea
the lane-id of the previous walkingArea
std::string nextWalkingArea
the lane-id of the next walkingArea
PositionVector shape
The crossing's shape.
EdgeVector edges
The edges being crossed.
double width
This crossing's width.
bool valid
whether this crossing is valid (and can be written to the net.xml). This is needed for netedit becaus...
Represents a single node (junction) during network building.
LinkState getLinkState(const NBEdge *incoming, NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
static const int FOUR_CONTROL_POINTS
static const int AVOID_INTERSECTING_LEFT_TURNS
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
void avoidOverlap()
fix overlap
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
void buildInnerEdges()
build internal lanes, pedestrian crossings and walking areas
std::vector< WalkingAreaCustomShape > myWalkingAreaCustomShapes
Vector of custom walking areas shapes.
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
bool mustBrake(const NBEdge *const from, const NBEdge *const to, int fromLane, int toLane, bool includePedCrossings) const
Returns the information whether the described flow must let any other flow pass.
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
NBEdge * getNextCompatibleOutgoing(const NBEdge *incoming, SVCPermissions vehPerm, EdgeVector::const_iterator start, bool clockwise) const
bool isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
int numNormalConnections() const
return the number of lane-to-lane connections at this junction (excluding crossings)
bool setCrossingTLIndices(const std::string &tlID, int startIndex)
static const double UNSPECIFIED_RADIUS
unspecified lane width
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
NBNode(const std::string &id, const Position &position, SumoXMLNodeType type)
Constructor.
void invalidateIncomingConnections()
invalidate incoming connections
bool forbidsPedestriansAfter(std::vector< std::pair< NBEdge *, bool > > normalizedLanes, int startIndex)
return whether there is a non-sidewalk lane after the given index;
bool needsCont(const NBEdge *fromE, const NBEdge *otherFromE, const NBEdge::Connection &c, const NBEdge::Connection &otherC) const
whether an internal junction should be built at from and respect other
void buildCrossingsAndWalkingAreas()
build crossings, and walkingareas. Also removes invalid loaded crossings if wished
static const int BACKWARD
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light
SumoXMLNodeType getType() const
Returns the type of this node.
void computeLogic2(bool checkLaneFoes)
compute right-of-way logic for all lane-to-lane connections
bool myTypeWasGuessed
whether the node type was guessed rather than loaded
void setCustomShape(const PositionVector &shape)
set the junction shape
void computeNodeShape(double mismatchThreshold)
Compute the junction shape for this node.
void buildWalkingAreas(int cornerDetail, double joinMinDist)
build pedestrian walking areas and set connections from/to walkingAreas
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas
void remapRemoved(NBTrafficLightLogicCont &tc, NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
remap removed
int buildCrossings()
build pedestrian crossings
SumoXMLNodeType myType
The type of the junction.
EdgeVector myOutgoingEdges
Vector of outgoing edges.
bool myKeepClear
whether the junction area must be kept clear
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
void discardWalkingareas()
discard previously built walkingareas (required for repeated computation by netedit)
void computeLogic(const NBEdgeCont &ec)
computes the node's type, logic and traffic light
NBRequest * myRequest
Node requests.
void mirrorX()
mirror coordinates along the x-axis
void invalidateOutgoingConnections()
invalidate outgoing connections
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
bool myHaveCustomPoly
whether this nodes shape was set by the user
Position getEmptyDir() const
Returns something like the most unused direction Should only be used to add source or sink nodes.
NBNode::Crossing * addCrossing(EdgeVector edges, double width, bool priority, int tlIndex=-1, int tlIndex2=-1, const PositionVector &customShape=PositionVector::EMPTY, bool fromSumoNet=false)
add a pedestrian crossing to this node
static const int AVOID_WIDE_RIGHT_TURN
flags for controlling shape generation
int myCrossingsLoadedFromSumoNet
number of crossings loaded from a sumo net
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
bool alreadyConnectedPaths(const NBEdge *e1, const NBEdge *e2, double dist) const
return true if the given pedestrian paths are connected at another junction within dist
bool mustBrakeForCrossing(const NBEdge *const from, const NBEdge *const to, const Crossing &crossing) const
Returns the information whether the described flow must brake for the given crossing.
bool hasConflict() const
whether there are conflicting streams of traffic at this node
void removeTrafficLights(bool setAsPriority=false)
Removes all references to traffic lights that control this tls.
void replaceInConnectionProhibitions(NBEdge *which, NBEdge *by, int whichLaneOff, int byLaneOff)
replace incoming connections prohibitions
bool mergeConflictYields(const NBEdge *from, int fromLane, int fromLaneFoe, NBEdge *to, int toLane) const
whether one of multple connections from the same edge targeting the same lane must yield
void replaceOutgoing(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of outgoing by the second Connections are remap...
void getReduction(const NBEdge *in, const NBEdge *out, int &inOffset, int &outOffset, int &reduction) const
get the reduction in driving lanes at this junction
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
void computeKeepClear()
compute keepClear status for all connections
void sortEdges(bool useNodeShape)
sort all edge containers for this node
RightOfWay myRightOfWay
how to compute right of way for this node
std::set< NBTrafficLightDefinition * > myTrafficLights
traffic lights of node
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
double myRadius
the turning radius (for all corners) at this node in m.
static bool includes(const std::set< NBEdge *, ComparatorIdLess > &super, const std::set< const NBEdge *, ComparatorIdLess > &sub)
returns whether sub is a subset of super
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0, int shapeFlag=0) const
Compute a smooth curve between the given geometries.
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
bool checkCrossingDuplicated(EdgeVector edges)
return true if there already exist a crossing with the same edges as the input
void setRoundabout()
update the type of this node as a roundabout
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multple connections from the same edge target the same lane
bool myDiscardAllCrossings
whether to discard all pedestrian crossings
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool removedConnections, bool addedConnections)
causes the traffic light to be computed anew
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
add shorted link FOES
Position myPosition
The position the node lies at.
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
bool turnFoes(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *from2, const NBEdge *to2, int fromLane2, bool lefthand=false) const
return whether the given laneToLane connection originate from the same edge and are in conflict due t...
void discardAllCrossings(bool rejectAll)
discard all current (and optionally future) crossings
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
NBEdge * getPossiblySplittedOutgoing(const std::string &edgeid)
get possibly splitted outgoing edge
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
std::vector< std::unique_ptr< Crossing > > myCrossings
Vector of crossings.
void removeJoinedTrafficLights()
remove all traffic light definitions that are part of a joined tls
bool crossingBetween(const NBEdge *e1, const NBEdge *e2) const
return true if the given edges are connected by a crossing
bool isDistrict() const
check if node is a district
NBDistrict * myDistrict
The district the node is the centre of.
void computeLanes2Lanes()
computes the connections of lanes to edges
void reshiftPosition(double xoff, double yoff)
Applies an offset to the node.
double myDisplacementError
geometry error after computation of internal lane shapes
static const int AVOID_WIDE_LEFT_TURN
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
const std::string getResponse(int linkIndex) const
get the 'response' string (right-of-way bit set) of the right-of-way logic
void addWalkingAreaShape(EdgeVector edges, const PositionVector &shape)
add custom shape for walkingArea
static bool isLongEnough(NBEdge *out, double minLength)
check if is long enough
bool tlsContConflict(const NBEdge *from, const NBEdge::Connection &c, const NBEdge *foeFrom, const NBEdge::Connection &foe) const
whether the connection must yield if the foe remains on the intersection after its phase ends
const PositionVector & getShape() const
retrieve the junction shape
std::vector< WalkingArea > myWalkingAreas
Vector of walking areas.
NBConnectionProhibits myBlockedConnections
The container for connection block dependencies.
void updateSurroundingGeometry()
update geometry of node and surrounding edges
int addedLanesRight(NBEdge *out, int addedLanes) const
check whether this edge has extra lanes on the right side
const Position & getPosition() const
FringeType myFringeType
fringe type of this node
bool checkIsRemovable() const
check if node is removable
bool isRoundabout() const
return whether this node is part of a roundabout
static const int FORWARD
edge directions (for pedestrian related stuff)
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
void displaceShapeAtWidthChange(const NBEdge *from, const NBEdge::Connection &con, PositionVector &fromShape, PositionVector &toShape) const
displace lane shapes to account for change in lane width at this node
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
void removeDoubleEdges()
remove duble edges
PositionVector myPoly
the (outer) shape of the junction
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
void getEdgesThatApproach(NBEdge *currentOutgoing, EdgeVector &approaching)
returns a list of edges which are connected to the given outgoing edge
EdgeVector getEdgesSortedByAngleAtNodeCenter() const
returns the list of all edges sorted clockwise by getAngleAtNodeToCenter
EdgeVector edgesBetween(const NBEdge *e1, const NBEdge *e2) const
return all edges that lie clockwise between the given edges
PositionVector computeInternalLaneShape(const NBEdge *fromE, const NBEdge::Connection &con, int numPoints, NBNode *recordError=0, int shapeFlag=0) const
Compute the shape for an internal lane.
NBEdge * getPossiblySplittedIncoming(const std::string &edgeid)
get possibly splitted incoming edge
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset, int threshold=-1)
patches loaded signal plans by modifying lane indices above threshold by the given offset
bool geometryLike() const
whether this is structurally similar to a geometry node
bool isNearDistrict() const
@chech if node is near district
EdgeVector myIncomingEdges
Vector of incoming edges.
int checkCrossing(EdgeVector candidates)
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
int guessCrossings()
guess pedestrian crossings and return how many were guessed
bool isTLControlled() const
Returns whether this node is controlled by any tls.
static const int SCURVE_IGNORE
const std::string getFoes(int linkIndex) const
get the 'foes' string (conflict bit set) of the right-of-way logic
NBEdge * getOppositeIncoming(NBEdge *e) const
returns the opposite incoming edge of certain edge
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
This class computes shapes of junctions.
double getRadius() const
get computed radius for node
PositionVector compute()
Computes the shape of the assigned junction.
static bool isRailwayNode(const NBNode *n)
whether the given node only has rail edges
Sorts crossings by minimum clockwise clockwise edge angle. Use the ordering found in myAllEdges of th...
Sorts incoming and outgoing edges clockwise around the given node.
static void swapWhenReversed(const NBNode *const n, const std::vector< NBEdge * >::iterator &i1, const std::vector< NBEdge * >::iterator &i2)
Assures correct order for same-angle opposite-direction edges.
A traffic light logics which must be computed (only nodes/edges are given)
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
bool hasConflictAtLink(int linkIndex) const
whether there are conflicting streams of traffic for the given link index
const std::string & getFoes(int linkIndex) const
bool hasConflict() const
whether there are conflicting streams of traffic at this node
void buildBitfieldLogic()
builds the bitset-representation of the logic
static bool mustBrakeForCrossing(const NBNode *node, const NBEdge *const from, const NBEdge *const to, const NBNode::Crossing &crossing)
Returns the information whether the described flow must brake for the given crossing.
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multple connections from the same edge target the same lane
void writeLogic(OutputDevice &into) const
void computeLogic(const bool checkLaneFoes)
writes the XML-representation of the logic as a bitset-logic XML representation
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect.
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
const std::string & getResponse(int linkIndex) const
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
The base class for traffic light logic definitions.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void removeNode(NBNode *node)
Removes the given node from the list of controlled nodes.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
SUMOTime getOffset()
Returns the offset.
A container for traffic light definitions and built programs.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
Base class for objects which have an id.
std::string myID
The name of the object.
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
An upper class for objects with additional parameters.
A point in 2D or 3D with translation and scaling methods.
void set(double x, double y)
set positions x and y
static const Position INVALID
used to indicate that a position is valid
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
void sub(double dx, double dy)
Substracts the given position from this one.
double x() const
Returns the x-position.
void add(const Position &pos)
Adds the given position to this one.
void mul(double val)
Multiplies both positions with the given value.
double z() const
Returns the z-position.
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
check if two position is almost the sme as other
double y() const
Returns the y-position.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
Position intersectionPosition2D(const Position &p1, const Position &p2, const double withinDist=0.) const
Returns the position of the intersection.
void push_front_noDoublePos(const Position &p)
insert in front a non double position
bool isNAN() const
check if PositionVector is NAN
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0, double deg=90) const
return orthogonal through p (extending this vector if necessary)
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector smoothedZFront(double dist=std::numeric_limits< double >::max()) const
returned vector that is smoothed at the front (within dist)
double angleAt2D(int pos) const
get angle in certain position of position vector
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
PositionVector bezier(int numPoints)
return a bezier interpolation
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
PositionVector reverse() const
reverse position vector
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
class for maintaining associations between enums and xml-strings
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
Some static methods for string processing.
A structure which describes a connection between edges or lanes.
int fromLane
The lane the connections starts at.
int toLane
The lane the connections yields in.
const std::string & getID() const
NBEdge * toEdge
The edge the connections yields in.
PositionVector customShape
custom shape for connection
std::string getDescription(const NBEdge *parent) const
get string describing this connection
std::string tlID
The id of the traffic light that controls this connection.
bool haveVia
check if Connection have a Via
int tlLinkIndex
The index of this connection within the controlling traffic light.
An (internal) definition of a single lane of an edge.
double width
This lane's width.
double endOffset
This lane's offset to the intersection begin.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
PositionVector shape
The lane's shape.
std::set< const NBEdge *, ComparatorIdLess > edges
A definition of a pedestrian walking area.
int minPrevCrossingEdges
minimum number of edges crossed by incoming crossings
std::vector< std::string > nextSidewalks
the lane-id of the next sidewalk lane or ""
std::vector< std::string > prevSidewalks
the lane-id of the previous sidewalk lane or ""
std::string id
the (edge)-id of this walkingArea
bool hasCustomShape
whether this walkingArea has a custom shape
double width
This lane's width.
std::vector< std::string > nextCrossings
the lane-id of the next crossing(s)
PositionVector shape
The polygonal shape.
double length
This lane's width.
int minNextCrossingEdges
minimum number of edges crossed by nextCrossings