59 #define DEBUGCOND (getID() == DEBUGID)
62 #define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUGID))
107 mayDefinitelyPass(mayDefinitelyPass_),
124 connectionsDone(false) {
137 assert((
int)myTransitions.size() > virtEdge);
139 NBEdge* succEdge = myTransitions[virtEdge];
140 std::vector<int> lanes;
144 std::map<NBEdge*, std::vector<int> >::iterator i =
myConnections.find(succEdge);
152 std::vector<int>::iterator j = std::find(lanes.begin(), lanes.end(), lane);
153 if (j == lanes.end()) {
155 lanes.push_back(lane);
168 const NBEdge* straight =
nullptr;
169 for (
const NBEdge*
const out : outgoing) {
171 for (
const int l : availableLanes) {
172 if ((parent->
myLanes[l].permissions & outPerms) != 0) {
173 if (straight ==
nullptr || sorter(out, straight)) {
180 if (straight ==
nullptr) {
183 myStraightest = (int)std::distance(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), straight));
186 assert(outgoing.size() > 0);
188 #ifdef DEBUG_CONNECTION_GUESSING
190 std::cout <<
" MainDirections edge=" << parent->
getID() <<
" straightest=" << straight->
getID() <<
" dir=" <<
toString(straightestDir) <<
"\n";
202 if (outgoing.back()->getJunctionPriority(to) == 1) {
206 if (outgoing.back()->getPriority() > straight->
getPriority() ||
207 outgoing.back()->getNumLanes() > straight->
getNumLanes()) {
224 return myDirs.empty();
230 return std::find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
250 std::string type,
double speed,
double friction,
int nolanes,
251 int priority,
double laneWidth,
double endOffset,
273 init(nolanes,
false,
"");
278 std::string type,
double speed,
double friction,
int nolanes,
279 int priority,
double laneWidth,
double endOffset,
282 const std::string& streetName,
283 const std::string& origID,
284 bool tryIgnoreNodePositions) :
288 myFrom(from), myTo(to),
289 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
290 myPriority(priority), mySpeed(speed), myFriction(friction),
292 myTurnDestination(nullptr),
293 myPossibleTurnDestination(nullptr),
294 myFromJunctionPriority(-1), myToJunctionPriority(-1),
295 myGeom(geom), myLaneSpreadFunction(spread), myEndOffset(endOffset),
296 myLaneWidth(laneWidth),
297 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
298 myAmInTLS(false), myAmMacroscopicConnector(false),
299 myStreetName(streetName),
301 mySignalNode(nullptr),
305 init(nolanes, tryIgnoreNodePositions, origID);
312 myType(tpl->getTypeID()),
313 myFrom(from), myTo(to),
314 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
315 myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
316 myFriction(tpl->getFriction()),
318 myTurnDestination(nullptr),
319 myPossibleTurnDestination(nullptr),
320 myFromJunctionPriority(-1), myToJunctionPriority(-1),
322 myLaneSpreadFunction(tpl->getLaneSpreadFunction()),
323 myEndOffset(tpl->getEndOffset()),
324 myEdgeStopOffset(tpl->getEdgeStopOffset()),
325 myLaneWidth(tpl->getLaneWidth()),
326 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
328 myAmMacroscopicConnector(false),
329 myStreetName(tpl->getStreetName()),
330 mySignalPosition(to == tpl->myTo ? tpl->mySignalPosition :
Position::
INVALID),
331 mySignalNode(to == tpl->myTo ? tpl->mySignalNode : nullptr),
343 myLanes[i].updateParameters(tpl->
myLanes[tplIndex].getParametersMap());
344 if (to == tpl->
myTo) {
359 myFrom(nullptr), myTo(nullptr),
360 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
361 myPriority(0), mySpeed(0), myFriction(UNSPECIFIED_FRICTION),
363 myTurnDestination(nullptr),
364 myPossibleTurnDestination(nullptr),
365 myFromJunctionPriority(-1), myToJunctionPriority(-1),
370 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
372 myAmMacroscopicConnector(false),
374 mySignalNode(nullptr) {
380 double speed,
double friction,
int nolanes,
int priority,
382 const std::string& streetName,
384 bool tryIgnoreNodePositions) {
406 const std::vector<Lane> oldLanes =
myLanes;
407 init(nolanes, tryIgnoreNodePositions, oldLanes.empty() ?
"" : oldLanes[0].getParameter(
SUMO_PARAM_ORIGID));
408 for (
int i = 0; i < (int)nolanes; ++i) {
410 myLanes[i] = oldLanes[
MIN2(i, (
int)oldLanes.size() - 1)];
432 if (from ==
nullptr || to ==
nullptr) {
456 NBEdge::init(
int noLanes,
bool tryIgnoreNodePositions,
const std::string& origID) {
479 if (!tryIgnoreNodePositions ||
myGeom.size() < 2) {
502 assert(
myGeom.size() >= 2);
504 if ((
int)
myLanes.size() > noLanes) {
506 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
511 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
512 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
513 (*i)->removeFromConnections(
this, -1, lane);
518 for (
int i = 0; i < noLanes; i++) {
524 #ifdef DEBUG_CONNECTION_GUESSING
526 std::cout <<
"init edge=" <<
getID() <<
"\n";
528 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
531 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
546 lane.customShape.add(xoff, yoff, 0);
550 (*i).customShape.add(xoff, yoff, 0);
565 for (
int i = 0; i < (int)
myLanes.size(); i++) {
567 myLanes[i].customShape.mirrorX();
571 c.viaShape.mirrorX();
572 c.customShape.mirrorX();
607 assert(node ==
myTo);
649 assert(node ==
myTo);
678 if (rectangularCut) {
679 const double extend = 100;
683 border.push_back(p2);
685 if (border.size() == 2) {
690 assert(node ==
myTo);
694 #ifdef DEBUG_NODE_BORDER
697 <<
" rect=" << rectangularCut
698 <<
" p=" << p <<
" p2=" << p2
699 <<
" border=" << border
712 assert(node ==
myTo);
723 assert(node ==
myTo);
778 #ifdef DEBUG_CUT_LANES
780 std::cout <<
getID() <<
" cutFrom=" << shape <<
"\n";
783 if (shape.size() < 2) {
785 const double oldLength = old.
length();
786 shape = old.
getSubpart(oldLength - 2 * POSITION_EPS, oldLength);
787 #ifdef DEBUG_CUT_LANES
789 std::cout <<
getID() <<
" cutFromFallback=" << shape <<
"\n";
794 #ifdef DEBUG_CUT_LANES
796 std::cout <<
getID() <<
" cutTo=" << shape <<
"\n";
800 if (shape.
length() < POSITION_EPS) {
801 if (old.
length() < 2 * POSITION_EPS) {
804 const double midpoint = old.
length() / 2;
806 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
807 assert(shape.size() >= 2);
808 assert(shape.
length() > 0);
809 #ifdef DEBUG_CUT_LANES
811 std::cout <<
getID() <<
" fallBackShort=" << shape <<
"\n";
821 tmp.push_back(shape[0]);
822 tmp.push_back(shape[-1]);
824 if (tmp.
length() < POSITION_EPS) {
826 if (old.
length() < 2 * POSITION_EPS) {
829 const double midpoint = old.
length() / 2;
831 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
832 assert(shape.size() >= 2);
833 assert(shape.
length() > 0);
835 #ifdef DEBUG_CUT_LANES
837 std::cout <<
getID() <<
" fallBackReversed=" << shape <<
"\n";
841 const double midpoint = shape.
length() / 2;
843 shape = shape.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
844 if (shape.
length() < POSITION_EPS) {
849 #ifdef DEBUG_CUT_LANES
851 std::cout <<
getID() <<
" fallBackReversed2=" << shape <<
" mid=" << midpoint <<
"\n";
856 const double z = (shape[0].z() + shape[1].z()) / 2;
872 const double d = cut[0].distanceTo2D(cut[1]);
873 const double dZ = fabs(cut[0].z() - cut[1].z());
874 if (dZ / smoothElevationThreshold > d) {
880 const double d = cut[-1].distanceTo2D(cut[-2]);
881 const double dZ = fabs(cut[-1].z() - cut[-2].z());
882 if (dZ / smoothElevationThreshold > d) {
893 for (
int i = 0; i < (int)
myLanes.size(); i++) {
897 double avgLength = 0;
898 for (
int i = 0; i < (int)
myLanes.size(); i++) {
899 avgLength +=
myLanes[i].shape.length();
908 if (nodeShape.size() == 0) {
917 assert(pbv.size() > 0);
925 const double delta = ns[0].z() - laneShape[0].z();
927 if (fabs(delta) > 2 * POSITION_EPS && (!startNode->
geometryLike() || pb < 1)) {
932 assert(ns.size() >= 2);
937 assert(pbv.size() > 0);
942 const double delta = np.
z() - laneShape[0].z();
944 if (fabs(delta) > 2 * POSITION_EPS && !startNode->
geometryLike()) {
1003 reverse = lane.customShape.
reverse();
1005 lane.customShape = reverse.
reverse();
1010 lane.customShape.removeDoublePoints(minDist,
true, 0, 0,
true);
1022 std::vector<double> angles;
1024 for (
int i = 0; i < (int)
myGeom.size() - 1; ++i) {
1029 for (
int i = 0; i < (int)angles.size() - 1; ++i) {
1032 if (maxAngle > 0 && relAngle > maxAngle && !silent) {
1038 if (i == 0 || i == (
int)angles.size() - 2) {
1039 const bool start = i == 0;
1041 const double r = tan(0.5 * (
M_PI - relAngle)) * dist;
1043 if (minRadius > 0 && r < minRadius) {
1045 WRITE_MESSAGEF(
TL(
"Removing sharp turn with radius % at the % of edge '%'."),
1050 }
else if (!silent) {
1070 if (dest !=
nullptr &&
myTo != dest->
myFrom) {
1073 if (dest ==
nullptr) {
1080 if (overrideRemoval) {
1083 if (it->toEdge == dest) {
1100 bool mayUseSameDestination,
1101 bool mayDefinitelyPass,
1112 const std::string& edgeType,
1128 return setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass, keepClear, contPos, visibility, speed, friction, length,
1129 customShape, uncontrolled, permissions, indirectLeft, edgeType, changeLeft, changeRight, postProcess);
1135 NBEdge* dest,
int toLane,
1137 bool invalidatePrevious,
1138 bool mayDefinitelyPass) {
1139 if (invalidatePrevious) {
1143 for (
int i = 0; i < no && ok; i++) {
1153 bool mayUseSameDestination,
1154 bool mayDefinitelyPass,
1165 const std::string& edgeType,
1193 if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
1197 permissions = (*i).permissions;
1205 if (mayDefinitelyPass) {
1238 if ((it->fromLane < 0 || it->fromLane == lane)
1239 && (it->toEdge ==
nullptr || it->toEdge == destEdge)
1240 && (it->toLane < 0 || it->toLane == destLane)) {
1251 std::vector<NBEdge::Connection>
1253 std::vector<NBEdge::Connection> ret;
1255 if ((lane < 0 || c.fromLane == lane)
1256 && (to ==
nullptr || to == c.toEdge)
1257 && (toLane < 0 || toLane == c.toLane)) {
1268 if (c.fromLane == fromLane && c.toEdge == to && c.toLane == toLane) {
1273 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1280 if (c.fromLane == fromLane && c.toEdge == to && c.toLane == toLane) {
1285 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1316 if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
1317 outgoing.push_back((*i).toEdge);
1322 if (it->fromLane < 0 && it->toLane < 0) {
1324 EdgeVector::iterator forbidden = std::find(outgoing.begin(), outgoing.end(), it->toEdge);
1325 if (forbidden != outgoing.end()) {
1326 outgoing.erase(forbidden);
1331 int size = (int) outgoing.size();
1333 edges->reserve(size);
1334 for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
1337 edges->push_back(outedge);
1349 if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
1350 ret.push_back((*i).toEdge);
1361 for (EdgeVector::const_iterator i = candidates.begin(); i != candidates.end(); i++) {
1362 if ((*i)->isConnectedTo(
this)) {
1372 std::vector<int> ret;
1376 ret.push_back(c.fromLane);
1399 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
1404 for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
1414 const bool keepPossibleTurns) {
1416 const int fromLaneRemoved = adaptToLaneRemoval && fromLane >= 0 ? fromLane : -1;
1417 const int toLaneRemoved = adaptToLaneRemoval && toLane >= 0 ? toLane : -1;
1420 if ((toEdge ==
nullptr || c.
toEdge == toEdge)
1421 && (fromLane < 0 || c.
fromLane == fromLane)
1422 && (toLane < 0 || c.
toLane == toLane)) {
1425 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1432 if (fromLaneRemoved >= 0 && c.
fromLane > fromLaneRemoved) {
1435 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1436 for (NBConnectionVector::iterator tlcon = (*it)->getControlledLinks().begin(); tlcon != (*it)->getControlledLinks().end(); ++tlcon) {
1447 if (toLaneRemoved >= 0 && c.
toLane > toLaneRemoved && (toEdge ==
nullptr || c.
toEdge == toEdge)) {
1463 #ifdef DEBUG_CONNECTION_GUESSING
1465 std::cout <<
"removeFromConnections " <<
getID() <<
"_" << fromLane <<
"->" << toEdge->
getID() <<
"_" << toLane <<
"\n";
1467 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
1470 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
1482 if ((i->toEdge == connectionToRemove.
toEdge) && (i->fromLane == connectionToRemove.
fromLane) && (i->toLane == connectionToRemove.
toLane)) {
1497 if (reallowSetting) {
1509 if ((*i).toEdge == which) {
1511 (*i).toLane += laneOff;
1522 std::map<int, int> laneMap;
1526 bool wasConnected =
false;
1528 if ((*i).toEdge != which) {
1531 wasConnected =
true;
1532 if ((*i).fromLane != -1) {
1533 int fromLane = (*i).fromLane;
1534 laneMap[(*i).toLane] = fromLane;
1535 if (minLane == -1 || minLane > fromLane) {
1538 if (maxLane == -1 || maxLane < fromLane) {
1543 if (!wasConnected) {
1547 std::vector<NBEdge::Connection> conns = origConns;
1549 for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
1550 if ((*i).toEdge == which || (*i).toEdge ==
this
1552 || std::find(origTargets.begin(), origTargets.end(), (*i).toEdge) != origTargets.end()) {
1553 #ifdef DEBUG_REPLACECONNECTION
1555 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID()
1556 <<
" origTargets=" <<
toString(origTargets) <<
" newTarget=" << i->toEdge->getID() <<
" skipped\n";
1566 int fromLane = (*i).fromLane;
1568 if (laneMap.find(fromLane) == laneMap.end()) {
1569 if (fromLane >= 0 && fromLane <= minLane) {
1572 for (
auto& item : laneMap) {
1573 if (item.first < fromLane) {
1574 item.second =
MIN2(item.second, minLane);
1578 if (fromLane >= 0 && fromLane >= maxLane) {
1581 for (
auto& item : laneMap) {
1582 if (item.first > fromLane) {
1583 item.second =
MAX2(item.second, maxLane);
1588 toUse = laneMap[fromLane];
1593 #ifdef DEBUG_REPLACECONNECTION
1595 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID() <<
" origTargets=" <<
toString(origTargets)
1596 <<
" origFrom=" << fromLane <<
" laneMap=" <<
joinToString(laneMap,
":",
",") <<
" minLane=" << minLane <<
" maxLane=" << maxLane
1597 <<
" newTarget=" << i->toEdge->getID() <<
" fromLane=" << toUse <<
" toLane=" << i->toLane <<
"\n";
1601 i->contPos, i->visibility, i->speed, i->friction, i->customLength, i->customShape, i->uncontrolled);
1632 std::vector<Connection>::iterator i =
myConnections.begin() + index;
1655 const int numPoints = oc.
getInt(
"junctions.internal-link-detail");
1656 const bool joinTurns = oc.
getBool(
"junctions.join-turns");
1657 const double limitTurnSpeed = oc.
getFloat(
"junctions.limit-turn-speed");
1658 const double limitTurnSpeedMinAngle =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle"));
1659 const double limitTurnSpeedMinAngleRail =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle.railway"));
1660 const double limitTurnSpeedWarnStraight = oc.
getFloat(
"junctions.limit-turn-speed.warn.straight");
1661 const double limitTurnSpeedWarnTurn = oc.
getFloat(
"junctions.limit-turn-speed.warn.turn");
1662 const bool higherSpeed = oc.
getBool(
"junctions.higher-speed");
1663 const double interalJunctionVehicleWidth = oc.
getFloat(
"internal-junctions.vehicle-width");
1665 std::string innerID =
":" + n.
getID();
1666 NBEdge* toEdge =
nullptr;
1667 int edgeIndex = linkIndex;
1668 int internalLaneIndex = 0;
1670 double lengthSum = 0;
1671 int avoidedIntersectingLeftOriginLane = std::numeric_limits<int>::max();
1672 bool averageLength =
true;
1673 double maxCross = 0.;
1677 if (con.
toEdge ==
nullptr) {
1684 if (con.
toEdge != toEdge) {
1687 edgeIndex = linkIndex;
1689 internalLaneIndex = 0;
1694 averageLength = !isTurn || joinTurns;
1698 std::vector<int> foeInternalLinks;
1705 std::pair<double, std::vector<int> > crossingPositions(-1, std::vector<int>());
1706 std::set<std::string> tmpFoeIncomingLanes;
1709 std::vector<PositionVector> otherShapes;
1711 const double width1OppositeLeft = 0;
1713 for (
const Connection& k2 : i2->getConnections()) {
1714 if (k2.toEdge ==
nullptr) {
1719 double width2 = k2.toEdge->getLaneWidth(k2.toLane);
1720 if (k2.toEdge->getPermissions(k2.toLane) !=
SVC_BICYCLE) {
1723 const bool foes = n.
foes(
this, con.
toEdge, i2, k2.toEdge);
1726 const bool avoidIntersectCandidate = !foes &&
bothLeftTurns(dir, i2, dir2);
1727 bool oppositeLeftIntersect = avoidIntersectCandidate &&
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2);
1732 && k2.customShape.size() == 0
1733 && (oppositeLeftIntersect || (avoidedIntersectingLeftOriginLane < con.
fromLane && avoidIntersectCandidate))
1734 && ((i2->getPermissions(k2.fromLane) & warn) != 0
1735 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0)) {
1741 oppositeLeftIntersect =
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2, shapeFlag);
1742 if (oppositeLeftIntersect
1747 if (avoidedIntersectingLeftOriginLane == std::numeric_limits<int>::max()
1748 || avoidedIntersectingLeftOriginLane < con.
fromLane) {
1751 const double minDV =
firstIntersection(shape, otherShape, width1OppositeLeft, width2,
1752 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1753 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1755 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1756 crossingPositions.first = minDV;
1762 avoidedIntersectingLeftOriginLane = con.
fromLane;
1768 const bool isBicycleLeftTurn = k2.indirectLeft || (dir2 ==
LinkDirection::LEFT && (i2->getPermissions(k2.fromLane) & k2.toEdge->getPermissions(k2.toLane)) ==
SVC_BICYCLE);
1771 crossingPositions.second.push_back(index);
1773 otherShapes.push_back(otherShape);
1776 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1777 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1779 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1780 crossingPositions.first = minDV;
1791 if (foes || rightTurnConflict || oppositeLeftIntersect || mergeConflict || indirectTurnConflit || bidiConflict) {
1792 foeInternalLinks.push_back(index);
1795 if (oppositeLeftIntersect &&
getID() > i2->getID()
1798 && (i2->getPermissions(k2.fromLane) & warn) != 0
1799 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0
1803 WRITE_WARNINGF(
TL(
"Intersecting left turns at junction '%' from lane '%' and lane '%' (increase junction radius to avoid this)."),
1808 if ((n.
forbids(i2, k2.toEdge,
this, con.
toEdge, signalised) || rightTurnConflict || indirectTurnConflit || mergeResponse)
1810 tmpFoeIncomingLanes.insert(i2->getID() +
"_" +
toString(k2.fromLane));
1812 if (bothPrio && oppositeLeftIntersect &&
getID() < i2->getID()) {
1816 tmpFoeIncomingLanes.insert(
":" +
toString(index));
1821 if (dir ==
LinkDirection::TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0 && shape.
length() > 2. * POSITION_EPS) {
1827 std::vector<NBNode::Crossing*> crossings = n.
getCrossings();
1828 for (
auto c : crossings) {
1830 for (EdgeVector::const_iterator it_e = crossing.
edges.begin(); it_e != crossing.
edges.end(); ++it_e) {
1831 const NBEdge* edge = *it_e;
1833 if ((
this == edge || con.
toEdge == edge) && !
isRailway(conPermissions)) {
1834 foeInternalLinks.push_back(index);
1835 if (con.
toEdge == edge &&
1841 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1843 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1844 crossingPositions.first = minDV;
1848 crossingPositions.first = 0;
1860 crossingPositions.first = -1;
1863 crossingPositions.first = con.
contPos;
1882 if (limitTurnSpeed > 0) {
1887 const double angle =
MAX2(0.0, angleRaw - (fromRail ? limitTurnSpeedMinAngleRail : limitTurnSpeedMinAngle));
1888 const double length = shape.
length2D();
1891 if (angle > 0 && length > 1) {
1894 const double limit = sqrt(limitTurnSpeed * radius);
1895 const double reduction = con.
vmax - limit;
1903 dirType =
"roundabout";
1905 WRITE_WARNINGF(
TL(
"Speed of % connection '%' reduced by % due to turning radius of % (length=%, angle=%)."),
1912 assert(con.
vmax > 0);
1927 assert(shape.size() >= 2);
1929 con.
id = innerID +
"_" +
toString(edgeIndex);
1930 const double shapeLength = shape.
length();
1931 double firstLength = shapeLength;
1932 if (crossingPositions.first > 0 && crossingPositions.first < shapeLength) {
1933 std::pair<PositionVector, PositionVector>
split = shape.
splitAt(crossingPositions.first);
1935 con.
foeIncomingLanes = std::vector<std::string>(tmpFoeIncomingLanes.begin(), tmpFoeIncomingLanes.end());
1937 con.
viaID = innerID +
"_" +
toString(splitIndex + noInternalNoSplits);
1946 ++internalLaneIndex;
1951 lengthSum += firstLength / shapeLength * con.
customLength;
1953 lengthSum += firstLength;
1965 double maxCross = 0.;
1967 for (
int prevIndex = 1; prevIndex <= numLanes; prevIndex++) {
1981 if (!averageLength) {
2002 double intersect = std::numeric_limits<double>::max();
2003 if (v2.
length() < POSITION_EPS) {
2020 bool skip = secondIntersection;
2026 intersect =
MIN2(intersect, cand);
2028 skip = secondIntersection;
2034 intersect =
MIN2(intersect, cand);
2036 skip = secondIntersection;
2042 intersect =
MIN2(intersect, cand);
2044 skip = secondIntersection;
2050 intersect =
MIN2(intersect, cand);
2066 if (otherFrom ==
this) {
2075 double width1,
double width2,
int shapeFlag)
const {
2078 return minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS;
2097 #ifdef DEBUG_JUNCTIONPRIO
2102 #ifdef DEBUG_JUNCTIONPRIO
2114 assert(atNode ==
myTo);
2125 assert(atNode ==
myTo);
2144 assert(atNode ==
myTo);
2152 if (!onlyPossible) {
2167 return myLanes[lane].friction;
2180 if (lane.changeLeft !=
SVCAll) {
2181 lane.changeLeft = ignoring;
2183 if (lane.changeRight !=
SVCAll) {
2184 lane.changeRight = ignoring;
2189 con.changeLeft = ignoring;
2192 con.changeRight = ignoring;
2205 std::vector<double> offsets(
myLanes.size(), 0.);
2207 for (
int i = (
int)
myLanes.size() - 2; i >= 0; --i) {
2209 offsets[i] = offset;
2213 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2219 offset = laneWidth / 2.;
2230 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2231 offsets[i] += offset;
2235 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2236 if (
myLanes[i].customShape.size() != 0) {
2272 if ((hasFromShape || hasToShape) &&
getNumLanes() > 0) {
2305 if (suspiciousFromShape) {
2306 std::cout <<
"suspiciousFromShape len=" << shape.
length() <<
" startA=" <<
myStartAngle <<
" startA2=" << myStartAngle2 <<
" startA3=" << myStartAngle3
2308 <<
" fromCenter=" << fromCenter
2310 <<
" refStart=" << referencePosStart
2313 if (suspiciousToShape) {
2314 std::cout <<
"suspiciousToShape len=" << shape.
length() <<
" endA=" <<
myEndAngle <<
" endA2=" << myEndAngle2 <<
" endA3=" << myEndAngle3
2316 <<
" toCenter=" << toCenter
2318 <<
" refEnd=" << referencePosEnd
2324 if (suspiciousFromShape && shape.
length() > 1) {
2335 if (suspiciousToShape && shape.
length() > 1) {
2349 <<
" fromCenter=" << fromCenter <<
" toCenter=" << toCenter
2350 <<
" refStart=" << referencePosStart <<
" refEnd=" << referencePosEnd <<
" shape=" << shape
2351 <<
" hasFromShape=" << hasFromShape
2352 <<
" hasToShape=" << hasToShape
2378 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2379 if ((*i).permissions !=
SVCAll) {
2389 std::vector<Lane>::const_iterator i =
myLanes.begin();
2392 for (; i !=
myLanes.end(); ++i) {
2393 if (i->permissions != firstLanePermissions) {
2403 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2413 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2414 if (i->friction !=
myLanes.begin()->friction) {
2423 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2424 if (i->width !=
myLanes.begin()->width) {
2434 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2435 if (i->type !=
myLanes.begin()->type) {
2445 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2446 if (i->endOffset !=
myLanes.begin()->endOffset) {
2456 for (
const auto& lane :
myLanes) {
2457 if (lane.laneStopOffset.isDefined()) {
2469 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2480 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2481 if (i->customShape.size() > 0) {
2491 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2492 if (i->getParametersMap().size() > 0) {
2502 if (lane.changeLeft !=
SVCAll || lane.changeRight !=
SVCAll) {
2528 #ifdef DEBUG_CONNECTION_GUESSING
2530 std::cout <<
"computeEdge2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
" noLeftMovers=" << noLeftMovers <<
"\n";
2532 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2535 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2550 if (fromRail &&
isRailway(out->getPermissions())) {
2554 }
else if (angle > 90) {
2562 if (radius < minRadius) {
2584 #ifdef DEBUG_CONNECTION_GUESSING
2586 std::cout <<
"computeLanes2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
"\n";
2588 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2591 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2617 std::vector<LinkDirection>
2619 std::vector<LinkDirection> result;
2620 for (
int i = 0; i < 8; i++) {
2622 if ((turnSigns & (1 << (i + shift))) != 0) {
2631 if (dirs.size() > 0) {
2632 if (std::find(dirs.begin(), dirs.end(), dir) == dirs.end()) {
2642 #ifdef DEBUG_TURNSIGNS
2643 std::cout <<
"applyTurnSigns edge=" <<
getID() <<
"\n";
2646 std::vector<const NBEdge*> targets;
2647 std::map<const NBEdge*, std::vector<int> > toLaneMap;
2649 if (
myLanes[c.fromLane].turnSigns != 0) {
2650 if (std::find(targets.begin(), targets.end(), c.toEdge) == targets.end()) {
2651 targets.push_back(c.toEdge);
2653 toLaneMap[c.toEdge].push_back(c.toLane);
2657 for (
auto& item : toLaneMap) {
2658 std::sort(item.second.begin(), item.second.end());
2662 std::map<LinkDirection, int> signCons;
2665 allDirs |= lane.turnSigns;
2675 targets.push_back(
nullptr);
2681 std::map<LinkDirection, const NBEdge*> dirMap;
2682 #ifdef DEBUG_TURNSIGNS
2683 std::cout <<
" numDirs=" << signedDirs.size() <<
" numTargets=" << targets.size() <<
"\n";
2685 if (signedDirs.size() > targets.size()) {
2686 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed directions but only % targets"),
getID(), signedDirs.size(), targets.size());
2688 }
else if (signedDirs.size() < targets.size()) {
2691 std::vector<LinkDirection> sumoDirs;
2692 for (
const NBEdge* to : targets) {
2696 bool checkMore =
true;
2697 while (signedDirs.size() < targets.size() && checkMore) {
2700 if (sumoDirs.back() != signedDirs.back()) {
2702 sumoDirs.pop_back();
2708 while (signedDirs.size() < targets.size() && checkMore) {
2710 if (sumoDirs.front() != signedDirs.front()) {
2711 targets.erase(targets.begin());
2712 sumoDirs.erase(sumoDirs.begin());
2718 while (signedDirs.size() < targets.size() && i < (
int)targets.size()) {
2719 if (targets[i] !=
nullptr && (targets[i]->
getPermissions() & defaultPermissions) == 0) {
2720 targets.erase(targets.begin() + i);
2721 sumoDirs.erase(sumoDirs.begin() + i);
2726 if (signedDirs.size() != targets.size()) {
2727 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed directions and % targets (after target pruning)"),
getID(), signedDirs.size(), targets.size());
2732 for (
int i = 0; i < (int)signedDirs.size(); i++) {
2733 dirMap[signedDirs[i]] = targets[i];
2736 for (
auto item : signCons) {
2741 const NBEdge* to = dirMap[dir];
2743 if (candidates == 0) {
2744 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because the target edge '%' has no suitable lanes"),
getID(), to->
getID());
2747 std::vector<int>& knownTargets = toLaneMap[to];
2748 if ((
int)knownTargets.size() < item.second) {
2749 if (candidates < item.second) {
2750 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed connections with directions '%' but target edge '%' has only % suitable lanes"),
2768 while ((
int)knownTargets.size() < item.second && i != iEnd) {
2770 if (std::find(knownTargets.begin(), knownTargets.end(), i) == knownTargets.end()) {
2771 knownTargets.push_back(i);
2776 if ((
int)knownTargets.size() != item.second) {
2777 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because not enough target lanes could be determined for direction '%'"),
getID(),
toString(dir));
2780 std::sort(knownTargets.begin(), knownTargets.end());
2783 std::map<const NBEdge*, int> toLaneIndex;
2785 const int turnSigns =
myLanes[i].turnSigns;
2787 if (turnSigns != 0) {
2790 if (it->fromLane == i) {
2797 int allSigns = (turnSigns
2817 if (to !=
nullptr) {
2818 if (toLaneIndex.count(to) == 0) {
2825 int toLane = toLaneMap[to][0];
2838 #ifdef DEBUG_TURNSIGNS
2839 std::cout <<
" target=" << to->
getID() <<
" initial toLane=" << toLane <<
"\n";
2841 toLaneIndex[to] = toLane;
2849 if (toLaneIndex[to] < to->getNumLanes() - 1) {
2864 #ifdef DEBUG_CONNECTION_GUESSING
2866 std::cout <<
"recheckLanes (initial) edge=" <<
getID() <<
"\n";
2868 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2871 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2879 std::vector<int> connNumbersPerLane(
myLanes.size(), 0);
2881 if ((*i).toEdge ==
nullptr || (*i).fromLane < 0 || (*i).toLane < 0) {
2884 if ((*i).fromLane >= 0) {
2885 ++connNumbersPerLane[(*i).fromLane];
2891 #ifdef DEBUG_TURNSIGNS
2892 if (
myLanes.back().turnSigns != 0) {
2893 std::cout <<
getID() <<
" hasTurnSigns\n";
2905 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2908 bool hasDeadEnd =
true;
2910 for (
int i2 = i - 1; hasDeadEnd && i2 >= 0; i2--) {
2914 if (connNumbersPerLane[i2] > 1) {
2915 connNumbersPerLane[i2]--;
2916 for (
int i3 = i2; i3 != i; i3++) {
2926 for (
int i2 = i + 1; hasDeadEnd && i2 <
getNumLanes(); i2++) {
2930 if (connNumbersPerLane[i2] > 1) {
2931 connNumbersPerLane[i2]--;
2932 for (
int i3 = i2; i3 != i; i3--) {
2942 int passengerLanes = 0;
2943 int passengerTargetLanes = 0;
2951 for (
const Lane& lane : out->getLanes()) {
2953 passengerTargetLanes++;
2958 if (passengerLanes > 0 && passengerLanes <= passengerTargetLanes) {
2963 if (rightCons.size() > 0) {
2966 int toLane = rc.
toLane + 1;
2995 if (leftCons.size() > 0) {
2996 NBEdge* to = leftCons.front().toEdge;
2997 int toLane = leftCons.front().toLane - 1;
3008 #ifdef ADDITIONAL_WARNINGS
3024 }
else if (common == 0) {
3027 const int origToLane = c.
toLane;
3029 int toLane = origToLane;
3042 toLane = origToLane;
3074 if (incoming.size() > 1) {
3075 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3077 bool connected =
false;
3078 for (std::vector<NBEdge*>::const_iterator in = incoming.begin(); in != incoming.end(); ++in) {
3079 if ((*in)->hasConnectionTo(
this, i)) {
3093 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3095 if ((connNumbersPerLane[i] == 0 || ((lane.
accelRamp || (i > 0 &&
myLanes[i - 1].accelRamp && connNumbersPerLane[i - 1] > 0))
3100 if (forbiddenLeft && (i == 0 || forbiddenRight)) {
3103 }
else if (forbiddenRight && (i ==
getNumLanes() - 1 || (i > 0 &&
myLanes[i - 1].accelRamp))) {
3110 #ifdef ADDITIONAL_WARNINGS
3117 bool hasAlternative =
false;
3119 if (c.fromLane == c2.fromLane && c.toEdge == c2.toEdge
3120 && (c.toEdge->getPermissions(c2.toLane) &
SVC_PASSENGER) != 0) {
3121 hasAlternative =
true;
3124 if (!hasAlternative) {
3125 WRITE_WARNING(
"Road lane ends on bikeLane for connection " + c.getDescription(
this));
3131 #ifdef DEBUG_CONNECTION_GUESSING
3133 std::cout <<
"recheckLanes (final) edge=" <<
getID() <<
"\n";
3135 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
3145 if (outgoing->size() == 0) {
3151 #ifdef DEBUG_CONNECTION_GUESSING
3153 std::cout <<
" divideOnEdges " <<
getID() <<
" outgoing=" <<
toString(*outgoing) <<
"\n";
3158 std::vector<int> availableLanes;
3159 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3161 availableLanes.push_back(i);
3164 if (availableLanes.size() > 0) {
3168 availableLanes.clear();
3169 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3174 availableLanes.push_back(i);
3176 if (availableLanes.size() > 0) {
3180 availableLanes.clear();
3181 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3186 availableLanes.push_back(i);
3188 if (availableLanes.size() > 0) {
3192 availableLanes.clear();
3193 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3198 availableLanes.push_back(i);
3200 if (availableLanes.size() > 0) {
3204 bool explicitTurnaround =
false;
3207 if ((*i).fromLane == -1) {
3209 explicitTurnaround =
true;
3210 turnaroundPermissions = (*i).permissions;
3214 if (c.toLane == -1 && c.toEdge == (*i).toEdge) {
3216 c.permissions = (*i).permissions;
3225 if (explicitTurnaround) {
3236 if (priorities.empty()) {
3239 #ifdef DEBUG_CONNECTION_GUESSING
3241 std::cout <<
"divideSelectedLanesOnEdges " <<
getID() <<
" out=" <<
toString(*outgoing) <<
" prios=" <<
toString(priorities) <<
" avail=" <<
toString(availableLanes) <<
"\n";
3245 const int numOutgoing = (int)outgoing->size();
3246 std::vector<int> resultingLanesFactor;
3247 resultingLanesFactor.reserve(numOutgoing);
3248 int minResulting = std::numeric_limits<int>::max();
3249 for (
int i = 0; i < numOutgoing; i++) {
3251 const int res = priorities[i] * (int)availableLanes.size();
3252 resultingLanesFactor.push_back(res);
3253 if (minResulting > res && res > 0) {
3265 transition.reserve(numOutgoing);
3266 for (
int i = 0; i < numOutgoing; i++) {
3268 assert(i < (
int)resultingLanesFactor.size());
3269 const int tmpNum = (resultingLanesFactor[i] + minResulting - 1) / minResulting;
3270 numVirtual += tmpNum;
3271 for (
int j = 0; j < tmpNum; j++) {
3272 transition.push_back((*outgoing)[i]);
3275 #ifdef DEBUG_CONNECTION_GUESSING
3277 std::cout <<
" minResulting=" << minResulting <<
" numVirtual=" << numVirtual <<
" availLanes=" <<
toString(availableLanes) <<
" resLanes=" <<
toString(resultingLanesFactor) <<
" transition=" <<
toString(transition) <<
"\n";
3286 for (
NBEdge*
const target : *outgoing) {
3287 assert(l2eConns.find(target) != l2eConns.end());
3288 for (
const int j : l2eConns.find(target)->second) {
3289 const int fromIndex = availableLanes[j];
3290 if ((
getPermissions(fromIndex) & target->getPermissions()) == 0) {
3304 int targetLanes = target->getNumLanes();
3308 if (numConsToTarget >= targetLanes) {
3311 if (
myLanes[fromIndex].connectionsDone) {
3314 #ifdef DEBUG_CONNECTION_GUESSING
3316 std::cout <<
" connectionsDone from " <<
getID() <<
"_" << fromIndex <<
": ";
3318 std::cout << c.getDescription(
this) <<
", ";
3326 #ifdef DEBUG_CONNECTION_GUESSING
3328 std::cout <<
" request connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->getID() <<
"\n";
3341 const int numOutgoing = (int) outgoing->size();
3342 NBEdge* target =
nullptr;
3343 NBEdge* rightOfTarget =
nullptr;
3344 NBEdge* leftOfTarget =
nullptr;
3346 for (
int i = 0; i < numOutgoing; i++) {
3347 if (maxPrio < priorities[i]) {
3350 maxPrio = priorities[i];
3351 target = (*outgoing)[i];
3352 rightOfTarget = i == 0 ? outgoing->back() : (*outgoing)[i - 1];
3353 leftOfTarget = i + 1 == numOutgoing ? outgoing->front() : (*outgoing)[i + 1];
3357 if (target ==
nullptr) {
3365 const int numDesiredConsToTarget =
MIN2(targetLanes, (
int)availableLanes.size());
3366 #ifdef DEBUG_CONNECTION_GUESSING
3368 std::cout <<
" checking extra lanes for target=" << target->
getID() <<
" cons=" << numConsToTarget <<
" desired=" << numDesiredConsToTarget <<
"\n";
3371 std::vector<int>::const_iterator it_avail = availableLanes.begin();
3372 while (numConsToTarget < numDesiredConsToTarget && it_avail != availableLanes.end()) {
3373 const int fromIndex = *it_avail;
3382 && !
myLanes[fromIndex].connectionsDone
3384 #ifdef DEBUG_CONNECTION_GUESSING
3386 std::cout <<
" candidate from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3395 #ifdef DEBUG_CONNECTION_GUESSING
3397 std::cout <<
" request additional connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3403 #ifdef DEBUG_CONNECTION_GUESSING
3408 <<
" rightOfTarget=" << rightOfTarget->
getID()
3409 <<
" leftOfTarget=" << leftOfTarget->
getID()
3420 const std::vector<int>
3422 std::vector<int> priorities;
3429 priorities.reserve(outgoing->size());
3430 for (
const NBEdge*
const out : *outgoing) {
3432 assert((prio + 1) * 2 > 0);
3433 prio = (prio + 1) * 2;
3434 priorities.push_back(prio);
3439 #ifdef DEBUG_CONNECTION_GUESSING
3441 <<
" outgoing=" <<
toString(*outgoing)
3442 <<
" priorities1=" <<
toString(priorities)
3447 assert(priorities.size() > 0);
3449 #ifdef DEBUG_CONNECTION_GUESSING
3451 std::cout <<
" priorities2=" <<
toString(priorities) <<
"\n";
3458 if (mainDirections.
empty()) {
3459 assert(dist < (
int)priorities.size());
3460 priorities[dist] *= 2;
3461 #ifdef DEBUG_CONNECTION_GUESSING
3463 std::cout <<
" priorities3=" <<
toString(priorities) <<
"\n";
3468 priorities[dist] += 1;
3473 priorities[(int)priorities.size() - 1] /= 2;
3474 #ifdef DEBUG_CONNECTION_GUESSING
3476 std::cout <<
" priorities6=" <<
toString(priorities) <<
"\n";
3480 && outgoing->size() > 2
3481 && availableLanes.size() == 2
3482 && (*outgoing)[dist]->getPriority() == (*outgoing)[0]->getPriority()) {
3484 priorities.back() /= 2;
3485 #ifdef DEBUG_CONNECTION_GUESSING
3487 std::cout <<
" priorities7=" <<
toString(priorities) <<
"\n";
3494 priorities[dist] *= 2;
3495 #ifdef DEBUG_CONNECTION_GUESSING
3497 std::cout <<
" priorities4=" <<
toString(priorities) <<
"\n";
3501 priorities[dist] *= 3;
3502 #ifdef DEBUG_CONNECTION_GUESSING
3504 std::cout <<
" priorities5=" <<
toString(priorities) <<
"\n";
3514 NBEdge::appendTurnaround(
bool noTLSControlled,
bool noFringe,
bool onlyDeadends,
bool onlyTurnlane,
bool noGeometryLike,
bool checkPermissions) {
3527 bool isDeadEnd =
true;
3529 if ((c.toEdge->getPermissions(c.toLane)
3537 if (onlyDeadends && !isDeadEnd) {
3550 if (checkPermissions) {
3574 if (noGeometryLike && !isDeadEnd) {
3583 if (turnIncoming.size() > 1) {
3609 if (pos < tolerance) {
3623 for (
int i = 0; i < lanes; i++) {
3625 assert(el.tlID ==
"");
3647 if (c.fromLane == fromLane && c.toEdge == toEdge && c.toLane == toLane && c.uncontrolled) {
3667 assert(fromLane < 0 || fromLane < (
int)
myLanes.size());
3669 if (fromLane >= 0 && toLane >= 0) {
3671 std::vector<Connection>::iterator i =
3679 connection.
tlID = tlID;
3688 bool hadError =
false;
3690 if ((*i).toEdge != toEdge) {
3693 if (fromLane >= 0 && fromLane != (*i).fromLane) {
3696 if (toLane >= 0 && toLane != (*i).toLane) {
3699 if ((*i).tlID ==
"") {
3701 (*i).tlLinkIndex = tlIndex;
3702 (*i).tlLinkIndex2 = tlIndex2;
3705 if ((*i).tlID != tlID && (*i).tlLinkIndex == tlIndex) {
3706 WRITE_WARNINGF(
TL(
"The lane '%' on edge '%' already had a traffic light signal."), i->fromLane,
getID());
3711 if (hadError && no == 0) {
3712 WRITE_WARNINGF(
TL(
"Could not set any signal of the tlLogic '%' (unknown group)."), tlID);
3737 ret =
myLanes[lane].shape.reverse();
3755 ret =
myLanes[lane].shape.reverse();
3766 reason =
"laneNumber";
3776 reason =
"bidi-rail";
3790 if (find(conn.begin(), conn.end(), possContinuation) == conn.end()) {
3791 reason =
"disconnected";
3802 reason =
"disconnected";
3808 if (conns.size() <
myLanes.size() - offset) {
3809 reason =
"some lanes disconnected";
3822 if (maxJunctionSize >= 0) {
3823 const double junctionSize =
myGeom.back().distanceTo2D(possContinuation->
myGeom.front());
3824 if (junctionSize > maxJunctionSize + POSITION_EPS) {
3825 reason =
"junction size (" +
toString(junctionSize) +
") > max-junction-size (" +
toString(maxJunctionSize) +
")";
3831 reason =
"priority";
3841 reason =
"spreadType";
3845 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3847 reason =
"lane " +
toString(i) +
" speed";
3849 }
else if (
myLanes[i].permissions != possContinuation->
myLanes[i].permissions) {
3850 reason =
"lane " +
toString(i) +
" permissions";
3852 }
else if (
myLanes[i].changeLeft != possContinuation->
myLanes[i].changeLeft ||
myLanes[i].changeRight != possContinuation->
myLanes[i].changeRight) {
3853 reason =
"lane " +
toString(i) +
" change restrictions";
3855 }
else if (
myLanes[i].width != possContinuation->
myLanes[i].width &&
3857 reason =
"lane " +
toString(i) +
" width";
3878 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3884 if (origID != origID2) {
3894 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3928 if ((*i).toEdge == e && (*i).tlID !=
"") {
3954 assert(distances.size() > 0);
3960 NBEdge::addLane(
int index,
bool recomputeShape,
bool recomputeConnections,
bool shiftIndices) {
3961 assert(index <= (
int)
myLanes.size());
3965 int templateIndex = index > 0 ? index - 1 : index + 1;
3975 if (recomputeShape) {
3978 if (recomputeConnections) {
3979 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
3980 (*i)->invalidateConnections(
true);
3983 }
else if (shiftIndices) {
3986 if (c.fromLane >= index) {
4005 int newLaneNo = (int)
myLanes.size() + by;
4006 while ((
int)
myLanes.size() < newLaneNo) {
4016 assert(index < (
int)
myLanes.size());
4021 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
4022 (*i)->invalidateConnections(
true);
4025 }
else if (shiftIndices) {
4028 inc->removeFromConnections(
this, -1, index,
false,
true);
4036 int newLaneNo = (int)
myLanes.size() - by;
4037 assert(newLaneNo > 0);
4038 while ((
int)
myLanes.size() > newLaneNo) {
4056 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4060 assert(lane < (
int)
myLanes.size());
4061 myLanes[lane].permissions |= vclass;
4069 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4073 assert(lane < (
int)
myLanes.size());
4074 myLanes[lane].permissions &= ~vclass;
4082 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4086 assert(lane < (
int)
myLanes.size());
4087 myLanes[lane].permissions |= vclasses;
4088 myLanes[lane].preferred |= vclasses;
4098 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4104 assert(lane < (
int)
myLanes.size());
4111 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4117 assert(lane < (
int)
myLanes.size());
4148 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4171 return myLanes[lane].laneStopOffset;
4181 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4187 assert(lane < (
int)
myLanes.size());
4188 myLanes[lane].endOffset = offset;
4206 }
else if (lane < (
int)
myLanes.size()) {
4207 if (!
myLanes[lane].laneStopOffset.isDefined() || overwrite) {
4212 myLanes[lane].laneStopOffset = offset;
4227 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4233 assert(lane < (
int)
myLanes.size());
4243 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4249 assert(lane < (
int)
myLanes.size());
4250 myLanes[lane].friction = friction;
4257 assert(lane < (
int)
myLanes.size());
4258 myLanes[lane].accelRamp = accelRamp;
4265 assert(lane < (
int)
myLanes.size());
4266 myLanes[lane].customShape = shape;
4273 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4278 assert(lane < (
int)
myLanes.size());
4279 myLanes[lane].permissions = permissions;
4287 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4292 assert(lane < (
int)
myLanes.size());
4293 myLanes[lane].preferred = permissions;
4301 assert(lane < (
int)
myLanes.size());
4302 myLanes[lane].changeLeft = changeLeft;
4303 myLanes[lane].changeRight = changeRight;
4311 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4316 assert(lane < (
int)
myLanes.size());
4317 return myLanes[lane].permissions;
4335 for (std::vector<Lane>::iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
4336 (*i).permissions =
SVCAll;
4372 for (
int i = start; i != end; i += direction) {
4388 for (
int i = start; i != end; i += direction) {
4402 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4403 if (
myLanes[i].permissions == permissions) {
4415 for (
int i = start; i != end; i += direction) {
4416 if (
myLanes[i].permissions != 0) {
4420 return end - direction;
4424 std::set<SVCPermissions>
4426 std::set<SVCPermissions> result;
4430 for (
int i = iStart; i < iEnd; ++i) {
4440 if ((allPermissions && (lane.permissions & permissions) == permissions)
4441 || (!allPermissions && (lane.permissions & permissions) != 0)) {
4470 std::cout <<
getID() <<
" angle=" <<
getAngleAtNode(node) <<
" convAngle=" << angle <<
"\n";
4488 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4493 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4527 if (lane.permissions == vclass) {
4548 if (newIndex == 0) {
4554 myLanes[newIndex].permissions = vclass;
4555 myLanes[newIndex].width = fabs(width);
4565 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4566 (*it)->shiftToLanesToEdge(
this, 1);
4577 if (
myLanes[0].permissions != vclass) {
4587 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4588 (*it)->shiftToLanesToEdge(
this, 0);
4601 if ((*it).toEdge == to && (*it).toLane >= 0) {
4602 (*it).toLane += laneOff;
4611 const int i = (node ==
myTo ? -1 : 0);
4612 const int i2 = (node ==
myTo ? 0 : -1);
4617 const double neededOffset2 = neededOffset + (other->
getTotalWidth()) / 2;
4618 if (dist < neededOffset && dist2 < neededOffset2) {
4653 double avgEndOffset = 0;
4655 avgEndOffset += lane.endOffset;
4660 avgEndOffset /= (double)
myLanes.size();
4661 return MAX2(result - avgEndOffset, POSITION_EPS);
4667 if (laneIdx == -1) {
4668 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4675 if (std::find(oldIDs.begin(), oldIDs.end(), origID) == oldIDs.end()) {
4676 oldIDs.push_back(origID);
4696 if (con.fromLane >= 0 && con.toLane >= 0 && con.toEdge !=
nullptr &&
4698 & con.toEdge->getPermissions(con.toLane) & vClass) != 0)
4713 std::pair<const NBEdge*, const Connection*> pair(con.toEdge,
nullptr);
4717 }
else if ((con.fromLane >= 0) && (con.toLane >= 0) &&
4718 (con.toEdge !=
nullptr) &&
4719 ((
getPermissions(con.fromLane) & con.toEdge->getPermissions(con.toLane) & vClass) == vClass)) {
4721 if (con.getLength() > 0) {
4735 std::cout <<
" " <<
getID() <<
"_" << c.fromLane <<
"->" << c.toEdge->getID() <<
"_" << c.toLane <<
"\n";
4757 bool haveJoined =
false;
4762 const std::string newType =
myLanes[i].type +
"|" +
myLanes[i + 1].type;
4778 for (
NBEdge* edge : edges) {
4779 if ((edge->getPermissions() & permissions) != 0) {
4780 result.push_back(edge);
4789 if (cands.size() == 0) {
4793 NBEdge* best = cands.front();
4804 if (cands.size() == 0) {
4808 NBEdge* best = cands.front();
4819 NBEdge* opposite =
nullptr;
4825 if (cand->getToNode() ==
getFromNode() && !cand->getLanes().empty()) {
4826 const double lastWidthCand = cand->getLaneWidth(cand->getNumLanes() - 1);
4829 const double threshold = 1.42 * 0.5 * (lastWidth + lastWidthCand) + 0.5;
4832 if (distance < threshold) {
4837 if (opposite !=
nullptr) {
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGEF(...)
#define WRITE_WARNING(msg)
std::vector< std::pair< const NBRouterEdge *, const NBRouterEdge * > > ConstRouterEdgePairVector
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
KeepClear
keepClear status of connections
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
bool isBikepath(SVCPermissions permissions)
Returns whether an edge with the given permission is a bicycle edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ 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_DELIVERY
vehicle is a small delivery vehicle
@ SVC_TRAM
vehicle is a light rail
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
@ RIGHT
At the rightmost side of the lane.
const std::string SUMO_PARAM_ORIGID
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
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.
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link)
int gPrecision
the precision for floating point outputs
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static void compute(BresenhamCallBack *callBack, const int val1, const int val2)
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
static double legacyDegree(const double angle, const bool positive=false)
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
int getFromLane() const
returns the from-lane
int getTLIndex() const
returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled
void shiftLaneIndex(NBEdge *edge, int offset, int threshold=-1)
patches lane indices refering to the given edge and above the threshold by the given offset
int getToLane() const
returns the to-lane
NBEdge * getTo() const
returns the to-edge (end of the connection)
Holds (- relative to the edge it is build from -!!!) the list of main directions a vehicle that drive...
bool empty() const
returns the information whether no following street has a higher priority
bool includes(Direction d) const
returns the information whether the street in the given direction has a higher priority
int getStraightest() const
returns the index of the straightmost among the given outgoing edges
MainDirections(const EdgeVector &outgoing, NBEdge *parent, NBNode *to, const std::vector< int > &availableLanes)
constructor
std::vector< Direction > myDirs
list of the main direction within the following junction relative to the edge
~MainDirections()
destructor
int myStraightest
the index of the straightmost among the given outgoing edges
Direction
enum of possible directions
A class that being a bresenham-callback assigns the incoming lanes to the edges.
void execute(const int lane, const int virtEdge)
executes a bresenham - step
const std::map< NBEdge *, std::vector< int > > & getBuiltConnections() const
get built connections
Class to sort edges by their angle.
int operator()(const Connection &c1, const Connection &c2) const
comparing operation
The representation of a single edge during network building.
void reinit(NBNode *from, NBNode *to, const std::string &type, double speed, double friction, int nolanes, int priority, PositionVector geom, double width, double endOffset, const std::string &streetName, LaneSpreadFunction spread, bool tryIgnoreNodePositions=false)
Resets initial values.
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
static std::vector< LinkDirection > decodeTurnSigns(int turnSigns, int shift=0)
decode bitset
void mirrorX()
mirror coordinates along the x-axis
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
static const int TURN_SIGN_SHIFT_BUS
shift values for decoding turn signs
double getLaneSpeed(int lane) const
get lane speed
static const int TURN_SIGN_SHIFT_BICYCLE
NBEdge * guessOpposite(bool reguess=false)
set oppositeID and return opposite edge if found
void setPermittedChanging(int lane, SVCPermissions changeLeft, SVCPermissions changeRight)
set allowed classes for changing to the left and right from the given lane
double getLength() const
Returns the computed length of the edge.
double myLaneWidth
This width of this edge's lanes.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
std::vector< Connection > myConnectionsToDelete
List of connections marked for delayed removal.
const EdgeVector * getConnectedSorted()
Returns the list of outgoing edges without the turnaround sorted in clockwise direction.
double getDistancAt(double pos) const
get distance at the given offset
double myEndOffset
This edges's offset to the intersection begin (will be applied to all lanes)
int myToJunctionPriority
The priority normalised for the node the edge is incoming in.
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
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
void addBikeLane(double width)
add a bicycle lane of the given width and shift existing connctions
bool expandableBy(NBEdge *possContinuation, std::string &reason) const
Check if Node is expandable.
double getLaneFriction(int lane) const
get lane friction of specified lane
const ConstRouterEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges for the given vClass.
void init(int noLanes, bool tryIgnoreNodePositions, const std::string &origID)
Initialization routines common to all constructors.
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
double mySpeed
The maximal speed.
bool hasLaneSpecificFriction() const
whether lanes differ in friction
double getLaneWidth() const
Returns the default width of lanes of this edge.
PositionVector getCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going clock-wise around the given node
std::vector< Connection > myConnections
List of connections to following edges.
Connection & getConnectionRef(int fromLane, const NBEdge *to, int toLane)
Returns reference to the specified connection This method goes through "myConnections" and returns th...
NBEdge()
constructor for dummy edge
void divideOnEdges(const EdgeVector *outgoing)
divides the lanes on the outgoing edges
ConstRouterEdgePairVector myViaSuccessors
PositionVector getCCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going counter-clock-wise around the given node
double buildInnerEdges(const NBNode &n, int noInternalNoSplits, int &linkIndex, int &splitIndex)
static const double UNSPECIFIED_FRICTION
unspecified lane friction
void incLaneNo(int by)
increment lane
static EdgeVector filterByPermissions(const EdgeVector &edges, SVCPermissions permissions)
return only those edges that permit at least one of the give permissions
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
const std::string & getStreetName() const
Returns the street name of this edge.
void addLane(int index, bool recomputeShape, bool recomputeConnections, bool shiftIndices)
add lane
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
void setAverageLengthWithOpposite(double val)
patch average lane length in regard to the opposite edge
void disallowVehicleClass(int lane, SUMOVehicleClass vclass)
set disallowed class for the given lane or for all lanes if -1 is given
double getShapeStartAngle() const
Returns the angle at the start of the edge.
static const int UNSPECIFIED_INTERNAL_LANE_INDEX
internal lane computation not yet done
void appendTurnaround(bool noTLSControlled, bool noFringe, bool onlyDeadends, bool onlyTurnlane, bool noGeometryLike, bool checkPermissions)
Add a connection to the previously computed turnaround, if wished and a turning direction exists (myT...
static bool connections_sorter(const Connection &c1, const Connection &c2)
connections_sorter sort by fromLane, toEdge and toLane
std::string myType
The type of the edge.
bool hasPermissions() const
whether at least one lane has restrictions
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
std::string myTurnSignTarget
node for which turnSign information applies
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
static const bool UNSPECIFIED_CONNECTION_UNCONTROLLED
TLS-controlled despite its node controlled not specified.
const EdgeVector & getSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges for the given vClass.
void dismissVehicleClassInformation()
dimiss vehicle class information
bool computeEdge2Edges(bool noLeftMovers)
computes the edge (step1: computation of approached edges)
EdgeBuildingStep getStep() const
The building step of this edge.
LaneSpreadFunction myLaneSpreadFunction
The information about how to spread the lanes.
void moveConnectionToLeft(int lane)
void updateChangeRestrictions(SVCPermissions ignoring)
modify all existing restrictions on lane changing
void restoreBikelane(std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore an previously added BikeLane
Position getEndpointAtNode(const NBNode *node) const
NBEdge * getStraightContinuation(SVCPermissions permissions) const
return the straightest follower edge for the given permissions or nullptr (never returns turn-arounds...
bool hasLoadedLength() const
Returns whether a length was set explicitly.
void restoreSidewalk(std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore an previously added sidewalk
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false, SVCPermissions permission=SVC_UNSPECIFIED)
Adds a connection to another edge.
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, 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, const bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
void divideSelectedLanesOnEdges(const EdgeVector *outgoing, const std::vector< int > &availableLanes)
divide selected lanes on edges
bool setEdgeStopOffset(int lane, const StopOffset &offset, bool overwrite=false)
set lane and vehicle class specific stopOffset (negative lane implies set for all lanes)
bool hasLaneSpecificStopOffsets() const
whether lanes differ in stopOffsets
void setNodeBorder(const NBNode *node, const Position &p, const Position &p2, bool rectangularCut)
Set Node border.
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
const std::string & getID() const
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
void shiftToLanesToEdge(NBEdge *to, int laneOff)
modifify the toLane for all connections to the given edge
void checkGeometry(const double maxAngle, const double minRadius, bool fix, bool silent)
Check the angles of successive geometry segments.
static double myDefaultConnectionLength
bool isNearEnough2BeJoined2(NBEdge *e, double threshold) const
Check if edge is near enought to be joined to another edge.
EdgeBuildingStep myStep
The building step.
NBNode * getToNode() const
Returns the destination node of the edge.
void setLaneType(int lane, const std::string &type)
set lane specific type (negative lane implies set for all lanes)
bool computeLanes2Edges()
computes the edge, step2: computation of which lanes approach the edges)
EdgeBuildingStep
Current state of the edge within the building process.
@ INIT_REJECT_CONNECTIONS
The edge has been loaded and connections shall not be added.
@ EDGE2EDGES
The relationships between edges are computed/loaded.
@ 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.
@ INIT
The edge has been loaded, nothing is computed yet.
NBEdge * getStraightPredecessor(SVCPermissions permissions) const
return the straightest predecessor edge for the given permissions or nullptr (never returns turn-arou...
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.
int getFirstAllowedLaneIndex(int direction) const
return the first lane that permits at least 1 vClass or the last lane if search direction of there is...
bool allowsChangingRight(int lane, SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
void resetLaneShapes()
reset lane shapes to what they would be before cutting with the junction shapes
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
bool bothLeftTurns(LinkDirection dir, const NBEdge *otherFrom, LinkDirection dir2) const
determine conflict between opposite left turns
void setAcceleration(int lane, bool accelRamp)
marks one lane as acceleration lane
const StopOffset & getEdgeStopOffset() const
Returns the stopOffset to the end of the edge.
NBNode * tryGetNodeAtPosition(double pos, double tolerance=5.0) const
Returns the node at the given edges length (using an epsilon)
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
void clearControllingTLInformation()
clears tlID for all connections
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
void addStraightConnections(const EdgeVector *outgoing, const std::vector< int > &availableLanes, const std::vector< int > &priorities)
add some straight connections
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
bool needsLaneSpecificOutput() const
whether at least one lane has values differing from the edges values
void computeAngle()
computes the angle of this edge and stores it in myAngle
bool isBidiEdge(bool checkPotential=false) const
whether this edge is part of a bidirectional edge pair
static const double UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
void addSidewalk(double width)
add a pedestrian sidewalk of the given width and shift existing connctions
bool hasSignalisedConnectionTo(const NBEdge *const e) const
Check if edge has signalised connections.
std::vector< Lane > myLanes
Lane information.
int getNumLanes() const
Returns the number of lanes.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
bool hasAccelLane() const
whether one of the lanes is an acceleration lane
bool myIsBidi
whether this edge is part of a non-rail bidi edge pair
static double firstIntersection(const PositionVector &v1, const PositionVector &v2, double width1, double width2, const std::string &error="", bool secondIntersection=false)
compute the first intersection point between the given lane geometries considering their rspective wi...
PositionVector myToBorder
void extendGeometryAtNode(const NBNode *node, double maxExtent)
linearly extend the geometry at the given node
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
static const double ANGLE_LOOKAHEAD
the distance at which to take the default angle
int getNumLanesThatAllow(SVCPermissions permissions, bool allPermissions=true) const
void reduceGeometry(const double minDist)
Removes points with a distance lesser than the given.
static NBEdge DummyEdge
Dummy edge to use when a reference must be supplied in the no-arguments constructor (FOX technicality...
bool joinLanes(SVCPermissions perms)
join adjacent lanes with the given permissions
void resetNodeBorder(const NBNode *node)
void markAsInLane2LaneState()
mark edge as in lane to state lane
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
return true if certain connection must be controlled by TLS
void addRestrictedLane(double width, SUMOVehicleClass vclass)
add a lane of the given width, restricted to the given class and shift existing connections
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
double myLength
The length of the edge.
NBEdge::Lane getFirstNonPedestrianLane(int direction) const
@brif get first non-pedestrian lane
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
const std::vector< int > prepareEdgePriorities(const EdgeVector *outgoing, const std::vector< int > &availableLanes)
recomputes the edge priorities and manipulates them for a distribution of lanes on edges which is mor...
int myIndex
the index of the edge in the list of all edges. Set by NBEdgeCont and requires re-set whenever the li...
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
PositionVector cutAtIntersection(const PositionVector &old) const
cut shape at the intersection shapes
Position geometryPositionAtOffset(double offset) const
return position taking into account loaded length
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
bool canMoveConnection(const Connection &con, int newFromLane) const
whether the connection can originate on newFromLane
double getInternalLaneWidth(const NBNode &node, const NBEdge::Connection &connection, const NBEdge::Lane &successor, bool isVia) const
Returns the width of the internal lane associated with the connection.
void allowVehicleClass(int lane, SUMOVehicleClass vclass)
set allowed class for the given lane or for all lanes if -1 is given
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)
double getMaxLaneOffset()
get max lane offset
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
NBEdge * myPossibleTurnDestination
The edge that would be the turn destination if there was one.
const PositionVector & getNodeBorder(const NBNode *node) const
const NBNode * mySignalNode
bool hasLaneSpecificWidth() const
whether lanes differ in width
void moveConnectionToRight(int lane)
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
void reshiftPosition(double xoff, double yoff)
Applies an offset to the edge.
static const int TURN_SIGN_SHIFT_TAXI
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
std::string getLaneID(int lane) const
get lane ID
bool myIsOffRamp
whether this edge is an Off-Ramp or leads to one
static const double UNSPECIFIED_SPEED
unspecified lane speed
Lane2LaneInfoType
Modes of setting connections between lanes.
@ USER
The connection was given by the user.
@ VALIDATED
The connection was computed and validated.
@ COMPUTED
The connection was computed.
double getFriction() const
Returns the friction on this edge.
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.
void computeLaneShapes()
compute lane shapes
const NBEdge * getBidiEdge() const
double getAngleAtNodeToCenter(const NBNode *const node) const
Returns the angle of from the node shape center to where the edge meets the node shape.
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.
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
double myDistance
The mileage/kilometrage at the start of this edge in a linear coordination system.
bool myAmMacroscopicConnector
Information whether this edge is a (macroscopic) connector.
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
void setLaneShape(int lane, const PositionVector &shape)
sets a custom lane shape
double myLoadedLength
An optional length to use (-1 if not valid)
static void updateTurnPermissions(SVCPermissions &perm, LinkDirection dir, SVCPermissions spec, std::vector< LinkDirection > dirs)
void sortOutgoingConnectionsByAngle()
sorts the outgoing connections by their angle relative to their junction
bool applyTurnSigns()
apply loaded turn sign information
bool haveIntersection(const NBNode &n, const PositionVector &shape, const NBEdge *otherFrom, const NBEdge::Connection &otherCon, int numPoints, double width1, double width2, int shapeFlag=0) const
void preferVehicleClass(int lane, SVCPermissions vclasses)
prefer certain vehicle classes for the given lane or for all lanes if -1 is given (ensures also permi...
double myStartAngle
The angles of the edge.
double getAngleAtNodeNormalized(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node and disregards edge direction.
NBEdge * getTurnDestination(bool possibleDestination=false) const
void shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
bool hasLaneSpecificType() const
whether lanes differ in type
PositionVector myFromBorder
intersection borders (because the node shape might be invalid)
double getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
bool hasDefaultGeometry() const
Returns whether the geometry consists only of the node positions.
bool myAmInTLS
Information whether this is lies within a joined tls.
void setTurningDestination(NBEdge *e, bool onlyPossible=false)
Sets the turing destination at the given edge.
bool hasDefaultGeometryEndpointAtNode(const NBNode *node) const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
NBEdge * myTurnDestination
The turn destination edge (if a connection exists)
int getPriority() const
Returns the priority of the edge.
void computeEdgeShape(double smoothElevationThreshold=-1)
Recomputeds the lane shapes to terminate at the node shape For every lane the intersection with the f...
double assignInternalLaneLength(std::vector< Connection >::iterator i, int numLanes, double lengthSum, bool averageLength)
assign length to all lanes of an internal edge
static const double UNSPECIFIED_WIDTH
unspecified lane width
bool hasRestrictedLane(SUMOVehicleClass vclass) const
returns whether any lane already allows the given vclass exclusively
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
const StopOffset & getLaneStopOffset(int lane) const
Returns the stop offset to the specified lane's end.
void debugPrintConnections(bool outgoing=true, bool incoming=false) const
debugging helper to print all connections
Position mySignalPosition
the position of a traffic light signal on this edge
void replaceInConnections(NBEdge *which, NBEdge *by, int laneOff)
replace in current connections of edge
bool lanesWereAssigned() const
Check if lanes were assigned.
void restoreRestrictedLane(SUMOVehicleClass vclass, std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore a restricted lane
double getEndOffset() const
Returns the offset to the destination node.
bool isRailDeadEnd() const
whether this edge is a railway edge that does not continue
double myFriction
The current friction.
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
static const double UNSPECIFIED_OFFSET
unspecified lane offset
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again
int myFromJunctionPriority
The priority normalised for the node the edge is outgoing of.
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.
void setOrigID(const std::string origID, const bool append, const int laneIdx=-1)
set origID for all lanes or for a specific lane
PositionVector computeLaneShape(int lane, double offset) const
Computes the shape for the given lane.
bool allowsChangingLeft(int lane, SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
static int getLaneIndexFromLaneID(const std::string laneID)
bool hasConnectionTo(const NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
bool hasCustomLaneShape() const
whether one of the lanes has a custom shape
bool hasLaneParams() const
whether one of the lanes has parameters set
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
double getShapeEndAngle() const
Returns the angle at the end of the edge.
bool prohibitsChanging() const
whether one of the lanes prohibits lane changing
void setLoadedLength(double val)
set loaded length
PositionVector myGeom
The geometry for the edge.
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
void decLaneNo(int by)
decrement lane
NBNode * myFrom
The source and the destination node.
void append(NBEdge *continuation)
append another edge
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
double getFinalLength() const
get length that will be assigned to the lanes in the final network
void shortenGeometryAtNode(const NBNode *node, double reduction)
linearly extend the geometry at the given node
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
int myPriority
The priority of the edge.
std::string myStreetName
The street name (or whatever arbitrary string you wish to attach)
NBNode * getFromNode() const
Returns the origin node of the edge.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
int getFirstNonPedestrianNonBicycleLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN, SVC_BICYCLE and 0
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
A definition of a pedestrian crossing.
PositionVector shape
The crossing's shape.
bool priority
whether the pedestrians have priority
EdgeVector edges
The edges being crossed.
double width
This crossing's width.
Represents a single node (junction) during network building.
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
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 AVOID_INTERSECTING_LEFT_TURNS
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
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
FringeType getFringeType() const
Returns fringe type.
static const int BACKWARD
SumoXMLNodeType getType() const
Returns the type of this node.
bool isTrafficLight() const
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...
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.
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
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.
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
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
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
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
const PositionVector & getShape() const
retrieve the junction shape
const Position & getPosition() const
static const int FORWARD
edge directions (for pedestrian related stuff)
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.
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.
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 isTLControlled() const
Returns whether this node is controlled by any tls.
static const int SCURVE_IGNORE
static const double MIN_SPEED_CROSSING_TIME
minimum speed for computing time to cross intersection
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)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
void mergeParameters(const Parameterised::Map &mapArg, const std::string separator=" ", bool uniqueValues=true)
Adds or appends all given parameters from the map.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
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.
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 add(const Position &pos)
Adds the given position to this one.
void setz(double z)
set position z
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...
void sety(double y)
set position y
double y() const
Returns the y-position.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position
double length() const
Returns the length.
void push_front_noDoublePos(const Position &p)
insert in front a non double position
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
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
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
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)
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
bool almostSame(const PositionVector &v2, double maxDiv=POSITION_EPS) const
check if the two vectors have the same length and pairwise similar positions
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
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)
bool hasElevation() const
return whether two positions differ in z-coordinate
static const PositionVector EMPTY
empty Vector
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
PositionVector reverse() const
reverse position vector
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
bool isDefined() const
check if stopOffset was defined
double getOffset() const
get offset
std::vector< std::string > getVector()
return vector of strings
Some static methods for string processing.
static std::string convertUmlaute(std::string str)
Converts german "Umlaute" to their latin-version.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static T maxValue(const std::vector< T > &v)
A structure which describes a connection between edges or lanes.
bool indirectLeft
Whether this connection is an indirect left turn.
int fromLane
The lane the connections starts at.
std::string viaID
if Connection have a via, ID of it
int toLane
The lane the connections yields in.
std::vector< int > foeInternalLinks
FOE Internal links.
Connection(int fromLane_, NBEdge *toEdge_, int toLane_, const bool mayDefinitelyPass_=false)
Constructor.
double speed
custom speed for connection
NBEdge * toEdge
The edge the connections yields in.
double customLength
custom length for connection
double vmax
maximum velocity
PositionVector customShape
custom shape for connection
PositionVector viaShape
shape of via
std::string getDescription(const NBEdge *parent) const
get string describing this connection
double contPos
custom position for internal junction on this connection
std::string getInternalLaneID() const
get ID of internal lane
int internalLaneIndex
The lane index of this internal lane within the internal edge.
std::string tlID
The id of the traffic light that controls this connection.
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
double length
computed length (average of all internal lane shape lengths that share an internal edge)
PositionVector shape
shape of Connection
std::string id
id of Connection
std::vector< std::string > foeIncomingLanes
FOE Incomings lanes.
bool haveVia
check if Connection have a Via
int tlLinkIndex
The index of this connection within the controlling traffic light.
double viaLength
the length of the via shape (maybe customized)
static ConstRouterEdgePairVector myViaSuccessors
An (internal) definition of a single lane of an edge.
double width
This lane's width.
std::string oppositeID
An opposite lane ID, if given.
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.
Lane(NBEdge *e, const std::string &_origID)
constructor
bool accelRamp
Whether this lane is an acceleration lane.
PositionVector shape
The lane's shape.