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))
98 myApproaching(approaching),
99 myCurrentOutgoing(currentOutgoing),
100 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE) {
102 std::set<int> approachedLanes;
106 approachedLanes.insert(con.toLane);
114 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
120 && approachedLanes.count(i) == 0) {
133 assert((
int)myApproaching.size() > src);
135 NBEdge* incomingEdge = myApproaching[src];
139 if (myAvailableLanes.size() == 0) {
143 if (approachingLanes.size() == 0) {
146 #ifdef DEBUG_CONNECTION_GUESSING
148 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
152 std::deque<int>* approachedLanes = spread(approachingLanes, dest);
153 assert(approachedLanes->size() <= myAvailableLanes.size());
155 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
156 assert((
int)approachingLanes.size() > i);
157 int approached = myAvailableLanes[(*approachedLanes)[i]];
160 delete approachedLanes;
166 std::deque<int>* ret =
new std::deque<int>();
167 const int numLanes = (int)approachingLanes.size();
171 ret->push_back(dest);
175 const int numOutgoingLanes = (int)myAvailableLanes.size();
177 ret->push_back(dest);
181 while (noSet < numLanes) {
187 if (numOutgoingLanes == noSet) {
196 if (dest + loffset >= numOutgoingLanes) {
199 for (
int i = 0; i < (int)ret->size(); i++) {
200 (*ret)[i] = (*ret)[i] - 1;
205 ret->push_back(dest + loffset);
210 if (numOutgoingLanes == noSet) {
215 if (noSet < numLanes) {
218 if (dest < roffset) {
221 for (
int i = 0; i < (int)ret->size(); i++) {
222 (*ret)[i] = (*ret)[i] + 1;
225 ret->push_front(dest - roffset);
244 customShape(_customShape),
245 tlLinkIndex(_customTLIndex),
246 tlLinkIndex2(_customTLIndex2),
247 customTLIndex(_customTLIndex),
248 customTLIndex2(_customTLIndex2),
281 myPosition(position),
283 myDistrict(district),
284 myHaveCustomPoly(false),
286 myRadius(UNSPECIFIED_RADIUS),
287 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
290 myDiscardAllCrossings(false),
291 myCrossingsLoadedFromSumoNet(0),
292 myDisplacementError(0),
293 myIsBentPriority(false),
294 myTypeWasGuessed(false) {
308 bool updateEdgeGeometries) {
315 if (updateEdgeGeometries) {
319 (*i)->setGeometry(geom);
324 (*i)->setGeometry(geom);
337 wacs.shape.add(xoff, yoff, 0);
340 c->customShape.add(xoff, yoff, 0);
351 c->customShape.mirrorX();
358 wacs.shape.mirrorX();
384 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
398 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
401 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
402 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
404 const std::vector<NBNode*>& nodes = orig->
getNodes();
405 while (!nodes.empty()) {
406 newDef->
addNode(nodes.front());
407 nodes.front()->removeTrafficLight(orig);
420 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
447 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
499 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
502 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
518 double extrapolateBeg,
519 double extrapolateEnd,
521 int shapeFlag)
const {
528 #ifdef DEBUG_SMOOTH_GEOM
530 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
533 if (init.size() == 0) {
535 ret.push_back(begShape.back());
536 ret.push_back(endShape.front());
548 double extrapolateBeg,
549 double extrapolateEnd,
552 double straightThresh,
555 const Position beg = begShape.back();
556 const Position end = endShape.front();
559 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
560 #ifdef DEBUG_SMOOTH_GEOM
561 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
577 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
578 init.push_back(center);
585 if (fabs(angle) <
M_PI / 4.) {
588 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
589 const double halfDistance = dist / 2;
590 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
591 #ifdef DEBUG_SMOOTH_GEOM
592 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
593 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
596 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
599 #ifdef DEBUG_SMOOTH_GEOM
600 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
601 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
602 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
603 <<
" displacementError=" << sin(displacementAngle) * dist
604 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
607 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
612 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
613 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
615 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
617 #ifdef DEBUG_SMOOTH_GEOM
618 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
619 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
620 <<
" halfDistance=" << halfDistance <<
"\n";
631 #ifdef DEBUG_SMOOTH_GEOM
633 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
634 <<
" endShapeBegLine=" << endShapeBegLine
635 <<
" begShapeEndLineRev=" << begShapeEndLineRev
640 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
646 const double minControlLength =
MIN2((
double)1.0, dist / 2);
649 const bool lengthenBeg = distBeg <= minControlLength;
650 const bool lengthenEnd = distEnd <= minControlLength;
651 if (lengthenBeg && lengthenEnd) {
652 #ifdef DEBUG_SMOOTH_GEOM
653 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
654 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
656 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
665 }
else if (lengthenBeg || lengthenEnd) {
674 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
677 :
MIN2(0.6, 16 / dist));
678 init.push_back(begShapeEndLineRev.
positionAtOffset2D(100 -
MIN2(distBeg * factor / 1.2, dist * factor / 1.8)));
679 init.push_back(endShapeBegLine.
positionAtOffset2D(100 -
MIN2(distEnd * factor / 1.2, dist * factor / 1.8)));
688 const double z3 = 0.5 * (beg.
z() + end.
z());
692 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
697 intersect.
set(intersect.
x(), intersect.
y(), z);
698 init.push_back(intersect);
711 result.push_back(begShape.back());
719 WRITE_WARNING(
"Could not compute indirect left turn shape at node '" +
getID() +
"'");
722 dir.
sub(endShape[0]);
726 result.push_back(intersect + dir);
728 result.push_back(endShape.front());
744 if (useCustomShape) {
747 if (startBorder.size() == 0) {
748 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
751 if (tmp.size() < 2) {
753 useCustomShape =
false;
757 tmp[0] = fromShape.back();
758 }
else if (recordError !=
nullptr) {
759 const double offset = tmp[0].distanceTo2D(fromShape.back());
765 if (endBorder.size() == 0) {
766 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
769 if (ret.size() < 2) {
771 useCustomShape =
false;
774 ret[-1] = toShape.front();
775 }
else if (recordError !=
nullptr) {
776 const double offset = ret[-1].distanceTo2D(toShape.front());
783 if (!useCustomShape) {
794 #ifdef DEBUG_SMOOTH_GEOM
796 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
801 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
833 for (
int i = 0; i < con.
toLane; ++i) {
837 for (
int i = 0; i < con.
fromLane; ++i) {
847 fromShape.
move2side(inCenter - outCenter);
903 const bool bothLeft = thisLeft && otherLeft;
904 if (fromE == otherFromE && !thisRight) {
911 if (c.
tlID !=
"" && !bothLeft) {
914 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
939 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
941 if ((*i)->getNodes().size() > 1) {
943 (*i)->removeNode(
this);
944 (*i)->setParticipantsInformation();
945 (*i)->setTLControllingInformation();
976 WRITE_WARNINGF(
"Junction '%' is too complicated (% connections, max %); will be set to %.",
978 }
else if (numConnections == 0) {
1002 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1010 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1013 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1070 edge->computeEdgeShape();
1098 if (mismatchThreshold >= 0
1125 #ifdef DEBUG_CONNECTION_GUESSING
1127 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a\n";
1130 int inOffset, outOffset, addedLanes;
1131 getReduction(out, in, outOffset, inOffset, addedLanes);
1136 const int addedLeft = addedLanes - addedRight;
1138 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1142 for (
int i = 0; i < addedRight; ++i) {
1147 const int outOffset2 = outOffset + addedRight + in->
getNumLanes() - inOffset;
1148 for (
int i = 0; i < addedLeft; ++i) {
1175 #ifdef DEBUG_CONNECTION_GUESSING
1177 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1186 std::swap(in1, in2);
1187 std::swap(in1Offset, in2Offset);
1217 #ifdef DEBUG_CONNECTION_GUESSING
1219 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1224 std::swap(out1, out2);
1225 std::swap(out1Offset, out2Offset);
1246 #ifdef DEBUG_CONNECTION_GUESSING
1248 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1257 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1273 #ifdef DEBUG_CONNECTION_GUESSING
1275 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f\n";
1278 int inOffset, outOffset, reduction;
1285 inOffset += reduction;
1286 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1302 const int numApproaching = (int)approaching.size();
1303 if (numApproaching != 0) {
1307 #ifdef DEBUG_CONNECTION_GUESSING
1309 std::cout <<
"l2l node=" <<
getID() <<
" bresenham:\n";
1311 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1312 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1313 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1322 bool targetProhibitsChange =
false;
1323 for (
int i = 0; i < currentOutgoing->getNumLanes(); i++) {
1324 const NBEdge::Lane& lane = currentOutgoing->getLanes()[i];
1327 targetProhibitsChange =
true;
1331 if (targetProhibitsChange) {
1335 std::map<int, int> outToIn;
1337 if (c.toEdge == currentOutgoing) {
1338 outToIn[c.toLane] = c.fromLane;
1341 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); toLane++) {
1342 if (outToIn.count(toLane) == 0) {
1345 for (
int i = 0; i < toLane; i++) {
1346 if (outToIn.count(i) != 0) {
1353 for (
int i = toLane; i < currentOutgoing->getNumLanes(); i++) {
1354 if (outToIn.count(i) != 0) {
1371 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1372 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1374 (*i)->removeFromConnections((*k).toEdge);
1385 incoming->markAsInLane2LaneState();
1389 #ifdef DEBUG_CONNECTION_GUESSING
1391 std::cout <<
"final connections at " <<
getID() <<
"\n";
1393 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1394 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1395 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1413 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1414 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1419 unsatisfied &= ~satisfied;
1422 if (unsatisfied != 0) {
1423 #ifdef DEBUG_CONNECTION_GUESSING
1425 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1429 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1430 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1431 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1433 if (satisfied != 0 && !incoming->getLaneStruct(fromLane).connectionsDone) {
1434 bool mayUseSameDestination = unsatisfied ==
SVC_TRAM;
1436 #ifdef DEBUG_CONNECTION_GUESSING
1438 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->
getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1441 unsatisfied &= ~satisfied;
1447 #ifdef DEBUG_CONNECTION_GUESSING
1449 if (unsatisfied != 0) {
1450 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1463 bool builtConnection =
false;
1464 for (
int i = 0; i < (int)incoming->getNumLanes(); i++) {
1466 && incoming->getConnectionsFromLane(i, currentOutgoing).size() == 0) {
1468 if (bikeLaneTarget >= 0) {
1470 builtConnection =
true;
1473 for (
int i2 = 0; i2 < (int)currentOutgoing->
getNumLanes(); i2++) {
1476 const bool allowDouble = (incoming->getPermissions(i) ==
SVC_BICYCLE
1479 builtConnection =
true;
1486 if (!builtConnection && bikeLaneTarget >= 0
1487 && incoming->getConnectionsFromLane(-1, currentOutgoing, bikeLaneTarget).size() == 0) {
1490 int end = (int)incoming->getNumLanes();
1493 std::swap(start, end);
1496 for (
int i = start; i < end; i += inc) {
1497 if ((incoming->getPermissions(i) &
SVC_BICYCLE) != 0) {
1524 int inOffset, outOffset, reduction;
1526 if (reduction > 0) {
1531 int outLanesRight = 0;
1532 int outLanesLeft = 0;
1533 int outLanesStraight = 0;
1536 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianLaneIndex(
FORWARD,
true));
1537 const int usableLanes = succ->getNumLanes() - outOffset;
1540 outLanesStraight += usableLanes;
1542 outLanesRight += usableLanes;
1544 outLanesLeft += usableLanes;
1549 const int usableLanes = out->
getNumLanes() - outOffset;
1550 int addedTurnLanes =
MIN3(
1552 MAX2(0, usableLanes - outLanesStraight),
1553 outLanesRight + outLanesLeft);
1554 if (outLanesLeft == 0) {
1555 return addedTurnLanes;
1557 return MIN2(addedTurnLanes / 2, outLanesRight);
1565 while (seen < minLength) {
1582 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1587 approaching.clear();
1588 for (; *i != currentOutgoing;) {
1590 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1591 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1592 if (connLanes.size() != 0) {
1593 approaching.push_back(*i);
1623 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1625 laneOff += (*i)->getNumLanes();
1655 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1657 laneOff += (*i)->getNumLanes();
1672 int whichLaneOff,
int byLaneOff) {
1676 bool changed =
false;
1678 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1681 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1695 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1697 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1698 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1758 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1759 edges.erase(find(edges.begin(), edges.end(), e));
1761 if (edges.size() == 0) {
1776 if (mayDrive.
getFrom() ==
nullptr ||
1777 mayDrive.
getTo() ==
nullptr ||
1778 mustStop.
getFrom() ==
nullptr ||
1779 mustStop.
getTo() ==
nullptr) {
1781 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1785 conn.push_back(mayDrive);
1792 int size = (int) edgeid.length();
1794 std::string
id = (*i)->
getID();
1795 if (
id.substr(0, size) == edgeid) {
1805 int size = (int) edgeid.length();
1807 std::string
id = (*i)->
getID();
1808 if (
id.substr(0, size) == edgeid) {
1833 if (removeFromConnections) {
1835 (*i)->removeFromConnections(edge);
1839 const bool incoming = edge->
getToNode() ==
this;
1841 tld->replaceRemoved(edge, -1,
nullptr, -1, incoming);
1850 EdgeVector::const_iterator i;
1852 NBNode* conn = (*i)->getFromNode();
1855 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1859 NBNode* conn = (*i)->getToNode();
1862 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1866 if (pos.
x() == 0 && pos.
y() == 0) {
1878 (*i)->invalidateConnections(reallowSetting);
1886 (*i)->invalidateConnections(reallowSetting);
1898 if (to ==
nullptr) {
1916 if (std::find(c->edges.begin(), c->edges.end(), to) != c->edges.end()) {
1926 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
1927 if (from != prohibitorFrom) {
1964 if ((!flip && fromLane <= prohibitorFromLane) ||
1965 (flip && fromLane >= prohibitorFromLane)) {
1968 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
1969 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
1998 bool lefthand)
const {
2000 if (from != from2 || to == to2 || fromLane == fromLane2) {
2008 bool result =
false;
2010 if (fromLane < fromLane2) {
2012 while (*it != to2) {
2020 while (*it != to2) {
2052 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
2062 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
2063 bool regardNonSignalisedLowerPriority)
const {
2065 possProhibitedFrom, possProhibitedTo,
2066 regardNonSignalisedLowerPriority);
2072 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
2081 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
2082 bool changed =
true;
2088 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
2093 bool blockedChanged =
false;
2095 NBConnectionVector::const_iterator j;
2096 for (j = blocked.begin(); j != blocked.end(); j++) {
2098 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
2099 blockedChanged =
true;
2103 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
2105 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2109 }
else if (sblocked.
getFrom() == removed) {
2110 assert(sblocked.
getTo() != removed);
2111 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2114 }
else if (sblocked.
getTo() == removed) {
2115 assert(sblocked.
getFrom() != removed);
2116 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2123 if (blockedChanged) {
2124 blockedConnectionsNew[blocker] = newBlocked;
2129 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2134 }
else if (blocker.
getFrom() == removed) {
2135 assert(blocker.
getTo() != removed);
2137 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2140 }
else if (blocker.
getTo() == removed) {
2141 assert(blocker.
getFrom() != removed);
2143 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2147 blockedConnectionsNew[blocker] = blocked;
2160 EdgeVector::const_iterator i = itOut;
2161 while (*i != incoming) {
2167 if ((*i)->getFromNode() !=
this) {
2175 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2185 if (candidate !=
nullptr) {
2188 if (fabs(angle - candAngle) < 5.) {
2192 if (fabs(candAngle) < fabs(angle) - 5.) {
2195 if (fabs(angle) < fabs(candAngle) - 5.) {
2198 if (fabs(candAngle) < 44.) {
2201 if (candModeLanes > modeLanes) {
2204 if (candModeLanes < modeLanes) {
2208 if (candAngle < 0 && angle > 0) {
2211 if (angle < 0 && candAngle > 0) {
2223 if (outgoing ==
nullptr) {
2242 if (fabs(angle) < 44.) {
2243 if (fabs(angle) > 6.) {
2251 if (angle > 0 && incoming->
getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
2263 if (outCW !=
nullptr) {
2270 if (angle < -170 && incoming->getGeometry().reverse() == outgoing->
getGeometry()) {
2272 }
else if (angle < -90) {
2276 if (outCCW !=
nullptr) {
2287 bool mayDefinitelyPass,
const std::string& tlID)
const {
2294 if (outgoing ==
nullptr) {
2306 if (!mayDefinitelyPass
2307 &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)
2335 reason =
"rail_signal";
2339 reason =
"crossing";
2342 EdgeVector::const_iterator i;
2347 reason =
"edges incompatible: " + reason;
2351 reason =
"turnaround";
2359 std::set<NBNode*> origSet;
2361 origSet.insert((*i)->getFromNode());
2363 if (origSet.size() < 2) {
2371 if (opposite !=
nullptr) {
2375 if (!(*i)->expandableBy(continuation, reason)) {
2376 reason =
"edges incompatible: " + reason;
2382 reason =
"not opposites";
2389 reason =
"intersection";
2394 std::vector<std::pair<NBEdge*, NBEdge*> >
2397 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2401 std::pair<NBEdge*, NBEdge*>(
2409 assert(opposite != 0);
2411 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2429 (*i)->resetNodeBorder(
this);
2438 if (e->getToNode() == n && e->getPermissions() != 0) {
2452 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2454 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2471 #ifdef DEBUG_PED_STRUCTURES
2480 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
2484 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2485 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2487 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2489 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2490 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2493 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2494 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2499 int firstSidewalk = -1;
2500 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2501 if (normalizedLanes[i].second) {
2506 int hadCandidates = 0;
2507 std::vector<int> connectedCandidates;
2508 if (firstSidewalk != -1) {
2510 std::vector<std::pair<NBEdge*, bool> > tmp;
2511 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2512 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2513 normalizedLanes = tmp;
2516 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2517 NBEdge* edge = normalizedLanes[i].first;
2518 const bool allowsPed = normalizedLanes[i].second;
2520 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2522 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2523 candidates.push_back(edge);
2524 }
else if (allowsPed) {
2525 if (candidates.size() > 0) {
2531 connectedCandidates.push_back(n);
2538 if (hadCandidates > 0 && candidates.size() > 0) {
2544 connectedCandidates.push_back(n);
2550 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2552 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2554 if (connectedCandidates.back() <= connectedCandidates.front()) {
2555 numGuessed -= connectedCandidates.back();
2558 numGuessed -= connectedCandidates.front();
2564 std::cout <<
"guessedCrossings:\n";
2566 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2573 e->computeEdgeShape();
2583 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2585 if (candidates.size() == 0) {
2587 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2592 double prevAngle = -100000;
2593 for (
int i = 0; i < (int)candidates.size(); ++i) {
2594 NBEdge* edge = candidates[i];
2599 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2605 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2614 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2619 prevAngle = -100000;
2620 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2621 double angle = (*it)->getCrossingAngle(
this);
2622 if (it != candidates.begin()) {
2623 NBEdge* prev = *(it - 1);
2628 double intermediateWidth = 0;
2631 prevPos = prev->
getLanes()[laneI].shape[-1];
2634 prevPos = prev->
getLanes()[laneI].shape[0];
2639 currPos = curr->
getLanes()[laneI].shape[0];
2642 currPos = curr->
getLanes()[laneI].shape[-1];
2648 <<
" prevAngle=" << prevAngle
2649 <<
" angle=" << angle
2650 <<
" intermediateWidth=" << intermediateWidth
2663 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2674 std::sort(edges.begin(), edges.end());
2678 EdgeVector edgesOfCrossing = crossing->edges;
2679 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2680 if (edgesOfCrossing == edges) {
2690 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2691 if (!normalizedLanes[i].second) {
2706 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2707 if (crossing->valid) {
2708 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found).",
2712 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2713 if (it_nc != wa.nextCrossings.end()) {
2714 wa.nextCrossings.erase(it_nc);
2717 crossing->valid =
false;
2718 crossing->prevWalkingArea =
"";
2719 crossing->nextWalkingArea =
"";
2724 std::vector<NBNode::Crossing*>
2726 std::vector<Crossing*> result;
2729 result.push_back(c.get());
2763 int noInternalNoSplits = 0;
2765 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2766 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2767 if ((*k).toEdge ==
nullptr) {
2770 noInternalNoSplits++;
2776 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2783 #ifdef DEBUG_PED_STRUCTURES
2787 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2803 c->nextWalkingArea =
"";
2804 c->prevWalkingArea =
"";
2807 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2813 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2816 double maxAngleDiff = 0;
2817 int maxAngleDiffIndex = 0;
2818 for (
int i = 0; i < (int) edges.size(); i++) {
2820 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2825 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2827 if (diff > maxAngleDiff) {
2828 maxAngleDiff = diff;
2829 maxAngleDiffIndex = i;
2832 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2834 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2836 std::cout <<
" rotatedEdges=" <<
toString(edges);
2840 std::reverse(edges.begin(), edges.end());
2842 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2846 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2847 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2848 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2849 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2851 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross).", c->id,
getID(),
toString(c->edges));
2853 }
else if (c->customShape.size() != 0) {
2854 c->shape = c->customShape;
2856 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2857 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2866 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (invalid shape).", c->id,
getID(),
toString(c->edges));
2869 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2870 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2880 #ifdef DEBUG_PED_STRUCTURES
2886 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2893 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2894 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2896 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2898 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2902 normalizedLanes.push_back(std::make_pair(edge, l));
2905 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2910 normalizedLanes.push_back(std::make_pair(edge, l));
2916 std::vector<std::pair<int, int> > waIndices;
2918 NBEdge* prevEdge = normalizedLanes.back().first;
2919 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2920 NBEdge* edge = normalizedLanes[i].first;
2930 waIndices.push_back(std::make_pair(start, i - start));
2940 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2945 const int waNumLanes = (int)normalizedLanes.size() - start;
2946 if (waIndices.size() == 0) {
2947 waIndices.push_back(std::make_pair(start, waNumLanes));
2949 std::cout <<
" single wa, end at wrap-around\n";
2952 if (waIndices.front().first == 0) {
2953 NBEdge* edge = normalizedLanes.front().first;
2956 waIndices.push_back(std::make_pair(start, waNumLanes));
2958 std::cout <<
" do not wrap around, turn-around in between\n";
2962 waIndices.front().first = start;
2963 waIndices.front().second = waNumLanes + waIndices.front().second;
2965 std::cout <<
" wrapping around\n";
2970 waIndices.push_back(std::make_pair(start, waNumLanes));
2972 std::cout <<
" end at wrap-around\n";
2978 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2979 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2980 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2984 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2985 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2986 const int startIdx = waIndices[i].first;
2987 const int prev = startIdx > 0 ? startIdx - 1 : (int)normalizedLanes.size() - 1;
2988 const int count = waIndices[i].second;
2989 const int end = (startIdx + count) % normalizedLanes.size();
2993 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << startIdx <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2995 double endCrossingWidth = 0;
2996 double startCrossingWidth = 0;
3000 bool connectsCrossing =
false;
3001 std::vector<Position> connectedPoints;
3004 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
3006 if (c->edges.back() == normalizedLanes[end].first
3007 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
3009 if (c->nextWalkingArea !=
"") {
3010 WRITE_WARNINGF(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'.",
3011 getID(), c->id, c->nextWalkingArea, wa.
id);
3014 c->nextWalkingArea = wa.
id;
3017 endCrossingWidth = c->width;
3018 endCrossingShape = c->shape;
3020 connectsCrossing =
true;
3021 connectedPoints.push_back(c->shape[-1]);
3025 std::cout <<
" crossing " << c->id <<
" ends\n";
3028 if (c->edges.front() == normalizedLanes[prev].first
3029 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
3031 if (c->prevWalkingArea !=
"") {
3032 WRITE_WARNINGF(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'.",
3033 getID(), c->id, c->prevWalkingArea, wa.
id);
3036 c->prevWalkingArea = wa.
id;
3040 startCrossingWidth = c->width;
3041 startCrossingShape = c->shape;
3043 connectsCrossing =
true;
3044 connectedPoints.push_back(c->shape[0]);
3048 std::cout <<
" crossing " << c->id <<
" starts\n";
3051 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
3052 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
3053 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[startIdx].first->getID()
3054 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
3057 if (count < 2 && !connectsCrossing) {
3060 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
3065 std::set<NBEdge*, ComparatorIdLess> connected;
3066 for (
int j = 0; j < count; ++j) {
3067 const int nlI = (startIdx + j) % normalizedLanes.size();
3068 NBEdge* edge = normalizedLanes[nlI].first;
3071 if (connected.count(edge) == 0) {
3079 connected.insert(edge);
3086 if (buildExtensions) {
3088 if (startCrossingShape.size() > 0) {
3090 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
3092 startCrossingShape.
move2side(startCrossingWidth / 2);
3094 startCrossingShape.
move2side(-startCrossingWidth);
3098 if (endCrossingShape.size() > 0) {
3100 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
3102 endCrossingShape.
move2side(endCrossingWidth / 2);
3104 endCrossingShape.
move2side(-endCrossingWidth);
3109 && normalizedLanes.size() == 2) {
3111 NBEdge* e1 = *connected.begin();
3112 NBEdge* e2 = *(++connected.begin());
3115 std::cout <<
" not building a walkingarea since normal connections exist\n";
3121 if (cornerDetail > 0) {
3122 int smoothEnd = end;
3123 int smoothPrev = prev;
3125 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
3126 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
3128 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
3129 if (smoothPrev == 0) {
3130 smoothPrev = (int)normalizedLanes.size() - 1;
3135 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
3136 begShape = begShape.
reverse();
3138 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3139 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3140 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3143 if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3146 if (curve.
length2D() - begShape.back().distanceTo2D(endShape.front()) > 5) {
3153 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3157 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
3158 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3159 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
3160 if (curve.size() > 2) {
3161 curve.erase(curve.begin());
3163 if (endCrossingWidth > 0) {
3164 wa.
shape.pop_back();
3166 if (startCrossingWidth > 0) {
3177 if (wacs.shape.size() != 0) {
3178 wa.
shape = wacs.shape;
3181 wa.
width = wacs.width;
3188 double lengthSum = 0;
3189 int combinations = 0;
3190 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3191 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3201 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
3203 wa.
length = POSITION_EPS;
3204 if (combinations > 0) {
3205 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3210 std::vector<Crossing*> validCrossings =
getCrossings();
3211 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3213 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3215 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
3230 wa.
shape.push_back(tmp[-1]);
3232 wa.
shape.push_back(tmp[-1]);
3236 wa.
shape.push_back(tmp[0]);
3238 wa.
shape.push_back(tmp[0]);
3241 std::set<NBEdge*, ComparatorIdLess> crossed(prev.
edges.begin(), prev.
edges.end());
3242 crossed.insert(next.
edges.begin(), next.
edges.end());
3245 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(crossed, wacs.edges)) {
3246 wa.
shape = wacs.shape;
3255 std::cout <<
" build wa=" << wa.
id <<
"\n";
3263 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3265 for (
const NBEdge* e : sub) {
3266 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3285 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3286 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3287 if (it1 != edges.end() && it2 != edges.end()) {
3312 return other1 == other2;
3324 while (it != it_end) {
3325 result.push_back(*it);
3335 wacs.
edges.insert(edges.begin(), edges.end());
3349 if (incoming.size() == 1 && outgoing.size() == 1) {
3352 if (incoming.size() == 2 && outgoing.size() == 2) {
3355 NBEdge* in0 = incoming[0];
3356 NBEdge* in1 = incoming[1];
3357 NBEdge* out0 = outgoing[0];
3358 NBEdge* out1 = outgoing[1];
3363 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
3367 if (
MAX2(angle0, angle1) <= 160) {
3387 if (out->getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
3397 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
3398 myCrossings.push_back(std::unique_ptr<Crossing>(c));
3408 EdgeSet edgeSet(edges.begin(), edges.end());
3410 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
3411 if (edgeSet == edgeSet2) {
3427 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
3433 EdgeSet edgeSet(edges.begin(), edges.end());
3435 EdgeSet edgeSet2(it->edges.begin(), it->edges.end());
3436 if (edgeSet == edgeSet2) {
3443 throw ProcessError(
"Request for unknown crossing for the given Edges");
3450 bool usedCustom =
false;
3452 c->tlLinkIndex = startIndex++;
3454 if (c->customTLIndex != -1) {
3455 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
3456 c->tlLinkIndex = c->customTLIndex;
3458 c->tlLinkIndex2 = c->customTLIndex2;
3470 result += (int)edge->getConnections().size();
3483 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
3484 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
3520 std::cout <<
" angles:\n";
3521 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3522 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3524 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3529 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
3531 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
3533 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
3545 if (turnDest !=
nullptr) {
3565 if (def->rightOnRedConflict(index, foeIndex)) {
3587 std::vector<NBEdge*>::iterator j;
3588 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3591 if (allEdges.size() > 1 && j != allEdges.end()) {
3596 NBEdge* firstOfAll = allEdges.front();
3597 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3598 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3604 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3605 if (firstOfIncoming !=
nullptr) {
3606 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3608 if (firstOfOutgoing !=
nullptr) {
3609 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3611 #ifdef DEBUG_EDGE_SORTING
3613 std::cout <<
"sortedEdges:\n";
3614 for (
NBEdge* e : allEdges) {
3615 std::cout <<
" " << e->getID()
3616 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3617 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3624 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3625 std::vector<NBEdge*>::const_iterator in, out;
3626 std::vector<NBEdge*> allTmp;
3627 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3628 if ((*in)->isTurningDirectionAt(*out)) {
3629 allTmp.push_back(*in);
3630 allTmp.push_back(*out);
3635 if (allTmp.size() == allEdges.size()) {
3648 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3652 e->computeEdgeShape();
3657 std::vector<std::pair<Position, std::string> >
3660 std::vector<std::pair<Position, std::string> >result;
3662 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3663 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
3665 for (
const auto& pair : result) {
3666 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
3672 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
const SVCPermissions SVCAll
all VClasses are allowed
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_IGNORING
vehicles ignoring classes
@ 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
FringeType
classifying boundary nodes
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 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 indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain 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.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
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
int getNumLanesThatAllow(SVCPermissions permissions) const
get lane indices that allow the given permissions
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
@ 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.
int getFirstNonPedestrianNonBicycleLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN, SVC_BICYCLE and 0
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 available 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
void invalidateOutgoingConnections(bool reallowSetting=false)
invalidate outgoing connections
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 addWalkingAreaShape(EdgeVector edges, const PositionVector &shape, double width)
add custom shape for walkingArea
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.
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 recheckVClassConnections(NBEdge *currentOutgoing)
ensure connectivity for all vClasses
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
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
void invalidateIncomingConnections(bool reallowSetting=false)
invalidate incoming connections
NBRequest * myRequest
Node requests.
void mirrorX()
mirror coordinates along the x-axis
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.
PositionVector indirectLeftShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints) const
compute shape of indirect left turn
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)
bool brakeForCrossingOnExit(const NBEdge *to) const
whether a connection to the given edge must brake for a crossing when leaving the intersection
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.
bool isStraighter(const NBEdge *const incoming, const double angle, const SVCPermissions vehPerm, const int modeLanes, const NBEdge *const candidate) const
check whether the candidate edge is more likely to be the straight continuation
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
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
static const int INDIRECT_LEFT
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
const 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
bool indirectLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether straight and indirect left turn are in conflict
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.
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
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.
bool indirectLeft
Whether this connection is an indirect left turn.
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 changeRight
List of vehicle types that are allowed to change right from this lane.
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this lane.
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