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),
323 myPosition(position),
325 myDistrict(district),
326 myHaveCustomPoly(false),
328 myRadius(UNSPECIFIED_RADIUS),
329 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
333 myDiscardAllCrossings(false),
334 myCrossingsLoadedFromSumoNet(0),
335 myDisplacementError(0),
336 myIsBentPriority(false),
337 myTypeWasGuessed(false) {
354 bool updateEdgeGeometries) {
364 if (updateEdgeGeometries) {
368 (*i)->setGeometry(geom);
373 (*i)->setGeometry(geom);
386 wacs.shape.add(xoff, yoff, 0);
389 c->customShape.add(xoff, yoff, 0);
415 c->customShape.mirrorX();
422 wacs.shape.mirrorX();
448 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
472 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
475 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(addedConnections, removedConnections);
476 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
478 const std::vector<NBNode*>& nodes = orig->
getNodes();
479 while (!nodes.empty()) {
480 newDef->
addNode(nodes.front());
481 nodes.front()->removeTrafficLight(orig);
494 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
521 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
573 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
576 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
592 double extrapolateBeg,
593 double extrapolateEnd,
595 int shapeFlag)
const {
602#ifdef DEBUG_SMOOTH_GEOM
604 std::cout <<
"computeSmoothShape node " <<
getID() <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" init=" << init <<
" shapeFlag=" << shapeFlag <<
"\n";
607 if (init.size() == 0) {
609 ret.push_back(begShape.back());
610 ret.push_back(endShape.front());
622 double extrapolateBeg,
623 double extrapolateEnd,
626 double straightThresh,
629 const Position beg = begShape.back();
630 const Position end = endShape.front();
633 if (dist < POSITION_EPS || beg.
distanceTo2D(begShape[-2]) < POSITION_EPS || end.
distanceTo2D(endShape[1]) < POSITION_EPS) {
634#ifdef DEBUG_SMOOTH_GEOM
635 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
651 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
652 init.push_back(center);
654 const double EXT = 100;
660#ifdef DEBUG_SMOOTH_GEOM
662 <<
" endShapeBegLine=" << endShapeBegLine
663 <<
" begShapeEndLineRev=" << begShapeEndLineRev
664 <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
666 if (fabs(angle) <
M_PI / 4.) {
669 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
670 const double halfDistance = dist / 2;
671 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
672#ifdef DEBUG_SMOOTH_GEOM
673 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
674 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
677 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
680#ifdef DEBUG_SMOOTH_GEOM
681 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
682 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
683 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
684 <<
" displacementError=" << sin(displacementAngle) * dist
685 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
688 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
693 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
694 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
696 const double off2 =
EXT -
MIN2(extrapolateEnd, halfDistance);
698#ifdef DEBUG_SMOOTH_GEOM
699 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
700 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
701 <<
" halfDistance=" << halfDistance <<
"\n";
712#ifdef DEBUG_SMOOTH_GEOM
714 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
715 <<
" endShapeBegLine=" << endShapeBegLine
716 <<
" begShapeEndLineRev=" << begShapeEndLineRev
721 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
740 const double minControlLength =
MIN2((
double)1.0, dist / 2);
743 const bool lengthenBeg = distBeg <= minControlLength;
744 const bool lengthenEnd = distEnd <= minControlLength;
745#ifdef DEBUG_SMOOTH_GEOM
747 <<
" beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
748 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd
749 <<
" begOffset=" << begOffset <<
" endOffset=" << endOffset
750 <<
" lEnd=" << lengthenEnd <<
" lBeg=" << lengthenBeg
753 if (lengthenBeg && lengthenEnd) {
754#ifdef DEBUG_SMOOTH_GEOM
756 std::cout <<
" bezierControlPoints failed\n";
759 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
768 }
else if (lengthenBeg || lengthenEnd) {
777 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
780 :
MIN2(0.6, 16 / dist));
791 const double z3 = 0.5 * (beg.
z() + end.
z());
795 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
800 intersect.
set(intersect.
x(), intersect.
y(), z);
801 init.push_back(intersect);
814 result.push_back(begShape.back());
825 dir.
sub(endShape[0]);
829 result.push_back(intersect + dir);
831 result.push_back(endShape.front());
847 if (useCustomShape) {
850 if (startBorder.size() == 0) {
851 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
854 if (tmp.size() < 2) {
856 useCustomShape =
false;
860 tmp[0] = fromShape.back();
861 }
else if (recordError !=
nullptr) {
862 const double offset = tmp[0].distanceTo2D(fromShape.back());
868 if (endBorder.size() == 0) {
869 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
872 if (ret.size() < 2) {
874 useCustomShape =
false;
877 ret[-1] = toShape.front();
878 }
else if (recordError !=
nullptr) {
879 const double offset = ret[-1].distanceTo2D(toShape.front());
886 if (!useCustomShape) {
897#ifdef DEBUG_SMOOTH_GEOM
899 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
904 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
936 for (
int i = 0; i < con.
toLane; ++i) {
940 for (
int i = 0; i < con.
fromLane; ++i) {
950 fromShape.
move2side(inCenter - outCenter);
1007 if (fromE == otherFromE && !thisRight) {
1018 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
1036 && !
needsCont(foeFrom, from, foe, c,
true));
1043 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
1045 if ((*i)->getNodes().size() > 1) {
1047 (*i)->removeNode(
this);
1048 (*i)->setParticipantsInformation();
1049 (*i)->setTLControllingInformation();
1080 WRITE_WARNINGF(
TL(
"Junction '%' is too complicated (% connections, max %); will be set to %."),
1082 }
else if (numConnections == 0) {
1106 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1114 std::vector<NBEdge::Connection>& connections = incoming->getConnections();
1117 const LinkState linkState =
getLinkState(incoming, c.toEdge, c.fromLane, c.toLane, c.mayDefinitelyPass, c.tlID);
1190 edge->computeEdgeShape();
1218 if (mismatchThreshold >= 0
1245 int inOffset, inEnd, outOffset, outEnd, addedLanes;
1246 getReduction(out, in, outOffset, outEnd, inOffset, inEnd, addedLanes);
1251 const int addedLeft = addedLanes - addedRight;
1252#ifdef DEBUG_CONNECTION_GUESSING
1254 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a. addedRight=" << addedRight <<
" addedLeft=" << addedLeft <<
" inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
"\n";
1258 for (
int i = inOffset; i < inEnd; ++i) {
1262 for (
int i = 0; i < addedRight; ++i) {
1266 const int inLeftMost = inEnd - 1;;
1267 const int outOffset2 = outOffset + addedRight + inEnd - inOffset;
1268 for (
int i = 0; i < addedLeft; ++i) {
1301#ifdef DEBUG_CONNECTION_GUESSING
1303 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1343#ifdef DEBUG_CONNECTION_GUESSING
1345 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1372#ifdef DEBUG_CONNECTION_GUESSING
1374 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1383 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1399 int inOffset, inEnd, outOffset, outEnd, reduction;
1400 getReduction(in, out, inOffset, inEnd, outOffset, outEnd, reduction);
1405#ifdef DEBUG_CONNECTION_GUESSING
1407 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f inOff=" << inOffset <<
" outOff=" << outOffset <<
" inEnd=" << inEnd <<
" outEnd=" << outEnd <<
" reduction=" << reduction <<
"\n";
1411 inOffset += reduction;
1412 for (
int i = outOffset; i < outEnd; ++i) {
1429 const int numApproaching = (int)approaching.size();
1430 if (numApproaching != 0) {
1434#ifdef DEBUG_CONNECTION_GUESSING
1436 std::cout <<
"l2l node=" <<
getID() <<
" outgoing=" << currentOutgoing->getID() <<
" bresenham:\n";
1438 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1439 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1440 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " <<
Named::getIDSecure((*k).toEdge) <<
"_" << (*k).toLane <<
"\n";
1449 bool targetProhibitsChange =
false;
1450 for (
int i = 0; i < currentOutgoing->getNumLanes(); i++) {
1451 const NBEdge::Lane& lane = currentOutgoing->getLanes()[i];
1454 targetProhibitsChange =
true;
1458 if (targetProhibitsChange) {
1462 std::map<int, int> outToIn;
1464 if (c.toEdge == currentOutgoing) {
1465 outToIn[c.toLane] = c.fromLane;
1468 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); toLane++) {
1469 if (outToIn.count(toLane) == 0) {
1472 for (
int i = 0; i < toLane; i++) {
1473 if (outToIn.count(i) != 0) {
1474#ifdef DEBUG_CONNECTION_GUESSING
1476 std::cout <<
"l2l node=" <<
getID() <<
" from=" << incoming->getID() <<
" to " << currentOutgoing->getLaneID(toLane) <<
" (changeProhibited, secondTarget)\n";
1485 for (
int i = toLane; i < currentOutgoing->getNumLanes(); i++) {
1486 if (outToIn.count(i) != 0) {
1487#ifdef DEBUG_CONNECTION_GUESSING
1489 std::cout <<
"l2l node=" <<
getID() <<
" from=" << incoming->getID() <<
" to " << currentOutgoing->getLaneID(toLane) <<
" (changeProhibited, newTarget)\n";
1508 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1509 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1511 (*i)->removeFromConnections((*k).toEdge);
1522 incoming->markAsInLane2LaneState();
1526#ifdef DEBUG_CONNECTION_GUESSING
1528 std::cout <<
"final connections at " <<
getID() <<
"\n";
1530 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1531 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1532 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " <<
Named::getIDSecure((*k).toEdge) <<
"_" << (*k).toLane <<
"\n";
1548 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1549 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1554 unsatisfied &= ~satisfied;
1557 if (unsatisfied != 0) {
1558#ifdef DEBUG_CONNECTION_GUESSING
1560 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1565 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1566 if (incoming->getPermissions(fromLane) == unsatisfied) {
1574 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1575 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0
1576 && incoming->getConnectionsFromLane(fromLane, currentOutgoing, -1).size() > 0) {
1583 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1584 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1589#ifdef DEBUG_CONNECTION_GUESSING
1591 if (unsatisfied != 0) {
1592 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->
getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1609 const int specialTarget = currentOutgoing->
getSpecialLane(svcSpecial);
1614 bool builtConnection =
false;
1615 for (
int i = 0; i < (int)incoming->
getNumLanes(); i++) {
1619 if (specialTarget >= 0) {
1621#ifdef DEBUG_CONNECTION_GUESSING
1626 builtConnection =
true;
1629 if (
avoidConfict(incoming, currentOutgoing, svcSpecial, dir, i)) {
1633 for (
int i2 = 0; i2 < (int)currentOutgoing->
getNumLanes(); i2++) {
1636 const bool allowDouble = (incoming->
getPermissions(i) == svcSpecial
1639#ifdef DEBUG_CONNECTION_GUESSING
1644 builtConnection =
true;
1651 if (!builtConnection && specialTarget >= 0
1661 for (
int i = start; i < end; i += inc) {
1664#ifdef DEBUG_CONNECTION_GUESSING
1680 if (incoming->
getPermissions(c.fromLane) == svcSpecial && c.toEdge == currentOutgoing) {
1686 if (c.fromLane < i && (c.toEdge != currentOutgoing || incoming->
getPermissions(c.fromLane) == svcSpecial)) {
1692 if (c.fromLane > i && (c.toEdge != currentOutgoing || incoming->
getPermissions(c.fromLane) == svcSpecial)) {
1716 reduction = (inEnd - inOffset) - (outEnd - outOffset);
1722 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1730 if (con.toEdge == currentOutgoing && con.toLane == toLane) {
1731#ifdef DEBUG_CONNECTION_GUESSING
1733 std::cout <<
" shifting connection from=" << con.fromLane <<
" to=" << currentOutgoing->
getID() <<
"_" << toLane <<
": newFromLane=" << fromLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1737 unsatisfied &= ~satisfied;
1745#ifdef DEBUG_CONNECTION_GUESSING
1747 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1750 unsatisfied &= ~satisfied;
1767 int inOffset, inEnd, outOffset, outEnd, reduction;
1770 if (reduction > 0) {
1775 int outLanesRight = 0;
1776 int outLanesLeft = 0;
1777 int outLanesStraight = 0;
1780 const int outOffset =
MAX2(0, succ->getFirstNonPedestrianNonBicycleLaneIndex(
FORWARD,
true));
1781 const int usableLanes = succ->getNumLanes() - outOffset;
1784 outLanesStraight += usableLanes;
1786 outLanesRight += usableLanes;
1788 outLanesLeft += usableLanes;
1794 const int usableLanes = outEnd - outOffset;
1795 int addedTurnLanes =
MIN3(
1797 MAX2(0, usableLanes - outLanesStraight),
1798 outLanesRight + outLanesLeft);
1799#ifdef DEBUG_CONNECTION_GUESSING
1801 std::cout <<
"out=" << out->
getID() <<
" usableLanes=" << usableLanes <<
" addedTurnLanes=" << addedTurnLanes <<
" addedLanes=" << addedLanes <<
" outLanesStraight=" << outLanesStraight <<
" outLanesLeft=" << outLanesLeft <<
" outLanesRight=" << outLanesRight <<
"\n";
1804 if (outLanesLeft == 0) {
1805 return addedTurnLanes;
1807 return MIN2(addedTurnLanes / 2, outLanesRight);
1815 while (seen < minLength) {
1832 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1837 approaching.clear();
1838 for (; *i != currentOutgoing;) {
1840 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1841 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1842 if (connLanes.size() != 0) {
1843 approaching.push_back(*i);
1873 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1875 laneOff += (*i)->getNumLanes();
1905 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1907 laneOff += (*i)->getNumLanes();
1922 int whichLaneOff,
int byLaneOff) {
1926 bool changed =
false;
1928 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1931 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1945 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1947 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1948 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
2008 if (find(edges.begin(), edges.end(), e) != edges.end()) {
2009 edges.erase(find(edges.begin(), edges.end(), e));
2011 if (edges.size() == 0) {
2026 if (mayDrive.
getFrom() ==
nullptr ||
2027 mayDrive.
getTo() ==
nullptr ||
2028 mustStop.
getFrom() ==
nullptr ||
2029 mustStop.
getTo() ==
nullptr) {
2031 WRITE_WARNING(
TL(
"Something went wrong during the building of a connection..."));
2035 conn.push_back(mayDrive);
2042 int size = (int) edgeid.length();
2044 std::string
id = (*i)->
getID();
2045 if (
id.substr(0, size) == edgeid) {
2055 int size = (int) edgeid.length();
2057 std::string
id = (*i)->
getID();
2058 if (
id.substr(0, size) == edgeid) {
2088 if (removeFromConnections) {
2090 (*i)->removeFromConnections(edge);
2094 const bool incoming = edge->
getToNode() ==
this;
2096 tld->replaceRemoved(edge, -1,
nullptr, -1, incoming);
2106 Position toAdd = in->getFromNode()->getPosition();
2112 Position toAdd = out->getToNode()->getPosition();
2118 if (pos.
x() == 0. && pos.
y() == 0.) {
2130 (*i)->invalidateConnections(reallowSetting);
2138 (*i)->invalidateConnections(reallowSetting);
2150 if (to ==
nullptr) {
2174 if (std::find(c->edges.begin(), c->edges.end(), to) != c->edges.end()) {
2184 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane) {
2185 if (from != prohibitorFrom) {
2222 if ((!flip && fromLane <= prohibitorFromLane) ||
2223 (flip && fromLane >= prohibitorFromLane)) {
2226 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
2227 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
2265 bool lefthand)
const {
2267 if (from != from2 || to == to2 || fromLane == fromLane2) {
2275 bool result =
false;
2277 if (fromLane < fromLane2) {
2279 while (*it != to2) {
2287 while (*it != to2) {
2319 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
2329 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
2330 bool regardNonSignalisedLowerPriority)
const {
2332 possProhibitedFrom, possProhibitedTo,
2333 regardNonSignalisedLowerPriority);
2339 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
2348 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
2349 bool changed =
true;
2355 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
2360 bool blockedChanged =
false;
2362 NBConnectionVector::const_iterator j;
2363 for (j = blocked.begin(); j != blocked.end(); j++) {
2365 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
2366 blockedChanged =
true;
2370 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
2372 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
2376 }
else if (sblocked.
getFrom() == removed) {
2377 assert(sblocked.
getTo() != removed);
2378 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2381 }
else if (sblocked.
getTo() == removed) {
2382 assert(sblocked.
getFrom() != removed);
2383 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2390 if (blockedChanged) {
2391 blockedConnectionsNew[blocker] = newBlocked;
2396 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
2401 }
else if (blocker.
getFrom() == removed) {
2402 assert(blocker.
getTo() != removed);
2404 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
2407 }
else if (blocker.
getTo() == removed) {
2408 assert(blocker.
getFrom() != removed);
2410 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
2414 blockedConnectionsNew[blocker] = blocked;
2427 EdgeVector::const_iterator i = itOut;
2428 while (*i != incoming) {
2434 if ((*i)->getFromNode() !=
this) {
2442 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
2452 if (candidate !=
nullptr) {
2455 if (fabs(angle - candAngle) < 5.) {
2459 if (fabs(candAngle) < fabs(angle) - 5.) {
2462 if (fabs(angle) < fabs(candAngle) - 5.) {
2465 if (fabs(candAngle) < 44.) {
2468 if (candModeLanes > modeLanes) {
2471 if (candModeLanes < modeLanes) {
2475 if (candAngle < 0 && angle > 0) {
2478 if (angle < 0 && candAngle > 0) {
2491 result.push_back(e);
2500 if (outgoing ==
nullptr) {
2521 vehPerm &= ~SVC_PEDESTRIAN;
2524 if (fabs(angle) < 44.) {
2525 if (fabs(angle) > 6.) {
2541 if (angle > 90 + NUMERICAL_EPS) {
2545 if (outCW !=
nullptr) {
2552 if (angle < -170 && incoming->getGeometry().reverse() == outgoing->
getGeometry()) {
2557 }
else if (angle < -(90 + NUMERICAL_EPS)) {
2561 if (outCCW !=
nullptr) {
2584 bool mayDefinitelyPass,
const std::string& tlID)
const {
2594 if (outgoing ==
nullptr) {
2598 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)) {
2607 if (!mayDefinitelyPass
2608 &&
mustBrake(incoming, outgoing, fromLane, toLane,
true)
2622 if (
mustBrake(incoming, outgoing, fromLane, toLane,
false)) {
2626 if ((in != incoming || c.fromLane != fromLane) && c.toEdge == outgoing && c.toLane == toLane) {
2642 assert(railClasses != 0);
2652 for (
auto it : nc) {
2653 const NBNode* n = it.second;
2680 reason =
"rail_signal";
2684 reason =
"crossing";
2687 EdgeVector::const_iterator i;
2692 reason =
"edges incompatible: " + reason;
2696 reason =
"turnaround";
2704 std::set<NBNode*> origSet;
2706 origSet.insert((*i)->getFromNode());
2708 if (origSet.size() < 2) {
2723 if (opposite !=
nullptr) {
2727 if (!(*i)->expandableBy(continuation, reason)) {
2728 reason =
"edges incompatible: " + reason;
2734 reason =
"not opposites";
2741 reason =
"intersection";
2746std::vector<std::pair<NBEdge*, NBEdge*> >
2749 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2774 assert(opposite != 0);
2776 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2794 (*i)->resetNodeBorder(
this);
2803 if (e->getToNode() == n && e->getPermissions() != 0) {
2817 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2819 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2836#ifdef DEBUG_PED_STRUCTURES
2847 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2848 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2850 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2852 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2853 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2856 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2857 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2862 int firstSidewalk = -1;
2863 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2864 if (normalizedLanes[i].second) {
2869 int hadCandidates = 0;
2870 std::vector<int> connectedCandidates;
2871 if (firstSidewalk != -1) {
2873 std::vector<std::pair<NBEdge*, bool> > tmp;
2874 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2875 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2876 normalizedLanes = tmp;
2879 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2880 NBEdge* edge = normalizedLanes[i].first;
2881 const bool allowsPed = normalizedLanes[i].second;
2883 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2884 candidates.push_back(edge);
2885 }
else if (allowsPed) {
2886 if (candidates.size() > 0) {
2892 connectedCandidates.push_back(n);
2899 if (hadCandidates > 0 && candidates.size() > 0) {
2905 connectedCandidates.push_back(n);
2911 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2913 if (connectedCandidates.back() <= connectedCandidates.front()) {
2914 numGuessed -= connectedCandidates.back();
2917 numGuessed -= connectedCandidates.front();
2922#ifdef DEBUG_PED_STRUCTURES
2924 std::cout <<
"guessedCrossings:\n";
2926 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2934 e->computeEdgeShape();
2944 if (candidates.size() == 0) {
2949 double prevAngle = -100000;
2950 for (
int i = 0; i < (int)candidates.size(); ++i) {
2951 NBEdge* edge = candidates[i];
2973 prevAngle = -100000;
2974 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2975 double angle = (*it)->getCrossingAngle(
this);
2976 if (it != candidates.begin()) {
2977 NBEdge* prev = *(it - 1);
2982 double intermediateWidth = 0;
2985 prevPos = prev->
getLanes()[laneI].shape[-1];
2988 prevPos = prev->
getLanes()[laneI].shape[0];
2993 currPos = curr->
getLanes()[laneI].shape[0];
2996 currPos = curr->
getLanes()[laneI].shape[-1];
3000 DEBUGCOUT(
gDebugFlag1,
" prevAngle=" << prevAngle <<
" angle=" << angle <<
" intermediateWidth=" << intermediateWidth <<
"\n")
3023 std::sort(edges.begin(), edges.end());
3027 EdgeVector edgesOfCrossing = crossing->edges;
3028 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
3029 if (edgesOfCrossing == edges) {
3039 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
3040 if (!normalizedLanes[i].second) {
3058 std::set<std::string> waIDs;
3059 int numSidewalks = 0;
3061 waIDs.insert(wa.id);
3062 numSidewalks += (int)(wa.prevSidewalks.size() + wa.nextSidewalks.size());
3064 if (numSidewalks < 2) {
3069 if (waIDs.count(crossing->prevWalkingArea) == 0 || waIDs.count(crossing->nextWalkingArea) == 0 || !crossing->valid) {
3070 if (crossing->valid) {
3071 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found)."),
3088 crossing->valid =
false;
3089 crossing->prevWalkingArea =
"";
3090 crossing->nextWalkingArea =
"";
3097std::vector<NBNode::Crossing*>
3099 std::vector<Crossing*> result;
3102 result.push_back(c.get());
3136 int noInternalNoSplits = 0;
3139 if (con.toEdge ==
nullptr) {
3142 noInternalNoSplits++;
3147 double maxCrossingSeconds = 0.;
3149 maxCrossingSeconds =
MAX2(maxCrossingSeconds, edge->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo));
3151 return maxCrossingSeconds;
3157#ifdef DEBUG_PED_STRUCTURES
3175 c->nextWalkingArea =
"";
3176 c->prevWalkingArea =
"";
3184 std::vector<double> rawAngleDiffs;
3185 double maxAngleDiff = 0;
3186 int maxAngleDiffIndex = 0;
3187 for (
int i = 0; i < (int) edges.size(); i++) {
3189 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
3194 edges[i]->getAngleAtNodeNormalized(
this),
3195 edges[(i + 1) % edges.size()]->getAngleAtNodeNormalized(
this));
3196 rawAngleDiffs.push_back(fabs(rawDiff));
3198 DEBUGCOUT(
gDebugFlag1,
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n")
3199 if (diff > maxAngleDiff) {
3200 maxAngleDiff = diff;
3201 maxAngleDiffIndex = i;
3204 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
3206 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
3209 bool diagonalCrossing =
false;
3210 std::sort(rawAngleDiffs.begin(), rawAngleDiffs.end());
3211 if (rawAngleDiffs.size() >= 2 && rawAngleDiffs[rawAngleDiffs.size() - 2] > 30) {
3212 diagonalCrossing =
true;
3213#ifdef DEBUG_PED_STRUCTURES
3215 std::cout <<
" detected pedScramble " << c->id <<
" edges=" <<
toString(edges) <<
" rawDiffs=" <<
toString(rawAngleDiffs) <<
"\n";
3216 for (
auto e : edges) {
3217 std::cout <<
" e=" << e->getID()
3218 <<
" aC=" << e->getAngleAtNodeToCenter(
this)
3219 <<
" a=" << e->getAngleAtNode(
this)
3220 <<
" aN=" << e->getAngleAtNodeNormalized(
this)
3227 std::reverse(edges.begin(), edges.end());
3230 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
3231 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
3232 int firstNonPedLane = edges.front()->getFirstNonPedestrianLaneIndex(begDir);
3233 int lastNonPedLane = edges.back()->getFirstNonPedestrianLaneIndex(endDir);
3234 DEBUGCOUT(
gDebugFlag1,
" finalEdges=" <<
toString(edges) <<
" firstNonPedLane=" << firstNonPedLane <<
" lastNonPedLane=" << lastNonPedLane <<
"\n")
3235 if (firstNonPedLane < 0 || lastNonPedLane < 0) {
3237 WRITE_WARNINGF(
TL(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross)."), c->id,
getID(),
toString(c->edges));
3240 firstNonPedLane = begDir ==
FORWARD ? 0 : edges.front()->getNumLanes() - 1;
3241 lastNonPedLane = endDir ==
FORWARD ? 0 : edges.back()->getNumLanes() - 1;
3243 if (c->customShape.size() != 0) {
3244 c->shape = c->customShape;
3246 NBEdge::Lane crossingBeg = edges.front()->getLanes()[firstNonPedLane];
3247 NBEdge::Lane crossingEnd = edges.back()->getLanes()[lastNonPedLane];
3252 double offset = c->width / 2;
3261 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
3262 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
3264 if (diagonalCrossing) {
3265 c->shape.move2side(-c->width);
3282 nonPedIncoming.push_back(e);
3284 pedIncoming.push_back(e);
3289 nonPedOutgoing.push_back(e);
3291 pedOutgoing.push_back(e);
3294 if (
geometryLike(nonPedIncoming, nonPedOutgoing) && (pedIncoming.size() > 0 || pedOutgoing.size() > 0)) {
3295 double maxAngle = 0;
3296 const NBEdge* in = nonPedIncoming.front();
3297 const NBEdge* out = nonPedOutgoing.front();
3298 if (nonPedIncoming.size() == 1) {
3301 for (
const NBEdge*
const in2 : nonPedIncoming) {
3302 double minAngle = 180;
3303 for (
const NBEdge*
const out2 : nonPedOutgoing) {
3304 double angle = fabs(
NBHelpers::relAngle(in2->getAngleAtNode(
this), out2->getAngleAtNode(
this)));
3305 if (angle < minAngle) {
3311 maxAngle =
MAX2(maxAngle, minAngle);
3315 if (maxAngle < 15) {
3318 if (inLane >= 0 && outLane >= 0) {
3325 double maxPathDist = 0;
3326 for (
NBEdge* e : pedIncoming) {
3330 for (
NBEdge* e : pedOutgoing) {
3347#ifdef DEBUG_PED_STRUCTURES
3358 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
3359 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
3361 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
3362 std::vector<NBEdge::Lane> tmp;
3363 bool hadSidewalk =
false;
3364 bool hadNonSidewalk =
false;
3365 for (
int i = 0; i < (int)lanes.size(); i++) {
3369 if (hadSidewalk && hadNonSidewalk) {
3371 WRITE_WARNINGF(
TL(
"Ignoring additional sidewalk lane % on edge '%' for walkingareas."),
3378 hadNonSidewalk =
true;
3383 std::reverse(tmp.begin(), tmp.end());
3386 l.shape = l.shape.reverse();
3390 l.shape = l.shape.getSubpartByIndex(0, 2);
3392 normalizedLanes.push_back(std::make_pair(edge, l));
3397 std::vector<std::pair<int, int> > waIndices;
3399 NBEdge* prevEdge = normalizedLanes.back().first;
3400 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
3401 NBEdge* edge = normalizedLanes[i].first;
3413 waIndices.push_back(std::make_pair(start, i - start));
3423 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n")
3428 const int waNumLanes = (int)normalizedLanes.size() - start;
3429 if (waIndices.size() == 0) {
3430 waIndices.push_back(std::make_pair(start, waNumLanes));
3433 if (waIndices.front().first == 0) {
3434 NBEdge* edge = normalizedLanes.front().first;
3438 waIndices.push_back(std::make_pair(start, waNumLanes));
3442 waIndices.front().first = start;
3443 waIndices.front().second = waNumLanes + waIndices.front().second;
3448 waIndices.push_back(std::make_pair(start, waNumLanes));
3453#ifdef DEBUG_PED_STRUCTURES
3455 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
3456 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3457 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
3462 for (
int i = 0; i < (int)waIndices.size(); ++i) {
3463 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
3464 int startIdx = waIndices[i].first;
3465 const int prev = startIdx > 0 ? startIdx - 1 : (int)normalizedLanes.size() - 1;
3466 const int count = waIndices[i].second;
3467 const int end = (startIdx + count) % normalizedLanes.size();
3468 int lastIdx = (startIdx + count - 1) % normalizedLanes.size();
3471 DEBUGCOUT(
gDebugFlag1,
"build walkingArea " << wa.
id <<
" start=" << startIdx <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n")
3472 double endCrossingWidth = 0;
3473 double startCrossingWidth = 0;
3477 bool connectsCrossing =
false;
3478 bool crossingNearSidewalk =
false;
3479 int numCrossings = 0;
3480 std::vector<Position> connectedPoints;
3483 if (c->edges.back() == normalizedLanes[end].first
3484 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
3486 if (c->nextWalkingArea !=
"") {
3487 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'."),
3488 getID(), c->id, c->nextWalkingArea, wa.
id);
3491 c->nextWalkingArea = wa.
id;
3495 endCrossingWidth = c->width;
3496 endCrossingShape = c->shape;
3498 connectsCrossing =
true;
3499 connectedPoints.push_back(c->shape[-1]);
3502 if (normalizedLanes[lastIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < endCrossingWidth) {
3503 crossingNearSidewalk =
true;
3509 if (c->edges.front() == normalizedLanes[prev].first
3510 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
3512 if (c->prevWalkingArea !=
"") {
3513 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'."),
3514 getID(), c->id, c->prevWalkingArea, wa.
id);
3518 WRITE_WARNINGF(
TL(
"Invalid pedestrian topology at junction '%'; crossing '%' starts and ends at walkingarea '%'."),
3522 c->prevWalkingArea = wa.
id;
3526 startCrossingWidth = c->width;
3527 startCrossingShape = c->shape;
3529 connectsCrossing =
true;
3530 connectedPoints.push_back(c->shape[0]);
3533 if (normalizedLanes[startIdx].second.shape[0].distanceTo2D(connectedPoints.back()) < startCrossingWidth) {
3534 crossingNearSidewalk =
true;
3541 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
3542 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[startIdx].first->getID()
3543 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
3546 if (count < 2 && !connectsCrossing) {
3548 DEBUGCOUT(
gDebugFlag1,
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n")
3552 std::set<const NBEdge*, ComparatorIdLess>& connected = wa.
refEdges;
3553 for (
int j = 0; j < count; ++j) {
3554 const int nlI = (startIdx + j) % normalizedLanes.size();
3555 NBEdge* edge = normalizedLanes[nlI].first;
3558 if (connected.count(edge) == 0) {
3567 connected.insert(edge);
3574 if (buildExtensions) {
3576 if (startCrossingShape.size() > 0) {
3577 startCrossingShape.
move2side(startCrossingWidth / 2);
3579 startCrossingShape.
move2side(-startCrossingWidth);
3584 if (endCrossingShape.size() > 0) {
3585 endCrossingShape.
move2side(endCrossingWidth / 2);
3587 endCrossingShape.
move2side(-endCrossingWidth);
3593 && normalizedLanes.size() == 2) {
3595 const NBEdge* e1 = *connected.begin();
3596 const NBEdge* e2 = *(++connected.begin());
3602 if (count == (
int)normalizedLanes.size()) {
3608 if (in->getFromNode() == out->getToNode() && in->getInnerGeometry().reverse() == out->getInnerGeometry()
3612 wa.
width =
MAX2(wa.
width, in->getTotalWidth() + out->getTotalWidth());
3616 }
else if (cornerDetail > 0) {
3618 int smoothEnd = end;
3619 int smoothPrev = prev;
3621 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
3622 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
3624 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
3625 if (smoothPrev == 0) {
3626 smoothPrev = (int)normalizedLanes.size() - 1;
3631 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
3632 begShape = begShape.
reverse();
3633 double shiftBegExtra = 0;
3634 double shiftEndExtra = 0;
3635 if (lastIdx == startIdx) {
3636 lastIdx = (startIdx + 1) % normalizedLanes.size();
3637 DEBUGCOUT(
gDebugFlag1,
" new lastIdx=" << lastIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3638 if (normalizedLanes[startIdx].first == normalizedLanes[lastIdx].first) {
3642 startIdx = (int)normalizedLanes.size() - 1;
3644 DEBUGCOUT(
gDebugFlag1,
" new startIdx=" << startIdx <<
" startEdge=" << normalizedLanes[startIdx].first->getID() <<
" lastEdge=" << normalizedLanes[lastIdx].first->getID() <<
"\n")
3650 PositionVector begShapeOuter = normalizedLanes[lastIdx].second.shape;
3651 begShapeOuter = begShapeOuter.
reverse();
3653 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
3654 begShapeOuter.
move2side(normalizedLanes[lastIdx].second.width / 2 + shiftBegExtra);
3655 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
3656 PositionVector endShapeOuter = normalizedLanes[startIdx].second.shape;;
3657 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
3658 endShapeOuter.
move2side(normalizedLanes[startIdx].second.width / 2 + shiftEndExtra);
3661 if (count != (
int)normalizedLanes.size() || count == 2) {
3663 if (count == 1 && angle > 0 && crossingNearSidewalk && numCrossings < 2) {
3667 }
else if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
3671 if (curve.
length2D() - begShape.back().distanceTo2D(endShape.front()) > 5) {
3672 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShape.back().distanceTo2D(endShape.front())
3673 <<
" curveLength=" << curve.
length2D()
3674 <<
" delta=" << curve.
length2D() - begShape.back().distanceTo2D(endShape.front())
3680 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
3683 if (curve.size() > 2) {
3684 curve.erase(curve.begin());
3686 if (endCrossingWidth > 0) {
3687 wa.
shape.pop_back();
3689 if (startCrossingWidth > 0) {
3692 if (count == (
int)normalizedLanes.size()) {
3698 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
3699 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve
3700 <<
" begShapeOuter=" << begShapeOuter <<
" endShapeOuter=" << endShapeOuter
3701 <<
" waShape=" << wa.
shape
3704 if (curve.size() > 2 && (count == 2 || (count == 1 && numCrossings > 0))) {
3705 const double innerDist = begShape.back().distanceTo2D(endShape[0]);
3706 const double outerDist = begShapeOuter.back().distanceTo2D(endShapeOuter[0]);
3708 if (outerDist > innerDist) {
3710 const double extend =
MIN2(10.0, begShapeOuter.back().distanceTo2D(endShapeOuter.front()) / 2);
3711 curve =
computeSmoothShape(begShapeOuter, endShapeOuter, cornerDetail + 2,
false, extend, extend,
nullptr);
3712 if (curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front()) > 5) {
3713 DEBUGCOUT(
gDebugFlag1,
" reduceBulge directLength=" << begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3714 <<
" curveLength=" << curve.
length2D()
3715 <<
" delta=" << curve.
length2D() - begShapeOuter.back().distanceTo2D(endShapeOuter.front())
3721 if (shiftBegExtra != 0) {
3724 }
else if (shiftEndExtra != 0) {
3730 wa.
shape.insert(wa.
shape.begin() + 1, curve.begin(), curve.end());
3740 if (wacs.shape.size() != 0) {
3741 wa.
shape = wacs.shape;
3744 wa.
width = wacs.width;
3751 double lengthSum = 0;
3752 int combinations = 0;
3753 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
3754 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
3763 DEBUGCOUT(
gDebugFlag1,
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n")
3764 wa.
length = POSITION_EPS;
3765 if (combinations > 0) {
3766 wa.
length =
MAX2(POSITION_EPS, lengthSum / combinations);
3771 std::vector<Crossing*> validCrossings =
getCrossings();
3772 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
3774 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
3789 wa.
shape.push_back(tmp[-1]);
3791 wa.
shape.push_back(tmp[-1]);
3795 wa.
shape.push_back(tmp[0]);
3797 wa.
shape.push_back(tmp[0]);
3804 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(wa.
refEdges, wacs.edges)) {
3805 wa.
shape = wacs.shape;
3821#ifdef DEBUG_CROSSING_OUTLINE
3823 std::cerr <<
"<add>\n";
3826 std::map<std::string, PositionVector> waShapes;
3828 waShapes[wa.id] = wa.shape;
3833 if (wa1.empty() || wa2.empty()) {
3846 side1 =
cutAtShapes(side1, wa1, wa2, side1default);
3847 side2 =
cutAtShapes(side2, wa1, wa2, side2default);
3851 side2ex.
extrapolate(side2 == side2default ? c->width / 2 : POSITION_EPS);
3854 c->outlineShape = side1;
3855 c->outlineShape.
append(side3, POSITION_EPS);
3856 c->outlineShape.append(side2, POSITION_EPS);
3857 c->outlineShape.append(side4, POSITION_EPS);
3858 c->outlineShape.removeDoublePoints();
3859 if (c->outlineShape.back().almostSame(c->outlineShape.front())) {
3860 c->outlineShape.pop_back();
3863#ifdef DEBUG_CROSSING_OUTLINE
3864 std::cout <<
" side1=" << side1 <<
"\n side2=" << side2 <<
"\n side3=" << side3 <<
"\n side4=" << side4 <<
"\n";
3865 std::cerr <<
"<poly id=\"" << c->id <<
"\" shape=\"" << c->outlineShape <<
"\" color=\"blue\" lineWidth=\"0.2\" layer=\"100\"/>\n";
3868#ifdef DEBUG_CROSSING_OUTLINE
3870 std::cerr <<
"</add>\n";
3880#ifdef DEBUG_CROSSING_OUTLINE
3881 std::cout <<
"is1=" << is1 <<
" is2=" << is2 <<
" cut=" << cut <<
" border1=" << border1 <<
" border2=" << border2 <<
"\n";
3883 if (is1.size() == 0 && border1.size() == 2) {
3884 const double d1 = cut.
distance2D(border1.front());
3885 const double d2 = cut.
distance2D(border1.back());
3886 Position closer = d1 < d2 ? border1.front() : border1.back();
3888#ifdef DEBUG_CROSSING_OUTLINE
3889 std::cout <<
" closer=" << closer <<
" nOp=" << nOp <<
"\n";
3891 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3897 if (is2.size() == 0 && border2.size() == 2) {
3898 const double d1 = cut.
distance2D(border2.front());
3899 const double d2 = cut.
distance2D(border2.back());
3900 Position closer = d1 < d2 ? border2.front() : border2.back();
3902 if (nOp <= 2 * POSITION_EPS && cut.back().distanceTo2D(closer) <= 2 * POSITION_EPS) {
3908 if (is1.size() > 0 && is2.size() > 0) {
3911#ifdef DEBUG_CROSSING_OUTLINE
3912 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3917#ifdef DEBUG_CROSSING_OUTLINE
3918 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3924#ifdef DEBUG_CROSSING_OUTLINE
3925 std::cout <<
" of1=" << of1 <<
" of2=" << of2 <<
"\n";
3938 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
3940 for (
const NBEdge* e : sub) {
3941 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
3960 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3961 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3962 if (it1 != edges.end() && it2 != edges.end()) {
3987 return other1 == other2;
4007 while (it != it_end) {
4008 result.push_back(*it);
4018 wacs.
edges.insert(edges.begin(), edges.end());
4032 if (incoming.size() == 1 && outgoing.size() == 1) {
4035 if (incoming.size() == 2 && outgoing.size() == 2) {
4038 NBEdge* in0 = incoming[0];
4039 NBEdge* in1 = incoming[1];
4040 NBEdge* out0 = outgoing[0];
4041 NBEdge* out1 = outgoing[1];
4050 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4054 if (
MAX2(angle0, angle1) <= 160) {
4084 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
4085 if (params !=
nullptr) {
4088 myCrossings.push_back(std::unique_ptr<Crossing>(c));
4098 EdgeSet edgeSet(edges.begin(), edges.end());
4100 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
4101 if (edgeSet == edgeSet2) {
4123 const EdgeSet edgeSet(edges.begin(), edges.end());
4125 const EdgeSet edgeSet2(crossing->edges.begin(), crossing->edges.end());
4126 if (edgeSet == edgeSet2) {
4127 return crossing.get();
4133 throw ProcessError(
TL(
"Request for unknown crossing for the given Edges"));
4140 if (walkingArea.id ==
id) {
4149 if (walkingArea.id ==
id) {
4155 WRITE_WARNINGF(
"Could not retrieve walkingarea '%' (edge ordering changed after recompute).",
id);
4164 bool usedCustom =
false;
4166 c->tlLinkIndex = startIndex++;
4168 if (c->customTLIndex != -1 && !ignoreCustom) {
4169 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
4170 c->tlLinkIndex = c->customTLIndex;
4172 if (c->customTLIndex2 != -1 && !ignoreCustom) {
4174 c->tlLinkIndex2 = c->customTLIndex2;
4187 result += (int)edge->getConnections().size();
4201 if (e == from && cand.fromLane == con.
fromLane && cand.toLane == con.
toLane && cand.toEdge == con.
toEdge) {
4231#ifdef DEBUG_PED_STRUCTURES
4233 std::cout <<
" angles:\n";
4234 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
4235 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
4237 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
4243 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
4252 bool haveModifications =
false;
4256 if (turnDest !=
nullptr) {
4261 if (haveModifications) {
4279 if (def->extraConflict(index, foeIndex)) {
4301 std::vector<NBEdge*>::iterator j;
4302 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
4305 if (allEdges.size() > 1 && j != allEdges.end()) {
4310 NBEdge* firstOfAll = allEdges.front();
4311 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
4312 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
4318 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
4319 if (firstOfIncoming !=
nullptr) {
4320 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
4322 if (firstOfOutgoing !=
nullptr) {
4323 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
4325#ifdef DEBUG_EDGE_SORTING
4327 std::cout <<
"sortedEdges (useNodeShape=" << useNodeShape <<
"):\n";
4328 for (
NBEdge* e : allEdges) {
4329 std::cout <<
" " << e->getID()
4330 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
4331 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
4338 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
4339 std::vector<NBEdge*>::const_iterator in, out;
4340 std::vector<NBEdge*> allTmp;
4341 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
4342 if ((*in)->isTurningDirectionAt(*out)) {
4343 allTmp.push_back(*in);
4344 allTmp.push_back(*out);
4349 if (allTmp.size() == allEdges.size()) {
4362 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
4366 e->computeEdgeShape();
4371std::vector<std::pair<Position, std::string> >
4374 std::vector<std::pair<Position, std::string> >result;
4376 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
4377 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
4379 for (
const auto& pair : result) {
4380 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
4386 result.push_back(std::make_pair(pos, origID));
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
#define EXTEND_CROSSING_ANGLE_THRESHOLD
#define SPLIT_CROSSING_WIDTH_THRESHOLD
#define SPLIT_CROSSING_ANGLE_THRESHOLD
#define DEBUGCOUT(cond, msg)
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permissions is a forbidden edge.
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TRAM
vehicle is a light rail
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
RoundaboutType
classifying roundabout type for nodes
FringeType
classifying boundary nodes
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ TURN_LEFTHAND
The link is a 180 degree turn (left-hand network)
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link)
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_ALLWAY_STOP
This is an uncontrolled, all-way stop link.
@ LINKSTATE_MAJOR
This is an uncontrolled, major link, may pass.
@ LINKSTATE_STOP
This is an uncontrolled, minor link, has to stop.
@ LINKSTATE_EQUAL
This is an uncontrolled, right-before-left link.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
@ LINKSTATE_TL_OFF_BLINKING
The link is controlled by a tls which is off and blinks, has to brake.
@ LINKSTATE_MINOR
This is an uncontrolled, minor link, has to brake.
@ LINKSTATE_TL_OFF_NOSIGNAL
The link is controlled by a tls which is off, not blinking, may pass.
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
@ TRAFFIC_LIGHT_RIGHT_ON_RED
@ TRAFFIC_LIGHT_NOJUNCTION
int gPrecision
the precision for floating point outputs
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static void compute(BresenhamCallBack *callBack, const int val1, const int val2)
static double getCCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle counter-clockwise.
static double getCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle clockwise.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
bool replaceTo(NBEdge *which, NBEdge *by)
replaces the to-edge by the one given
bool replaceFrom(NBEdge *which, NBEdge *by)
replaces the from-edge by the one given
NBEdge * getTo() const
returns the to-edge (end of the connection)
Class to sort edges by their angle in relation to the given edge.
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
A container for districts.
A class representing a single district.
void replaceIncoming(const EdgeVector &which, NBEdge *const by)
Replaces incoming edges from the vector (sinks) by the given edge.
void replaceOutgoing(const EdgeVector &which, NBEdge *const by)
Replaces outgoing edges from the vector (source) by the given edge.
Storage for edges, including some functionality operating on multiple edges.
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
The representation of a single edge during network building.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
const std::vector< Connection > & getConnections() const
Returns the connections.
bool isInsideTLS() const
Returns whether this edge was marked as being within an intersection.
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
double getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
double getLaneWidth() const
Returns the default width of lanes of this edge.
NBNode * getToNode() const
Returns the destination node of the edge.
Connection & getConnectionRef(int fromLane, const NBEdge *to, int toLane)
Returns reference to the specified connection This method goes through "myConnections" and returns th...
Lane & getLaneStruct(int lane)
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
const PositionVector & getGeometry() const
Returns the geometry of the edge.
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
EdgeBuildingStep getStep() const
The building step of this edge.
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
@ LANES2LANES_RECHECK
Lanes to lanes - relationships are computed; should be rechecked.
@ LANES2LANES_DONE
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
@ LANES2EDGES
Lanes to edges - relationships are computed/loaded.
@ LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
double getSpeed() const
Returns the speed allowed on this edge.
const std::string & getID() const
bool shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap and return whether geometry was changed
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
int getNumLanes() const
Returns the number of lanes.
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
int getNumLanesThatAllow(SVCPermissions permissions, bool allPermissions=true) const
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
const PositionVector & getNodeBorder(const NBNode *node) const
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
std::string getLaneID(int lane) const
get lane ID
@ COMPUTED
The connection was computed.
static PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode, PositionVector nodeShape)
std::string getSidewalkID()
get the lane id for the canonical sidewalk lane
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
RoundaboutType myRoundaboutType
roundabout type of this node
void sortEdges(bool useNodeShape)
sort all edge containers for this node
RightOfWay myRightOfWay
how to compute right of way for this node
std::set< NBTrafficLightDefinition * > myTrafficLights
traffic lights of node
double myRadius
the turning radius (for all corners) at this node in m.
static bool includes(const std::set< const NBEdge *, ComparatorIdLess > &super, const std::set< const NBEdge *, ComparatorIdLess > &sub)
returns whether sub is a subset of super
static SVCPermissions myHaveRailSignalClasses
all vehicle classes for which rail signals exist
bool bidiConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether the foe connections is oncoming on the same lane
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0, int shapeFlag=0) const
Compute a smooth curve between the given geometries.
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
bool checkCrossingDuplicated(EdgeVector edges)
return true if there already exist a crossing with the same edges as the input
void setRoundabout()
update the type of this node as a roundabout
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multiple connections from the same edge target the same lane
bool myDiscardAllCrossings
whether to discard all pedestrian crossings
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
add shorted link FOES
Position myPosition
The position the node lies at.
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurrences of the first edge within the list of incoming by the second Connections are rema...
bool turnFoes(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *from2, const NBEdge *to2, int fromLane2, bool lefthand=false) const
return whether the given laneToLane connection originate from the same edge and are in conflict due t...
void discardAllCrossings(bool rejectAll)
discard all current (and optionally future) crossings
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
EdgeVector getPassengerEdges(bool incoming) const
return edges that permit passengers (either incoming or outgoing)
NBEdge * getPossiblySplittedOutgoing(const std::string &edgeid)
get possibly splitted outgoing edge
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
std::vector< std::unique_ptr< Crossing > > myCrossings
Vector of crossings.
bool isStraighter(const NBEdge *const incoming, const double angle, const SVCPermissions vehPerm, const int modeLanes, const NBEdge *const candidate) const
check whether the candidate edge is more likely to be the straight continuation
void removeJoinedTrafficLights()
remove all traffic light definitions that are part of a joined tls
bool crossingBetween(const NBEdge *e1, const NBEdge *e2) const
return true if the given edges are connected by a crossing
bool isDistrict() const
check if node is a district
NBDistrict * myDistrict
The district the node is the centre of.
void computeLanes2Lanes()
computes the connections of lanes to edges
void reshiftPosition(double xoff, double yoff)
Applies an offset to the node.
double myDisplacementError
geometry error after computation of internal lane shapes
static const int AVOID_WIDE_LEFT_TURN
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
const std::string getResponse(int linkIndex) const
get the 'response' string (right-of-way bit set) of the right-of-way logic
void buildCrossingOutlines()
build crossing outlines after walkingareas are finished
static bool isLongEnough(NBEdge *out, double minLength)
check if is long enough
const PositionVector & getShape() const
retrieve the junction shape
std::vector< WalkingArea > myWalkingAreas
Vector of walking areas.
NBConnectionProhibits myBlockedConnections
The container for connection block dependencies.
void updateSurroundingGeometry()
update geometry of node and surrounding edges
int addedLanesRight(NBEdge *out, int addedLanes) const
check whether this edge has extra lanes on the right side
FringeType myFringeType
fringe type of this node
void roundGeometry()
ensure consistency between input and output geometries
bool setCrossingTLIndices(const std::string &tlID, int startIndex, bool ignoreCustom=false)
bool checkIsRemovable() const
check if node is removable
bool isRoundabout() const
return whether this node is part of a roundabout
static const int FORWARD
edge directions (for pedestrian related stuff)
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
void displaceShapeAtWidthChange(const NBEdge *from, const NBEdge::Connection &con, PositionVector &fromShape, PositionVector &toShape) const
displace lane shapes to account for change in lane width at this node
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
void removeDoubleEdges()
remove duble edges
bool avoidConfict(NBEdge *incoming, NBEdge *currentOutgoing, SVCPermissions svcSpecial, LinkDirection dir, int i)
helper function for recheckSpecialConnections
double buildInnerEdges()
build internal lanes, pedestrian crossings and walking areas
PositionVector myPoly
the (outer) shape of the junction
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
bool crossesFringe(const NBEdge *e1, const NBEdge *e2) const
return true if the given sidewalks are separated by a fringe road
void getEdgesThatApproach(NBEdge *currentOutgoing, EdgeVector &approaching)
returns a list of edges which are connected to the given outgoing edge
EdgeVector getEdgesSortedByAngleAtNodeCenter() const
returns the list of all edges sorted clockwise by getAngleAtNodeToCenter
EdgeVector edgesBetween(const NBEdge *e1, const NBEdge *e2) const
return all edges that lie clockwise between the given edges
PositionVector computeInternalLaneShape(const NBEdge *fromE, const NBEdge::Connection &con, int numPoints, NBNode *recordError=0, int shapeFlag=0) const
Compute the shape for an internal lane.
NBEdge * getPossiblySplittedIncoming(const std::string &edgeid)
get possibly splitted incoming edge
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset, int threshold=-1)
patches loaded signal plans by modifying lane indices above threshold by the given offset
bool geometryLike() const
whether this is structurally similar to a geometry node
bool isNearDistrict() const
@chech if node is near district
static const int INDIRECT_LEFT
EdgeVector myIncomingEdges
Vector of incoming edges.
WalkingArea & getWalkingArea(const std::string &id)
return the walkingArea with the given ID
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
static SVCPermissions myPermitUnsignalizedClasses
all rail classes for which operation without rail signals is permitted
int guessCrossings()
guess pedestrian crossings and return how many were guessed
bool isTLControlled() const
Returns whether this node is controlled by any tls.
static const int SCURVE_IGNORE
const std::string getFoes(int linkIndex) const
get the 'foes' string (conflict bit set) of the right-of-way logic
NBEdge * getOppositeIncoming(NBEdge *e) const
returns the opposite incoming edge of certain edge
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
This class computes shapes of junctions.
double getRadius() const
get computed radius for node
const PositionVector compute(bool forceSmall)
Computes the shape of the assigned junction.
static bool isRailwayNode(const NBNode *n)
whether the given node only has rail edges
Sorts crossings by minimum clockwise clockwise edge angle. Use the ordering found in myAllEdges of th...
Sorts incoming and outgoing edges clockwise around the given node.
static void swapWhenReversed(const NBNode *const n, const std::vector< NBEdge * >::iterator &i1, const std::vector< NBEdge * >::iterator &i2)
Assures correct order for same-angle opposite-direction edges.
A traffic light logics which must be computed (only nodes/edges are given)
bool bidiConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether straight connections are in conflict via bidirectional lane use
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
bool hasConflictAtLink(int linkIndex) const
whether there are conflicting streams of traffic for the given link index
const std::string & getFoes(int linkIndex) const
bool hasConflict() const
whether there are conflicting streams of traffic at this node
void buildBitfieldLogic()
builds the bitset-representation of the logic
bool indirectLeftTurnConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether straight and indirect left turn are in conflict
static bool mustBrakeForCrossing(const NBNode *node, const NBEdge *const from, const NBEdge *const to, const NBNode::Crossing &crossing)
Returns the information whether the described flow must brake for the given crossing.
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multple connections from the same edge target the same lane
void writeLogic(OutputDevice &into) const
void computeLogic(const bool checkLaneFoes)
writes the XML-representation of the logic as a bitset-logic XML representation
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect.
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
const std::string & getResponse(int linkIndex) const
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
The base class for traffic light logic definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
TrafficLightType getType() const
get the algorithm type (static etc..)
virtual void removeNode(NBNode *node)
Removes the given node from the list of controlled nodes.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
SUMOTime getOffset()
Returns the offset.
A container for traffic light definitions and built programs.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurrences of the removed edge in incoming/outgoing edges of all definitions.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
Base class for objects which have an id.
std::string myID
The name of the object.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
An upper class for objects with additional parameters.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
void updateParameters(const Parameterised::Map &mapArg)
Adds or updates all given parameters from the map.
A point in 2D or 3D with translation and scaling methods.
bool isNAN() const
check if position is NAN
void set(double x, double y)
set positions x and y
static const Position INVALID
used to indicate that a position is valid
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
void norm2D()
Normalizes the given vector.
void sub(double dx, double dy)
Subtracts the given position from this one.
double x() const
Returns the x-position.
void round(int precision)
round all coordinates to the given precision
void add(const Position &pos)
Adds the given position to this one.
void mul(double val)
Multiplies position with the given value.
double z() const
Returns the z-position.
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position (in radians bet...
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
check whether the other position has a euclidean distance of less than maxDiv
double y() const
Returns the y-position.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
void round(int precision, bool avoidDegeneration=true)
round all coordinates to the given precision
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
Position intersectionPosition2D(const Position &p1, const Position &p2, const double withinDist=0.) const
Returns the position of the intersection.
void push_front_noDoublePos(const Position &p)
insert in front a non double position
bool isNAN() const
check if PositionVector is NAN
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0, double deg=90) const
return orthogonal through p (extending this vector if necessary)
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
PositionVector smoothedZFront(double dist=std::numeric_limits< double >::max()) const
returned vector that is smoothed at the front (within dist)
double angleAt2D(int pos) const
get angle in certain position of position vector (in radians between -M_PI and M_PI)
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
PositionVector bezier(int numPoints)
return a bezier interpolation
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
PositionVector reverse() const
reverse position vector
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
class for maintaining associations between enums and xml-strings
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
Some static methods for string processing.
static T maxValue(const std::vector< T > &v)
static T minValue(const std::vector< T > &v)
#define UNUSED_PARAMETER(x)
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
A structure which describes a connection between edges or lanes.
bool indirectLeft
Whether this connection is an indirect left turn.
const std::string & getID() const
int fromLane
The lane the connections starts at.
int toLane
The lane the connections yields in.
NBEdge * toEdge
The edge the connections yields in.
PositionVector customShape
custom shape for connection
std::string getDescription(const NBEdge *parent) const
get string describing this connection
std::string tlID
The id of the traffic light that controls this connection.
bool haveVia
check if Connection have a Via
int tlLinkIndex
The index of this connection within the controlling traffic light.
An (internal) definition of a single lane of an edge.
double width
This lane's width.
double endOffset
This lane's offset to the intersection begin.
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this lane.
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this lane.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
bool connectionsDone
Whether connection information for this lane is already completed.
PositionVector shape
The lane's shape.
std::set< const NBEdge *, ComparatorIdLess > edges
A definition of a pedestrian walking area.
int minPrevCrossingEdges
minimum number of edges crossed by incoming crossings
std::vector< std::string > nextSidewalks
the lane-id of the next sidewalk lane or ""
std::vector< std::string > prevSidewalks
the lane-id of the previous sidewalk lane or ""
std::string id
the (edge)-id of this walkingArea
bool hasCustomShape
whether this walkingArea has a custom shape
std::set< const NBEdge *, ComparatorIdLess > refEdges
reference edges that uniquely identify this walkingarea
double width
This lane's width.
std::vector< std::string > nextCrossings
the lane-id of the next crossing(s)
std::vector< std::string > prevCrossings
the lane-id of the previous crossing(s)
PositionVector shape
The polygonal shape.
double length
This lane's width.
int minNextCrossingEdges
minimum number of edges crossed by nextCrossings