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
74#define DEBUG_NODE_ID "C"
75#define DEBUGCOND (getID() == DEBUG_NODE_ID)
76#define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUG_NODE_ID))
77#ifdef DEBUG_PED_STRUCTURES
78#define DEBUGCOUT(cond, msg) DEBUGOUT(cond, msg)
80#define DEBUGCOUT(cond, msg)
107 myApproaching(approaching),
108 myCurrentOutgoing(currentOutgoing),
110 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE),
111 myIsBusEdge((currentOutgoing->getPermissions() &
SVC_BUS) != 0 && (currentOutgoing->getPermissions() & ~(
SVC_BUS |
SVC_VULNERABLE)) == 0)
114 std::set<int> approachedLanes;
115 bool hasIncomingBusLane =
false;
119 approachedLanes.insert(con.toLane);
122 myDirections.push_back(approachingEdge->getToNode()->getDirection(approachingEdge, currentOutgoing));
126 hasIncomingBusLane |= (approachingEdge->getSpecialLane(
SVC_BUS) != -1);
132 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
138 || (lp ==
SVC_BUS && hasIncomingBusLane)
140 && approachedLanes.count(i) == 0) {
153 assert((
int)myApproaching.size() > src);
155 NBEdge* incomingEdge = myApproaching[src];
159 if (myAvailableLanes.size() == 0) {
163 std::vector<int> approachingLanes = incomingEdge->
getConnectionLanes(myCurrentOutgoing, withBikes,
true);
164 if (approachingLanes.size() > myAvailableLanes.size() ||
167 approachingLanes = incomingEdge->
getConnectionLanes(myCurrentOutgoing, withBikes, withBusLanes);
169 if (approachingLanes.size() == 0) {
172#ifdef DEBUG_CONNECTION_GUESSING
174 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
178 int numConnections = (int)approachingLanes.size();
190 numConnections = (int)myAvailableLanes.size();
191 factor = (double)approachingLanes.size() / (double)numConnections;
196 std::deque<int>* approachedLanes = spread(numConnections, dest);
197 assert(approachedLanes->size() <= myAvailableLanes.size());
199 const int maxFrom = (int)approachingLanes.size() - 1;
200 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
203 int fromLane = approachingLanes[
MIN2((
int)(i * factor), maxFrom)];
204 int approached = myAvailableLanes[(*approachedLanes)[i]];
207 delete approachedLanes;
213 std::deque<int>* ret =
new std::deque<int>();
217 ret->push_back(dest);
221 const int numOutgoingLanes = (int)myAvailableLanes.size();
223 ret->push_back(dest);
227 while (noSet < numLanes) {
233 if (numOutgoingLanes == noSet) {
242 if (dest + loffset >= numOutgoingLanes) {
245 for (
int i = 0; i < (int)ret->size(); i++) {
246 (*ret)[i] = (*ret)[i] - 1;
251 ret->push_back(dest + loffset);
256 if (numOutgoingLanes == noSet) {
261 if (noSet < numLanes) {
264 if (dest < roffset) {
267 for (
int i = 0; i < (int)ret->size(); i++) {
268 (*ret)[i] = (*ret)[i] + 1;
271 ret->push_front(dest - roffset);
290 customShape(_customShape),
291 tlLinkIndex(_customTLIndex),
292 tlLinkIndex2(_customTLIndex2),
293 customTLIndex(_customTLIndex),
294 customTLIndex2(_customTLIndex2),
331 myPosition(position),
333 myDistrict(district),
334 myHaveCustomPoly(false),
336 myRadius(UNSPECIFIED_RADIUS),
337 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
341 myDiscardAllCrossings(false),
342 myCrossingsLoadedFromSumoNet(0),
343 myDisplacementError(0),
344 myIsBentPriority(false),
345 myTypeWasGuessed(false) {
362 bool updateEdgeGeometries) {
372 if (updateEdgeGeometries) {
376 (*i)->setGeometry(geom);
381 (*i)->setGeometry(geom);
394 wacs.shape.add(xoff, yoff, 0);
397 c->customShape.add(xoff, yoff, 0);
423 c->customShape.mirrorX();
430 wacs.shape.mirrorX();
456 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
480 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
483 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(addedConnections, removedConnections);
484 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
486 const std::vector<NBNode*>& nodes = orig->
getNodes();
487 while (!nodes.empty()) {
488 newDef->
addNode(nodes.front());
489 nodes.front()->removeTrafficLight(orig);
502 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
529 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
581 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
584 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
600 double extrapolateBeg,
601 double extrapolateEnd,
603 int shapeFlag)
const {
610#ifdef DEBUG_SMOOTH_GEOM
612 std::cout <<
"computeSmoothShape node " <<
getID() <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" init=" << init <<
" shapeFlag=" << shapeFlag <<
"\n";
615 if (init.size() == 0) {
617 ret.push_back(begShape.back());
618 ret.push_back(endShape.front());
630 double extrapolateBeg,
631 double extrapolateEnd,
634 double straightThresh,
637 const Position beg = begShape.back();
638 const Position end = endShape.front();
641 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
642#ifdef DEBUG_SMOOTH_GEOM
643 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
659 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
660 init.push_back(center);
662 const double EXT = 100;
668#ifdef DEBUG_SMOOTH_GEOM
670 <<
" endShapeBegLine=" << endShapeBegLine
671 <<
" begShapeEndLineRev=" << begShapeEndLineRev
672 <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
674 if (fabs(angle) <
M_PI / 4.) {
677 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
678 const double halfDistance = dist / 2;
679 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
680#ifdef DEBUG_SMOOTH_GEOM
681 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
682 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
685 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
688#ifdef DEBUG_SMOOTH_GEOM
689 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
690 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
691 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
692 <<
" displacementError=" << sin(displacementAngle) * dist
693 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
696 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
701 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
702 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
704 const double off2 =
EXT -
MIN2(extrapolateEnd, halfDistance);
706#ifdef DEBUG_SMOOTH_GEOM
707 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
708 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
709 <<
" halfDistance=" << halfDistance <<
"\n";
720#ifdef DEBUG_SMOOTH_GEOM
722 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
723 <<
" endShapeBegLine=" << endShapeBegLine
724 <<
" begShapeEndLineRev=" << begShapeEndLineRev
729 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
748 const double minControlLength =
MIN2((
double)1.0, dist / 2);
751 const bool lengthenBeg = distBeg <= minControlLength;
752 const bool lengthenEnd = distEnd <= minControlLength;
753#ifdef DEBUG_SMOOTH_GEOM
755 <<
" beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
756 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd
757 <<
" begOffset=" << begOffset <<
" endOffset=" << endOffset
758 <<
" lEnd=" << lengthenEnd <<
" lBeg=" << lengthenBeg
761 if (lengthenBeg && lengthenEnd) {
762#ifdef DEBUG_SMOOTH_GEOM
764 std::cout <<
" bezierControlPoints failed\n";
767 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
776 }
else if (lengthenBeg || lengthenEnd) {
785 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
788 :
MIN2(0.6, 16 / dist));
799 const double z3 = 0.5 * (beg.
z() + end.
z());
803 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
808 intersect.
set(intersect.
x(), intersect.
y(), z);
809 init.push_back(intersect);
822 result.push_back(begShape.back());
833 dir.
sub(endShape[0]);
837 result.push_back(intersect + dir);
839 result.push_back(endShape.front());
855 if (useCustomShape) {
858 if (startBorder.size() == 0) {
859 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
862 if (tmp.size() < 2) {
864 useCustomShape =
false;
868 tmp[0] = fromShape.back();
869 }
else if (recordError !=
nullptr) {
870 const double offset = tmp[0].distanceTo2D(fromShape.back());
876 if (endBorder.size() == 0) {
877 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
880 if (ret.size() < 2) {
882 useCustomShape =
false;
885 ret[-1] = toShape.front();
886 }
else if (recordError !=
nullptr) {
887 const double offset = ret[-1].distanceTo2D(toShape.front());
894 if (!useCustomShape) {
905#ifdef DEBUG_SMOOTH_GEOM
907 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
912 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
944 for (
int i = 0; i < con.
toLane; ++i) {
948 for (
int i = 0; i < con.
fromLane; ++i) {
958 fromShape.
move2side(inCenter - outCenter);
1016 if (fromE == otherFromE && !thisRight) {
1027 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
1045 && !
needsCont(foeFrom, from, foe, c,
true));
1052 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
1054 if ((*i)->getNodes().size() > 1) {
1056 (*i)->removeNode(
this);
1057 (*i)->setParticipantsInformation();
1058 (*i)->setTLControllingInformation();
1089 WRITE_WARNINGF(
TL(
"Junction '%' is too complicated (% connections, max %); will be set to %."),
1091 }
else if (numConnections == 0) {
1115 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1123 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1126 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1199 edge->computeEdgeShape();
1227 if (mismatchThreshold >= 0
1254 int inOffset, inEnd, outOffset, outEnd, addedLanes;
1255 getReduction(out, in, outOffset, outEnd, inOffset, inEnd, addedLanes);
1260 const int addedLeft = addedLanes - addedRight;
1261#ifdef DEBUG_CONNECTION_GUESSING
1263 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a. addedRight=" << addedRight <<
" addedLeft=" << addedLeft <<
" inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
"\n";
1267 for (
int i = inOffset; i < inEnd; ++i) {
1271 for (
int i = 0; i < addedRight; ++i) {
1275 const int inLeftMost = inEnd - 1;;
1276 const int outOffset2 = outOffset + addedRight + inEnd - inOffset;
1277 for (
int i = 0; i < addedLeft; ++i) {
1310#ifdef DEBUG_CONNECTION_GUESSING
1312 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1352#ifdef DEBUG_CONNECTION_GUESSING
1354 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1381#ifdef DEBUG_CONNECTION_GUESSING
1383 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1392 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1408 int inOffset, inEnd, outOffset, outEnd, reduction;
1409 getReduction(in, out, inOffset, inEnd, outOffset, outEnd, reduction);
1414#ifdef DEBUG_CONNECTION_GUESSING
1416 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
" reduction=" << reduction <<
"\n";
1420 inOffset += reduction;
1421 for (
int i = outOffset; i < outEnd; ++i) {
1438 const int numApproaching = (int)approaching.size();
1439 if (numApproaching != 0) {
1443#ifdef DEBUG_CONNECTION_GUESSING
1445 std::cout <<
"l2l node=" <<
getID() <<
" outgoing=" << currentOutgoing->getID() <<
" bresenham:\n";
1447 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1448 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1449 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " <<
Named::getIDSecure((*k).toEdge) <<
"_" << (*k).toLane <<
"\n";
1458 bool targetProhibitsChange =
false;
1459 for (
int i = 0; i < currentOutgoing->getNumLanes(); i++) {
1460 const NBEdge::Lane& lane = currentOutgoing->getLanes()[i];
1463 targetProhibitsChange =
true;
1467 if (targetProhibitsChange) {
1471 std::map<int, int> outToIn;
1473 if (c.toEdge == currentOutgoing) {
1474 outToIn[c.toLane] = c.fromLane;
1477 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); toLane++) {
1478 if (outToIn.count(toLane) == 0) {
1481 for (
int i = 0; i < toLane; i++) {
1482 if (outToIn.count(i) != 0) {
1483#ifdef DEBUG_CONNECTION_GUESSING
1485 std::cout <<
"l2l node=" <<
getID() <<
" from=" << incoming->getID() <<
" to " << currentOutgoing->getLaneID(toLane) <<
" (changeProhibited, secondTarget)\n";
1494 for (
int i = toLane; i < currentOutgoing->getNumLanes(); i++) {
1495 if (outToIn.count(i) != 0) {
1496#ifdef DEBUG_CONNECTION_GUESSING
1498 std::cout <<
"l2l node=" <<
getID() <<
" from=" << incoming->getID() <<
" to " << currentOutgoing->getLaneID(toLane) <<
" (changeProhibited, newTarget)\n";
1517 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1518 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1520 (*i)->removeFromConnections((*k).toEdge);
1531 incoming->markAsInLane2LaneState();
1535#ifdef DEBUG_CONNECTION_GUESSING
1537 std::cout <<
"final connections at " <<
getID() <<
"\n";
1539 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1540 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1541 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " <<
Named::getIDSecure((*k).toEdge) <<
"_" << (*k).toLane <<
"\n";
1557 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1558 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1563 unsatisfied &= ~satisfied;
1566 if (unsatisfied != 0) {
1567#ifdef DEBUG_CONNECTION_GUESSING
1569 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1574 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1575 if (incoming->getPermissions(fromLane) == unsatisfied) {
1583 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1584 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0
1585 && incoming->getConnectionsFromLane(fromLane, currentOutgoing, -1).size() > 0) {
1592 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1593 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1598#ifdef DEBUG_CONNECTION_GUESSING
1600 if (unsatisfied != 0) {
1601 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1618 const int specialTarget = currentOutgoing->
getSpecialLane(svcSpecial);
1623 bool builtConnection =
false;
1624 for (
int i = 0; i < (int)incoming->
getNumLanes(); i++) {
1628 if (specialTarget >= 0) {
1630#ifdef DEBUG_CONNECTION_GUESSING
1635 builtConnection =
true;
1638 if (
avoidConfict(incoming, currentOutgoing, svcSpecial, dir, i)) {
1642 for (
int i2 = 0; i2 < (int)currentOutgoing->
getNumLanes(); i2++) {
1645 const bool allowDouble = (incoming->
getPermissions(i) == svcSpecial
1648#ifdef DEBUG_CONNECTION_GUESSING
1653 builtConnection =
true;
1660 if (!builtConnection && specialTarget >= 0
1670 for (
int i = start; i < end; i += inc) {
1673#ifdef DEBUG_CONNECTION_GUESSING
1689 if (incoming->
getPermissions(c.fromLane) == svcSpecial && c.toEdge == currentOutgoing) {
1695 if (c.fromLane < i && (c.toEdge != currentOutgoing || incoming->
getPermissions(c.fromLane) == svcSpecial)) {
1701 if (c.fromLane > i && (c.toEdge != currentOutgoing || incoming->
getPermissions(c.fromLane) == svcSpecial)) {
1725 reduction = (inEnd - inOffset) - (outEnd - outOffset);
1731 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1739 if (con.toEdge == currentOutgoing && con.toLane == toLane) {
1740#ifdef DEBUG_CONNECTION_GUESSING
1742 std::cout <<
" shifting connection from=" << con.fromLane <<
" to=" << currentOutgoing->
getID() <<
"_" << toLane <<
": newFromLane=" << fromLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1746 unsatisfied &= ~satisfied;
1754#ifdef DEBUG_CONNECTION_GUESSING
1756 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1759 unsatisfied &= ~satisfied;
1776 int inOffset, inEnd, outOffset, outEnd, reduction;
1779 if (reduction > 0) {
1784 int outLanesRight = 0;
1785 int outLanesLeft = 0;
1786 int outLanesStraight = 0;
1789 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianNonBicycleLaneIndex(
FORWARD,
true));
1790 const int usableLanes = succ->getNumLanes() - outOffset;
1793 outLanesStraight += usableLanes;
1795 outLanesRight += usableLanes;
1797 outLanesLeft += usableLanes;
1803 const int usableLanes = outEnd - outOffset;
1804 int addedTurnLanes =
MIN3(
1806 MAX2(0, usableLanes - outLanesStraight),
1807 outLanesRight + outLanesLeft);
1808#ifdef DEBUG_CONNECTION_GUESSING
1810 std::cout <<
"out=" << out->
getID() <<
" usableLanes=" << usableLanes <<
" addedTurnLanes=" << addedTurnLanes <<
" addedLanes=" << addedLanes <<
" outLanesStraight=" << outLanesStraight <<
" outLanesLeft=" << outLanesLeft <<
" outLanesRight=" << outLanesRight <<
"\n";
1813 if (outLanesLeft == 0) {
1814 return addedTurnLanes;
1816 return MIN2(addedTurnLanes / 2, outLanesRight);
1824 while (seen < minLength) {
1841 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1846 approaching.clear();
1847 for (; *i != currentOutgoing;) {
1849 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1850 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1851 if (connLanes.size() != 0) {
1852 approaching.push_back(*i);
1882 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1884 laneOff += (*i)->getNumLanes();
1914 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1916 laneOff += (*i)->getNumLanes();
1931 int whichLaneOff,
int byLaneOff) {
1935 bool changed =
false;
1937 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1940 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1954 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1956 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1957 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
2017 if (find(edges.begin(), edges.end(), e) != edges.end()) {
2018 edges.erase(find(edges.begin(), edges.end(), e));
2020 if (edges.size() == 0) {
2035 if (mayDrive.
getFrom() ==
nullptr ||
2036 mayDrive.
getTo() ==
nullptr ||
2037 mustStop.
getFrom() ==
nullptr ||
2038 mustStop.
getTo() ==
nullptr) {
2040 WRITE_WARNING(
TL(
"Something went wrong during the building of a connection..."));
2044 conn.push_back(mayDrive);
2051 int size = (int) edgeid.length();
2053 std::string
id = (*i)->
getID();
2054 if (
id.substr(0, size) == edgeid) {
2064 int size = (int) edgeid.length();
2066 std::string
id = (*i)->
getID();
2067 if (
id.substr(0, size) == edgeid) {
2097 if (removeFromConnections) {
2099 (*i)->removeFromConnections(edge);
2103 const bool incoming = edge->
getToNode() ==
this;
2105 tld->replaceRemoved(edge, -1,
nullptr, -1, incoming);
2115 Position toAdd = in->getFromNode()->getPosition();
2121 Position toAdd = out->getToNode()->getPosition();
2127 if (pos.
x() == 0. && pos.
y() == 0.) {
2139 (*i)->invalidateConnections(reallowSetting);
2147 (*i)->invalidateConnections(reallowSetting);
2159 if (to ==
nullptr) {
2183 if (std::find(c->edges.begin(), c->edges.end(), to) != c->edges.end()) {
2193 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
2194 if (from != prohibitorFrom) {
2231 if ((!flip && fromLane <= prohibitorFromLane) ||
2232 (flip && fromLane >= prohibitorFromLane)) {
2235 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
2236 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
2274 bool lefthand)
const {
2276 if (from != from2 || to == to2 || fromLane == fromLane2) {
2284 bool result =
false;
2286 if (fromLane < fromLane2) {
2288 while (*it != to2) {
2296 while (*it != to2) {
2328 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
2338 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
2339 bool regardNonSignalisedLowerPriority)
const {
2341 possProhibitedFrom, possProhibitedTo,
2342 regardNonSignalisedLowerPriority);
2348 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
2357 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
2358 bool changed =
true;
2364 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
2369 bool blockedChanged =
false;
2371 NBConnectionVector::const_iterator j;
2372 for (j = blocked.begin(); j != blocked.end(); j++) {
2374 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
2375 blockedChanged =
true;
2379 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
2381 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2385 }
else if (sblocked.
getFrom() == removed) {
2386 assert(sblocked.
getTo() != removed);
2387 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2390 }
else if (sblocked.
getTo() == removed) {
2391 assert(sblocked.
getFrom() != removed);
2392 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2399 if (blockedChanged) {
2400 blockedConnectionsNew[blocker] = newBlocked;
2405 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2410 }
else if (blocker.
getFrom() == removed) {
2411 assert(blocker.
getTo() != removed);
2413 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2416 }
else if (blocker.
getTo() == removed) {
2417 assert(blocker.
getFrom() != removed);
2419 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2423 blockedConnectionsNew[blocker] = blocked;
2436 EdgeVector::const_iterator i = itOut;
2437 while (*i != incoming) {
2443 if ((*i)->getFromNode() !=
this) {
2451 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2461 if (candidate !=
nullptr) {
2464 if (fabs(angle - candAngle) < 5.) {
2468 if (fabs(candAngle) < fabs(angle) - 5.) {
2471 if (fabs(angle) < fabs(candAngle) - 5.) {
2474 if (fabs(candAngle) < 44.) {
2477 if (candModeLanes > modeLanes) {
2480 if (candModeLanes < modeLanes) {
2484 if (candAngle < 0 && angle > 0) {
2487 if (angle < 0 && candAngle > 0) {
2500 result.push_back(e);
2509 if (outgoing ==
nullptr) {
2530 vehPerm &= ~SVC_PEDESTRIAN;
2533 if (fabs(angle) < 44.) {
2534 if (fabs(angle) > 6.) {
2550 if (angle > 90 + NUMERICAL_EPS) {
2554 if (outCW !=
nullptr) {
2561 if (angle < -170 && incoming->getGeometry().reverse() == outgoing->
getGeometry()) {
2566 }
else if (angle < -(90 + NUMERICAL_EPS)) {
2570 if (outCCW !=
nullptr) {
2593 bool mayDefinitelyPass,
const std::string& tlID)
const {
2603 if (outgoing ==
nullptr) {
2607 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)) {
2616 if (!mayDefinitelyPass
2617 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)
2631 if (
mustBrake(incoming, outgoing, fromLane, toLane,
false)) {
2635 if ((in != incoming || c.fromLane != fromLane) && c.toEdge == outgoing && c.toLane == toLane) {
2651 assert(railClasses != 0);
2661 for (
auto it : nc) {
2662 const NBNode* n = it.second;
2689 reason =
"rail_signal";
2693 reason =
"crossing";
2696 EdgeVector::const_iterator i;
2701 reason =
"edges incompatible: " + reason;
2705 reason =
"turnaround";
2713 std::set<NBNode*> origSet;
2715 origSet.insert((*i)->getFromNode());
2717 if (origSet.size() < 2) {
2732 if (opposite !=
nullptr) {
2736 if (!(*i)->expandableBy(continuation, reason)) {
2737 reason =
"edges incompatible: " + reason;
2743 reason =
"not opposites";
2750 reason =
"intersection";
2755std::vector<std::pair<NBEdge*, NBEdge*> >
2758 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2783 assert(opposite != 0);
2785 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2803 (*i)->resetNodeBorder(
this);
2812 if (e->getToNode() == n && e->getPermissions() != 0) {
2826 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2828 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2845#ifdef DEBUG_PED_STRUCTURES
2856 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2857 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2859 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2861 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2862 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2865 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2866 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2871 int firstSidewalk = -1;
2872 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2873 if (normalizedLanes[i].second) {
2878 int hadCandidates = 0;
2879 std::vector<int> connectedCandidates;
2880 if (firstSidewalk != -1) {
2882 std::vector<std::pair<NBEdge*, bool> > tmp;
2883 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2884 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2885 normalizedLanes = tmp;
2888 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2889 NBEdge* edge = normalizedLanes[i].first;
2890 const bool allowsPed = normalizedLanes[i].second;
2892 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2893 candidates.push_back(edge);
2894 }
else if (allowsPed) {
2895 if (candidates.size() > 0) {
2901 connectedCandidates.push_back(n);
2908 if (hadCandidates > 0 && candidates.size() > 0) {
2914 connectedCandidates.push_back(n);
2920 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2922 if (connectedCandidates.back() <= connectedCandidates.front()) {
2923 numGuessed -= connectedCandidates.back();
2926 numGuessed -= connectedCandidates.front();
2931#ifdef DEBUG_PED_STRUCTURES
2933 std::cout <<
"guessedCrossings:\n";
2935 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2943 e->computeEdgeShape();
2953 if (candidates.size() == 0) {
2958 double prevAngle = -100000;
2959 for (
int i = 0; i < (int)candidates.size(); ++i) {
2960 NBEdge* edge = candidates[i];
2982 prevAngle = -100000;
2983 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2984 double angle = (*it)->getCrossingAngle(
this);
2985 if (it != candidates.begin()) {
2986 NBEdge* prev = *(it - 1);
2991 double intermediateWidth = 0;
2994 prevPos = prev->
getLanes()[laneI].shape[-1];
2997 prevPos = prev->
getLanes()[laneI].shape[0];
3002 currPos = curr->
getLanes()[laneI].shape[0];
3005 currPos = curr->
getLanes()[laneI].shape[-1];
3009 DEBUGCOUT(
gDebugFlag1,
" prevAngle=" << prevAngle <<
" angle=" << angle <<
" intermediateWidth=" << intermediateWidth <<
"\n")
3032 std::sort(edges.begin(), edges.end());
3036 EdgeVector edgesOfCrossing = crossing->edges;
3037 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
3038 if (edgesOfCrossing == edges) {
3048 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
3049 if (!normalizedLanes[i].second) {
3067 std::set<std::string> waIDs;
3068 int numSidewalks = 0;
3070 waIDs.insert(wa.id);
3071 numSidewalks += (int)(wa.prevSidewalks.size() + wa.nextSidewalks.size());
3073 if (numSidewalks < 2) {
3078 if (waIDs.count(crossing->prevWalkingArea) == 0 || waIDs.count(crossing->nextWalkingArea) == 0 || !crossing->valid) {
3079 if (crossing->valid) {
3080 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found)."),
3097 crossing->valid =
false;
3098 crossing->prevWalkingArea =
"";
3099 crossing->nextWalkingArea =
"";
3106std::vector<NBNode::Crossing*>
3108 std::vector<Crossing*> result;
3111 result.push_back(c.get());
3145 int noInternalNoSplits = 0;
3148 if (con.toEdge ==
nullptr) {
3151 noInternalNoSplits++;
3156 double maxCrossingSeconds = 0.;
3158 maxCrossingSeconds =
MAX2(maxCrossingSeconds, edge->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo));
3160 return maxCrossingSeconds;
3166#ifdef DEBUG_PED_STRUCTURES
3182 c->nextWalkingArea =
"";
3183 c->prevWalkingArea =
"";
3191 std::vector<double> rawAngleDiffs;
3192 double maxAngleDiff = 0;
3193 int maxAngleDiffIndex = 0;
3194 for (
int i = 0; i < (int) edges.size(); i++) {
3196 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
3201 edges[i]->getAngleAtNodeNormalized(
this),
3202 edges[(i + 1) % edges.size()]->getAngleAtNodeNormalized(
this));
3203 rawAngleDiffs.push_back(fabs(rawDiff));
3205 DEBUGCOUT(
gDebugFlag1,
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n")
3206 if (diff > maxAngleDiff) {
3207 maxAngleDiff = diff;
3208 maxAngleDiffIndex = i;
3211 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
3213 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
3216 bool diagonalCrossing =
false;
3217 std::sort(rawAngleDiffs.begin(), rawAngleDiffs.end());
3218 if (rawAngleDiffs.size() >= 2 && rawAngleDiffs[rawAngleDiffs.size() - 2] > 30) {
3219 diagonalCrossing =
true;
3220#ifdef DEBUG_PED_STRUCTURES
3222 std::cout <<
" detected pedScramble " << c->id <<
" edges=" <<
toString(edges) <<
" rawDiffs=" <<
toString(rawAngleDiffs) <<
"\n";
3223 for (
auto e : edges) {
3224 std::cout <<
" e=" << e->getID()
3225 <<
" aC=" << e->getAngleAtNodeToCenter(
this)
3226 <<
" a=" << e->getAngleAtNode(
this)
3227 <<
" aN=" << e->getAngleAtNodeNormalized(
this)
3234 std::reverse(edges.begin(), edges.end());
3237 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
3238 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
3239 int firstNonPedLane = edges.front()->getFirstNonPedestrianLaneIndex(begDir);
3240 int lastNonPedLane = edges.back()->getFirstNonPedestrianLaneIndex(endDir);
3241 DEBUGCOUT(
gDebugFlag1,
" finalEdges=" <<
toString(edges) <<
" firstNonPedLane=" << firstNonPedLane <<
" lastNonPedLane=" << lastNonPedLane <<
"\n")
3242 if (firstNonPedLane < 0 || lastNonPedLane < 0) {
3244 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross)."), c->id,
getID(),
toString(c->edges));
3247 firstNonPedLane = begDir ==
FORWARD ? 0 : edges.front()->getNumLanes() - 1;
3248 lastNonPedLane = endDir ==
FORWARD ? 0 : edges.back()->getNumLanes() - 1;
3250 if (c->customShape.size() != 0) {
3251 c->shape = c->customShape;
3253 NBEdge::Lane crossingBeg = edges.front()->getLanes()[firstNonPedLane];
3254 NBEdge::Lane crossingEnd = edges.back()->getLanes()[lastNonPedLane];
3259 double offset = c->width / 2;
3268 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
3269 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
3271 if (diagonalCrossing) {
3272 c->shape.move2side(-c->width);
3289 nonPedIncoming.push_back(e);
3291 pedIncoming.push_back(e);
3296 nonPedOutgoing.push_back(e);
3298 pedOutgoing.push_back(e);
3301 if (
geometryLike(nonPedIncoming, nonPedOutgoing) && (pedIncoming.size() > 0 || pedOutgoing.size() > 0)) {
3302 double maxAngle = 0;
3303 const NBEdge* in = nonPedIncoming.front();
3304 const NBEdge* out = nonPedOutgoing.front();
3305 if (nonPedIncoming.size() == 1) {
3308 for (
const NBEdge*
const in2 : nonPedIncoming) {
3309 double minAngle = 180;
3310 for (
const NBEdge*
const out2 : nonPedOutgoing) {
3311 double angle = fabs(
NBHelpers::relAngle(in2->getAngleAtNode(
this), out2->getAngleAtNode(
this)));
3312 if (angle < minAngle) {
3318 maxAngle =
MAX2(maxAngle, minAngle);
3322 if (maxAngle < 15) {
3325 if (inLane >= 0 && outLane >= 0) {
3332 double maxPathDist = 0;
3333 for (
NBEdge* e : pedIncoming) {
3337 for (
NBEdge* e : pedOutgoing) {
3354#ifdef DEBUG_PED_STRUCTURES
3365 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
3366 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
3368 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
3369 std::vector<NBEdge::Lane> tmp;
3370 bool hadSidewalk =
false;
3371 bool hadNonSidewalk =
false;
3372 for (
int i = 0; i < (int)lanes.size(); i++) {
3376 if (hadSidewalk && hadNonSidewalk) {
3378 WRITE_WARNINGF(
TL(
"Ignoring additional sidewalk lane % on edge '%' for walkingareas."),
3385 hadNonSidewalk =
true;
3390 std::reverse(tmp.begin(), tmp.end());
3393 l.shape = l.shape.reverse();
3397 l.shape = l.shape.getSubpartByIndex(0, 2);
3399 normalizedLanes.push_back(std::make_pair(edge, l));
3404 std::vector<std::pair<int, int> > waIndices;
3406 NBEdge* prevEdge = normalizedLanes.back().first;
3407 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
3408 NBEdge* edge = normalizedLanes[i].first;
3420 waIndices.push_back(std::make_pair(start, i - start));
3430 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n")
3435 const int waNumLanes = (int)normalizedLanes.size() - start;
3436 if (waIndices.size() == 0) {
3437 waIndices.push_back(std::make_pair(start, waNumLanes));
3440 if (waIndices.front().first == 0) {
3441 NBEdge* edge = normalizedLanes.front().first;
3445 waIndices.push_back(std::make_pair(start, waNumLanes));
3449 waIndices.front().first = start;
3450 waIndices.front().second = waNumLanes + waIndices.front().second;
3455 waIndices.push_back(std::make_pair(start, waNumLanes));
3460#ifdef DEBUG_PED_STRUCTURES
3462 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
3463 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3464 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
3469 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3470 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
3471 int startIdx = waIndices[i].first;
3472 const int prev = startIdx > 0 ? startIdx - 1 : (int)normalizedLanes.size() - 1;
3473 const int count = waIndices[i].second;
3474 const int end = (startIdx + count) % normalizedLanes.size();
3475 int lastIdx = (startIdx + count - 1) % normalizedLanes.size();
3478 DEBUGCOUT(
gDebugFlag1,
"build walkingArea " << wa.
id <<
" start=" << startIdx <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n")
3479 double endCrossingWidth = 0;
3480 double startCrossingWidth = 0;
3484 bool connectsCrossing =
false;
3485 bool crossingNearSidewalk =
false;
3486 int numCrossings = 0;
3487 std::vector<Position> connectedPoints;
3490 if (c->edges.back() == normalizedLanes[end].first
3491 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
3493 if (c->nextWalkingArea !=
"") {
3494 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'."),
3495 getID(), c->id, c->nextWalkingArea, wa.
id);
3498 c->nextWalkingArea = wa.
id;
3502 endCrossingWidth = c->width;
3503 endCrossingShape = c->shape;
3505 connectsCrossing =
true;
3506 connectedPoints.push_back(c->shape[-1]);
3509 if (normalizedLanes[lastIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < endCrossingWidth) {
3510 crossingNearSidewalk =
true;
3516 if (c->edges.front() == normalizedLanes[prev].first
3517 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
3519 if (c->prevWalkingArea !=
"") {
3520 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'."),
3521 getID(), c->id, c->prevWalkingArea, wa.
id);
3525 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' starts and ends at walkingarea '%'."),
3529 c->prevWalkingArea = wa.
id;
3533 startCrossingWidth = c->width;
3534 startCrossingShape = c->shape;
3536 connectsCrossing =
true;
3537 connectedPoints.push_back(c->shape[0]);
3540 if (normalizedLanes[startIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < startCrossingWidth) {
3541 crossingNearSidewalk =
true;
3548 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
3549 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[startIdx].first->getID()
3550 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
3553 if (count < 2 && !connectsCrossing) {
3555 DEBUGCOUT(
gDebugFlag1,
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n")
3559 std::set<const NBEdge*, ComparatorIdLess>& connected = wa.
refEdges;
3560 for (
int j = 0; j < count; ++j) {
3561 const int nlI = (startIdx + j) % normalizedLanes.size();
3562 NBEdge* edge = normalizedLanes[nlI].first;
3565 if (connected.count(edge) == 0) {
3574 connected.insert(edge);
3581 if (buildExtensions) {
3583 if (startCrossingShape.size() > 0) {
3584 startCrossingShape.
move2side(startCrossingWidth / 2);
3586 startCrossingShape.
move2side(-startCrossingWidth);
3591 if (endCrossingShape.size() > 0) {
3592 endCrossingShape.
move2side(endCrossingWidth / 2);
3594 endCrossingShape.
move2side(-endCrossingWidth);
3600 && normalizedLanes.size() == 2) {
3602 const NBEdge* e1 = *connected.begin();
3603 const NBEdge* e2 = *(++connected.begin());
3609 if (count == (
int)normalizedLanes.size()) {
3615 if (in->getFromNode() == out->getToNode() && in->getInnerGeometry().reverse() == out->getInnerGeometry()
3619 wa.
width =
MAX2(wa.
width, in->getTotalWidth() + out->getTotalWidth());
3623 }
else if (cornerDetail > 0) {
3625 int smoothEnd = end;
3626 int smoothPrev = prev;
3628 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
3629 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
3631 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
3632 if (smoothPrev == 0) {
3633 smoothPrev = (int)normalizedLanes.size() - 1;
3638 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
3639 begShape = begShape.
reverse();
3640 double shiftBegExtra = 0;
3641 double shiftEndExtra = 0;
3642 if (lastIdx == startIdx) {
3643 lastIdx = (startIdx + 1) % normalizedLanes.size();
3644 DEBUGCOUT(
gDebugFlag1,
" new lastIdx=" << lastIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3645 if (normalizedLanes[startIdx].first == normalizedLanes[lastIdx].first) {
3649 startIdx = (int)normalizedLanes.size() - 1;
3651 DEBUGCOUT(
gDebugFlag1,
" new startIdx=" << startIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3657 PositionVector begShapeOuter = normalizedLanes[lastIdx].second.shape;
3658 begShapeOuter = begShapeOuter.
reverse();
3660 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3661 begShapeOuter.
move2side(normalizedLanes[lastIdx].second.width / 2 + shiftBegExtra);
3662 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3663 PositionVector endShapeOuter = normalizedLanes[startIdx].second.shape;;
3664 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3665 endShapeOuter.
move2side(normalizedLanes[startIdx].second.width / 2 + shiftEndExtra);
3668 if (count != (
int)normalizedLanes.size() || count == 2) {
3670 if (count == 1 && angle > 0 && crossingNearSidewalk && numCrossings < 2) {
3674 }
else if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3678 if (curve.
length2D() - begShape.back().distanceTo2D(endShape.front()) > 5) {
3679 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShape.back().distanceTo2D(endShape.front())
3680 <<
" curveLength=" << curve.
length2D()
3681 <<
" delta=" << curve.
length2D() - begShape.back().distanceTo2D(endShape.front())
3687 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3690 if (curve.size() > 2) {
3691 curve.erase(curve.begin());
3693 if (endCrossingWidth > 0) {
3694 wa.
shape.pop_back();
3696 if (startCrossingWidth > 0) {
3699 if (count == (
int)normalizedLanes.size()) {
3705 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3706 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve
3707 <<
" begShapeOuter=" << begShapeOuter <<
" endShapeOuter=" << endShapeOuter
3708 <<
" waShape=" << wa.
shape
3711 if (curve.size() > 2 && (count == 2 || (count == 1 && numCrossings > 0))) {
3712 const double innerDist = begShape.back().distanceTo2D(endShape[0]);
3713 const double outerDist = begShapeOuter.back().distanceTo2D(endShapeOuter[0]);
3715 if (outerDist > innerDist) {
3717 const double extend =
MIN2(10.0, begShapeOuter.back().distanceTo2D(endShapeOuter.front()) / 2);
3718 curve =
computeSmoothShape(begShapeOuter, endShapeOuter, cornerDetail + 2,
false, extend, extend,
nullptr);
3719 if (curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front()) > 5) {
3720 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3721 <<
" curveLength=" << curve.
length2D()
3722 <<
" delta=" << curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3728 if (shiftBegExtra != 0) {
3731 }
else if (shiftEndExtra != 0) {
3737 wa.
shape.insert(wa.
shape.begin() + 1, curve.begin(), curve.end());
3747 if (wacs.shape.size() != 0) {
3748 wa.
shape = wacs.shape;
3751 wa.
width = wacs.width;
3758 double lengthSum = 0;
3759 int combinations = 0;
3760 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3761 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3770 DEBUGCOUT(
gDebugFlag1,
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n")
3771 wa.
length = POSITION_EPS;
3772 if (combinations > 0) {
3773 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3778 std::vector<Crossing*> validCrossings =
getCrossings();
3779 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3781 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3796 wa.
shape.push_back(tmp[-1]);
3798 wa.
shape.push_back(tmp[-1]);
3802 wa.
shape.push_back(tmp[0]);
3804 wa.
shape.push_back(tmp[0]);
3811 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(wa.
refEdges, wacs.edges)) {
3812 wa.
shape = wacs.shape;
3828#ifdef DEBUG_CROSSING_OUTLINE
3830 std::cerr <<
"<add>\n";
3833 std::map<std::string, PositionVector> waShapes;
3835 waShapes[wa.id] = wa.shape;
3840 if (wa1.empty() || wa2.empty()) {
3853 side1 =
cutAtShapes(side1, wa1, wa2, side1default);
3854 side2 =
cutAtShapes(side2, wa1, wa2, side2default);
3858 side2ex.
extrapolate(side2 == side2default ? c->width / 2 : POSITION_EPS);
3861 c->outlineShape = side1;
3862 c->outlineShape.
append(side3, POSITION_EPS);
3863 c->outlineShape.append(side2, POSITION_EPS);
3864 c->outlineShape.append(side4, POSITION_EPS);
3865 c->outlineShape.removeDoublePoints();
3866 if (c->outlineShape.back().almostSame(c->outlineShape.front())) {
3867 c->outlineShape.pop_back();
3870#ifdef DEBUG_CROSSING_OUTLINE
3871 std::cout <<
" side1=" << side1 <<
"\n side2=" << side2 <<
"\n side3=" << side3 <<
"\n side4=" << side4 <<
"\n";
3872 std::cerr <<
"<poly id=\"" << c->id <<
"\" shape=\"" << c->outlineShape <<
"\" color=\"blue\" lineWidth=\"0.2\" layer=\"100\"/>\n";
3875#ifdef DEBUG_CROSSING_OUTLINE
3877 std::cerr <<
"</add>\n";
3887#ifdef DEBUG_CROSSING_OUTLINE
3888 std::cout <<
"is1=" << is1 <<
" is2=" << is2 <<
" cut=" << cut <<
" border1=" << border1 <<
" border2=" << border2 <<
"\n";
3890 if (is1.size() == 0 && border1.size() == 2) {
3891 const double d1 = cut.
distance2D(border1.front());
3892 const double d2 = cut.
distance2D(border1.back());
3893 Position closer = d1 < d2 ? border1.front() : border1.back();
3895#ifdef DEBUG_CROSSING_OUTLINE
3896 std::cout <<
" closer=" << closer <<
" nOp=" << nOp <<
"\n";
3898 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3904 if (is2.size() == 0 && border2.size() == 2) {
3905 const double d1 = cut.
distance2D(border2.front());
3906 const double d2 = cut.
distance2D(border2.back());
3907 Position closer = d1 < d2 ? border2.front() : border2.back();
3909 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3915 if (is1.size() > 0 && is2.size() > 0) {
3918#ifdef DEBUG_CROSSING_OUTLINE
3919 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3924#ifdef DEBUG_CROSSING_OUTLINE
3925 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3931#ifdef DEBUG_CROSSING_OUTLINE
3932 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3945 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3947 for (
const NBEdge* e : sub) {
3948 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3967 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3968 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3969 if (it1 != edges.end() && it2 != edges.end()) {
3994 return other1 == other2;
4014 while (it != it_end) {
4015 result.push_back(*it);
4025 wacs.
edges.insert(edges.begin(), edges.end());
4039 if (incoming.size() == 1 && outgoing.size() == 1) {
4040 return incoming.front()->getBidiEdge() != outgoing.front();
4042 if (incoming.size() == 2 && outgoing.size() == 2) {
4045 NBEdge* in0 = incoming[0];
4046 NBEdge* in1 = incoming[1];
4047 NBEdge* out0 = outgoing[0];
4048 NBEdge* out1 = outgoing[1];
4057 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4061 if (
MAX2(angle0, angle1) <= 160) {
4091 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
4092 if (params !=
nullptr) {
4095 myCrossings.push_back(std::unique_ptr<Crossing>(c));
4105 EdgeSet edgeSet(edges.begin(), edges.end());
4107 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
4108 if (edgeSet == edgeSet2) {
4130 const EdgeSet edgeSet(edges.begin(), edges.end());
4132 const EdgeSet edgeSet2(crossing->edges.begin(), crossing->edges.end());
4133 if (edgeSet == edgeSet2) {
4134 return crossing.get();
4140 throw ProcessError(
TL(
"Request for unknown crossing for the given Edges"));
4147 if (walkingArea.id ==
id) {
4156 if (walkingArea.id ==
id) {
4162 WRITE_WARNINGF(
"Could not retrieve walkingarea '%' (edge ordering changed after recompute).",
id);
4171 bool usedCustom =
false;
4173 c->tlLinkIndex = startIndex++;
4175 if (c->customTLIndex != -1 && !ignoreCustom) {
4176 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
4177 c->tlLinkIndex = c->customTLIndex;
4179 if (c->customTLIndex2 != -1 && !ignoreCustom) {
4181 c->tlLinkIndex2 = c->customTLIndex2;
4194 result += (int)edge->getConnections().size();
4208 if (e == from && cand.fromLane == con.
fromLane && cand.toLane == con.
toLane && cand.toEdge == con.
toEdge) {
4238#ifdef DEBUG_PED_STRUCTURES
4240 std::cout <<
" angles:\n";
4241 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
4242 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
4244 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
4250 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
4259 bool haveModifications =
false;
4263 if (turnDest !=
nullptr) {
4268 if (haveModifications) {
4286 if (def->extraConflict(index, foeIndex)) {
4308 std::vector<NBEdge*>::iterator j;
4309 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
4312 if (allEdges.size() > 1 && j != allEdges.end()) {
4317 NBEdge* firstOfAll = allEdges.front();
4318 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
4319 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
4325 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
4326 if (firstOfIncoming !=
nullptr) {
4327 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
4329 if (firstOfOutgoing !=
nullptr) {
4330 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
4332#ifdef DEBUG_EDGE_SORTING
4334 std::cout <<
"sortedEdges (useNodeShape=" << useNodeShape <<
"):\n";
4335 for (
NBEdge* e : allEdges) {
4336 std::cout <<
" " << e->getID()
4337 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
4338 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
4345 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
4346 std::vector<NBEdge*>::const_iterator in, out;
4347 std::vector<NBEdge*> allTmp;
4348 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
4349 if ((*in)->isTurningDirectionAt(*out)) {
4350 allTmp.push_back(*in);
4351 allTmp.push_back(*out);
4356 if (allTmp.size() == allEdges.size()) {
4369 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
4373 e->computeEdgeShape();
4378std::vector<std::pair<Position, std::string> >
4381 std::vector<std::pair<Position, std::string> >result;
4383 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
4384 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
4386 for (
const auto& pair : result) {
4387 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
4393 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
#define DEBUGCOUT(cond, msg)
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) 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 permissions is a forbidden edge.
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ 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_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
RoundaboutType
classifying roundabout type for nodes
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
int gPrecision
the precision for floating point outputs
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
#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.
Connection & getConnectionRef(int fromLane, const NBEdge *to, int toLane)
Returns reference to the specified connection This method goes through "myConnections" and returns th...
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 shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap and return whether geometry was changed
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.
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
int getNumLanesThatAllow(SVCPermissions permissions, bool allPermissions=true) const
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
const PositionVector & getNodeBorder(const NBNode *node) const
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
std::string getLaneID(int lane) const
get lane ID
@ 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
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
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing, bool withBikes=true, bool withBusLanes=true) const
Returns the list of lanes that may be used to reach the given edge.
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...
Container for nodes during the netbuilding process.
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
void patchOffset_pathAcrossStreet(double &offset)
compute offset for centering path-across-street crossings
SVCPermissions findToLaneForPermissions(NBEdge *currentOutgoing, int fromLane, NBEdge *incoming, SVCPermissions unsatisfied)
helper function to add connections for unsatisfied modes
NBNode::Crossing * addCrossing(EdgeVector edges, double width, bool priority, int tlIndex=-1, int tlIndex2=-1, const PositionVector &customShape=PositionVector::EMPTY, bool fromSumoNet=false, const Parameterised *params=nullptr)
add a pedestrian crossing to this node
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)
static const double UNSPECIFIED_RADIUS
unspecified lane width
bool needsCont(const NBEdge *fromE, const NBEdge *otherFromE, const NBEdge::Connection &c, const NBEdge::Connection &otherC, bool checkOnlyTLS=false) const
whether an internal junction should be built at from and respect other
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;
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
bool unsignalizedOperation() const
whether the given rail connections at this node may run in unsignalized (right-of-way) mode
static bool isExplicitRailNoBidi(const NBEdge *incoming, const NBEdge *outgoing)
detect explict rail turns with potential geometry problem
SumoXMLNodeType getType() const
Returns the type of this node.
bool isTrafficLight() const
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.
void getReduction(const NBEdge *in, const NBEdge *out, int &inOffset, int &inEnd, int &outOffset, int &outEnd, int &reduction) const
get the reduction in driving lanes at this junction
bool myKeepClear
whether the junction area must be kept clear
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)
bool tlsStrandedConflict(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
void mirrorX()
mirror coordinates along the x-axis
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool addedConnections, bool removedConnections)
causes the traffic light to be computed anew
bool brakeForCrossingOnExit(const NBEdge *to, LinkDirection dir, bool indirect) const
whether a connection to the given edge must brake for a crossing when leaving the intersection
bool extraConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light
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 hadSignal() const
whether this node was marked as having a signal in the (OSM) input
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.
static void initRailSignalClasses(const NBNodeCont &nc)
initialize signalized rail classes
PositionVector indirectLeftShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints) const
compute shape of indirect left turn
void recheckSpecialConnections(NBEdge *incoming, NBEdge *currentOutgoing, SVCPermissions svcSpecial)
ensure connectivity for all special vClass
PositionVector cutAtShapes(const PositionVector &cut, const PositionVector &border1, const PositionVector &border2, const PositionVector &def)
geometry helper that cuts the first shape where bordered by the other two
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...
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
void computeKeepClear()
compute keepClear status for all connections
RoundaboutType myRoundaboutType
roundabout type of this node
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
static SVCPermissions myHaveRailSignalClasses
all vehicle classes for which rail signals exist
bool bidiConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether the foe connections is oncoming on the same lane
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 multiple connections from the same edge target the same lane
bool myDiscardAllCrossings
whether to discard all pedestrian crossings
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
void buildCrossingOutlines()
build crossing outlines after walkingareas are finished
static bool isLongEnough(NBEdge *out, double minLength)
check if is long enough
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
void roundGeometry()
ensure consistency between input and output geometries
bool setCrossingTLIndices(const std::string &tlID, int startIndex, bool ignoreCustom=false)
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
bool avoidConfict(NBEdge *incoming, NBEdge *currentOutgoing, SVCPermissions svcSpecial, LinkDirection dir, int i)
helper function for recheckSpecialConnections
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.
static SVCPermissions myPermitUnsignalizedClasses
all rail classes for which operation without rail signals is permitted
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(bool forceSmall)
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 bidiConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether straight connections are in conflict via bidirectional lane use
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.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
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.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
void updateParameters(const Parameterised::Map &mapArg)
Adds or updates all given parameters from the map.
A point in 2D or 3D with translation and scaling methods.
bool isNAN() const
check if position is NAN
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 norm2D()
Normalizes the given vector.
void sub(double dx, double dy)
Subtracts the given position from this one.
double x() const
Returns the x-position.
void round(int precision)
round all coordinates to the given precision
void add(const Position &pos)
Adds the given position to this one.
void mul(double val)
Multiplies position 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 (in radians bet...
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
check whether the other position has a euclidean distance of less than maxDiv
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.
void round(int precision, bool avoidDegeneration=true)
round all coordinates to the given precision
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
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
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 amount
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 (in radians between -M_PI and M_PI)
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)
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
PositionVector reverse() const
reverse position vector
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.
static T maxValue(const std::vector< T > &v)
static T minValue(const std::vector< T > &v)
#define UNUSED_PARAMETER(x)
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.
bool connectionsDone
Whether connection information for this lane is already completed.
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