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 ""
74#define DEBUGCOND (getID() == DEBUG_NODE_ID)
75#define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUG_NODE_ID))
98 myApproaching(approaching),
99 myCurrentOutgoing(currentOutgoing),
101 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE) {
103 std::set<int> approachedLanes;
107 approachedLanes.insert(con.toLane);
110 myDirections.push_back(approachingEdge->getToNode()->getDirection(approachingEdge, currentOutgoing));
119 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
125 && approachedLanes.count(i) == 0) {
138 assert((
int)myApproaching.size() > src);
140 NBEdge* incomingEdge = myApproaching[src];
144 if (myAvailableLanes.size() == 0) {
148 if (approachingLanes.size() == 0) {
151#ifdef DEBUG_CONNECTION_GUESSING
153 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
157 int numConnections = (int)approachingLanes.size();
169 numConnections = (int)myAvailableLanes.size();
170 factor = (double)approachingLanes.size() / (double)numConnections;
175 std::deque<int>* approachedLanes = spread(numConnections, dest);
176 assert(approachedLanes->size() <= myAvailableLanes.size());
178 const int maxFrom = (int)approachingLanes.size() - 1;
179 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
182 int fromLane = approachingLanes[
MIN2((
int)(i * factor), maxFrom)];
183 int approached = myAvailableLanes[(*approachedLanes)[i]];
186 delete approachedLanes;
192 std::deque<int>* ret =
new std::deque<int>();
196 ret->push_back(dest);
200 const int numOutgoingLanes = (int)myAvailableLanes.size();
202 ret->push_back(dest);
206 while (noSet < numLanes) {
212 if (numOutgoingLanes == noSet) {
221 if (dest + loffset >= numOutgoingLanes) {
224 for (
int i = 0; i < (int)ret->size(); i++) {
225 (*ret)[i] = (*ret)[i] - 1;
230 ret->push_back(dest + loffset);
235 if (numOutgoingLanes == noSet) {
240 if (noSet < numLanes) {
243 if (dest < roffset) {
246 for (
int i = 0; i < (int)ret->size(); i++) {
247 (*ret)[i] = (*ret)[i] + 1;
250 ret->push_front(dest - roffset);
269 customShape(_customShape),
270 tlLinkIndex(_customTLIndex),
271 tlLinkIndex2(_customTLIndex2),
272 customTLIndex(_customTLIndex),
273 customTLIndex2(_customTLIndex2),
306 myPosition(position),
308 myDistrict(district),
309 myHaveCustomPoly(false),
311 myRadius(UNSPECIFIED_RADIUS),
312 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
315 myDiscardAllCrossings(false),
316 myCrossingsLoadedFromSumoNet(0),
317 myDisplacementError(0),
318 myIsBentPriority(false),
319 myTypeWasGuessed(false) {
333 bool updateEdgeGeometries) {
340 if (updateEdgeGeometries) {
344 (*i)->setGeometry(geom);
349 (*i)->setGeometry(geom);
362 wacs.shape.add(xoff, yoff, 0);
365 c->customShape.add(xoff, yoff, 0);
376 c->customShape.mirrorX();
383 wacs.shape.mirrorX();
409 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
423 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
426 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
427 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
429 const std::vector<NBNode*>& nodes = orig->
getNodes();
430 while (!nodes.empty()) {
431 newDef->
addNode(nodes.front());
432 nodes.front()->removeTrafficLight(orig);
445 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
472 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
524 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
527 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
543 double extrapolateBeg,
544 double extrapolateEnd,
546 int shapeFlag)
const {
553#ifdef DEBUG_SMOOTH_GEOM
555 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
558 if (init.size() == 0) {
560 ret.push_back(begShape.back());
561 ret.push_back(endShape.front());
573 double extrapolateBeg,
574 double extrapolateEnd,
577 double straightThresh,
580 const Position beg = begShape.back();
581 const Position end = endShape.front();
584 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
585#ifdef DEBUG_SMOOTH_GEOM
586 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
602 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
603 init.push_back(center);
610 if (fabs(angle) <
M_PI / 4.) {
613 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
614 const double halfDistance = dist / 2;
615 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
616#ifdef DEBUG_SMOOTH_GEOM
617 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
618 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
621 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
624#ifdef DEBUG_SMOOTH_GEOM
625 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
626 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
627 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
628 <<
" displacementError=" << sin(displacementAngle) * dist
629 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
632 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
637 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
638 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
640 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
642#ifdef DEBUG_SMOOTH_GEOM
643 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
644 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
645 <<
" halfDistance=" << halfDistance <<
"\n";
656#ifdef DEBUG_SMOOTH_GEOM
658 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
659 <<
" endShapeBegLine=" << endShapeBegLine
660 <<
" begShapeEndLineRev=" << begShapeEndLineRev
665 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
671 const double minControlLength =
MIN2((
double)1.0, dist / 2);
674 const bool lengthenBeg = distBeg <= minControlLength;
675 const bool lengthenEnd = distEnd <= minControlLength;
676 if (lengthenBeg && lengthenEnd) {
677#ifdef DEBUG_SMOOTH_GEOM
678 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
679 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
681 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
690 }
else if (lengthenBeg || lengthenEnd) {
699 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
702 :
MIN2(0.6, 16 / dist));
703 init.push_back(begShapeEndLineRev.
positionAtOffset2D(100 -
MIN2(distBeg * factor / 1.2, dist * factor / 1.8)));
704 init.push_back(endShapeBegLine.
positionAtOffset2D(100 -
MIN2(distEnd * factor / 1.2, dist * factor / 1.8)));
713 const double z3 = 0.5 * (beg.
z() + end.
z());
717 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
722 intersect.
set(intersect.
x(), intersect.
y(), z);
723 init.push_back(intersect);
736 result.push_back(begShape.back());
747 dir.
sub(endShape[0]);
751 result.push_back(intersect + dir);
753 result.push_back(endShape.front());
769 if (useCustomShape) {
772 if (startBorder.size() == 0) {
773 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
776 if (tmp.size() < 2) {
778 useCustomShape =
false;
782 tmp[0] = fromShape.back();
783 }
else if (recordError !=
nullptr) {
784 const double offset = tmp[0].distanceTo2D(fromShape.back());
790 if (endBorder.size() == 0) {
791 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
794 if (ret.size() < 2) {
796 useCustomShape =
false;
799 ret[-1] = toShape.front();
800 }
else if (recordError !=
nullptr) {
801 const double offset = ret[-1].distanceTo2D(toShape.front());
808 if (!useCustomShape) {
819#ifdef DEBUG_SMOOTH_GEOM
821 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
826 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
858 for (
int i = 0; i < con.
toLane; ++i) {
862 for (
int i = 0; i < con.
fromLane; ++i) {
872 fromShape.
move2side(inCenter - outCenter);
930 const bool bothLeft = thisLeft && otherLeft;
931 if (fromE == otherFromE && !thisRight) {
938 if (c.
tlID !=
"" && !bothLeft) {
941 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
966 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
968 if ((*i)->getNodes().size() > 1) {
970 (*i)->removeNode(
this);
971 (*i)->setParticipantsInformation();
972 (*i)->setTLControllingInformation();
1003 WRITE_WARNINGF(
TL(
"Junction '%' is too complicated (% connections, max %); will be set to %."),
1005 }
else if (numConnections == 0) {
1029 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1037 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1040 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1113 edge->computeEdgeShape();
1141 if (mismatchThreshold >= 0
1168 int inOffset, outOffset, addedLanes;
1169 getReduction(out, in, outOffset, inOffset, addedLanes);
1173#ifdef DEBUG_CONNECTION_GUESSING
1175 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a\n";
1179 const int addedLeft = addedLanes - addedRight;
1181 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1185 for (
int i = 0; i < addedRight; ++i) {
1190 const int outOffset2 = outOffset + addedRight + in->
getNumLanes() - inOffset;
1191 for (
int i = 0; i < addedLeft; ++i) {
1224#ifdef DEBUG_CONNECTION_GUESSING
1226 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1266#ifdef DEBUG_CONNECTION_GUESSING
1268 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1295#ifdef DEBUG_CONNECTION_GUESSING
1297 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1306 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1322 int inOffset, outOffset, reduction;
1328#ifdef DEBUG_CONNECTION_GUESSING
1330 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f\n";
1334 inOffset += reduction;
1335 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1352 const int numApproaching = (int)approaching.size();
1353 if (numApproaching != 0) {
1357#ifdef DEBUG_CONNECTION_GUESSING
1359 std::cout <<
"l2l node=" <<
getID() <<
" bresenham:\n";
1361 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1362 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1363 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1372 bool targetProhibitsChange =
false;
1373 for (
int i = 0; i < currentOutgoing->getNumLanes(); i++) {
1374 const NBEdge::Lane& lane = currentOutgoing->getLanes()[i];
1377 targetProhibitsChange =
true;
1381 if (targetProhibitsChange) {
1385 std::map<int, int> outToIn;
1387 if (c.toEdge == currentOutgoing) {
1388 outToIn[c.toLane] = c.fromLane;
1391 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); toLane++) {
1392 if (outToIn.count(toLane) == 0) {
1395 for (
int i = 0; i < toLane; i++) {
1396 if (outToIn.count(i) != 0) {
1403 for (
int i = toLane; i < currentOutgoing->getNumLanes(); i++) {
1404 if (outToIn.count(i) != 0) {
1421 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1422 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1424 (*i)->removeFromConnections((*k).toEdge);
1435 incoming->markAsInLane2LaneState();
1439#ifdef DEBUG_CONNECTION_GUESSING
1441 std::cout <<
"final connections at " <<
getID() <<
"\n";
1443 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1444 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1445 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1463 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1464 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1469 unsatisfied &= ~satisfied;
1472 if (unsatisfied != 0) {
1473#ifdef DEBUG_CONNECTION_GUESSING
1475 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1479 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1480 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1481 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1483 if (satisfied != 0 && !incoming->getLaneStruct(fromLane).connectionsDone) {
1484 if (incoming->hasConnectionTo(currentOutgoing, toLane)
1486 && incoming->getPermissions(fromLane) == currentOutgoing->
getPermissions(toLane)) {
1488 for (
auto con : incoming->getConnections()) {
1489 if (con.toEdge == currentOutgoing && con.toLane == toLane) {
1490#ifdef DEBUG_CONNECTION_GUESSING
1492 std::cout <<
" shifting connection from=" << con.fromLane <<
" to=" << currentOutgoing->
getID() <<
"_" << toLane <<
": newFromLane=" << fromLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1495 incoming->getConnectionRef(con.fromLane, con.toEdge, toLane).fromLane = fromLane;
1496 unsatisfied &= ~satisfied;
1504#ifdef DEBUG_CONNECTION_GUESSING
1506 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1509 unsatisfied &= ~satisfied;
1516#ifdef DEBUG_CONNECTION_GUESSING
1518 if (unsatisfied != 0) {
1519 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1532 bool builtConnection =
false;
1533 for (
int i = 0; i < (int)incoming->getNumLanes(); i++) {
1535 && incoming->getConnectionsFromLane(i, currentOutgoing).size() == 0) {
1537 if (bikeLaneTarget >= 0) {
1539 builtConnection =
true;
1542 for (
int i2 = 0; i2 < (int)currentOutgoing->
getNumLanes(); i2++) {
1545 const bool allowDouble = (incoming->getPermissions(i) ==
SVC_BICYCLE
1548 builtConnection =
true;
1555 if (!builtConnection && bikeLaneTarget >= 0
1556 && incoming->getConnectionsFromLane(-1, currentOutgoing, bikeLaneTarget).size() == 0) {
1559 int end = incoming->getNumLanes();
1565 for (
int i = start; i < end; i += inc) {
1566 if ((incoming->getPermissions(i) &
SVC_BICYCLE) != 0) {
1593 int inOffset, outOffset, reduction;
1595 if (reduction > 0) {
1600 int outLanesRight = 0;
1601 int outLanesLeft = 0;
1602 int outLanesStraight = 0;
1605 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianNonBicycleLaneIndex(
FORWARD,
true));
1606 const int usableLanes = succ->getNumLanes() - outOffset;
1609 outLanesStraight += usableLanes;
1611 outLanesRight += usableLanes;
1613 outLanesLeft += usableLanes;
1618 const int usableLanes = out->
getNumLanes() - outOffset;
1619 int addedTurnLanes =
MIN3(
1621 MAX2(0, usableLanes - outLanesStraight),
1622 outLanesRight + outLanesLeft);
1623 if (outLanesLeft == 0) {
1624 return addedTurnLanes;
1626 return MIN2(addedTurnLanes / 2, outLanesRight);
1634 while (seen < minLength) {
1651 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1656 approaching.clear();
1657 for (; *i != currentOutgoing;) {
1659 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1660 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1661 if (connLanes.size() != 0) {
1662 approaching.push_back(*i);
1692 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1694 laneOff += (*i)->getNumLanes();
1724 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1726 laneOff += (*i)->getNumLanes();
1741 int whichLaneOff,
int byLaneOff) {
1745 bool changed =
false;
1747 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1750 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1764 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1766 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1767 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1827 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1828 edges.erase(find(edges.begin(), edges.end(), e));
1830 if (edges.size() == 0) {
1845 if (mayDrive.
getFrom() ==
nullptr ||
1846 mayDrive.
getTo() ==
nullptr ||
1847 mustStop.
getFrom() ==
nullptr ||
1848 mustStop.
getTo() ==
nullptr) {
1850 WRITE_WARNING(
TL(
"Something went wrong during the building of a connection..."));
1854 conn.push_back(mayDrive);
1861 int size = (int) edgeid.length();
1863 std::string
id = (*i)->
getID();
1864 if (
id.substr(0, size) == edgeid) {
1874 int size = (int) edgeid.length();
1876 std::string
id = (*i)->
getID();
1877 if (
id.substr(0, size) == edgeid) {
1907 if (removeFromConnections) {
1909 (*i)->removeFromConnections(edge);
1913 const bool incoming = edge->
getToNode() ==
this;
1915 tld->replaceRemoved(edge, -1,
nullptr, -1, incoming);
1925 Position toAdd = in->getFromNode()->getPosition();
1931 Position toAdd = out->getToNode()->getPosition();
1937 if (pos.
x() == 0. && pos.
y() == 0.) {
1949 (*i)->invalidateConnections(reallowSetting);
1957 (*i)->invalidateConnections(reallowSetting);
1969 if (to ==
nullptr) {
1991 if (std::find(c->edges.begin(), c->edges.end(), to) != c->edges.end()) {
2001 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
2002 if (from != prohibitorFrom) {
2039 if ((!flip && fromLane <= prohibitorFromLane) ||
2040 (flip && fromLane >= prohibitorFromLane)) {
2043 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
2044 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
2073 bool lefthand)
const {
2075 if (from != from2 || to == to2 || fromLane == fromLane2) {
2083 bool result =
false;
2085 if (fromLane < fromLane2) {
2087 while (*it != to2) {
2095 while (*it != to2) {
2127 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
2137 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
2138 bool regardNonSignalisedLowerPriority)
const {
2140 possProhibitedFrom, possProhibitedTo,
2141 regardNonSignalisedLowerPriority);
2147 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
2156 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
2157 bool changed =
true;
2163 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
2168 bool blockedChanged =
false;
2170 NBConnectionVector::const_iterator j;
2171 for (j = blocked.begin(); j != blocked.end(); j++) {
2173 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
2174 blockedChanged =
true;
2178 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
2180 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2184 }
else if (sblocked.
getFrom() == removed) {
2185 assert(sblocked.
getTo() != removed);
2186 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2189 }
else if (sblocked.
getTo() == removed) {
2190 assert(sblocked.
getFrom() != removed);
2191 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2198 if (blockedChanged) {
2199 blockedConnectionsNew[blocker] = newBlocked;
2204 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2209 }
else if (blocker.
getFrom() == removed) {
2210 assert(blocker.
getTo() != removed);
2212 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2215 }
else if (blocker.
getTo() == removed) {
2216 assert(blocker.
getFrom() != removed);
2218 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2222 blockedConnectionsNew[blocker] = blocked;
2235 EdgeVector::const_iterator i = itOut;
2236 while (*i != incoming) {
2242 if ((*i)->getFromNode() !=
this) {
2250 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2260 if (candidate !=
nullptr) {
2263 if (fabs(angle - candAngle) < 5.) {
2267 if (fabs(candAngle) < fabs(angle) - 5.) {
2270 if (fabs(angle) < fabs(candAngle) - 5.) {
2273 if (fabs(candAngle) < 44.) {
2276 if (candModeLanes > modeLanes) {
2279 if (candModeLanes < modeLanes) {
2283 if (candAngle < 0 && angle > 0) {
2286 if (angle < 0 && candAngle > 0) {
2299 result.push_back(e);
2308 if (outgoing ==
nullptr) {
2327 vehPerm &= ~SVC_PEDESTRIAN;
2330 if (fabs(angle) < 44.) {
2331 if (fabs(angle) > 6.) {
2339 if (angle > 0 && incoming->
getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
2351 if (outCW !=
nullptr) {
2358 if (angle < -170 && incoming->getGeometry().reverse() == outgoing->
getGeometry()) {
2363 }
else if (angle < -90) {
2367 if (outCCW !=
nullptr) {
2390 bool mayDefinitelyPass,
const std::string& tlID)
const {
2400 if (outgoing ==
nullptr) {
2404 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)) {
2413 if (!mayDefinitelyPass
2414 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)
2428 if (
mustBrake(incoming, outgoing, fromLane, toLane,
false)) {
2432 if ((in != incoming || c.fromLane != fromLane) && c.toEdge == outgoing && c.toLane == toLane) {
2459 reason =
"rail_signal";
2463 reason =
"crossing";
2466 EdgeVector::const_iterator i;
2471 reason =
"edges incompatible: " + reason;
2475 reason =
"turnaround";
2483 std::set<NBNode*> origSet;
2485 origSet.insert((*i)->getFromNode());
2487 if (origSet.size() < 2) {
2502 if (opposite !=
nullptr) {
2506 if (!(*i)->expandableBy(continuation, reason)) {
2507 reason =
"edges incompatible: " + reason;
2513 reason =
"not opposites";
2520 reason =
"intersection";
2525std::vector<std::pair<NBEdge*, NBEdge*> >
2528 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2553 assert(opposite != 0);
2555 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2573 (*i)->resetNodeBorder(
this);
2582 if (e->getToNode() == n && e->getPermissions() != 0) {
2596 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2598 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2615#ifdef DEBUG_PED_STRUCTURES
2624 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
2628 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2629 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2631 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2633 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2634 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2637 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2638 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2643 int firstSidewalk = -1;
2644 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2645 if (normalizedLanes[i].second) {
2650 int hadCandidates = 0;
2651 std::vector<int> connectedCandidates;
2652 if (firstSidewalk != -1) {
2654 std::vector<std::pair<NBEdge*, bool> > tmp;
2655 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2656 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2657 normalizedLanes = tmp;
2660 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2661 NBEdge* edge = normalizedLanes[i].first;
2662 const bool allowsPed = normalizedLanes[i].second;
2664 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2666 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2667 candidates.push_back(edge);
2668 }
else if (allowsPed) {
2669 if (candidates.size() > 0) {
2675 connectedCandidates.push_back(n);
2682 if (hadCandidates > 0 && candidates.size() > 0) {
2688 connectedCandidates.push_back(n);
2694 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2696 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2698 if (connectedCandidates.back() <= connectedCandidates.front()) {
2699 numGuessed -= connectedCandidates.back();
2702 numGuessed -= connectedCandidates.front();
2708 std::cout <<
"guessedCrossings:\n";
2710 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2717 e->computeEdgeShape();
2727 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2729 if (candidates.size() == 0) {
2731 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2736 double prevAngle = -100000;
2737 for (
int i = 0; i < (int)candidates.size(); ++i) {
2738 NBEdge* edge = candidates[i];
2743 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2749 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2759 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2765 prevAngle = -100000;
2766 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2767 double angle = (*it)->getCrossingAngle(
this);
2768 if (it != candidates.begin()) {
2769 NBEdge* prev = *(it - 1);
2774 double intermediateWidth = 0;
2777 prevPos = prev->
getLanes()[laneI].shape[-1];
2780 prevPos = prev->
getLanes()[laneI].shape[0];
2785 currPos = curr->
getLanes()[laneI].shape[0];
2788 currPos = curr->
getLanes()[laneI].shape[-1];
2794 <<
" prevAngle=" << prevAngle
2795 <<
" angle=" << angle
2796 <<
" intermediateWidth=" << intermediateWidth
2810 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2822 std::sort(edges.begin(), edges.end());
2826 EdgeVector edgesOfCrossing = crossing->edges;
2827 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2828 if (edgesOfCrossing == edges) {
2838 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2839 if (!normalizedLanes[i].second) {
2856 std::set<std::string> waIDs;
2857 int numSidewalks = 0;
2859 waIDs.insert(wa.id);
2860 numSidewalks += (int)(wa.prevSidewalks.size() + wa.nextSidewalks.size());
2862 if (numSidewalks < 2) {
2867 if (waIDs.count(crossing->prevWalkingArea) == 0 || waIDs.count(crossing->nextWalkingArea) == 0 || !crossing->valid) {
2868 if (crossing->valid) {
2869 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found)."),
2886 crossing->valid =
false;
2887 crossing->prevWalkingArea =
"";
2888 crossing->nextWalkingArea =
"";
2895std::vector<NBNode::Crossing*>
2897 std::vector<Crossing*> result;
2900 result.push_back(c.get());
2934 int noInternalNoSplits = 0;
2937 if (con.toEdge ==
nullptr) {
2940 noInternalNoSplits++;
2945 double maxCrossingSeconds = 0.;
2947 maxCrossingSeconds =
MAX2(maxCrossingSeconds, edge->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo));
2949 return maxCrossingSeconds;
2955#ifdef DEBUG_PED_STRUCTURES
2959 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2975 c->nextWalkingArea =
"";
2976 c->prevWalkingArea =
"";
2979 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2985 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2988 std::vector<double> rawAngleDiffs;
2989 double maxAngleDiff = 0;
2990 int maxAngleDiffIndex = 0;
2991 for (
int i = 0; i < (int) edges.size(); i++) {
2993 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2998 edges[i]->getAngleAtNodeNormalized(
this),
2999 edges[(i + 1) % edges.size()]->getAngleAtNodeNormalized(
this));
3000 rawAngleDiffs.push_back(fabs(rawDiff));
3003 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
3005 if (diff > maxAngleDiff) {
3006 maxAngleDiff = diff;
3007 maxAngleDiffIndex = i;
3010 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
3012 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
3014 std::cout <<
" rotatedEdges=" <<
toString(edges);
3017 bool diagonalCrossing =
false;
3018 std::sort(rawAngleDiffs.begin(), rawAngleDiffs.end());
3019 if (rawAngleDiffs.size() >= 2 && rawAngleDiffs[rawAngleDiffs.size() - 2] > 30) {
3020 diagonalCrossing =
true;
3022 std::cout <<
" detected pedScramble " << c->id <<
" edges=" <<
toString(edges) <<
" rawDiffs=" <<
toString(rawAngleDiffs) <<
"\n";
3023 for (
auto e : edges) {
3024 std::cout <<
" e=" << e->getID()
3025 <<
" aC=" << e->getAngleAtNodeToCenter(
this)
3026 <<
" a=" << e->getAngleAtNode(
this)
3027 <<
" aN=" << e->getAngleAtNodeNormalized(
this)
3033 std::reverse(edges.begin(), edges.end());
3036 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
3037 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
3038 int firstNonPedLane = edges.front()->getFirstNonPedestrianLaneIndex(begDir);
3039 int lastNonPedLane = edges.back()->getFirstNonPedestrianLaneIndex(endDir);
3041 std::cout <<
" finalEdges=" <<
toString(edges) <<
" firstNonPedLane=" << firstNonPedLane <<
" lastNonPedLane=" << lastNonPedLane <<
"\n";
3043 if (firstNonPedLane < 0 || lastNonPedLane < 0) {
3045 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross)."), c->id,
getID(),
toString(c->edges));
3048 firstNonPedLane = begDir ==
FORWARD ? 0 : edges.front()->getNumLanes() - 1;
3049 lastNonPedLane = endDir ==
FORWARD ? 0 : edges.back()->getNumLanes() - 1;
3051 if (c->customShape.size() != 0) {
3052 c->shape = c->customShape;
3054 NBEdge::Lane crossingBeg = edges.front()->getLanes()[firstNonPedLane];
3055 NBEdge::Lane crossingEnd = edges.back()->getLanes()[lastNonPedLane];
3067 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
3068 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
3070 if (diagonalCrossing) {
3071 c->shape.move2side(-c->width);
3081#ifdef DEBUG_PED_STRUCTURES
3087 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
3094 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
3095 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
3097 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
3099 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
3103 normalizedLanes.push_back(std::make_pair(edge, l));
3106 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
3111 normalizedLanes.push_back(std::make_pair(edge, l));
3117 std::vector<std::pair<int, int> > waIndices;
3119 NBEdge* prevEdge = normalizedLanes.back().first;
3120 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
3121 NBEdge* edge = normalizedLanes[i].first;
3133 waIndices.push_back(std::make_pair(start, i - start));
3143 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
3148 const int waNumLanes = (int)normalizedLanes.size() - start;
3149 if (waIndices.size() == 0) {
3150 waIndices.push_back(std::make_pair(start, waNumLanes));
3152 std::cout <<
" single wa, end at wrap-around\n";
3155 if (waIndices.front().first == 0) {
3156 NBEdge* edge = normalizedLanes.front().first;
3160 waIndices.push_back(std::make_pair(start, waNumLanes));
3162 std::cout <<
" do not wrap around\n";
3166 waIndices.front().first = start;
3167 waIndices.front().second = waNumLanes + waIndices.front().second;
3169 std::cout <<
" wrapping around\n";
3174 waIndices.push_back(std::make_pair(start, waNumLanes));
3176 std::cout <<
" end at wrap-around\n";
3182 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
3183 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3184 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
3188 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3189 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
3190 const int startIdx = waIndices[i].first;
3191 const int prev = startIdx > 0 ? startIdx - 1 : (int)normalizedLanes.size() - 1;
3192 const int count = waIndices[i].second;
3193 const int end = (startIdx + count) % normalizedLanes.size();
3194 const int lastIdx = (startIdx + count - 1) % normalizedLanes.size();
3198 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << startIdx <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
3200 double endCrossingWidth = 0;
3201 double startCrossingWidth = 0;
3205 bool connectsCrossing =
false;
3206 std::vector<Position> connectedPoints;
3209 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
3211 if (c->edges.back() == normalizedLanes[end].first
3212 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
3214 if (c->nextWalkingArea !=
"") {
3215 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'."),
3216 getID(), c->id, c->nextWalkingArea, wa.
id);
3219 c->nextWalkingArea = wa.
id;
3223 endCrossingWidth = c->width;
3224 endCrossingShape = c->shape;
3226 connectsCrossing =
true;
3227 connectedPoints.push_back(c->shape[-1]);
3231 std::cout <<
" crossing " << c->id <<
" ends\n";
3234 if (c->edges.front() == normalizedLanes[prev].first
3235 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
3237 if (c->prevWalkingArea !=
"") {
3238 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'."),
3239 getID(), c->id, c->prevWalkingArea, wa.
id);
3243 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' starts and ends at walkingarea '%'."),
3247 c->prevWalkingArea = wa.
id;
3251 startCrossingWidth = c->width;
3252 startCrossingShape = c->shape;
3254 connectsCrossing =
true;
3255 connectedPoints.push_back(c->shape[0]);
3259 std::cout <<
" crossing " << c->id <<
" starts\n";
3262 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
3263 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
3264 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[startIdx].first->getID()
3265 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
3268 if (count < 2 && !connectsCrossing) {
3271 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
3276 std::set<const NBEdge*, ComparatorIdLess>& connected = wa.
refEdges;
3277 for (
int j = 0; j < count; ++j) {
3278 const int nlI = (startIdx + j) % normalizedLanes.size();
3279 NBEdge* edge = normalizedLanes[nlI].first;
3282 if (connected.count(edge) == 0) {
3290 connected.insert(edge);
3297 if (buildExtensions) {
3299 if (startCrossingShape.size() > 0) {
3301 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
3303 startCrossingShape.
move2side(startCrossingWidth / 2);
3305 startCrossingShape.
move2side(-startCrossingWidth);
3309 if (endCrossingShape.size() > 0) {
3311 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
3313 endCrossingShape.
move2side(endCrossingWidth / 2);
3315 endCrossingShape.
move2side(-endCrossingWidth);
3320 && normalizedLanes.size() == 2) {
3322 const NBEdge* e1 = *connected.begin();
3323 const NBEdge* e2 = *(++connected.begin());
3326 std::cout <<
" not building a walkingarea since normal connections exist\n";
3331 if (count == (
int)normalizedLanes.size()) {
3334 }
else if (cornerDetail > 0) {
3336 int smoothEnd = end;
3337 int smoothPrev = prev;
3339 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
3340 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
3342 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
3343 if (smoothPrev == 0) {
3344 smoothPrev = (int)normalizedLanes.size() - 1;
3349 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
3350 begShape = begShape.
reverse();
3351 PositionVector begShapeOuter = normalizedLanes[lastIdx].second.shape;
3352 begShapeOuter = begShapeOuter.
reverse();
3354 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3355 begShapeOuter.
move2side(normalizedLanes[lastIdx].second.width / 2);
3356 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3357 PositionVector endShapeOuter = normalizedLanes[startIdx].second.shape;;
3358 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3359 endShapeOuter.
move2side(normalizedLanes[startIdx].second.width / 2);
3362 if (count != (
int)normalizedLanes.size() || count == 2) {
3363 if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3366 if (curve.
length2D() - begShape.back().distanceTo2D(endShape.front()) > 5) {
3373 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3377 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
3378 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3379 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve
3380 <<
" begShapeOuter=" << begShapeOuter <<
" endShapeOuter=" << endShapeOuter
3382 if (curve.size() > 2) {
3383 curve.erase(curve.begin());
3385 if (endCrossingWidth > 0) {
3386 wa.
shape.pop_back();
3388 if (startCrossingWidth > 0) {
3391 if (count == (
int)normalizedLanes.size()) {
3397 if (curve.size() > 2 && count == 2) {
3398 const double innerDist = begShape.back().distanceTo2D(endShape[0]);
3399 const double outerDist = begShapeOuter.back().distanceTo2D(endShapeOuter[0]);
3401 std::cout <<
" innerDist=" << innerDist <<
" outerDist=" << outerDist <<
"\n";
3403 if (outerDist > innerDist) {
3405 const double extend =
MIN2(10.0, begShapeOuter.back().distanceTo2D(endShapeOuter.front()) / 2);
3409 wa.
shape.insert(wa.
shape.begin() + 1, curve.begin(), curve.end());
3411 std::cout <<
" outerCurve=" << curve <<
"\n";
3421 if (wacs.shape.size() != 0) {
3422 wa.
shape = wacs.shape;
3425 wa.
width = wacs.width;
3432 double lengthSum = 0;
3433 int combinations = 0;
3434 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3435 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3445 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
3447 wa.
length = POSITION_EPS;
3448 if (combinations > 0) {
3449 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3454 std::vector<Crossing*> validCrossings =
getCrossings();
3455 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3457 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3459 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
3474 wa.
shape.push_back(tmp[-1]);
3476 wa.
shape.push_back(tmp[-1]);
3480 wa.
shape.push_back(tmp[0]);
3482 wa.
shape.push_back(tmp[0]);
3489 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(wa.
refEdges, wacs.edges)) {
3490 wa.
shape = wacs.shape;
3499 std::cout <<
" build wa=" << wa.
id <<
"\n";
3507 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3509 for (
const NBEdge* e : sub) {
3510 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3529 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3530 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3531 if (it1 != edges.end() && it2 != edges.end()) {
3556 return other1 == other2;
3576 while (it != it_end) {
3577 result.push_back(*it);
3587 wacs.
edges.insert(edges.begin(), edges.end());
3601 if (incoming.size() == 1 && outgoing.size() == 1) {
3604 if (incoming.size() == 2 && outgoing.size() == 2) {
3607 NBEdge* in0 = incoming[0];
3608 NBEdge* in1 = incoming[1];
3609 NBEdge* out0 = outgoing[0];
3610 NBEdge* out1 = outgoing[1];
3619 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
3623 if (
MAX2(angle0, angle1) <= 160) {
3643 if (out->getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
3653 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
3654 myCrossings.push_back(std::unique_ptr<Crossing>(c));
3664 EdgeSet edgeSet(edges.begin(), edges.end());
3666 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
3667 if (edgeSet == edgeSet2) {
3689 const EdgeSet edgeSet(edges.begin(), edges.end());
3691 const EdgeSet edgeSet2(crossing->edges.begin(), crossing->edges.end());
3692 if (edgeSet == edgeSet2) {
3693 return crossing.get();
3699 throw ProcessError(
TL(
"Request for unknown crossing for the given Edges"));
3706 if (walkingArea.id ==
id) {
3710 throw ProcessError(
TL(
"Request for unknown crossing for the given Edges"));
3716 bool usedCustom =
false;
3718 c->tlLinkIndex = startIndex++;
3720 if (c->customTLIndex != -1) {
3721 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
3722 c->tlLinkIndex = c->customTLIndex;
3724 c->tlLinkIndex2 = c->customTLIndex2;
3736 result += (int)edge->getConnections().size();
3750 if (e == from && cand.fromLane == con.
fromLane && cand.toLane == con.
toLane && cand.toEdge == con.
toEdge) {
3781 std::cout <<
" angles:\n";
3782 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3783 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3785 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3790 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
3792 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
3794 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
3806 if (turnDest !=
nullptr) {
3826 if (def->rightOnRedConflict(index, foeIndex)) {
3848 std::vector<NBEdge*>::iterator j;
3849 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3852 if (allEdges.size() > 1 && j != allEdges.end()) {
3857 NBEdge* firstOfAll = allEdges.front();
3858 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3859 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3865 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3866 if (firstOfIncoming !=
nullptr) {
3867 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3869 if (firstOfOutgoing !=
nullptr) {
3870 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3872#ifdef DEBUG_EDGE_SORTING
3874 std::cout <<
"sortedEdges (useNodeShape=" << useNodeShape <<
"):\n";
3875 for (
NBEdge* e : allEdges) {
3876 std::cout <<
" " << e->getID()
3877 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3878 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3885 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3886 std::vector<NBEdge*>::const_iterator in, out;
3887 std::vector<NBEdge*> allTmp;
3888 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3889 if ((*in)->isTurningDirectionAt(*out)) {
3890 allTmp.push_back(*in);
3891 allTmp.push_back(*out);
3896 if (allTmp.size() == allEdges.size()) {
3909 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3913 e->computeEdgeShape();
3918std::vector<std::pair<Position, std::string> >
3921 std::vector<std::pair<Position, std::string> >result;
3923 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3924 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
3926 for (
const auto& pair : result) {
3927 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
3933 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_PASSENGER
vehicle is a passenger car (a "normal" car)
@ 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
const std::vector< Connection > & getConnections() const
Returns the connections.
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.
NBNode * getToNode() const
Returns the destination node of the edge.
Lane & getLaneStruct(int lane)
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
const PositionVector & getGeometry() const
Returns the geometry of the 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.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
@ LANES2LANES_RECHECK
Lanes to lanes - relationships are computed; should be rechecked.
@ 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.
const std::string & getID() const
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
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
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[
@ 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
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 friction=UNSPECIFIED_FRICTION, 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.
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.
const NBEdge * getBidiEdge() const
NBNode * getFromNode() const
Returns the origin node of the edge.
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
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.
bool hasConnectionTo(const NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
double getFinalLength() const
get length that will be assigned to the lanes in the final network
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::vector< LinkDirection > myDirections
directions from each incoming edge to the outgoing edge
int myNumStraight
number of straight connections to the outgoing edge
NBEdge * myCurrentOutgoing
The approached current edge.
std::deque< int > * spread(int numLanes, int dest) const
the method that spreads the wished number of lanes from the lane given by the bresenham-call to both ...
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.
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.
std::vector< WalkingAreaCustomShape > myWalkingAreaCustomShapes
Vector of custom walking areas shapes.
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
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
LinkState getLinkState(const NBEdge *incoming, const NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
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
bool zipperConflict(const NBEdge *incoming, const NBEdge *outgoing, int fromLane, int toLane) const
void buildCrossingsAndWalkingAreas()
build crossings, and walkingareas. Also removes invalid loaded crossings if wished
static const int BACKWARD
static bool isExplicitRailNoBidi(const NBEdge *incoming, const NBEdge *outgoing)
detect explict rail turns with potential geometry problem
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.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
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
int checkCrossing(EdgeVector candidates, bool checkOnly=false)
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
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
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 occurrences of the first edge within the list of outgoing by the second Connections are rema...
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
double myRadius
the turning radius (for all corners) at this node in m.
static bool includes(const std::set< const NBEdge *, ComparatorIdLess > &super, const std::set< const NBEdge *, ComparatorIdLess > &sub)
returns whether sub is a subset of super
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
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 occurrences of the first edge within the list of incoming by the second Connections are rema...
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
EdgeVector getPassengerEdges(bool incoming) const
return edges that permit passengers (either incoming or outgoing)
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 EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at 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
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
double buildInnerEdges()
build internal lanes, pedestrian crossings and walking areas
PositionVector myPoly
the (outer) shape of the junction
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
bool crossesFringe(const NBEdge *e1, const NBEdge *e2) const
return true if the given sidewalks are separated by a fringe road
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.
WalkingArea & getWalkingArea(const std::string &id)
return the walkingArea with the given ID
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.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
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.
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 occurrences 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 norm2d()
Normalises the given 2d position.
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)
Subtracts 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.
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
A structure which describes a connection between edges or lanes.
bool indirectLeft
Whether this connection is an indirect left turn.
const std::string & getID() const
int fromLane
The lane the connections starts at.
int toLane
The lane the connections yields in.
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
std::set< const NBEdge *, ComparatorIdLess > refEdges
reference edges that uniquely identify this walkingarea
double width
This lane's width.
std::vector< std::string > nextCrossings
the lane-id of the next crossing(s)
std::vector< std::string > prevCrossings
the lane-id of the previous crossing(s)
PositionVector shape
The polygonal shape.
double length
This lane's width.
int minNextCrossingEdges
minimum number of edges crossed by nextCrossings