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) {
112 std::set<int> approachedLanes;
113 bool hasIncomingBusLane =
false;
117 approachedLanes.insert(con.toLane);
120 myDirections.push_back(approachingEdge->getToNode()->getDirection(approachingEdge, currentOutgoing));
124 hasIncomingBusLane |= (approachingEdge->getSpecialLane(
SVC_BUS) != -1);
130 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
136 || (lp ==
SVC_BUS && hasIncomingBusLane)
138 && approachedLanes.count(i) == 0) {
151 assert((
int)myApproaching.size() > src);
153 NBEdge* incomingEdge = myApproaching[src];
157 if (myAvailableLanes.size() == 0) {
161 if (approachingLanes.size() == 0) {
164#ifdef DEBUG_CONNECTION_GUESSING
166 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
170 int numConnections = (int)approachingLanes.size();
182 numConnections = (int)myAvailableLanes.size();
183 factor = (double)approachingLanes.size() / (double)numConnections;
188 std::deque<int>* approachedLanes = spread(numConnections, dest);
189 assert(approachedLanes->size() <= myAvailableLanes.size());
191 const int maxFrom = (int)approachingLanes.size() - 1;
192 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
195 int fromLane = approachingLanes[
MIN2((
int)(i * factor), maxFrom)];
196 int approached = myAvailableLanes[(*approachedLanes)[i]];
199 delete approachedLanes;
205 std::deque<int>* ret =
new std::deque<int>();
209 ret->push_back(dest);
213 const int numOutgoingLanes = (int)myAvailableLanes.size();
215 ret->push_back(dest);
219 while (noSet < numLanes) {
225 if (numOutgoingLanes == noSet) {
234 if (dest + loffset >= numOutgoingLanes) {
237 for (
int i = 0; i < (int)ret->size(); i++) {
238 (*ret)[i] = (*ret)[i] - 1;
243 ret->push_back(dest + loffset);
248 if (numOutgoingLanes == noSet) {
253 if (noSet < numLanes) {
256 if (dest < roffset) {
259 for (
int i = 0; i < (int)ret->size(); i++) {
260 (*ret)[i] = (*ret)[i] + 1;
263 ret->push_front(dest - roffset);
282 customShape(_customShape),
283 tlLinkIndex(_customTLIndex),
284 tlLinkIndex2(_customTLIndex2),
285 customTLIndex(_customTLIndex),
286 customTLIndex2(_customTLIndex2),
322 myPosition(position),
324 myDistrict(district),
325 myHaveCustomPoly(false),
327 myRadius(UNSPECIFIED_RADIUS),
328 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
331 myDiscardAllCrossings(false),
332 myCrossingsLoadedFromSumoNet(0),
333 myDisplacementError(0),
334 myIsBentPriority(false),
335 myTypeWasGuessed(false) {
352 bool updateEdgeGeometries) {
362 if (updateEdgeGeometries) {
366 (*i)->setGeometry(geom);
371 (*i)->setGeometry(geom);
384 wacs.shape.add(xoff, yoff, 0);
387 c->customShape.add(xoff, yoff, 0);
413 c->customShape.mirrorX();
420 wacs.shape.mirrorX();
446 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
470 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
473 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(addedConnections, removedConnections);
474 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
476 const std::vector<NBNode*>& nodes = orig->
getNodes();
477 while (!nodes.empty()) {
478 newDef->
addNode(nodes.front());
479 nodes.front()->removeTrafficLight(orig);
492 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
519 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
571 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
574 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
590 double extrapolateBeg,
591 double extrapolateEnd,
593 int shapeFlag)
const {
600#ifdef DEBUG_SMOOTH_GEOM
602 std::cout <<
"computeSmoothShape node " <<
getID() <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" init=" << init <<
" shapeFlag=" << shapeFlag <<
"\n";
605 if (init.size() == 0) {
607 ret.push_back(begShape.back());
608 ret.push_back(endShape.front());
620 double extrapolateBeg,
621 double extrapolateEnd,
624 double straightThresh,
627 const Position beg = begShape.back();
628 const Position end = endShape.front();
631 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
632#ifdef DEBUG_SMOOTH_GEOM
633 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
649 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
650 init.push_back(center);
652 const double EXT = 100;
658#ifdef DEBUG_SMOOTH_GEOM
660 <<
" endShapeBegLine=" << endShapeBegLine
661 <<
" begShapeEndLineRev=" << begShapeEndLineRev
662 <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
664 if (fabs(angle) <
M_PI / 4.) {
667 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
668 const double halfDistance = dist / 2;
669 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
670#ifdef DEBUG_SMOOTH_GEOM
671 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
672 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
675 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
678#ifdef DEBUG_SMOOTH_GEOM
679 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
680 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
681 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
682 <<
" displacementError=" << sin(displacementAngle) * dist
683 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
686 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
691 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
692 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
694 const double off2 =
EXT -
MIN2(extrapolateEnd, halfDistance);
696#ifdef DEBUG_SMOOTH_GEOM
697 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
698 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
699 <<
" halfDistance=" << halfDistance <<
"\n";
710#ifdef DEBUG_SMOOTH_GEOM
712 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
713 <<
" endShapeBegLine=" << endShapeBegLine
714 <<
" begShapeEndLineRev=" << begShapeEndLineRev
719 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
738 const double minControlLength =
MIN2((
double)1.0, dist / 2);
741 const bool lengthenBeg = distBeg <= minControlLength;
742 const bool lengthenEnd = distEnd <= minControlLength;
743#ifdef DEBUG_SMOOTH_GEOM
745 <<
" beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
746 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd
747 <<
" begOffset=" << begOffset <<
" endOffset=" << endOffset
748 <<
" lEnd=" << lengthenEnd <<
" lBeg=" << lengthenBeg
751 if (lengthenBeg && lengthenEnd) {
752#ifdef DEBUG_SMOOTH_GEOM
754 std::cout <<
" bezierControlPoints failed\n";
757 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
766 }
else if (lengthenBeg || lengthenEnd) {
775 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
778 :
MIN2(0.6, 16 / dist));
789 const double z3 = 0.5 * (beg.
z() + end.
z());
793 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
798 intersect.
set(intersect.
x(), intersect.
y(), z);
799 init.push_back(intersect);
812 result.push_back(begShape.back());
823 dir.
sub(endShape[0]);
827 result.push_back(intersect + dir);
829 result.push_back(endShape.front());
845 if (useCustomShape) {
848 if (startBorder.size() == 0) {
849 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
852 if (tmp.size() < 2) {
854 useCustomShape =
false;
858 tmp[0] = fromShape.back();
859 }
else if (recordError !=
nullptr) {
860 const double offset = tmp[0].distanceTo2D(fromShape.back());
866 if (endBorder.size() == 0) {
867 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
870 if (ret.size() < 2) {
872 useCustomShape =
false;
875 ret[-1] = toShape.front();
876 }
else if (recordError !=
nullptr) {
877 const double offset = ret[-1].distanceTo2D(toShape.front());
884 if (!useCustomShape) {
895#ifdef DEBUG_SMOOTH_GEOM
897 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
902 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
934 for (
int i = 0; i < con.
toLane; ++i) {
938 for (
int i = 0; i < con.
fromLane; ++i) {
948 fromShape.
move2side(inCenter - outCenter);
1005 if (fromE == otherFromE && !thisRight) {
1016 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
1034 && !
needsCont(foeFrom, from, foe, c,
true));
1041 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
1043 if ((*i)->getNodes().size() > 1) {
1045 (*i)->removeNode(
this);
1046 (*i)->setParticipantsInformation();
1047 (*i)->setTLControllingInformation();
1078 WRITE_WARNINGF(
TL(
"Junction '%' is too complicated (% connections, max %); will be set to %."),
1080 }
else if (numConnections == 0) {
1104 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1112 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1115 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1188 edge->computeEdgeShape();
1216 if (mismatchThreshold >= 0
1243 int inOffset, inEnd, outOffset, outEnd, addedLanes;
1244 getReduction(out, in, outOffset, outEnd, inOffset, inEnd, addedLanes);
1249 const int addedLeft = addedLanes - addedRight;
1250#ifdef DEBUG_CONNECTION_GUESSING
1252 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a. addedRight=" << addedRight <<
" addedLeft=" << addedLeft <<
" inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
"\n";
1256 for (
int i = inOffset; i < inEnd; ++i) {
1260 for (
int i = 0; i < addedRight; ++i) {
1264 const int inLeftMost = inEnd - 1;;
1265 const int outOffset2 = outOffset + addedRight + inEnd - inOffset;
1266 for (
int i = 0; i < addedLeft; ++i) {
1299#ifdef DEBUG_CONNECTION_GUESSING
1301 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1341#ifdef DEBUG_CONNECTION_GUESSING
1343 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1370#ifdef DEBUG_CONNECTION_GUESSING
1372 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1381 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1397 int inOffset, inEnd, outOffset, outEnd, reduction;
1398 getReduction(in, out, inOffset, inEnd, outOffset, outEnd, reduction);
1403#ifdef DEBUG_CONNECTION_GUESSING
1405 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
" reduction=" << reduction <<
"\n";
1409 inOffset += reduction;
1410 for (
int i = outOffset; i < outEnd; ++i) {
1427 const int numApproaching = (int)approaching.size();
1428 if (numApproaching != 0) {
1432#ifdef DEBUG_CONNECTION_GUESSING
1434 std::cout <<
"l2l node=" <<
getID() <<
" outgoing=" << currentOutgoing->getID() <<
" bresenham:\n";
1436 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1437 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1438 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " <<
Named::getIDSecure((*k).toEdge) <<
"_" << (*k).toLane <<
"\n";
1447 bool targetProhibitsChange =
false;
1448 for (
int i = 0; i < currentOutgoing->getNumLanes(); i++) {
1449 const NBEdge::Lane& lane = currentOutgoing->getLanes()[i];
1452 targetProhibitsChange =
true;
1456 if (targetProhibitsChange) {
1460 std::map<int, int> outToIn;
1462 if (c.toEdge == currentOutgoing) {
1463 outToIn[c.toLane] = c.fromLane;
1466 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); toLane++) {
1467 if (outToIn.count(toLane) == 0) {
1470 for (
int i = 0; i < toLane; i++) {
1471 if (outToIn.count(i) != 0) {
1472#ifdef DEBUG_CONNECTION_GUESSING
1474 std::cout <<
"l2l node=" <<
getID() <<
" from=" << incoming->getID() <<
" to " << currentOutgoing->getLaneID(toLane) <<
" (changeProhibited, secondTarget)\n";
1483 for (
int i = toLane; i < currentOutgoing->getNumLanes(); i++) {
1484 if (outToIn.count(i) != 0) {
1485#ifdef DEBUG_CONNECTION_GUESSING
1487 std::cout <<
"l2l node=" <<
getID() <<
" from=" << incoming->getID() <<
" to " << currentOutgoing->getLaneID(toLane) <<
" (changeProhibited, newTarget)\n";
1506 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1507 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1509 (*i)->removeFromConnections((*k).toEdge);
1520 incoming->markAsInLane2LaneState();
1524#ifdef DEBUG_CONNECTION_GUESSING
1526 std::cout <<
"final connections at " <<
getID() <<
"\n";
1528 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1529 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1530 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " <<
Named::getIDSecure((*k).toEdge) <<
"_" << (*k).toLane <<
"\n";
1546 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1547 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1552 unsatisfied &= ~satisfied;
1555 if (unsatisfied != 0) {
1556#ifdef DEBUG_CONNECTION_GUESSING
1558 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1563 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1564 if (incoming->getPermissions(fromLane) == unsatisfied) {
1572 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1573 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0
1574 && incoming->getConnectionsFromLane(fromLane, currentOutgoing, -1).size() > 0) {
1581 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1582 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1587#ifdef DEBUG_CONNECTION_GUESSING
1589 if (unsatisfied != 0) {
1590 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1607 const int specialTarget = currentOutgoing->
getSpecialLane(svcSpecial);
1612 bool builtConnection =
false;
1613 for (
int i = 0; i < (int)incoming->
getNumLanes(); i++) {
1617 if (specialTarget >= 0) {
1619#ifdef DEBUG_CONNECTION_GUESSING
1624 builtConnection =
true;
1627 if (
avoidConfict(incoming, currentOutgoing, svcSpecial, dir, i)) {
1631 for (
int i2 = 0; i2 < (int)currentOutgoing->
getNumLanes(); i2++) {
1634 const bool allowDouble = (incoming->
getPermissions(i) == svcSpecial
1637#ifdef DEBUG_CONNECTION_GUESSING
1642 builtConnection =
true;
1649 if (!builtConnection && specialTarget >= 0
1659 for (
int i = start; i < end; i += inc) {
1662#ifdef DEBUG_CONNECTION_GUESSING
1678 if (incoming->
getPermissions(c.fromLane) == svcSpecial && c.toEdge == currentOutgoing) {
1684 if (c.fromLane < i && (c.toEdge != currentOutgoing || incoming->
getPermissions(c.fromLane) == svcSpecial)) {
1690 if (c.fromLane > i && (c.toEdge != currentOutgoing || incoming->
getPermissions(c.fromLane) == svcSpecial)) {
1714 reduction = (inEnd - inOffset) - (outEnd - outOffset);
1720 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1728 if (con.toEdge == currentOutgoing && con.toLane == toLane) {
1729#ifdef DEBUG_CONNECTION_GUESSING
1731 std::cout <<
" shifting connection from=" << con.fromLane <<
" to=" << currentOutgoing->
getID() <<
"_" << toLane <<
": newFromLane=" << fromLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1735 unsatisfied &= ~satisfied;
1743#ifdef DEBUG_CONNECTION_GUESSING
1745 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1748 unsatisfied &= ~satisfied;
1765 int inOffset, inEnd, outOffset, outEnd, reduction;
1768 if (reduction > 0) {
1773 int outLanesRight = 0;
1774 int outLanesLeft = 0;
1775 int outLanesStraight = 0;
1778 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianNonBicycleLaneIndex(
FORWARD,
true));
1779 const int usableLanes = succ->getNumLanes() - outOffset;
1782 outLanesStraight += usableLanes;
1784 outLanesRight += usableLanes;
1786 outLanesLeft += usableLanes;
1792 const int usableLanes = outEnd - outOffset;
1793 int addedTurnLanes =
MIN3(
1795 MAX2(0, usableLanes - outLanesStraight),
1796 outLanesRight + outLanesLeft);
1797#ifdef DEBUG_CONNECTION_GUESSING
1799 std::cout <<
"out=" << out->
getID() <<
" usableLanes=" << usableLanes <<
" addedTurnLanes=" << addedTurnLanes <<
" addedLanes=" << addedLanes <<
" outLanesStraight=" << outLanesStraight <<
" outLanesLeft=" << outLanesLeft <<
" outLanesRight=" << outLanesRight <<
"\n";
1802 if (outLanesLeft == 0) {
1803 return addedTurnLanes;
1805 return MIN2(addedTurnLanes / 2, outLanesRight);
1813 while (seen < minLength) {
1830 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1835 approaching.clear();
1836 for (; *i != currentOutgoing;) {
1838 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1839 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1840 if (connLanes.size() != 0) {
1841 approaching.push_back(*i);
1871 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1873 laneOff += (*i)->getNumLanes();
1903 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1905 laneOff += (*i)->getNumLanes();
1920 int whichLaneOff,
int byLaneOff) {
1924 bool changed =
false;
1926 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1929 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1943 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1945 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1946 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
2006 if (find(edges.begin(), edges.end(), e) != edges.end()) {
2007 edges.erase(find(edges.begin(), edges.end(), e));
2009 if (edges.size() == 0) {
2024 if (mayDrive.
getFrom() ==
nullptr ||
2025 mayDrive.
getTo() ==
nullptr ||
2026 mustStop.
getFrom() ==
nullptr ||
2027 mustStop.
getTo() ==
nullptr) {
2029 WRITE_WARNING(
TL(
"Something went wrong during the building of a connection..."));
2033 conn.push_back(mayDrive);
2040 int size = (int) edgeid.length();
2042 std::string
id = (*i)->
getID();
2043 if (
id.substr(0, size) == edgeid) {
2053 int size = (int) edgeid.length();
2055 std::string
id = (*i)->
getID();
2056 if (
id.substr(0, size) == edgeid) {
2086 if (removeFromConnections) {
2088 (*i)->removeFromConnections(edge);
2092 const bool incoming = edge->
getToNode() ==
this;
2094 tld->replaceRemoved(edge, -1,
nullptr, -1, incoming);
2104 Position toAdd = in->getFromNode()->getPosition();
2110 Position toAdd = out->getToNode()->getPosition();
2116 if (pos.
x() == 0. && pos.
y() == 0.) {
2128 (*i)->invalidateConnections(reallowSetting);
2136 (*i)->invalidateConnections(reallowSetting);
2148 if (to ==
nullptr) {
2172 if (std::find(c->edges.begin(), c->edges.end(), to) != c->edges.end()) {
2182 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
2183 if (from != prohibitorFrom) {
2220 if ((!flip && fromLane <= prohibitorFromLane) ||
2221 (flip && fromLane >= prohibitorFromLane)) {
2224 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
2225 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
2263 bool lefthand)
const {
2265 if (from != from2 || to == to2 || fromLane == fromLane2) {
2273 bool result =
false;
2275 if (fromLane < fromLane2) {
2277 while (*it != to2) {
2285 while (*it != to2) {
2317 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
2327 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
2328 bool regardNonSignalisedLowerPriority)
const {
2330 possProhibitedFrom, possProhibitedTo,
2331 regardNonSignalisedLowerPriority);
2337 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
2346 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
2347 bool changed =
true;
2353 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
2358 bool blockedChanged =
false;
2360 NBConnectionVector::const_iterator j;
2361 for (j = blocked.begin(); j != blocked.end(); j++) {
2363 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
2364 blockedChanged =
true;
2368 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
2370 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2374 }
else if (sblocked.
getFrom() == removed) {
2375 assert(sblocked.
getTo() != removed);
2376 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2379 }
else if (sblocked.
getTo() == removed) {
2380 assert(sblocked.
getFrom() != removed);
2381 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2388 if (blockedChanged) {
2389 blockedConnectionsNew[blocker] = newBlocked;
2394 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2399 }
else if (blocker.
getFrom() == removed) {
2400 assert(blocker.
getTo() != removed);
2402 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2405 }
else if (blocker.
getTo() == removed) {
2406 assert(blocker.
getFrom() != removed);
2408 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2412 blockedConnectionsNew[blocker] = blocked;
2425 EdgeVector::const_iterator i = itOut;
2426 while (*i != incoming) {
2432 if ((*i)->getFromNode() !=
this) {
2440 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2450 if (candidate !=
nullptr) {
2453 if (fabs(angle - candAngle) < 5.) {
2457 if (fabs(candAngle) < fabs(angle) - 5.) {
2460 if (fabs(angle) < fabs(candAngle) - 5.) {
2463 if (fabs(candAngle) < 44.) {
2466 if (candModeLanes > modeLanes) {
2469 if (candModeLanes < modeLanes) {
2473 if (candAngle < 0 && angle > 0) {
2476 if (angle < 0 && candAngle > 0) {
2489 result.push_back(e);
2498 if (outgoing ==
nullptr) {
2519 vehPerm &= ~SVC_PEDESTRIAN;
2522 if (fabs(angle) < 44.) {
2523 if (fabs(angle) > 6.) {
2539 if (angle > 90 + NUMERICAL_EPS) {
2543 if (outCW !=
nullptr) {
2550 if (angle < -170 && incoming->getGeometry().reverse() == outgoing->
getGeometry()) {
2555 }
else if (angle < -(90 + NUMERICAL_EPS)) {
2559 if (outCCW !=
nullptr) {
2582 bool mayDefinitelyPass,
const std::string& tlID)
const {
2592 if (outgoing ==
nullptr) {
2596 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)) {
2605 if (!mayDefinitelyPass
2606 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)
2620 if (
mustBrake(incoming, outgoing, fromLane, toLane,
false)) {
2624 if ((in != incoming || c.fromLane != fromLane) && c.toEdge == outgoing && c.toLane == toLane) {
2640 assert(railClasses != 0);
2650 for (
auto it : nc) {
2651 const NBNode* n = it.second;
2678 reason =
"rail_signal";
2682 reason =
"crossing";
2685 EdgeVector::const_iterator i;
2690 reason =
"edges incompatible: " + reason;
2694 reason =
"turnaround";
2702 std::set<NBNode*> origSet;
2704 origSet.insert((*i)->getFromNode());
2706 if (origSet.size() < 2) {
2721 if (opposite !=
nullptr) {
2725 if (!(*i)->expandableBy(continuation, reason)) {
2726 reason =
"edges incompatible: " + reason;
2732 reason =
"not opposites";
2739 reason =
"intersection";
2744std::vector<std::pair<NBEdge*, NBEdge*> >
2747 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2772 assert(opposite != 0);
2774 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2792 (*i)->resetNodeBorder(
this);
2801 if (e->getToNode() == n && e->getPermissions() != 0) {
2815 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2817 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2834#ifdef DEBUG_PED_STRUCTURES
2845 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2846 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2848 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2850 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2851 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2854 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2855 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2860 int firstSidewalk = -1;
2861 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2862 if (normalizedLanes[i].second) {
2867 int hadCandidates = 0;
2868 std::vector<int> connectedCandidates;
2869 if (firstSidewalk != -1) {
2871 std::vector<std::pair<NBEdge*, bool> > tmp;
2872 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2873 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2874 normalizedLanes = tmp;
2877 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2878 NBEdge* edge = normalizedLanes[i].first;
2879 const bool allowsPed = normalizedLanes[i].second;
2881 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2882 candidates.push_back(edge);
2883 }
else if (allowsPed) {
2884 if (candidates.size() > 0) {
2890 connectedCandidates.push_back(n);
2897 if (hadCandidates > 0 && candidates.size() > 0) {
2903 connectedCandidates.push_back(n);
2909 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2911 if (connectedCandidates.back() <= connectedCandidates.front()) {
2912 numGuessed -= connectedCandidates.back();
2915 numGuessed -= connectedCandidates.front();
2920#ifdef DEBUG_PED_STRUCTURES
2922 std::cout <<
"guessedCrossings:\n";
2924 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2932 e->computeEdgeShape();
2942 if (candidates.size() == 0) {
2947 double prevAngle = -100000;
2948 for (
int i = 0; i < (int)candidates.size(); ++i) {
2949 NBEdge* edge = candidates[i];
2971 prevAngle = -100000;
2972 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2973 double angle = (*it)->getCrossingAngle(
this);
2974 if (it != candidates.begin()) {
2975 NBEdge* prev = *(it - 1);
2980 double intermediateWidth = 0;
2983 prevPos = prev->
getLanes()[laneI].shape[-1];
2986 prevPos = prev->
getLanes()[laneI].shape[0];
2991 currPos = curr->
getLanes()[laneI].shape[0];
2994 currPos = curr->
getLanes()[laneI].shape[-1];
2998 DEBUGCOUT(
gDebugFlag1,
" prevAngle=" << prevAngle <<
" angle=" << angle <<
" intermediateWidth=" << intermediateWidth <<
"\n")
3021 std::sort(edges.begin(), edges.end());
3025 EdgeVector edgesOfCrossing = crossing->edges;
3026 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
3027 if (edgesOfCrossing == edges) {
3037 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
3038 if (!normalizedLanes[i].second) {
3056 std::set<std::string> waIDs;
3057 int numSidewalks = 0;
3059 waIDs.insert(wa.id);
3060 numSidewalks += (int)(wa.prevSidewalks.size() + wa.nextSidewalks.size());
3062 if (numSidewalks < 2) {
3067 if (waIDs.count(crossing->prevWalkingArea) == 0 || waIDs.count(crossing->nextWalkingArea) == 0 || !crossing->valid) {
3068 if (crossing->valid) {
3069 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found)."),
3086 crossing->valid =
false;
3087 crossing->prevWalkingArea =
"";
3088 crossing->nextWalkingArea =
"";
3095std::vector<NBNode::Crossing*>
3097 std::vector<Crossing*> result;
3100 result.push_back(c.get());
3134 int noInternalNoSplits = 0;
3137 if (con.toEdge ==
nullptr) {
3140 noInternalNoSplits++;
3145 double maxCrossingSeconds = 0.;
3147 maxCrossingSeconds =
MAX2(maxCrossingSeconds, edge->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo));
3149 return maxCrossingSeconds;
3155#ifdef DEBUG_PED_STRUCTURES
3173 c->nextWalkingArea =
"";
3174 c->prevWalkingArea =
"";
3182 std::vector<double> rawAngleDiffs;
3183 double maxAngleDiff = 0;
3184 int maxAngleDiffIndex = 0;
3185 for (
int i = 0; i < (int) edges.size(); i++) {
3187 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
3192 edges[i]->getAngleAtNodeNormalized(
this),
3193 edges[(i + 1) % edges.size()]->getAngleAtNodeNormalized(
this));
3194 rawAngleDiffs.push_back(fabs(rawDiff));
3196 DEBUGCOUT(
gDebugFlag1,
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n")
3197 if (diff > maxAngleDiff) {
3198 maxAngleDiff = diff;
3199 maxAngleDiffIndex = i;
3202 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
3204 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
3207 bool diagonalCrossing =
false;
3208 std::sort(rawAngleDiffs.begin(), rawAngleDiffs.end());
3209 if (rawAngleDiffs.size() >= 2 && rawAngleDiffs[rawAngleDiffs.size() - 2] > 30) {
3210 diagonalCrossing =
true;
3211#ifdef DEBUG_PED_STRUCTURES
3213 std::cout <<
" detected pedScramble " << c->id <<
" edges=" <<
toString(edges) <<
" rawDiffs=" <<
toString(rawAngleDiffs) <<
"\n";
3214 for (
auto e : edges) {
3215 std::cout <<
" e=" << e->getID()
3216 <<
" aC=" << e->getAngleAtNodeToCenter(
this)
3217 <<
" a=" << e->getAngleAtNode(
this)
3218 <<
" aN=" << e->getAngleAtNodeNormalized(
this)
3225 std::reverse(edges.begin(), edges.end());
3228 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
3229 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
3230 int firstNonPedLane = edges.front()->getFirstNonPedestrianLaneIndex(begDir);
3231 int lastNonPedLane = edges.back()->getFirstNonPedestrianLaneIndex(endDir);
3232 DEBUGCOUT(
gDebugFlag1,
" finalEdges=" <<
toString(edges) <<
" firstNonPedLane=" << firstNonPedLane <<
" lastNonPedLane=" << lastNonPedLane <<
"\n")
3233 if (firstNonPedLane < 0 || lastNonPedLane < 0) {
3235 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross)."), c->id,
getID(),
toString(c->edges));
3238 firstNonPedLane = begDir ==
FORWARD ? 0 : edges.front()->getNumLanes() - 1;
3239 lastNonPedLane = endDir ==
FORWARD ? 0 : edges.back()->getNumLanes() - 1;
3241 if (c->customShape.size() != 0) {
3242 c->shape = c->customShape;
3244 NBEdge::Lane crossingBeg = edges.front()->getLanes()[firstNonPedLane];
3245 NBEdge::Lane crossingEnd = edges.back()->getLanes()[lastNonPedLane];
3250 double offset = c->width / 2;
3259 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
3260 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
3262 if (diagonalCrossing) {
3263 c->shape.move2side(-c->width);
3280 nonPedIncoming.push_back(e);
3282 pedIncoming.push_back(e);
3287 nonPedOutgoing.push_back(e);
3289 pedOutgoing.push_back(e);
3292 if (
geometryLike(nonPedIncoming, nonPedOutgoing) && (pedIncoming.size() > 0 || pedOutgoing.size() > 0)) {
3293 double maxAngle = 0;
3295 double outWidth = 0;
3296 NBEdge* in = nonPedIncoming.front();
3297 NBEdge* out = nonPedOutgoing.front();
3298 if (nonPedIncoming.size() == 1) {
3304 for (
NBEdge* in2 : nonPedIncoming) {
3305 double minAngle = 180;
3306 for (
NBEdge* out2 : nonPedOutgoing) {
3307 double angle = fabs(
NBHelpers::relAngle(in2->getAngleAtNode(
this), out2->getAngleAtNode(
this)));
3308 if (angle < minAngle) {
3316 maxAngle =
MAX2(maxAngle, minAngle);
3320 if (maxAngle < 15 && inWidth == outWidth) {
3323 if (inLane >= 0 && outLane >= 0) {
3330 double maxPathDist = 0;
3331 for (
NBEdge* e : pedIncoming) {
3335 for (
NBEdge* e : pedOutgoing) {
3356#ifdef DEBUG_PED_STRUCTURES
3367 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
3368 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
3370 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
3371 std::vector<NBEdge::Lane> tmp;
3372 bool hadSidewalk =
false;
3373 bool hadNonSidewalk =
false;
3374 for (
int i = 0; i < (int)lanes.size(); i++) {
3378 if (hadSidewalk && hadNonSidewalk) {
3380 WRITE_WARNINGF(
TL(
"Ignoring additional sidewalk lane % on edge '%' for walkingareas."),
3387 hadNonSidewalk =
true;
3392 std::reverse(tmp.begin(), tmp.end());
3395 l.shape = l.shape.reverse();
3399 l.shape = l.shape.getSubpartByIndex(0, 2);
3401 normalizedLanes.push_back(std::make_pair(edge, l));
3406 std::vector<std::pair<int, int> > waIndices;
3408 NBEdge* prevEdge = normalizedLanes.back().first;
3409 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
3410 NBEdge* edge = normalizedLanes[i].first;
3422 waIndices.push_back(std::make_pair(start, i - start));
3432 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n")
3437 const int waNumLanes = (int)normalizedLanes.size() - start;
3438 if (waIndices.size() == 0) {
3439 waIndices.push_back(std::make_pair(start, waNumLanes));
3442 if (waIndices.front().first == 0) {
3443 NBEdge* edge = normalizedLanes.front().first;
3447 waIndices.push_back(std::make_pair(start, waNumLanes));
3451 waIndices.front().first = start;
3452 waIndices.front().second = waNumLanes + waIndices.front().second;
3457 waIndices.push_back(std::make_pair(start, waNumLanes));
3462#ifdef DEBUG_PED_STRUCTURES
3464 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
3465 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3466 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
3471 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3472 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
3473 int startIdx = waIndices[i].first;
3474 const int prev = startIdx > 0 ? startIdx - 1 : (int)normalizedLanes.size() - 1;
3475 const int count = waIndices[i].second;
3476 const int end = (startIdx + count) % normalizedLanes.size();
3477 int lastIdx = (startIdx + count - 1) % normalizedLanes.size();
3480 DEBUGCOUT(
gDebugFlag1,
"build walkingArea " << wa.
id <<
" start=" << startIdx <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n")
3481 double endCrossingWidth = 0;
3482 double startCrossingWidth = 0;
3486 bool connectsCrossing =
false;
3487 bool crossingNearSidewalk =
false;
3488 int numCrossings = 0;
3489 std::vector<Position> connectedPoints;
3492 if (c->edges.back() == normalizedLanes[end].first
3493 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
3495 if (c->nextWalkingArea !=
"") {
3496 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'."),
3497 getID(), c->id, c->nextWalkingArea, wa.
id);
3500 c->nextWalkingArea = wa.
id;
3504 endCrossingWidth = c->width;
3505 endCrossingShape = c->shape;
3507 connectsCrossing =
true;
3508 connectedPoints.push_back(c->shape[-1]);
3511 if (normalizedLanes[lastIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < endCrossingWidth) {
3512 crossingNearSidewalk =
true;
3518 if (c->edges.front() == normalizedLanes[prev].first
3519 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
3521 if (c->prevWalkingArea !=
"") {
3522 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'."),
3523 getID(), c->id, c->prevWalkingArea, wa.
id);
3527 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' starts and ends at walkingarea '%'."),
3531 c->prevWalkingArea = wa.
id;
3535 startCrossingWidth = c->width;
3536 startCrossingShape = c->shape;
3538 connectsCrossing =
true;
3539 connectedPoints.push_back(c->shape[0]);
3542 if (normalizedLanes[startIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < startCrossingWidth) {
3543 crossingNearSidewalk =
true;
3550 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
3551 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[startIdx].first->getID()
3552 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
3555 if (count < 2 && !connectsCrossing) {
3557 DEBUGCOUT(
gDebugFlag1,
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n")
3561 std::set<const NBEdge*, ComparatorIdLess>& connected = wa.
refEdges;
3562 for (
int j = 0; j < count; ++j) {
3563 const int nlI = (startIdx + j) % normalizedLanes.size();
3564 NBEdge* edge = normalizedLanes[nlI].first;
3567 if (connected.count(edge) == 0) {
3576 connected.insert(edge);
3583 if (buildExtensions) {
3585 if (startCrossingShape.size() > 0) {
3586 startCrossingShape.
move2side(startCrossingWidth / 2);
3588 startCrossingShape.
move2side(-startCrossingWidth);
3593 if (endCrossingShape.size() > 0) {
3594 endCrossingShape.
move2side(endCrossingWidth / 2);
3596 endCrossingShape.
move2side(-endCrossingWidth);
3602 && normalizedLanes.size() == 2) {
3604 const NBEdge* e1 = *connected.begin();
3605 const NBEdge* e2 = *(++connected.begin());
3611 if (count == (
int)normalizedLanes.size()) {
3617 if (in->getFromNode() == out->getToNode() && in->getInnerGeometry().reverse() == out->getInnerGeometry()
3621 wa.
width =
MAX2(wa.
width, in->getTotalWidth() + out->getTotalWidth());
3625 }
else if (cornerDetail > 0) {
3627 int smoothEnd = end;
3628 int smoothPrev = prev;
3630 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
3631 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
3633 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
3634 if (smoothPrev == 0) {
3635 smoothPrev = (int)normalizedLanes.size() - 1;
3640 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
3641 begShape = begShape.
reverse();
3642 double shiftBegExtra = 0;
3643 double shiftEndExtra = 0;
3644 if (lastIdx == startIdx) {
3645 lastIdx = (startIdx + 1) % normalizedLanes.size();
3646 DEBUGCOUT(
gDebugFlag1,
" new lastIdx=" << lastIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3647 if (normalizedLanes[startIdx].first == normalizedLanes[lastIdx].first) {
3651 startIdx = (int)normalizedLanes.size() - 1;
3653 DEBUGCOUT(
gDebugFlag1,
" new startIdx=" << startIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3659 PositionVector begShapeOuter = normalizedLanes[lastIdx].second.shape;
3660 begShapeOuter = begShapeOuter.
reverse();
3662 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3663 begShapeOuter.
move2side(normalizedLanes[lastIdx].second.width / 2 + shiftBegExtra);
3664 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3665 PositionVector endShapeOuter = normalizedLanes[startIdx].second.shape;;
3666 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3667 endShapeOuter.
move2side(normalizedLanes[startIdx].second.width / 2 + shiftEndExtra);
3670 if (count != (
int)normalizedLanes.size() || count == 2) {
3672 if (count == 1 && angle > 0 && crossingNearSidewalk && numCrossings < 2) {
3676 }
else if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3680 if (curve.
length2D() - begShape.back().distanceTo2D(endShape.front()) > 5) {
3681 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShape.back().distanceTo2D(endShape.front())
3682 <<
" curveLength=" << curve.
length2D()
3683 <<
" delta=" << curve.
length2D() - begShape.back().distanceTo2D(endShape.front())
3689 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3692 if (curve.size() > 2) {
3693 curve.erase(curve.begin());
3695 if (endCrossingWidth > 0) {
3696 wa.
shape.pop_back();
3698 if (startCrossingWidth > 0) {
3701 if (count == (
int)normalizedLanes.size()) {
3707 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3708 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve
3709 <<
" begShapeOuter=" << begShapeOuter <<
" endShapeOuter=" << endShapeOuter
3710 <<
" waShape=" << wa.
shape
3713 if (curve.size() > 2 && (count == 2 || (count == 1 && numCrossings > 0))) {
3714 const double innerDist = begShape.back().distanceTo2D(endShape[0]);
3715 const double outerDist = begShapeOuter.back().distanceTo2D(endShapeOuter[0]);
3717 if (outerDist > innerDist) {
3719 const double extend =
MIN2(10.0, begShapeOuter.back().distanceTo2D(endShapeOuter.front()) / 2);
3720 curve =
computeSmoothShape(begShapeOuter, endShapeOuter, cornerDetail + 2,
false, extend, extend,
nullptr);
3721 if (curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front()) > 5) {
3722 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3723 <<
" curveLength=" << curve.
length2D()
3724 <<
" delta=" << curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3730 if (shiftBegExtra != 0) {
3733 }
else if (shiftEndExtra != 0) {
3739 wa.
shape.insert(wa.
shape.begin() + 1, curve.begin(), curve.end());
3749 if (wacs.shape.size() != 0) {
3750 wa.
shape = wacs.shape;
3753 wa.
width = wacs.width;
3760 double lengthSum = 0;
3761 int combinations = 0;
3762 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3763 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3772 DEBUGCOUT(
gDebugFlag1,
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n")
3773 wa.
length = POSITION_EPS;
3774 if (combinations > 0) {
3775 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3780 std::vector<Crossing*> validCrossings =
getCrossings();
3781 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3783 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3798 wa.
shape.push_back(tmp[-1]);
3800 wa.
shape.push_back(tmp[-1]);
3804 wa.
shape.push_back(tmp[0]);
3806 wa.
shape.push_back(tmp[0]);
3813 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(wa.
refEdges, wacs.edges)) {
3814 wa.
shape = wacs.shape;
3830#ifdef DEBUG_CROSSING_OUTLINE
3832 std::cerr <<
"<add>\n";
3835 std::map<std::string, PositionVector> waShapes;
3837 waShapes[wa.id] = wa.shape;
3842 if (wa1.empty() || wa2.empty()) {
3855 side1 =
cutAtShapes(side1, wa1, wa2, side1default);
3856 side2 =
cutAtShapes(side2, wa1, wa2, side2default);
3860 side2ex.
extrapolate(side2 == side2default ? c->width / 2 : POSITION_EPS);
3863 c->outlineShape = side1;
3864 c->outlineShape.
append(side3, POSITION_EPS);
3865 c->outlineShape.append(side2, POSITION_EPS);
3866 c->outlineShape.append(side4, POSITION_EPS);
3867 c->outlineShape.removeDoublePoints();
3868 if (c->outlineShape.back().almostSame(c->outlineShape.front())) {
3869 c->outlineShape.pop_back();
3872#ifdef DEBUG_CROSSING_OUTLINE
3873 std::cout <<
" side1=" << side1 <<
"\n side2=" << side2 <<
"\n side3=" << side3 <<
"\n side4=" << side4 <<
"\n";
3874 std::cerr <<
"<poly id=\"" << c->id <<
"\" shape=\"" << c->outlineShape <<
"\" color=\"blue\" lineWidth=\"0.2\" layer=\"100\"/>\n";
3877#ifdef DEBUG_CROSSING_OUTLINE
3879 std::cerr <<
"</add>\n";
3889#ifdef DEBUG_CROSSING_OUTLINE
3890 std::cout <<
"is1=" << is1 <<
" is2=" << is2 <<
" cut=" << cut <<
" border1=" << border1 <<
" border2=" << border2 <<
"\n";
3892 if (is1.size() == 0 && border1.size() == 2) {
3893 const double d1 = cut.
distance2D(border1.front());
3894 const double d2 = cut.
distance2D(border1.back());
3895 Position closer = d1 < d2 ? border1.front() : border1.back();
3897#ifdef DEBUG_CROSSING_OUTLINE
3898 std::cout <<
" closer=" << closer <<
" nOp=" << nOp <<
"\n";
3900 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3906 if (is2.size() == 0 && border2.size() == 2) {
3907 const double d1 = cut.
distance2D(border2.front());
3908 const double d2 = cut.
distance2D(border2.back());
3909 Position closer = d1 < d2 ? border2.front() : border2.back();
3911 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3917 if (is1.size() > 0 && is2.size() > 0) {
3920#ifdef DEBUG_CROSSING_OUTLINE
3921 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3926#ifdef DEBUG_CROSSING_OUTLINE
3927 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3933#ifdef DEBUG_CROSSING_OUTLINE
3934 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3947 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3949 for (
const NBEdge* e : sub) {
3950 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3969 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3970 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3971 if (it1 != edges.end() && it2 != edges.end()) {
3996 return other1 == other2;
4016 while (it != it_end) {
4017 result.push_back(*it);
4027 wacs.
edges.insert(edges.begin(), edges.end());
4041 if (incoming.size() == 1 && outgoing.size() == 1) {
4044 if (incoming.size() == 2 && outgoing.size() == 2) {
4047 NBEdge* in0 = incoming[0];
4048 NBEdge* in1 = incoming[1];
4049 NBEdge* out0 = outgoing[0];
4050 NBEdge* out1 = outgoing[1];
4059 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4063 if (
MAX2(angle0, angle1) <= 160) {
4093 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
4094 if (params !=
nullptr) {
4097 myCrossings.push_back(std::unique_ptr<Crossing>(c));
4107 EdgeSet edgeSet(edges.begin(), edges.end());
4109 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
4110 if (edgeSet == edgeSet2) {
4132 const EdgeSet edgeSet(edges.begin(), edges.end());
4134 const EdgeSet edgeSet2(crossing->edges.begin(), crossing->edges.end());
4135 if (edgeSet == edgeSet2) {
4136 return crossing.get();
4142 throw ProcessError(
TL(
"Request for unknown crossing for the given Edges"));
4149 if (walkingArea.id ==
id) {
4158 if (walkingArea.id ==
id) {
4164 WRITE_WARNINGF(
"Could not retrieve walkingarea '%' (edge ordering changed after recompute).",
id);
4173 bool usedCustom =
false;
4175 c->tlLinkIndex = startIndex++;
4177 if (c->customTLIndex != -1 && !ignoreCustom) {
4178 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
4179 c->tlLinkIndex = c->customTLIndex;
4181 if (c->customTLIndex2 != -1 && !ignoreCustom) {
4183 c->tlLinkIndex2 = c->customTLIndex2;
4196 result += (int)edge->getConnections().size();
4210 if (e == from && cand.fromLane == con.
fromLane && cand.toLane == con.
toLane && cand.toEdge == con.
toEdge) {
4240#ifdef DEBUG_PED_STRUCTURES
4242 std::cout <<
" angles:\n";
4243 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
4244 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
4246 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
4252 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
4261 bool haveModifications =
false;
4265 if (turnDest !=
nullptr) {
4270 if (haveModifications) {
4288 if (def->extraConflict(index, foeIndex)) {
4310 std::vector<NBEdge*>::iterator j;
4311 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
4314 if (allEdges.size() > 1 && j != allEdges.end()) {
4319 NBEdge* firstOfAll = allEdges.front();
4320 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
4321 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
4327 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
4328 if (firstOfIncoming !=
nullptr) {
4329 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
4331 if (firstOfOutgoing !=
nullptr) {
4332 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
4334#ifdef DEBUG_EDGE_SORTING
4336 std::cout <<
"sortedEdges (useNodeShape=" << useNodeShape <<
"):\n";
4337 for (
NBEdge* e : allEdges) {
4338 std::cout <<
" " << e->getID()
4339 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
4340 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
4347 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
4348 std::vector<NBEdge*>::const_iterator in, out;
4349 std::vector<NBEdge*> allTmp;
4350 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
4351 if ((*in)->isTurningDirectionAt(*out)) {
4352 allTmp.push_back(*in);
4353 allTmp.push_back(*out);
4358 if (allTmp.size() == allEdges.size()) {
4371 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
4375 e->computeEdgeShape();
4380std::vector<std::pair<Position, std::string> >
4383 std::vector<std::pair<Position, std::string> >result;
4385 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
4386 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
4388 for (
const auto& pair : result) {
4389 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
4395 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
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
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing, bool withBikes=true) const
Returns the list of lanes that may be used to reach the given edge.
double getStartAngle() const
Returns the angle at the start of the edge (relative to the node shape center) The angle is computed ...
int getSpecialLane(SVCPermissions permissions) const
return index of the first lane that allows the given permissions
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
const NBEdge * getBidiEdge() const
NBNode * getFromNode() const
Returns the origin node of the edge.
NBEdge * getTurnDestination(bool possibleDestination=false) const
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
static const double UNSPECIFIED_WIDTH
unspecified lane width
double getEndAngle() const
Returns the angle at the end of the edge (relative to the node shape center) The angle is computed in...
void replaceInConnections(NBEdge *which, NBEdge *by, int laneOff)
replace in current connections of edge
double getEndOffset() const
Returns the offset to the destination node.
bool addLane2LaneConnections(int fromLane, NBEdge *dest, int toLane, int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
bool hasConnectionTo(const NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
double getFinalLength() const
get length that will be assigned to the lanes in the final network
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
int getFirstNonPedestrianNonBicycleLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN, SVC_BICYCLE and 0
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
A loaded (complete) traffic light logic.
Computes lane-2-lane connections.
bool myIsBikeEdge
whether the outgoing edge is exclusively used by bikes
ApproachingDivider(const EdgeVector &approaching, NBEdge *currentOutgoing)
Constructor.
~ApproachingDivider()
Destructor.
const EdgeVector & myApproaching
The list of edges that approach the current edge.
int numAvailableLanes() const
@ get number of available lanes
std::vector< LinkDirection > myDirections
directions from each incoming edge to the outgoing edge
int myNumStraight
number of straight connections to the outgoing edge
NBEdge * myCurrentOutgoing
The approached current edge.
std::deque< int > * spread(int numLanes, int dest) const
the method that spreads the wished number of lanes from the lane given by the bresenham-call to both ...
void execute(const int src, const int dest)
the bresenham-callback
std::vector< int > myAvailableLanes
The available lanes to which connections shall be built.
A definition of a pedestrian crossing.
Crossing(const NBNode *_node, const EdgeVector &_edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector &_customShape)
constructor
std::string id
the (edge)-id of this crossing
std::string prevWalkingArea
the lane-id of the previous walkingArea
std::string nextWalkingArea
the lane-id of the next walkingArea
PositionVector shape
The crossing's shape.
EdgeVector edges
The edges being crossed.
double width
This crossing's width.
bool valid
whether this crossing is valid (and can be written to the net.xml). This is needed for netedit becaus...
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
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