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)
104 myApproaching(approaching),
105 myCurrentOutgoing(currentOutgoing),
107 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE) {
109 std::set<int> approachedLanes;
113 approachedLanes.insert(con.toLane);
116 myDirections.push_back(approachingEdge->getToNode()->getDirection(approachingEdge, currentOutgoing));
125 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
131 && approachedLanes.count(i) == 0) {
144 assert((
int)myApproaching.size() > src);
146 NBEdge* incomingEdge = myApproaching[src];
150 if (myAvailableLanes.size() == 0) {
154 if (approachingLanes.size() == 0) {
157 #ifdef DEBUG_CONNECTION_GUESSING
159 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
163 int numConnections = (int)approachingLanes.size();
175 numConnections = (int)myAvailableLanes.size();
176 factor = (double)approachingLanes.size() / (double)numConnections;
181 std::deque<int>* approachedLanes = spread(numConnections, dest);
182 assert(approachedLanes->size() <= myAvailableLanes.size());
184 const int maxFrom = (int)approachingLanes.size() - 1;
185 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
188 int fromLane = approachingLanes[
MIN2((
int)(i * factor), maxFrom)];
189 int approached = myAvailableLanes[(*approachedLanes)[i]];
192 delete approachedLanes;
198 std::deque<int>* ret =
new std::deque<int>();
202 ret->push_back(dest);
206 const int numOutgoingLanes = (int)myAvailableLanes.size();
208 ret->push_back(dest);
212 while (noSet < numLanes) {
218 if (numOutgoingLanes == noSet) {
227 if (dest + loffset >= numOutgoingLanes) {
230 for (
int i = 0; i < (int)ret->size(); i++) {
231 (*ret)[i] = (*ret)[i] - 1;
236 ret->push_back(dest + loffset);
241 if (numOutgoingLanes == noSet) {
246 if (noSet < numLanes) {
249 if (dest < roffset) {
252 for (
int i = 0; i < (int)ret->size(); i++) {
253 (*ret)[i] = (*ret)[i] + 1;
256 ret->push_front(dest - roffset);
275 customShape(_customShape),
276 tlLinkIndex(_customTLIndex),
277 tlLinkIndex2(_customTLIndex2),
278 customTLIndex(_customTLIndex),
279 customTLIndex2(_customTLIndex2),
312 myPosition(position),
314 myDistrict(district),
315 myHaveCustomPoly(false),
317 myRadius(UNSPECIFIED_RADIUS),
318 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
321 myDiscardAllCrossings(false),
322 myCrossingsLoadedFromSumoNet(0),
323 myDisplacementError(0),
324 myIsBentPriority(false),
325 myTypeWasGuessed(false) {
339 bool updateEdgeGeometries) {
346 if (updateEdgeGeometries) {
350 (*i)->setGeometry(geom);
355 (*i)->setGeometry(geom);
368 wacs.shape.add(xoff, yoff, 0);
371 c->customShape.add(xoff, yoff, 0);
382 c->customShape.mirrorX();
389 wacs.shape.mirrorX();
415 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
429 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
432 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
433 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
435 const std::vector<NBNode*>& nodes = orig->
getNodes();
436 while (!nodes.empty()) {
437 newDef->
addNode(nodes.front());
438 nodes.front()->removeTrafficLight(orig);
451 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
478 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
530 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
533 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
549 double extrapolateBeg,
550 double extrapolateEnd,
552 int shapeFlag)
const {
559 #ifdef DEBUG_SMOOTH_GEOM
561 std::cout <<
"computeSmoothShape node " <<
getID() <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" init=" << init <<
" shapeFlag=" << shapeFlag <<
"\n";
564 if (init.size() == 0) {
566 ret.push_back(begShape.back());
567 ret.push_back(endShape.front());
579 double extrapolateBeg,
580 double extrapolateEnd,
583 double straightThresh,
586 const Position beg = begShape.back();
587 const Position end = endShape.front();
590 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
591 #ifdef DEBUG_SMOOTH_GEOM
592 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
608 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
609 init.push_back(center);
611 const double EXT = 100;
617 #ifdef DEBUG_SMOOTH_GEOM
619 <<
" endShapeBegLine=" << endShapeBegLine
620 <<
" begShapeEndLineRev=" << begShapeEndLineRev
621 <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
623 if (fabs(angle) <
M_PI / 4.) {
626 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
627 const double halfDistance = dist / 2;
628 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
629 #ifdef DEBUG_SMOOTH_GEOM
630 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
631 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
634 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
637 #ifdef DEBUG_SMOOTH_GEOM
638 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
639 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
640 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
641 <<
" displacementError=" << sin(displacementAngle) * dist
642 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
645 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
650 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
651 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
653 const double off2 =
EXT -
MIN2(extrapolateEnd, halfDistance);
655 #ifdef DEBUG_SMOOTH_GEOM
656 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
657 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
658 <<
" halfDistance=" << halfDistance <<
"\n";
669 #ifdef DEBUG_SMOOTH_GEOM
671 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
672 <<
" endShapeBegLine=" << endShapeBegLine
673 <<
" begShapeEndLineRev=" << begShapeEndLineRev
678 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
697 const double minControlLength =
MIN2((
double)1.0, dist / 2);
700 const bool lengthenBeg = distBeg <= minControlLength;
701 const bool lengthenEnd = distEnd <= minControlLength;
702 #ifdef DEBUG_SMOOTH_GEOM
704 <<
" beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
705 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd
706 <<
" begOffset=" << begOffset <<
" endOffset=" << endOffset
707 <<
" lEnd=" << lengthenEnd <<
" lBeg=" << lengthenBeg
710 if (lengthenBeg && lengthenEnd) {
711 #ifdef DEBUG_SMOOTH_GEOM
713 std::cout <<
" bezierControlPoints failed\n";
716 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
725 }
else if (lengthenBeg || lengthenEnd) {
734 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
737 :
MIN2(0.6, 16 / dist));
748 const double z3 = 0.5 * (beg.
z() + end.
z());
752 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
757 intersect.
set(intersect.
x(), intersect.
y(), z);
758 init.push_back(intersect);
771 result.push_back(begShape.back());
782 dir.
sub(endShape[0]);
786 result.push_back(intersect + dir);
788 result.push_back(endShape.front());
804 if (useCustomShape) {
807 if (startBorder.size() == 0) {
808 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
811 if (tmp.size() < 2) {
813 useCustomShape =
false;
817 tmp[0] = fromShape.back();
818 }
else if (recordError !=
nullptr) {
819 const double offset = tmp[0].distanceTo2D(fromShape.back());
825 if (endBorder.size() == 0) {
826 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
829 if (ret.size() < 2) {
831 useCustomShape =
false;
834 ret[-1] = toShape.front();
835 }
else if (recordError !=
nullptr) {
836 const double offset = ret[-1].distanceTo2D(toShape.front());
843 if (!useCustomShape) {
854 #ifdef DEBUG_SMOOTH_GEOM
856 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
861 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
893 for (
int i = 0; i < con.
toLane; ++i) {
897 for (
int i = 0; i < con.
fromLane; ++i) {
907 fromShape.
move2side(inCenter - outCenter);
964 if (fromE == otherFromE && !thisRight) {
975 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
993 && !
needsCont(foeFrom, from, foe, c,
true));
1000 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
1002 if ((*i)->getNodes().size() > 1) {
1004 (*i)->removeNode(
this);
1005 (*i)->setParticipantsInformation();
1006 (*i)->setTLControllingInformation();
1037 WRITE_WARNINGF(
TL(
"Junction '%' is too complicated (% connections, max %); will be set to %."),
1039 }
else if (numConnections == 0) {
1063 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1071 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1074 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1147 edge->computeEdgeShape();
1175 if (mismatchThreshold >= 0
1202 int inOffset, inEnd, outOffset, outEnd, addedLanes;
1203 getReduction(out, in, outOffset, outEnd, inOffset, inEnd, addedLanes);
1208 const int addedLeft = addedLanes - addedRight;
1209 #ifdef DEBUG_CONNECTION_GUESSING
1211 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a. addedRight=" << addedRight <<
" addedLeft=" << addedLeft <<
" inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
"\n";
1215 for (
int i = inOffset; i < inEnd; ++i) {
1219 for (
int i = 0; i < addedRight; ++i) {
1223 const int inLeftMost = inEnd - 1;;
1224 const int outOffset2 = outOffset + addedRight + inEnd - inOffset;
1225 for (
int i = 0; i < addedLeft; ++i) {
1258 #ifdef DEBUG_CONNECTION_GUESSING
1260 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1300 #ifdef DEBUG_CONNECTION_GUESSING
1302 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1329 #ifdef DEBUG_CONNECTION_GUESSING
1331 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1340 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1356 int inOffset, inEnd, outOffset, outEnd, reduction;
1357 getReduction(in, out, inOffset, inEnd, outOffset, outEnd, reduction);
1362 #ifdef DEBUG_CONNECTION_GUESSING
1364 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
" reduction=" << reduction <<
"\n";
1368 inOffset += reduction;
1369 for (
int i = outOffset; i < outEnd; ++i) {
1386 const int numApproaching = (int)approaching.size();
1387 if (numApproaching != 0) {
1391 #ifdef DEBUG_CONNECTION_GUESSING
1393 std::cout <<
"l2l node=" <<
getID() <<
" bresenham:\n";
1395 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1396 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1397 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1406 bool targetProhibitsChange =
false;
1407 for (
int i = 0; i < currentOutgoing->getNumLanes(); i++) {
1408 const NBEdge::Lane& lane = currentOutgoing->getLanes()[i];
1411 targetProhibitsChange =
true;
1415 if (targetProhibitsChange) {
1419 std::map<int, int> outToIn;
1421 if (c.toEdge == currentOutgoing) {
1422 outToIn[c.toLane] = c.fromLane;
1425 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); toLane++) {
1426 if (outToIn.count(toLane) == 0) {
1429 for (
int i = 0; i < toLane; i++) {
1430 if (outToIn.count(i) != 0) {
1437 for (
int i = toLane; i < currentOutgoing->getNumLanes(); i++) {
1438 if (outToIn.count(i) != 0) {
1455 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1456 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1458 (*i)->removeFromConnections((*k).toEdge);
1469 incoming->markAsInLane2LaneState();
1473 #ifdef DEBUG_CONNECTION_GUESSING
1475 std::cout <<
"final connections at " <<
getID() <<
"\n";
1477 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1478 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1479 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1497 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1498 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1503 unsatisfied &= ~satisfied;
1506 if (unsatisfied != 0) {
1507 #ifdef DEBUG_CONNECTION_GUESSING
1509 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1513 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1514 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1515 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1517 if (satisfied != 0 && !incoming->getLaneStruct(fromLane).connectionsDone) {
1518 if (incoming->hasConnectionTo(currentOutgoing, toLane)
1520 && incoming->getPermissions(fromLane) == currentOutgoing->
getPermissions(toLane)) {
1522 for (
auto con : incoming->getConnections()) {
1523 if (con.toEdge == currentOutgoing && con.toLane == toLane) {
1524 #ifdef DEBUG_CONNECTION_GUESSING
1526 std::cout <<
" shifting connection from=" << con.fromLane <<
" to=" << currentOutgoing->
getID() <<
"_" << toLane <<
": newFromLane=" << fromLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1529 incoming->getConnectionRef(con.fromLane, con.toEdge, toLane).fromLane = fromLane;
1530 unsatisfied &= ~satisfied;
1538 #ifdef DEBUG_CONNECTION_GUESSING
1540 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1543 unsatisfied &= ~satisfied;
1550 #ifdef DEBUG_CONNECTION_GUESSING
1552 if (unsatisfied != 0) {
1553 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1566 bool builtConnection =
false;
1567 for (
int i = 0; i < (int)incoming->getNumLanes(); i++) {
1569 && incoming->getConnectionsFromLane(i, currentOutgoing).size() == 0) {
1571 if (bikeLaneTarget >= 0) {
1573 builtConnection =
true;
1576 for (
int i2 = 0; i2 < (int)currentOutgoing->
getNumLanes(); i2++) {
1579 const bool allowDouble = (incoming->getPermissions(i) ==
SVC_BICYCLE
1582 builtConnection =
true;
1589 if (!builtConnection && bikeLaneTarget >= 0
1590 && incoming->getConnectionsFromLane(-1, currentOutgoing, bikeLaneTarget).size() == 0) {
1593 int end = incoming->getNumLanes();
1599 for (
int i = start; i < end; i += inc) {
1600 if ((incoming->getPermissions(i) &
SVC_BICYCLE) != 0) {
1616 reduction = (inEnd - inOffset) - (outEnd - outOffset);
1629 int inOffset, inEnd, outOffset, outEnd, reduction;
1632 if (reduction > 0) {
1637 int outLanesRight = 0;
1638 int outLanesLeft = 0;
1639 int outLanesStraight = 0;
1642 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianNonBicycleLaneIndex(
FORWARD,
true));
1643 const int usableLanes = succ->getNumLanes() - outOffset;
1646 outLanesStraight += usableLanes;
1648 outLanesRight += usableLanes;
1650 outLanesLeft += usableLanes;
1656 const int usableLanes = outEnd - outOffset;
1657 int addedTurnLanes =
MIN3(
1659 MAX2(0, usableLanes - outLanesStraight),
1660 outLanesRight + outLanesLeft);
1661 #ifdef DEBUG_CONNECTION_GUESSING
1663 std::cout <<
"out=" << out->
getID() <<
" usableLanes=" << usableLanes <<
" addedTurnLanes=" << addedTurnLanes <<
" addedLanes=" << addedLanes <<
" outLanesStraight=" << outLanesStraight <<
" outLanesLeft=" << outLanesLeft <<
" outLanesRight=" << outLanesRight <<
"\n";
1666 if (outLanesLeft == 0) {
1667 return addedTurnLanes;
1669 return MIN2(addedTurnLanes / 2, outLanesRight);
1677 while (seen < minLength) {
1694 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1699 approaching.clear();
1700 for (; *i != currentOutgoing;) {
1702 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1703 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1704 if (connLanes.size() != 0) {
1705 approaching.push_back(*i);
1735 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1737 laneOff += (*i)->getNumLanes();
1767 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1769 laneOff += (*i)->getNumLanes();
1784 int whichLaneOff,
int byLaneOff) {
1788 bool changed =
false;
1790 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1793 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1807 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1809 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1810 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1870 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1871 edges.erase(find(edges.begin(), edges.end(), e));
1873 if (edges.size() == 0) {
1888 if (mayDrive.
getFrom() ==
nullptr ||
1889 mayDrive.
getTo() ==
nullptr ||
1890 mustStop.
getFrom() ==
nullptr ||
1891 mustStop.
getTo() ==
nullptr) {
1893 WRITE_WARNING(
TL(
"Something went wrong during the building of a connection..."));
1897 conn.push_back(mayDrive);
1904 int size = (int) edgeid.length();
1906 std::string
id = (*i)->
getID();
1907 if (
id.substr(0, size) == edgeid) {
1917 int size = (int) edgeid.length();
1919 std::string
id = (*i)->
getID();
1920 if (
id.substr(0, size) == edgeid) {
1950 if (removeFromConnections) {
1952 (*i)->removeFromConnections(edge);
1956 const bool incoming = edge->
getToNode() ==
this;
1958 tld->replaceRemoved(edge, -1,
nullptr, -1, incoming);
1968 Position toAdd = in->getFromNode()->getPosition();
1974 Position toAdd = out->getToNode()->getPosition();
1980 if (pos.
x() == 0. && pos.
y() == 0.) {
1992 (*i)->invalidateConnections(reallowSetting);
2000 (*i)->invalidateConnections(reallowSetting);
2012 if (to ==
nullptr) {
2034 if (std::find(c->edges.begin(), c->edges.end(), to) != c->edges.end()) {
2044 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
2045 if (from != prohibitorFrom) {
2082 if ((!flip && fromLane <= prohibitorFromLane) ||
2083 (flip && fromLane >= prohibitorFromLane)) {
2086 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
2087 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
2125 bool lefthand)
const {
2127 if (from != from2 || to == to2 || fromLane == fromLane2) {
2135 bool result =
false;
2137 if (fromLane < fromLane2) {
2139 while (*it != to2) {
2147 while (*it != to2) {
2179 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
2189 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
2190 bool regardNonSignalisedLowerPriority)
const {
2192 possProhibitedFrom, possProhibitedTo,
2193 regardNonSignalisedLowerPriority);
2199 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
2208 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
2209 bool changed =
true;
2215 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
2220 bool blockedChanged =
false;
2222 NBConnectionVector::const_iterator j;
2223 for (j = blocked.begin(); j != blocked.end(); j++) {
2225 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
2226 blockedChanged =
true;
2230 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
2232 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2236 }
else if (sblocked.
getFrom() == removed) {
2237 assert(sblocked.
getTo() != removed);
2238 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2241 }
else if (sblocked.
getTo() == removed) {
2242 assert(sblocked.
getFrom() != removed);
2243 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2250 if (blockedChanged) {
2251 blockedConnectionsNew[blocker] = newBlocked;
2256 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2261 }
else if (blocker.
getFrom() == removed) {
2262 assert(blocker.
getTo() != removed);
2264 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2267 }
else if (blocker.
getTo() == removed) {
2268 assert(blocker.
getFrom() != removed);
2270 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2274 blockedConnectionsNew[blocker] = blocked;
2287 EdgeVector::const_iterator i = itOut;
2288 while (*i != incoming) {
2294 if ((*i)->getFromNode() !=
this) {
2302 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2312 if (candidate !=
nullptr) {
2315 if (fabs(angle - candAngle) < 5.) {
2319 if (fabs(candAngle) < fabs(angle) - 5.) {
2322 if (fabs(angle) < fabs(candAngle) - 5.) {
2325 if (fabs(candAngle) < 44.) {
2328 if (candModeLanes > modeLanes) {
2331 if (candModeLanes < modeLanes) {
2335 if (candAngle < 0 && angle > 0) {
2338 if (angle < 0 && candAngle > 0) {
2351 result.push_back(e);
2360 if (outgoing ==
nullptr) {
2382 if (fabs(angle) < 44.) {
2383 if (fabs(angle) > 6.) {
2391 if (angle > 0 && incoming->
getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
2403 if (outCW !=
nullptr) {
2410 if (angle < -170 && incoming->getGeometry().reverse() == outgoing->
getGeometry()) {
2415 }
else if (angle < -90) {
2419 if (outCCW !=
nullptr) {
2442 bool mayDefinitelyPass,
const std::string& tlID)
const {
2452 if (outgoing ==
nullptr) {
2456 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)) {
2465 if (!mayDefinitelyPass
2466 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)
2480 if (
mustBrake(incoming, outgoing, fromLane, toLane,
false)) {
2484 if ((in != incoming || c.fromLane != fromLane) && c.toEdge == outgoing && c.toLane == toLane) {
2511 reason =
"rail_signal";
2515 reason =
"crossing";
2518 EdgeVector::const_iterator i;
2523 reason =
"edges incompatible: " + reason;
2527 reason =
"turnaround";
2535 std::set<NBNode*> origSet;
2537 origSet.insert((*i)->getFromNode());
2539 if (origSet.size() < 2) {
2554 if (opposite !=
nullptr) {
2558 if (!(*i)->expandableBy(continuation, reason)) {
2559 reason =
"edges incompatible: " + reason;
2565 reason =
"not opposites";
2572 reason =
"intersection";
2577 std::vector<std::pair<NBEdge*, NBEdge*> >
2580 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2605 assert(opposite != 0);
2607 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2625 (*i)->resetNodeBorder(
this);
2634 if (e->getToNode() == n && e->getPermissions() != 0) {
2648 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2650 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2667 #ifdef DEBUG_PED_STRUCTURES
2678 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2679 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2681 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2683 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2684 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2687 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2688 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2693 int firstSidewalk = -1;
2694 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2695 if (normalizedLanes[i].second) {
2700 int hadCandidates = 0;
2701 std::vector<int> connectedCandidates;
2702 if (firstSidewalk != -1) {
2704 std::vector<std::pair<NBEdge*, bool> > tmp;
2705 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2706 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2707 normalizedLanes = tmp;
2710 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2711 NBEdge* edge = normalizedLanes[i].first;
2712 const bool allowsPed = normalizedLanes[i].second;
2714 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2715 candidates.push_back(edge);
2716 }
else if (allowsPed) {
2717 if (candidates.size() > 0) {
2723 connectedCandidates.push_back(n);
2730 if (hadCandidates > 0 && candidates.size() > 0) {
2736 connectedCandidates.push_back(n);
2742 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2744 if (connectedCandidates.back() <= connectedCandidates.front()) {
2745 numGuessed -= connectedCandidates.back();
2748 numGuessed -= connectedCandidates.front();
2753 #ifdef DEBUG_PED_STRUCTURES
2755 std::cout <<
"guessedCrossings:\n";
2757 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2765 e->computeEdgeShape();
2775 if (candidates.size() == 0) {
2780 double prevAngle = -100000;
2781 for (
int i = 0; i < (int)candidates.size(); ++i) {
2782 NBEdge* edge = candidates[i];
2803 prevAngle = -100000;
2804 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2805 double angle = (*it)->getCrossingAngle(
this);
2806 if (it != candidates.begin()) {
2807 NBEdge* prev = *(it - 1);
2812 double intermediateWidth = 0;
2815 prevPos = prev->
getLanes()[laneI].shape[-1];
2818 prevPos = prev->
getLanes()[laneI].shape[0];
2823 currPos = curr->
getLanes()[laneI].shape[0];
2826 currPos = curr->
getLanes()[laneI].shape[-1];
2830 DEBUGCOUT(
gDebugFlag1,
" prevAngle=" << prevAngle <<
" angle=" << angle <<
" intermediateWidth=" << intermediateWidth <<
"\n")
2852 std::sort(edges.begin(), edges.end());
2856 EdgeVector edgesOfCrossing = crossing->edges;
2857 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2858 if (edgesOfCrossing == edges) {
2868 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2869 if (!normalizedLanes[i].second) {
2887 std::set<std::string> waIDs;
2888 int numSidewalks = 0;
2890 waIDs.insert(wa.id);
2891 numSidewalks += (int)(wa.prevSidewalks.size() + wa.nextSidewalks.size());
2893 if (numSidewalks < 2) {
2898 if (waIDs.count(crossing->prevWalkingArea) == 0 || waIDs.count(crossing->nextWalkingArea) == 0 || !crossing->valid) {
2899 if (crossing->valid) {
2900 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found)."),
2917 crossing->valid =
false;
2918 crossing->prevWalkingArea =
"";
2919 crossing->nextWalkingArea =
"";
2926 std::vector<NBNode::Crossing*>
2928 std::vector<Crossing*> result;
2931 result.push_back(c.get());
2965 int noInternalNoSplits = 0;
2968 if (con.toEdge ==
nullptr) {
2971 noInternalNoSplits++;
2976 double maxCrossingSeconds = 0.;
2978 maxCrossingSeconds =
MAX2(maxCrossingSeconds, edge->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo));
2980 return maxCrossingSeconds;
2986 #ifdef DEBUG_PED_STRUCTURES
3004 c->nextWalkingArea =
"";
3005 c->prevWalkingArea =
"";
3013 std::vector<double> rawAngleDiffs;
3014 double maxAngleDiff = 0;
3015 int maxAngleDiffIndex = 0;
3016 for (
int i = 0; i < (int) edges.size(); i++) {
3018 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
3023 edges[i]->getAngleAtNodeNormalized(
this),
3024 edges[(i + 1) % edges.size()]->getAngleAtNodeNormalized(
this));
3025 rawAngleDiffs.push_back(fabs(rawDiff));
3027 DEBUGCOUT(
gDebugFlag1,
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n")
3028 if (diff > maxAngleDiff) {
3029 maxAngleDiff = diff;
3030 maxAngleDiffIndex = i;
3033 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
3035 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
3038 bool diagonalCrossing =
false;
3039 std::sort(rawAngleDiffs.begin(), rawAngleDiffs.end());
3040 if (rawAngleDiffs.size() >= 2 && rawAngleDiffs[rawAngleDiffs.size() - 2] > 30) {
3041 diagonalCrossing =
true;
3042 #ifdef DEBUG_PED_STRUCTURES
3044 std::cout <<
" detected pedScramble " << c->id <<
" edges=" <<
toString(edges) <<
" rawDiffs=" <<
toString(rawAngleDiffs) <<
"\n";
3045 for (
auto e : edges) {
3046 std::cout <<
" e=" << e->getID()
3047 <<
" aC=" << e->getAngleAtNodeToCenter(
this)
3048 <<
" a=" << e->getAngleAtNode(
this)
3049 <<
" aN=" << e->getAngleAtNodeNormalized(
this)
3056 std::reverse(edges.begin(), edges.end());
3059 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
3060 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
3061 int firstNonPedLane = edges.front()->getFirstNonPedestrianLaneIndex(begDir);
3062 int lastNonPedLane = edges.back()->getFirstNonPedestrianLaneIndex(endDir);
3063 DEBUGCOUT(
gDebugFlag1,
" finalEdges=" <<
toString(edges) <<
" firstNonPedLane=" << firstNonPedLane <<
" lastNonPedLane=" << lastNonPedLane <<
"\n")
3064 if (firstNonPedLane < 0 || lastNonPedLane < 0) {
3066 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross)."), c->id,
getID(),
toString(c->edges));
3069 firstNonPedLane = begDir ==
FORWARD ? 0 : edges.front()->getNumLanes() - 1;
3070 lastNonPedLane = endDir ==
FORWARD ? 0 : edges.back()->getNumLanes() - 1;
3072 if (c->customShape.size() != 0) {
3073 c->shape = c->customShape;
3075 NBEdge::Lane crossingBeg = edges.front()->getLanes()[firstNonPedLane];
3076 NBEdge::Lane crossingEnd = edges.back()->getLanes()[lastNonPedLane];
3088 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
3089 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
3091 if (diagonalCrossing) {
3092 c->shape.move2side(-c->width);
3102 #ifdef DEBUG_PED_STRUCTURES
3113 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
3114 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
3116 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
3117 std::vector<NBEdge::Lane> tmp;
3118 bool hadSidewalk =
false;
3119 bool hadNonSidewalk =
false;
3120 for (
int i = 0; i < (int)lanes.size(); i++) {
3124 if (hadSidewalk && hadNonSidewalk) {
3126 WRITE_WARNINGF(
TL(
"Ignoring additional sidewalk lane % on edge '%' for walkingareas."),
3133 hadNonSidewalk =
true;
3138 std::reverse(tmp.begin(), tmp.end());
3141 l.shape = l.shape.reverse();
3145 l.shape = l.shape.getSubpartByIndex(0, 2);
3147 normalizedLanes.push_back(std::make_pair(edge, l));
3152 std::vector<std::pair<int, int> > waIndices;
3154 NBEdge* prevEdge = normalizedLanes.back().first;
3155 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
3156 NBEdge* edge = normalizedLanes[i].first;
3168 waIndices.push_back(std::make_pair(start, i - start));
3178 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n")
3183 const int waNumLanes = (int)normalizedLanes.size() - start;
3184 if (waIndices.size() == 0) {
3185 waIndices.push_back(std::make_pair(start, waNumLanes));
3188 if (waIndices.front().first == 0) {
3189 NBEdge* edge = normalizedLanes.front().first;
3193 waIndices.push_back(std::make_pair(start, waNumLanes));
3197 waIndices.front().first = start;
3198 waIndices.front().second = waNumLanes + waIndices.front().second;
3203 waIndices.push_back(std::make_pair(start, waNumLanes));
3208 #ifdef DEBUG_PED_STRUCTURES
3210 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
3211 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3212 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
3217 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3218 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
3219 int startIdx = waIndices[i].first;
3220 const int prev = startIdx > 0 ? startIdx - 1 : (int)normalizedLanes.size() - 1;
3221 const int count = waIndices[i].second;
3222 const int end = (startIdx + count) % normalizedLanes.size();
3223 int lastIdx = (startIdx + count - 1) % normalizedLanes.size();
3226 DEBUGCOUT(
gDebugFlag1,
"build walkingArea " << wa.
id <<
" start=" << startIdx <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n")
3227 double endCrossingWidth = 0;
3228 double startCrossingWidth = 0;
3232 bool connectsCrossing =
false;
3233 bool crossingNearSidewalk =
false;
3234 int numCrossings = 0;
3235 std::vector<Position> connectedPoints;
3238 if (c->edges.back() == normalizedLanes[end].first
3239 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
3241 if (c->nextWalkingArea !=
"") {
3242 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'."),
3243 getID(), c->id, c->nextWalkingArea, wa.
id);
3246 c->nextWalkingArea = wa.
id;
3250 endCrossingWidth = c->width;
3251 endCrossingShape = c->shape;
3253 connectsCrossing =
true;
3254 connectedPoints.push_back(c->shape[-1]);
3257 if (normalizedLanes[lastIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < endCrossingWidth) {
3258 crossingNearSidewalk =
true;
3264 if (c->edges.front() == normalizedLanes[prev].first
3265 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
3267 if (c->prevWalkingArea !=
"") {
3268 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'."),
3269 getID(), c->id, c->prevWalkingArea, wa.
id);
3273 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' starts and ends at walkingarea '%'."),
3277 c->prevWalkingArea = wa.
id;
3281 startCrossingWidth = c->width;
3282 startCrossingShape = c->shape;
3284 connectsCrossing =
true;
3285 connectedPoints.push_back(c->shape[0]);
3288 if (normalizedLanes[startIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < startCrossingWidth) {
3289 crossingNearSidewalk =
true;
3296 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
3297 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[startIdx].first->getID()
3298 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
3301 if (count < 2 && !connectsCrossing) {
3303 DEBUGCOUT(
gDebugFlag1,
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n")
3307 std::set<const NBEdge*, ComparatorIdLess>& connected = wa.
refEdges;
3308 for (
int j = 0; j < count; ++j) {
3309 const int nlI = (startIdx + j) % normalizedLanes.size();
3310 NBEdge* edge = normalizedLanes[nlI].first;
3313 if (connected.count(edge) == 0) {
3322 connected.insert(edge);
3329 if (buildExtensions) {
3331 if (startCrossingShape.size() > 0) {
3332 startCrossingShape.
move2side(startCrossingWidth / 2);
3334 startCrossingShape.
move2side(-startCrossingWidth);
3339 if (endCrossingShape.size() > 0) {
3340 endCrossingShape.
move2side(endCrossingWidth / 2);
3342 endCrossingShape.
move2side(-endCrossingWidth);
3348 && normalizedLanes.size() == 2) {
3350 const NBEdge* e1 = *connected.begin();
3351 const NBEdge* e2 = *(++connected.begin());
3357 if (count == (
int)normalizedLanes.size()) {
3363 if (in->getFromNode() == out->getToNode() && in->getInnerGeometry().reverse() == out->getInnerGeometry()
3367 wa.
width =
MAX2(wa.
width, in->getTotalWidth() + out->getTotalWidth());
3371 }
else if (cornerDetail > 0) {
3373 int smoothEnd = end;
3374 int smoothPrev = prev;
3376 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
3377 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
3379 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
3380 if (smoothPrev == 0) {
3381 smoothPrev = (int)normalizedLanes.size() - 1;
3386 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
3387 begShape = begShape.
reverse();
3388 double shiftBegExtra = 0;
3389 double shiftEndExtra = 0;
3390 if (lastIdx == startIdx) {
3391 lastIdx = (startIdx + 1) % normalizedLanes.size();
3392 DEBUGCOUT(
gDebugFlag1,
" new lastIdx=" << lastIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3393 if (normalizedLanes[startIdx].first == normalizedLanes[lastIdx].first) {
3397 startIdx = (int)normalizedLanes.size() - 1;
3399 DEBUGCOUT(
gDebugFlag1,
" new startIdx=" << startIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3405 PositionVector begShapeOuter = normalizedLanes[lastIdx].second.shape;
3406 begShapeOuter = begShapeOuter.
reverse();
3408 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3409 begShapeOuter.
move2side(normalizedLanes[lastIdx].second.width / 2 + shiftBegExtra);
3410 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3411 PositionVector endShapeOuter = normalizedLanes[startIdx].second.shape;;
3412 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3413 endShapeOuter.
move2side(normalizedLanes[startIdx].second.width / 2 + shiftEndExtra);
3416 if (count != (
int)normalizedLanes.size() || count == 2) {
3418 if (count == 1 && angle > 0 && crossingNearSidewalk && numCrossings < 2) {
3422 }
else if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3426 if (curve.
length2D() - begShape.back().distanceTo2D(endShape.front()) > 5) {
3427 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShape.back().distanceTo2D(endShape.front())
3428 <<
" curveLength=" << curve.
length2D()
3429 <<
" delta=" << curve.
length2D() - begShape.back().distanceTo2D(endShape.front())
3435 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3438 if (curve.size() > 2) {
3439 curve.erase(curve.begin());
3441 if (endCrossingWidth > 0) {
3442 wa.
shape.pop_back();
3444 if (startCrossingWidth > 0) {
3447 if (count == (
int)normalizedLanes.size()) {
3453 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3454 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve
3455 <<
" begShapeOuter=" << begShapeOuter <<
" endShapeOuter=" << endShapeOuter
3456 <<
" waShape=" << wa.
shape
3459 if (curve.size() > 2 && (count == 2 || (count == 1 && numCrossings > 0))) {
3460 const double innerDist = begShape.back().distanceTo2D(endShape[0]);
3461 const double outerDist = begShapeOuter.back().distanceTo2D(endShapeOuter[0]);
3463 if (outerDist > innerDist) {
3465 const double extend =
MIN2(10.0, begShapeOuter.back().distanceTo2D(endShapeOuter.front()) / 2);
3466 curve =
computeSmoothShape(begShapeOuter, endShapeOuter, cornerDetail + 2,
false, extend, extend,
nullptr);
3467 if (curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front()) > 5) {
3468 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3469 <<
" curveLength=" << curve.
length2D()
3470 <<
" delta=" << curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3476 if (shiftBegExtra != 0) {
3479 }
else if (shiftEndExtra != 0) {
3485 wa.
shape.insert(wa.
shape.begin() + 1, curve.begin(), curve.end());
3495 if (wacs.shape.size() != 0) {
3496 wa.
shape = wacs.shape;
3499 wa.
width = wacs.width;
3506 double lengthSum = 0;
3507 int combinations = 0;
3508 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3509 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3518 DEBUGCOUT(
gDebugFlag1,
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n")
3519 wa.
length = POSITION_EPS;
3520 if (combinations > 0) {
3521 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3526 std::vector<Crossing*> validCrossings =
getCrossings();
3527 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3529 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3544 wa.
shape.push_back(tmp[-1]);
3546 wa.
shape.push_back(tmp[-1]);
3550 wa.
shape.push_back(tmp[0]);
3552 wa.
shape.push_back(tmp[0]);
3559 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(wa.
refEdges, wacs.edges)) {
3560 wa.
shape = wacs.shape;
3576 #ifdef DEBUG_CROSSING_OUTLINE
3578 std::cerr <<
"<add>\n";
3581 std::map<std::string, PositionVector> waShapes;
3583 waShapes[wa.id] = wa.shape;
3588 if (wa1.empty() || wa2.empty()) {
3601 side1 =
cutAtShapes(side1, wa1, wa2, side1default);
3602 side2 =
cutAtShapes(side2, wa1, wa2, side2default);
3606 side2ex.
extrapolate(side2 == side2default ? c->width / 2 : POSITION_EPS);
3609 c->outlineShape = side1;
3610 c->outlineShape.
append(side3, POSITION_EPS);
3611 c->outlineShape.append(side2, POSITION_EPS);
3612 c->outlineShape.append(side4, POSITION_EPS);
3613 c->outlineShape.removeDoublePoints();
3614 if (c->outlineShape.back().almostSame(c->outlineShape.front())) {
3615 c->outlineShape.pop_back();
3618 #ifdef DEBUG_CROSSING_OUTLINE
3619 std::cout <<
" side1=" << side1 <<
"\n side2=" << side2 <<
"\n side3=" << side3 <<
"\n side4=" << side4 <<
"\n";
3620 std::cerr <<
"<poly id=\"" << c->id <<
"\" shape=\"" << c->outlineShape <<
"\" color=\"blue\" lineWidth=\"0.2\" layer=\"100\"/>\n";
3623 #ifdef DEBUG_CROSSING_OUTLINE
3625 std::cerr <<
"</add>\n";
3635 #ifdef DEBUG_CROSSING_OUTLINE
3636 std::cout <<
"is1=" << is1 <<
" is2=" << is2 <<
" cut=" << cut <<
" border1=" << border1 <<
" border2=" << border2 <<
"\n";
3638 if (is1.size() == 0 && border1.size() == 2) {
3639 const double d1 = cut.
distance2D(border1.front());
3640 const double d2 = cut.
distance2D(border1.back());
3641 Position closer = d1 < d2 ? border1.front() : border1.back();
3643 #ifdef DEBUG_CROSSING_OUTLINE
3644 std::cout <<
" closer=" << closer <<
" nOp=" << nOp <<
"\n";
3646 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3652 if (is2.size() == 0 && border2.size() == 2) {
3653 const double d1 = cut.
distance2D(border2.front());
3654 const double d2 = cut.
distance2D(border2.back());
3655 Position closer = d1 < d2 ? border2.front() : border2.back();
3657 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3663 if (is1.size() > 0 && is2.size() > 0) {
3666 #ifdef DEBUG_CROSSING_OUTLINE
3667 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3672 #ifdef DEBUG_CROSSING_OUTLINE
3673 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3679 #ifdef DEBUG_CROSSING_OUTLINE
3680 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3693 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3695 for (
const NBEdge* e : sub) {
3696 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3715 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3716 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3717 if (it1 != edges.end() && it2 != edges.end()) {
3742 return other1 == other2;
3762 while (it != it_end) {
3763 result.push_back(*it);
3773 wacs.
edges.insert(edges.begin(), edges.end());
3787 if (incoming.size() == 1 && outgoing.size() == 1) {
3790 if (incoming.size() == 2 && outgoing.size() == 2) {
3793 NBEdge* in0 = incoming[0];
3794 NBEdge* in1 = incoming[1];
3795 NBEdge* out0 = outgoing[0];
3796 NBEdge* out1 = outgoing[1];
3805 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
3809 if (
MAX2(angle0, angle1) <= 160) {
3829 if (out->getJunctionPriority(
this) == NBEdge::JunctionPriority::ROUNDABOUT) {
3839 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
3840 if (params !=
nullptr) {
3843 myCrossings.push_back(std::unique_ptr<Crossing>(c));
3853 EdgeSet edgeSet(edges.begin(), edges.end());
3855 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
3856 if (edgeSet == edgeSet2) {
3878 const EdgeSet edgeSet(edges.begin(), edges.end());
3880 const EdgeSet edgeSet2(crossing->edges.begin(), crossing->edges.end());
3881 if (edgeSet == edgeSet2) {
3882 return crossing.get();
3888 throw ProcessError(
TL(
"Request for unknown crossing for the given Edges"));
3895 if (walkingArea.id ==
id) {
3904 if (walkingArea.id ==
id) {
3910 WRITE_WARNINGF(
"Could not retrieve walkingarea '%' (edge ordering changed after recompute).",
id);
3919 bool usedCustom =
false;
3921 c->tlLinkIndex = startIndex++;
3923 if (c->customTLIndex != -1) {
3924 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
3925 c->tlLinkIndex = c->customTLIndex;
3927 c->tlLinkIndex2 = c->customTLIndex2;
3939 result += (int)edge->getConnections().size();
3953 if (e == from && cand.fromLane == con.
fromLane && cand.toLane == con.
toLane && cand.toEdge == con.
toEdge) {
3983 #ifdef DEBUG_PED_STRUCTURES
3985 std::cout <<
" angles:\n";
3986 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3987 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3989 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3995 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
4007 if (turnDest !=
nullptr) {
4027 if (def->rightOnRedConflict(index, foeIndex)) {
4049 std::vector<NBEdge*>::iterator j;
4050 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
4053 if (allEdges.size() > 1 && j != allEdges.end()) {
4058 NBEdge* firstOfAll = allEdges.front();
4059 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
4060 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
4066 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
4067 if (firstOfIncoming !=
nullptr) {
4068 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
4070 if (firstOfOutgoing !=
nullptr) {
4071 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
4073 #ifdef DEBUG_EDGE_SORTING
4075 std::cout <<
"sortedEdges (useNodeShape=" << useNodeShape <<
"):\n";
4076 for (
NBEdge* e : allEdges) {
4077 std::cout <<
" " << e->getID()
4078 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
4079 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
4086 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
4087 std::vector<NBEdge*>::const_iterator in, out;
4088 std::vector<NBEdge*> allTmp;
4089 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
4090 if ((*in)->isTurningDirectionAt(*out)) {
4091 allTmp.push_back(*in);
4092 allTmp.push_back(*out);
4097 if (allTmp.size() == allEdges.size()) {
4110 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
4114 e->computeEdgeShape();
4119 std::vector<std::pair<Position, std::string> >
4122 std::vector<std::pair<Position, std::string> >result;
4124 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
4125 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
4127 for (
const auto& pair : result) {
4128 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
4134 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 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.
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_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
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
#define UNUSED_PARAMETER(x)
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static void compute(BresenhamCallBack *callBack, const int val1, const int val2)
static double getCCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle counter-clockwise.
static double getCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle clockwise.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
bool replaceTo(NBEdge *which, NBEdge *by)
replaces the to-edge by the one given
bool replaceFrom(NBEdge *which, NBEdge *by)
replaces the from-edge by the one given
NBEdge * getTo() const
returns the to-edge (end of the connection)
Class to sort edges by their angle in relation to the given edge.
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
A container for districts.
A class representing a single district.
void replaceIncoming(const EdgeVector &which, NBEdge *const by)
Replaces incoming edges from the vector (sinks) by the given edge.
void replaceOutgoing(const EdgeVector &which, NBEdge *const by)
Replaces outgoing edges from the vector (source) by the given edge.
Storage for edges, including some functionality operating on multiple edges.
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
The representation of a single edge during network building.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
bool isInsideTLS() const
Returns whether this edge was marked as being within an intersection.
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
double getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
double getLaneWidth() const
Returns the default width of lanes of this edge.
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
EdgeBuildingStep getStep() const
The building step of this edge.
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
const std::string & getID() const
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
NBNode * getToNode() const
Returns the destination node of the edge.
@ LANES2LANES_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.
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.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
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[
@ 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.
const NBEdge * getBidiEdge() const
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.
NBEdge * getTurnDestination(bool possibleDestination=false) const
void shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
static const double UNSPECIFIED_WIDTH
unspecified lane width
const std::vector< Connection > & getConnections() const
Returns the connections.
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.
Lane & getLaneStruct(int lane)
double getFinalLength() const
get length that will be assigned to the lanes in the final network
NBNode * getFromNode() const
Returns the origin node of the edge.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
int getFirstNonPedestrianNonBicycleLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN, SVC_BICYCLE and 0
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
A loaded (complete) traffic light logic.
Computes lane-2-lane connections.
bool myIsBikeEdge
whether the outgoing edge is exclusively used by bikes
ApproachingDivider(const EdgeVector &approaching, NBEdge *currentOutgoing)
Constructor.
~ApproachingDivider()
Destructor.
const EdgeVector & myApproaching
The list of edges that approach the current edge.
int numAvailableLanes() const
@ get number of available lanes
std::vector< LinkDirection > myDirections
directions from each incoming edge to the outgoing edge
int myNumStraight
number of straight connections to the outgoing edge
NBEdge * myCurrentOutgoing
The approached current edge.
std::deque< int > * spread(int numLanes, int dest) const
the method that spreads the wished number of lanes from the lane given by the bresenham-call to both ...
void execute(const int src, const int dest)
the bresenham-callback
std::vector< int > myAvailableLanes
The available lanes to which connections shall be built.
A definition of a pedestrian crossing.
Crossing(const NBNode *_node, const EdgeVector &_edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector &_customShape)
constructor
std::string id
the (edge)-id of this crossing
std::string prevWalkingArea
the lane-id of the previous walkingArea
std::string nextWalkingArea
the lane-id of the next walkingArea
PositionVector shape
The crossing's shape.
EdgeVector edges
The edges being crossed.
double width
This crossing's width.
bool valid
whether this crossing is valid (and can be written to the net.xml). This is needed for netedit becaus...
Represents a single node (junction) during network building.
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
void invalidateOutgoingConnections(bool reallowSetting=false)
invalidate outgoing connections
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
static const int FOUR_CONTROL_POINTS
static const int AVOID_INTERSECTING_LEFT_TURNS
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
void addWalkingAreaShape(EdgeVector edges, const PositionVector &shape, double width)
add custom shape for walkingArea
void avoidOverlap()
fix overlap
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
std::vector< WalkingAreaCustomShape > myWalkingAreaCustomShapes
Vector of custom walking areas shapes.
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
bool mustBrake(const NBEdge *const from, const NBEdge *const to, int fromLane, int toLane, bool includePedCrossings) const
Returns the information whether the described flow must let any other flow pass.
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
NBEdge * getNextCompatibleOutgoing(const NBEdge *incoming, SVCPermissions vehPerm, EdgeVector::const_iterator start, bool clockwise) const
bool isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
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)
bool setCrossingTLIndices(const std::string &tlID, int startIndex)
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
static bool isExplicitRailNoBidi(const NBEdge *incoming, const NBEdge *outgoing)
detect explict rail turns with potential geometry problem
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light
SumoXMLNodeType getType() const
Returns the type of this node.
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.
void mirrorX()
mirror coordinates along the x-axis
std::vector< std::pair< Position, std::string > > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
int checkCrossing(EdgeVector candidates, bool checkOnly=false)
bool myHaveCustomPoly
whether this nodes shape was set by the user
Position getEmptyDir() const
Returns something like the most unused direction Should only be used to add source or sink nodes.
PositionVector indirectLeftShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints) const
compute shape of indirect left turn
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
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
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
double myRadius
the turning radius (for all corners) at this node in m.
static bool includes(const std::set< const NBEdge *, ComparatorIdLess > &super, const std::set< const NBEdge *, ComparatorIdLess > &sub)
returns whether sub is a subset of super
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
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0, int shapeFlag=0) const
Compute a smooth curve between the given geometries.
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
bool checkCrossingDuplicated(EdgeVector edges)
return true if there already exist a crossing with the same edges as the input
void setRoundabout()
update the type of this node as a roundabout
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multiple connections from the same edge target the same lane
bool myDiscardAllCrossings
whether to discard all pedestrian crossings
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool removedConnections, bool addedConnections)
causes the traffic light to be computed anew
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
bool brakeForCrossingOnExit(const NBEdge *to) const
whether a connection to the given edge must brake for a crossing when leaving the intersection
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
add shorted link FOES
Position myPosition
The position the node lies at.
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces 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 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
bool tlsContConflict(const NBEdge *from, const NBEdge::Connection &c, const NBEdge *foeFrom, const NBEdge::Connection &foe) const
whether the connection must yield if the foe remains on the intersection after its phase ends
const PositionVector & getShape() const
retrieve the junction shape
std::vector< WalkingArea > myWalkingAreas
Vector of walking areas.
NBConnectionProhibits myBlockedConnections
The container for connection block dependencies.
void updateSurroundingGeometry()
update geometry of node and surrounding edges
int addedLanesRight(NBEdge *out, int addedLanes) const
check whether this edge has extra lanes on the right side
FringeType myFringeType
fringe type of this node
bool checkIsRemovable() const
check if node is removable
bool isRoundabout() const
return whether this node is part of a roundabout
static const int FORWARD
edge directions (for pedestrian related stuff)
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
void displaceShapeAtWidthChange(const NBEdge *from, const NBEdge::Connection &con, PositionVector &fromShape, PositionVector &toShape) const
displace lane shapes to account for change in lane width at this node
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
void removeDoubleEdges()
remove duble edges
double buildInnerEdges()
build internal lanes, pedestrian crossings and walking areas
PositionVector myPoly
the (outer) shape of the junction
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
bool crossesFringe(const NBEdge *e1, const NBEdge *e2) const
return true if the given sidewalks are separated by a fringe road
void getEdgesThatApproach(NBEdge *currentOutgoing, EdgeVector &approaching)
returns a list of edges which are connected to the given outgoing edge
EdgeVector getEdgesSortedByAngleAtNodeCenter() const
returns the list of all edges sorted clockwise by getAngleAtNodeToCenter
EdgeVector edgesBetween(const NBEdge *e1, const NBEdge *e2) const
return all edges that lie clockwise between the given edges
PositionVector computeInternalLaneShape(const NBEdge *fromE, const NBEdge::Connection &con, int numPoints, NBNode *recordError=0, int shapeFlag=0) const
Compute the shape for an internal lane.
NBEdge * getPossiblySplittedIncoming(const std::string &edgeid)
get possibly splitted incoming edge
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset, int threshold=-1)
patches loaded signal plans by modifying lane indices above threshold by the given offset
bool geometryLike() const
whether this is structurally similar to a geometry node
bool isNearDistrict() const
@chech if node is near district
static const int INDIRECT_LEFT
EdgeVector myIncomingEdges
Vector of incoming edges.
WalkingArea & getWalkingArea(const std::string &id)
return the walkingArea with the given ID
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
int guessCrossings()
guess pedestrian crossings and return how many were guessed
bool isTLControlled() const
Returns whether this node is controlled by any tls.
static const int SCURVE_IGNORE
const std::string getFoes(int linkIndex) const
get the 'foes' string (conflict bit set) of the right-of-way logic
NBEdge * getOppositeIncoming(NBEdge *e) const
returns the opposite incoming edge of certain edge
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
This class computes shapes of junctions.
double getRadius() const
get computed radius for node
const PositionVector compute(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.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void removeNode(NBNode *node)
Removes the given node from the list of controlled nodes.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
SUMOTime getOffset()
Returns the offset.
A container for traffic light definitions and built programs.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurrences of the removed edge in incoming/outgoing edges of all definitions.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
Base class for objects which have an id.
std::string myID
The name of the object.
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
An upper class for objects with additional parameters.
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.
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 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.
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)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
PositionVector reverse() const
reverse position vector
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
class for maintaining associations between enums and xml-strings
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
Some static methods for string processing.
static T maxValue(const std::vector< T > &v)
static T minValue(const std::vector< T > &v)
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
A structure which describes a connection between edges or lanes.
bool indirectLeft
Whether this connection is an indirect left turn.
int fromLane
The lane the connections starts at.
int toLane
The lane the connections yields in.
const std::string & getID() const
NBEdge * toEdge
The edge the connections yields in.
PositionVector customShape
custom shape for connection
std::string getDescription(const NBEdge *parent) const
get string describing this connection
std::string tlID
The id of the traffic light that controls this connection.
bool haveVia
check if Connection have a Via
int tlLinkIndex
The index of this connection within the controlling traffic light.
An (internal) definition of a single lane of an edge.
double width
This lane's width.
double endOffset
This lane's offset to the intersection begin.
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this lane.
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this lane.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
PositionVector shape
The lane's shape.
std::set< const NBEdge *, ComparatorIdLess > edges
A definition of a pedestrian walking area.
int minPrevCrossingEdges
minimum number of edges crossed by incoming crossings
std::vector< std::string > nextSidewalks
the lane-id of the next sidewalk lane or ""
std::vector< std::string > prevSidewalks
the lane-id of the previous sidewalk lane or ""
std::string id
the (edge)-id of this walkingArea
bool hasCustomShape
whether this walkingArea has a custom shape
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