57#define DEBUGCOND (getID() == DEBUGID)
60#define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUGID))
106 mayDefinitelyPass(false),
120 uncontrolled(false) {
125 double visibility_,
double speed_,
double friction_,
double length_,
bool haveVia_,
bool uncontrolled_,
const PositionVector& customShape_,
126 SVCPermissions permissions_,
bool indirectLeft_,
const std::string& edgeType_,
133 mayDefinitelyPass(mayDefinitelyPass_),
134 keepClear(keepClear_),
136 visibility(visibility_),
139 customLength(length_),
140 customShape(customShape_),
141 permissions(permissions_),
142 changeLeft(changeLeft_),
143 changeRight(changeRight_),
144 indirectLeft(indirectLeft_),
150 uncontrolled(uncontrolled_)
165 connectionsDone(false) {
178 assert((
int)myTransitions.size() > virtEdge);
180 NBEdge* succEdge = myTransitions[virtEdge];
181 std::vector<int> lanes;
185 std::map<NBEdge*, std::vector<int> >::iterator i =
myConnections.find(succEdge);
193 std::vector<int>::iterator j = std::find(lanes.begin(), lanes.end(), lane);
194 if (j == lanes.end()) {
196 lanes.push_back(lane);
209 const NBEdge* straight =
nullptr;
210 for (
const NBEdge*
const out : outgoing) {
212 for (
const int l : availableLanes) {
213 if ((parent->
myLanes[l].permissions & outPerms) != 0) {
214 if (straight ==
nullptr || sorter(out, straight)) {
221 if (straight ==
nullptr) {
224 myStraightest = (int)std::distance(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), straight));
227 assert(outgoing.size() > 0);
229#ifdef DEBUG_CONNECTION_GUESSING
231 std::cout <<
" MainDirections edge=" << parent->
getID() <<
" straightest=" << straight->
getID() <<
" dir=" <<
toString(straightestDir) <<
"\n";
243 if (outgoing.back()->getJunctionPriority(to) == 1) {
247 if (outgoing.back()->getPriority() > straight->
getPriority() ||
248 outgoing.back()->getNumLanes() > straight->
getNumLanes()) {
265 return myDirs.empty();
271 return std::find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
291 std::string type,
double speed,
double friction,
int nolanes,
292 int priority,
double laneWidth,
double endOffset,
314 init(nolanes,
false,
"");
319 std::string type,
double speed,
double friction,
int nolanes,
320 int priority,
double laneWidth,
double endOffset,
323 const std::string& streetName,
324 const std::string& origID,
325 bool tryIgnoreNodePositions) :
329 myFrom(from), myTo(to),
330 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
331 myPriority(priority), mySpeed(speed), myFriction(friction),
333 myTurnDestination(nullptr),
334 myPossibleTurnDestination(nullptr),
335 myFromJunctionPriority(-1), myToJunctionPriority(-1),
336 myGeom(geom), myLaneSpreadFunction(spread), myEndOffset(endOffset),
337 myLaneWidth(laneWidth),
338 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
339 myAmInTLS(false), myAmMacroscopicConnector(false),
340 myStreetName(streetName),
342 mySignalNode(nullptr),
346 init(nolanes, tryIgnoreNodePositions, origID);
353 myType(tpl->getTypeID()),
354 myFrom(from), myTo(to),
355 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
356 myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
357 myFriction(tpl->getFriction()),
359 myTurnDestination(nullptr),
360 myPossibleTurnDestination(nullptr),
361 myFromJunctionPriority(-1), myToJunctionPriority(-1),
363 myLaneSpreadFunction(tpl->getLaneSpreadFunction()),
364 myEndOffset(tpl->getEndOffset()),
365 myEdgeStopOffset(tpl->getEdgeStopOffset()),
366 myLaneWidth(tpl->getLaneWidth()),
367 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
369 myAmMacroscopicConnector(false),
370 myStreetName(tpl->getStreetName()),
371 mySignalPosition(to == tpl->myTo ? tpl->mySignalPosition :
Position::
INVALID),
372 mySignalNode(to == tpl->myTo ? tpl->mySignalNode : nullptr),
384 myLanes[i].updateParameters(tpl->
myLanes[tplIndex].getParametersMap());
385 if (to == tpl->
myTo) {
400 myFrom(nullptr), myTo(nullptr),
401 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
402 myPriority(0), mySpeed(0), myFriction(UNSPECIFIED_FRICTION),
404 myTurnDestination(nullptr),
405 myPossibleTurnDestination(nullptr),
406 myFromJunctionPriority(-1), myToJunctionPriority(-1),
411 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
413 myAmMacroscopicConnector(false),
415 mySignalNode(nullptr) {
421 double speed,
double friction,
int nolanes,
int priority,
423 const std::string& streetName,
425 bool tryIgnoreNodePositions) {
447 const std::vector<Lane> oldLanes =
myLanes;
448 init(nolanes, tryIgnoreNodePositions, oldLanes.empty() ?
"" : oldLanes[0].getParameter(
SUMO_PARAM_ORIGID));
449 for (
int i = 0; i < (int)nolanes; ++i) {
451 myLanes[i] = oldLanes[
MIN2(i, (
int)oldLanes.size() - 1)];
473 if (from ==
nullptr || to ==
nullptr) {
474 throw ProcessError(
"At least one of edge's '" +
myID +
"' nodes is not known.");
497NBEdge::init(
int noLanes,
bool tryIgnoreNodePositions,
const std::string& origID) {
502 throw ProcessError(
"At least one of edge's '" +
myID +
"' nodes is not known.");
511 if (!tryIgnoreNodePositions ||
myGeom.size() < 2) {
534 assert(
myGeom.size() >= 2);
536 if ((
int)
myLanes.size() > noLanes) {
538 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
543 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
544 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
545 (*i)->removeFromConnections(
this, -1, lane);
550 for (
int i = 0; i < noLanes; i++) {
556#ifdef DEBUG_CONNECTION_GUESSING
558 std::cout <<
"init edge=" <<
getID() <<
"\n";
560 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
563 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
578 lane.customShape.add(xoff, yoff, 0);
582 (*i).customShape.add(xoff, yoff, 0);
597 for (
int i = 0; i < (int)
myLanes.size(); i++) {
599 myLanes[i].customShape.mirrorX();
603 c.viaShape.mirrorX();
604 c.customShape.mirrorX();
639 assert(node ==
myTo);
681 assert(node ==
myTo);
710 if (rectangularCut) {
711 const double extend = 100;
715 border.push_back(p2);
717 if (border.size() == 2) {
722 assert(node ==
myTo);
726#ifdef DEBUG_NODE_BORDER
729 <<
" rect=" << rectangularCut
730 <<
" p=" << p <<
" p2=" << p2
731 <<
" border=" << border
744 assert(node ==
myTo);
755 assert(node ==
myTo);
803 if (shape.size() < 2) {
805 const double oldLength = old.
length();
806 shape = old.
getSubpart(oldLength - 2 * POSITION_EPS, oldLength);
810 if (shape.
length() < POSITION_EPS) {
811 if (old.
length() < 2 * POSITION_EPS) {
814 const double midpoint = old.
length() / 2;
816 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
817 assert(shape.size() >= 2);
818 assert(shape.
length() > 0);
826 tmp.push_back(shape[0]);
827 tmp.push_back(shape[-1]);
829 if (tmp.
length() < POSITION_EPS) {
831 if (old.
length() < 2 * POSITION_EPS) {
834 const double midpoint = old.
length() / 2;
836 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
837 assert(shape.size() >= 2);
838 assert(shape.
length() > 0);
841 const double midpoint = shape.
length() / 2;
843 shape = shape.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
844 if (shape.
length() < POSITION_EPS) {
851 const double z = (shape[0].z() + shape[1].z()) / 2;
867 const double d = cut[0].distanceTo2D(cut[1]);
868 const double dZ = fabs(cut[0].z() - cut[1].z());
869 if (dZ / smoothElevationThreshold > d) {
875 const double d = cut[-1].distanceTo2D(cut[-2]);
876 const double dZ = fabs(cut[-1].z() - cut[-2].z());
877 if (dZ / smoothElevationThreshold > d) {
888 for (
int i = 0; i < (int)
myLanes.size(); i++) {
892 double avgLength = 0;
893 for (
int i = 0; i < (int)
myLanes.size(); i++) {
894 avgLength +=
myLanes[i].shape.length();
903 if (nodeShape.size() == 0) {
912 assert(pbv.size() > 0);
920 const double delta = ns[0].z() - laneShape[0].z();
922 if (fabs(delta) > 2 * POSITION_EPS && (!startNode->
geometryLike() || pb < 1)) {
927 assert(ns.size() >= 2);
932 assert(pbv.size() > 0);
937 const double delta = np.
z() - laneShape[0].z();
939 if (fabs(delta) > 2 * POSITION_EPS && !startNode->
geometryLike()) {
998 reverse = lane.customShape.
reverse();
1000 lane.customShape = reverse.
reverse();
1005 lane.customShape.removeDoublePoints(minDist,
true, 0, 0,
true);
1017 std::vector<double> angles;
1019 for (
int i = 0; i < (int)
myGeom.size() - 1; ++i) {
1024 for (
int i = 0; i < (int)angles.size() - 1; ++i) {
1027 if (maxAngle > 0 && relAngle > maxAngle && !silent) {
1033 if (i == 0 || i == (
int)angles.size() - 2) {
1034 const bool start = i == 0;
1036 const double r = tan(0.5 * (
M_PI - relAngle)) * dist;
1038 if (minRadius > 0 && r < minRadius) {
1041 (start ?
"start" :
"end") +
" of edge '" +
getID() +
"'.");
1045 }
else if (!silent) {
1047 toString(start ?
"start" :
"end") +
" of edge '%'.", r,
getID());
1065 if (dest !=
nullptr &&
myTo != dest->
myFrom) {
1068 if (dest ==
nullptr) {
1074 if (overrideRemoval) {
1077 if (it->toEdge == dest) {
1094 bool mayUseSameDestination,
1095 bool mayDefinitelyPass,
1106 const std::string& edgeType,
1122 return setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass, keepClear, contPos, visibility, speed, friction, length,
1123 customShape, uncontrolled, permissions, indirectLeft, edgeType, changeLeft, changeRight, postProcess);
1129 NBEdge* dest,
int toLane,
1131 bool invalidatePrevious,
1132 bool mayDefinitelyPass) {
1133 if (invalidatePrevious) {
1137 for (
int i = 0; i < no && ok; i++) {
1147 bool mayUseSameDestination,
1148 bool mayDefinitelyPass,
1159 const std::string& edgeType,
1187 if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
1194 if (mayDefinitelyPass) {
1227 if ((it->fromLane < 0 || it->fromLane == lane)
1228 && (it->toEdge ==
nullptr || it->toEdge == destEdge)
1229 && (it->toLane < 0 || it->toLane == destLane)) {
1240std::vector<NBEdge::Connection>
1242 std::vector<NBEdge::Connection> ret;
1244 if ((lane < 0 || c.fromLane == lane)
1245 && (to ==
nullptr || to == c.toEdge)
1246 && (toLane < 0 || toLane == c.toLane)) {
1257 if (c.fromLane == fromLane && c.toEdge == to && c.toLane == toLane) {
1262 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1269 if (c.fromLane == fromLane && c.toEdge == to && c.toLane == toLane) {
1274 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1305 if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
1306 outgoing.push_back((*i).toEdge);
1311 if (it->fromLane < 0 && it->toLane < 0) {
1313 EdgeVector::iterator forbidden = std::find(outgoing.begin(), outgoing.end(), it->toEdge);
1314 if (forbidden != outgoing.end()) {
1315 outgoing.erase(forbidden);
1320 int size = (int) outgoing.size();
1322 edges->reserve(size);
1323 for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
1326 edges->push_back(outedge);
1338 if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
1339 ret.push_back((*i).toEdge);
1350 for (EdgeVector::const_iterator i = candidates.begin(); i != candidates.end(); i++) {
1351 if ((*i)->isConnectedTo(
this)) {
1361 std::vector<int> ret;
1365 ret.push_back(c.fromLane);
1388 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
1393 for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
1403 const bool keepPossibleTurns) {
1405 const int fromLaneRemoved = adaptToLaneRemoval && fromLane >= 0 ? fromLane : -1;
1406 const int toLaneRemoved = adaptToLaneRemoval && toLane >= 0 ? toLane : -1;
1409 if ((toEdge ==
nullptr || c.
toEdge == toEdge)
1410 && (fromLane < 0 || c.
fromLane == fromLane)
1411 && (toLane < 0 || c.
toLane == toLane)) {
1414 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1421 if (fromLaneRemoved >= 0 && c.
fromLane > fromLaneRemoved) {
1424 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1425 for (NBConnectionVector::iterator tlcon = (*it)->getControlledLinks().begin(); tlcon != (*it)->getControlledLinks().end(); ++tlcon) {
1436 if (toLaneRemoved >= 0 && c.
toLane > toLaneRemoved && (toEdge ==
nullptr || c.
toEdge == toEdge)) {
1452#ifdef DEBUG_CONNECTION_GUESSING
1454 std::cout <<
"removeFromConnections " <<
getID() <<
"_" << fromLane <<
"->" << toEdge->
getID() <<
"_" << toLane <<
"\n";
1456 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
1459 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
1471 if ((i->toEdge == connectionToRemove.
toEdge) && (i->fromLane == connectionToRemove.
fromLane) && (i->toLane == connectionToRemove.
toLane)) {
1486 if (reallowSetting) {
1498 if ((*i).toEdge == which) {
1500 (*i).toLane += laneOff;
1511 std::map<int, int> laneMap;
1515 bool wasConnected =
false;
1517 if ((*i).toEdge != which) {
1520 wasConnected =
true;
1521 if ((*i).fromLane != -1) {
1522 int fromLane = (*i).fromLane;
1523 laneMap[(*i).toLane] = fromLane;
1524 if (minLane == -1 || minLane > fromLane) {
1527 if (maxLane == -1 || maxLane < fromLane) {
1532 if (!wasConnected) {
1536 std::vector<NBEdge::Connection> conns = origConns;
1538 for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
1539 if ((*i).toEdge == which || (*i).toEdge ==
this
1541 || std::find(origTargets.begin(), origTargets.end(), (*i).toEdge) != origTargets.end()) {
1542#ifdef DEBUG_REPLACECONNECTION
1544 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID()
1545 <<
" origTargets=" <<
toString(origTargets) <<
" newTarget=" << i->toEdge->getID() <<
" skipped\n";
1555 int fromLane = (*i).fromLane;
1557 if (laneMap.find(fromLane) == laneMap.end()) {
1558 if (fromLane >= 0 && fromLane <= minLane) {
1561 for (
auto& item : laneMap) {
1562 if (item.first < fromLane) {
1563 item.second =
MIN2(item.second, minLane);
1567 if (fromLane >= 0 && fromLane >= maxLane) {
1570 for (
auto& item : laneMap) {
1571 if (item.first > fromLane) {
1572 item.second =
MAX2(item.second, maxLane);
1577 toUse = laneMap[fromLane];
1582#ifdef DEBUG_REPLACECONNECTION
1584 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID() <<
" origTargets=" <<
toString(origTargets)
1585 <<
" origFrom=" << fromLane <<
" laneMap=" <<
joinToString(laneMap,
":",
",") <<
" minLane=" << minLane <<
" maxLane=" << maxLane
1586 <<
" newTarget=" << i->toEdge->getID() <<
" fromLane=" << toUse <<
" toLane=" << i->toLane <<
"\n";
1590 i->contPos, i->visibility, i->speed, i->friction, i->customLength, i->customShape, i->uncontrolled);
1621 std::vector<Connection>::iterator i =
myConnections.begin() + index;
1644 const int numPoints = oc.
getInt(
"junctions.internal-link-detail");
1645 const bool joinTurns = oc.
getBool(
"junctions.join-turns");
1646 const double limitTurnSpeed = oc.
getFloat(
"junctions.limit-turn-speed");
1647 const double limitTurnSpeedMinAngle =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle"));
1648 const double limitTurnSpeedMinAngleRail =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle.railway"));
1649 const double limitTurnSpeedWarnStraight = oc.
getFloat(
"junctions.limit-turn-speed.warn.straight");
1650 const double limitTurnSpeedWarnTurn = oc.
getFloat(
"junctions.limit-turn-speed.warn.turn");
1651 const bool higherSpeed = oc.
getBool(
"junctions.higher-speed");
1652 const double interalJunctionVehicleWidth = oc.
getFloat(
"internal-junctions.vehicle-width");
1654 std::string innerID =
":" + n.
getID();
1655 NBEdge* toEdge =
nullptr;
1656 int edgeIndex = linkIndex;
1657 int internalLaneIndex = 0;
1659 double lengthSum = 0;
1660 int avoidedIntersectingLeftOriginLane = std::numeric_limits<int>::max();
1661 bool averageLength =
true;
1662 double maxCross = 0.;
1666 if (con.
toEdge ==
nullptr) {
1673 if (con.
toEdge != toEdge) {
1676 edgeIndex = linkIndex;
1678 internalLaneIndex = 0;
1683 averageLength = !isTurn || joinTurns;
1687 std::vector<int> foeInternalLinks;
1694 std::pair<double, std::vector<int> > crossingPositions(-1, std::vector<int>());
1695 std::set<std::string> tmpFoeIncomingLanes;
1698 std::vector<PositionVector> otherShapes;
1700 const double width1OppositeLeft = 0;
1702 for (
const Connection& k2 : i2->getConnections()) {
1703 if (k2.toEdge ==
nullptr) {
1708 double width2 = k2.toEdge->getLaneWidth(k2.toLane);
1709 if (k2.toEdge->getPermissions(k2.toLane) !=
SVC_BICYCLE) {
1712 const bool foes = n.
foes(
this, con.
toEdge, i2, k2.toEdge);
1715 const bool avoidIntersectCandidate = !foes &&
bothLeftTurns(dir, i2, dir2);
1716 bool oppositeLeftIntersect = avoidIntersectCandidate &&
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2);
1721 && k2.customShape.size() == 0
1722 && (oppositeLeftIntersect || (avoidedIntersectingLeftOriginLane < con.
fromLane && avoidIntersectCandidate))
1723 && ((i2->getPermissions(k2.fromLane) & warn) != 0
1724 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0)) {
1730 oppositeLeftIntersect =
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2, shapeFlag);
1731 if (oppositeLeftIntersect
1736 if (avoidedIntersectingLeftOriginLane == std::numeric_limits<int>::max()
1737 || avoidedIntersectingLeftOriginLane < con.
fromLane) {
1740 const double minDV =
firstIntersection(shape, otherShape, width1OppositeLeft, width2,
1741 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1742 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1744 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1745 crossingPositions.first = minDV;
1751 avoidedIntersectingLeftOriginLane = con.
fromLane;
1757 const bool isBicycleLeftTurn = k2.indirectLeft || (dir2 ==
LinkDirection::LEFT && (i2->getPermissions(k2.fromLane) & k2.toEdge->getPermissions(k2.toLane)) ==
SVC_BICYCLE);
1760 crossingPositions.second.push_back(index);
1762 otherShapes.push_back(otherShape);
1765 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1766 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1768 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1769 crossingPositions.first = minDV;
1778 if (foes || rightTurnConflict || oppositeLeftIntersect || mergeConflict || indirectTurnConflit) {
1779 foeInternalLinks.push_back(index);
1782 if (oppositeLeftIntersect &&
getID() > i2->getID()
1785 && (i2->getPermissions(k2.fromLane) & warn) != 0
1786 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0
1790 WRITE_WARNINGF(
TL(
"Intersecting left turns at junction '%' from lane '%' and lane '%' (increase junction radius to avoid this)."),
1795 if ((n.
forbids(i2, k2.toEdge,
this, con.
toEdge, signalised) || rightTurnConflict || indirectTurnConflit)
1797 tmpFoeIncomingLanes.insert(i2->getID() +
"_" +
toString(k2.fromLane));
1799 if (bothPrio && oppositeLeftIntersect &&
getID() < i2->getID()) {
1803 tmpFoeIncomingLanes.insert(
":" +
toString(index));
1809 std::vector<NBNode::Crossing*> crossings = n.
getCrossings();
1810 for (
auto c : crossings) {
1812 for (EdgeVector::const_iterator it_e = crossing.
edges.begin(); it_e != crossing.
edges.end(); ++it_e) {
1813 const NBEdge* edge = *it_e;
1815 if (
this == edge || con.
toEdge == edge) {
1816 foeInternalLinks.push_back(index);
1817 if (con.
toEdge == edge &&
1823 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1825 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1826 crossingPositions.first = minDV;
1835 if (dir ==
LinkDirection::TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0 && shape.
length() > 2. * POSITION_EPS) {
1845 crossingPositions.first = -1;
1848 crossingPositions.first = con.
contPos;
1867 if (limitTurnSpeed > 0) {
1872 const double angle =
MAX2(0.0, angleRaw - (fromRail ? limitTurnSpeedMinAngleRail : limitTurnSpeedMinAngle));
1873 const double length = shape.
length2D();
1876 if (angle > 0 && length > 1) {
1879 const double limit = sqrt(limitTurnSpeed * radius);
1880 const double reduction = con.
vmax - limit;
1888 dirType =
"roundabout";
1890 WRITE_WARNINGF(
TL(
"Speed of % connection '%' reduced by % due to turning radius of % (length=%, angle=%)."),
1897 assert(con.
vmax > 0);
1912 assert(shape.size() >= 2);
1914 con.
id = innerID +
"_" +
toString(edgeIndex);
1915 if (crossingPositions.first >= 0 && crossingPositions.first < shape.
length()) {
1916 std::pair<PositionVector, PositionVector>
split = shape.
splitAt(crossingPositions.first);
1918 con.
foeIncomingLanes = std::vector<std::string>(tmpFoeIncomingLanes.begin(), tmpFoeIncomingLanes.end());
1920 con.
viaID = innerID +
"_" +
toString(splitIndex + noInternalNoSplits);
1928 ++internalLaneIndex;
1950 for (
int prevIndex = 1; prevIndex <= numLanes; prevIndex++) {
1954 if (averageLength) {
1955 c.
length =
MAX2(minLength, lengthSum / numLanes);
1964 const double a = firstLength / (firstLength + c.
viaLength);
1975 double intersect = std::numeric_limits<double>::max();
1976 if (v2.
length() < POSITION_EPS) {
1993 bool skip = secondIntersection;
1999 intersect =
MIN2(intersect, cand);
2001 skip = secondIntersection;
2007 intersect =
MIN2(intersect, cand);
2009 skip = secondIntersection;
2015 intersect =
MIN2(intersect, cand);
2017 skip = secondIntersection;
2023 intersect =
MIN2(intersect, cand);
2039 if (otherFrom ==
this) {
2048 double width1,
double width2,
int shapeFlag)
const {
2051 return minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS;
2070#ifdef DEBUG_JUNCTIONPRIO
2075#ifdef DEBUG_JUNCTIONPRIO
2088 assert(atNode ==
myTo);
2100 assert(atNode ==
myTo);
2119 assert(atNode ==
myTo);
2127 if (!onlyPossible) {
2142 return myLanes[lane].friction;
2155 if (lane.changeLeft !=
SVCAll) {
2156 lane.changeLeft = ignoring;
2158 if (lane.changeRight !=
SVCAll) {
2159 lane.changeRight = ignoring;
2164 con.changeLeft = ignoring;
2167 con.changeRight = ignoring;
2180 std::vector<double> offsets(
myLanes.size(), 0.);
2182 for (
int i = (
int)
myLanes.size() - 2; i >= 0; --i) {
2184 offsets[i] = offset;
2188 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2194 offset = laneWidth / 2.;
2205 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2206 offsets[i] += offset;
2210 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2211 if (
myLanes[i].customShape.size() != 0) {
2247 if ((hasFromShape || hasToShape) &&
getNumLanes() > 0) {
2280 if (suspiciousFromShape) {
2281 std::cout <<
" len=" << shape.
length() <<
" startA=" <<
myStartAngle <<
" startA2=" << myStartAngle2 <<
" startA3=" << myStartAngle3
2283 <<
" fromCenter=" << fromCenter
2285 <<
" refStart=" << referencePosStart
2288 if (suspiciousToShape) {
2289 std::cout <<
" len=" << shape.
length() <<
" endA=" <<
myEndAngle <<
" endA2=" << myEndAngle2 <<
" endA3=" << myEndAngle3
2291 <<
" toCenter=" << toCenter
2293 <<
" refEnd=" << referencePosEnd
2299 if (suspiciousFromShape && shape.
length() > 1) {
2310 if (suspiciousToShape && shape.
length() > 1) {
2324 <<
" fromCenter=" << fromCenter <<
" toCenter=" << toCenter
2325 <<
" refStart=" << referencePosStart <<
" refEnd=" << referencePosEnd <<
" shape=" << shape
2326 <<
" hasFromShape=" << hasFromShape
2327 <<
" hasToShape=" << hasToShape
2353 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2354 if ((*i).permissions !=
SVCAll) {
2364 std::vector<Lane>::const_iterator i =
myLanes.begin();
2367 for (; i !=
myLanes.end(); ++i) {
2368 if (i->permissions != firstLanePermissions) {
2378 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2388 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2389 if (i->friction !=
myLanes.begin()->friction) {
2398 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2399 if (i->width !=
myLanes.begin()->width) {
2409 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2410 if (i->type !=
myLanes.begin()->type) {
2420 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2421 if (i->endOffset !=
myLanes.begin()->endOffset) {
2431 for (
const auto& lane :
myLanes) {
2432 if (lane.laneStopOffset.isDefined()) {
2444 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2455 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2456 if (i->customShape.size() > 0) {
2466 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2467 if (i->getParametersMap().size() > 0) {
2477 if (lane.changeLeft !=
SVCAll || lane.changeRight !=
SVCAll) {
2503#ifdef DEBUG_CONNECTION_GUESSING
2505 std::cout <<
"computeEdge2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
" noLeftMovers=" << noLeftMovers <<
"\n";
2507 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2510 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2521 for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
2526 if (fromRail &&
isRailway((*i)->getPermissions())) {
2530 }
else if (angle > 90) {
2538 if (radius < minRadius) {
2556#ifdef DEBUG_CONNECTION_GUESSING
2558 std::cout <<
"computeLanes2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
"\n";
2560 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2563 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2589std::vector<LinkDirection>
2591 std::vector<LinkDirection> result;
2592 for (
int i = 0; i < 8; i++) {
2594 if ((turnSigns & (1 << i)) != 0) {
2604 std::vector<const NBEdge*> targets;
2605 std::map<const NBEdge*, std::vector<int> > toLaneMap;
2607 if (
myLanes[c.fromLane].turnSigns != 0) {
2608 if (std::find(targets.begin(), targets.end(), c.toEdge) == targets.end()) {
2609 targets.push_back(c.toEdge);
2611 toLaneMap[c.toEdge].push_back(c.toLane);
2615 for (
auto& item : toLaneMap) {
2616 std::sort(item.second.begin(), item.second.end());
2620 std::map<LinkDirection, int> signCons;
2623 allDirs |= lane.turnSigns;
2629 targets.push_back(
nullptr);
2634 std::map<LinkDirection, const NBEdge*> dirMap;
2635 if (signedDirs.size() > targets.size()) {
2636 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed directions but only % targets"),
getID(), signedDirs.size(), targets.size());
2638 }
else if (signedDirs.size() < targets.size()) {
2641 std::vector<LinkDirection> sumoDirs;
2642 for (
const NBEdge* to : targets) {
2646 bool checkMore =
true;
2647 while (signedDirs.size() < targets.size() && checkMore) {
2650 if (sumoDirs.back() != signedDirs.back()) {
2652 sumoDirs.pop_back();
2658 while (signedDirs.size() < targets.size() && checkMore) {
2660 if (sumoDirs.front() != signedDirs.front()) {
2661 targets.erase(targets.begin());
2662 sumoDirs.erase(sumoDirs.begin());
2668 while (signedDirs.size() < targets.size() && i < (
int)targets.size()) {
2670 targets.erase(targets.begin() + i);
2671 sumoDirs.erase(sumoDirs.begin() + i);
2676 if (signedDirs.size() != targets.size()) {
2677 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());
2682 for (
int i = 0; i < (int)signedDirs.size(); i++) {
2683 dirMap[signedDirs[i]] = targets[i];
2686 for (
auto item : signCons) {
2691 const NBEdge* to = dirMap[dir];
2692 std::vector<int>& knownTargets = toLaneMap[to];
2693 if ((
int)knownTargets.size() < item.second) {
2695 if (candidates < item.second) {
2696 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed connections with directions '%' but target edge '%' has only % suitable lanes"),
2714 while ((
int)knownTargets.size() < item.second && i != iEnd) {
2716 if (std::find(knownTargets.begin(), knownTargets.end(), i) == knownTargets.end()) {
2717 knownTargets.push_back(i);
2722 if ((
int)knownTargets.size() != item.second) {
2723 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because not enough target lanes could be determined for direction '%'"),
getID(),
toString(dir));
2726 std::sort(knownTargets.begin(), knownTargets.end());
2730 std::map<const NBEdge*, int> toLaneIndex;
2732 const int turnSigns =
myLanes[i].turnSigns;
2734 if (turnSigns != 0) {
2737 if (it->fromLane == i) {
2746 if (to !=
nullptr) {
2760#ifdef DEBUG_CONNECTION_GUESSING
2762 std::cout <<
"recheckLanes (initial) edge=" <<
getID() <<
"\n";
2764 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2767 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2775 std::vector<int> connNumbersPerLane(
myLanes.size(), 0);
2777 if ((*i).toEdge ==
nullptr || (*i).fromLane < 0 || (*i).toLane < 0) {
2780 if ((*i).fromLane >= 0) {
2781 ++connNumbersPerLane[(*i).fromLane];
2796 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2799 bool hasDeadEnd =
true;
2801 for (
int i2 = i - 1; hasDeadEnd && i2 >= 0; i2--) {
2805 if (connNumbersPerLane[i2] > 1) {
2806 connNumbersPerLane[i2]--;
2807 for (
int i3 = i2; i3 != i; i3++) {
2817 for (
int i2 = i + 1; hasDeadEnd && i2 <
getNumLanes(); i2++) {
2821 if (connNumbersPerLane[i2] > 1) {
2822 connNumbersPerLane[i2]--;
2823 for (
int i3 = i2; i3 != i; i3--) {
2841 }
else if (common == 0) {
2844 const int origToLane = c.
toLane;
2846 int toLane = origToLane;
2859 toLane = origToLane;
2891 if (incoming.size() > 1) {
2892 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2894 bool connected =
false;
2895 for (std::vector<NBEdge*>::const_iterator in = incoming.begin(); in != incoming.end(); ++in) {
2896 if ((*in)->hasConnectionTo(
this, i)) {
2910 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2912 if ((connNumbersPerLane[i] == 0 || ((lane.
accelRamp || (i > 0 &&
myLanes[i - 1].accelRamp && connNumbersPerLane[i - 1] > 0))
2917 if (forbiddenLeft && (i == 0 || forbiddenRight)) {
2920 }
else if (forbiddenRight && (i ==
getNumLanes() - 1 || (i > 0 &&
myLanes[i - 1].accelRamp))) {
2927#ifdef ADDITIONAL_WARNINGS
2934 bool hasAlternative =
false;
2936 if (c.fromLane == c2.fromLane && c.toEdge == c2.toEdge
2937 && (c.toEdge->getPermissions(c2.toLane) &
SVC_PASSENGER) != 0) {
2938 hasAlternative =
true;
2941 if (!hasAlternative) {
2942 WRITE_WARNING(
"Road lane ends on bikeLane for connection " + c.getDescription(
this));
2947 int passengerLanes = 0;
2948 int passengerTargetLanes = 0;
2956 for (
const Lane& lane : out->getLanes()) {
2958 passengerTargetLanes++;
2963 if (passengerLanes <= passengerTargetLanes) {
2965 connNumbersPerLane = std::vector<int>(
myLanes.size(), 0);
2967 connNumbersPerLane[c.fromLane]++;
2969 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2978#ifdef DEBUG_CONNECTION_GUESSING
2980 std::cout <<
"recheckLanes (final) edge=" <<
getID() <<
"\n";
2982 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2992 if (outgoing->size() == 0) {
2998#ifdef DEBUG_CONNECTION_GUESSING
3000 std::cout <<
" divideOnEdges " <<
getID() <<
" outgoing=" <<
toString(*outgoing) <<
"\n";
3005 std::vector<int> availableLanes;
3006 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3008 availableLanes.push_back(i);
3011 if (availableLanes.size() > 0) {
3015 availableLanes.clear();
3016 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3021 availableLanes.push_back(i);
3023 if (availableLanes.size() > 0) {
3027 availableLanes.clear();
3028 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3033 availableLanes.push_back(i);
3035 if (availableLanes.size() > 0) {
3039 availableLanes.clear();
3040 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3045 availableLanes.push_back(i);
3047 if (availableLanes.size() > 0) {
3051 bool explicitTurnaround =
false;
3053 if ((*i).fromLane == -1) {
3055 explicitTurnaround =
true;
3062 if (explicitTurnaround) {
3072 if (priorities.empty()) {
3075#ifdef DEBUG_CONNECTION_GUESSING
3077 std::cout <<
"divideSelectedLanesOnEdges " <<
getID() <<
" out=" <<
toString(*outgoing) <<
" prios=" <<
toString(priorities) <<
" avail=" <<
toString(availableLanes) <<
"\n";
3081 const int numOutgoing = (int)outgoing->size();
3082 std::vector<int> resultingLanesFactor;
3083 resultingLanesFactor.reserve(numOutgoing);
3084 int minResulting = std::numeric_limits<int>::max();
3085 for (
int i = 0; i < numOutgoing; i++) {
3087 const int res = priorities[i] * (int)availableLanes.size();
3088 resultingLanesFactor.push_back(res);
3089 if (minResulting > res && res > 0) {
3101 transition.reserve(numOutgoing);
3102 for (
int i = 0; i < numOutgoing; i++) {
3104 assert(i < (
int)resultingLanesFactor.size());
3105 const int tmpNum = (resultingLanesFactor[i] + minResulting - 1) / minResulting;
3106 numVirtual += tmpNum;
3107 for (
int j = 0; j < tmpNum; j++) {
3108 transition.push_back((*outgoing)[i]);
3111#ifdef DEBUG_CONNECTION_GUESSING
3113 std::cout <<
" minResulting=" << minResulting <<
" numVirtual=" << numVirtual <<
" availLanes=" <<
toString(availableLanes) <<
" resLanes=" <<
toString(resultingLanesFactor) <<
" transition=" <<
toString(transition) <<
"\n";
3122 for (
NBEdge*
const target : *outgoing) {
3123 assert(l2eConns.find(target) != l2eConns.end());
3124 for (
const int j : l2eConns.find(target)->second) {
3125 const int fromIndex = availableLanes[j];
3126 if ((
getPermissions(fromIndex) & target->getPermissions()) == 0) {
3140 int targetLanes = target->getNumLanes();
3144 if (numConsToTarget >= targetLanes) {
3147 if (
myLanes[fromIndex].connectionsDone) {
3150#ifdef DEBUG_CONNECTION_GUESSING
3152 std::cout <<
" connectionsDone from " <<
getID() <<
"_" << fromIndex <<
": ";
3154 std::cout << c.getDescription(
this) <<
", ";
3162#ifdef DEBUG_CONNECTION_GUESSING
3164 std::cout <<
" request connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->getID() <<
"\n";
3177 const int numOutgoing = (int) outgoing->size();
3178 NBEdge* target =
nullptr;
3179 NBEdge* rightOfTarget =
nullptr;
3180 NBEdge* leftOfTarget =
nullptr;
3182 for (
int i = 0; i < numOutgoing; i++) {
3183 if (maxPrio < priorities[i]) {
3186 maxPrio = priorities[i];
3187 target = (*outgoing)[i];
3188 rightOfTarget = i == 0 ? outgoing->back() : (*outgoing)[i - 1];
3189 leftOfTarget = i + 1 == numOutgoing ? outgoing->front() : (*outgoing)[i + 1];
3193 if (target ==
nullptr) {
3201 const int numDesiredConsToTarget =
MIN2(targetLanes, (
int)availableLanes.size());
3202#ifdef DEBUG_CONNECTION_GUESSING
3204 std::cout <<
" checking extra lanes for target=" << target->
getID() <<
" cons=" << numConsToTarget <<
" desired=" << numDesiredConsToTarget <<
"\n";
3207 std::vector<int>::const_iterator it_avail = availableLanes.begin();
3208 while (numConsToTarget < numDesiredConsToTarget && it_avail != availableLanes.end()) {
3209 const int fromIndex = *it_avail;
3218 && !
myLanes[fromIndex].connectionsDone
3220#ifdef DEBUG_CONNECTION_GUESSING
3222 std::cout <<
" candidate from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3231#ifdef DEBUG_CONNECTION_GUESSING
3233 std::cout <<
" request additional connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3239#ifdef DEBUG_CONNECTION_GUESSING
3244 <<
" rightOfTarget=" << rightOfTarget->
getID()
3245 <<
" leftOfTarget=" << leftOfTarget->
getID()
3256const std::vector<int>
3258 std::vector<int> priorities;
3265 priorities.reserve(outgoing->size());
3266 for (
const NBEdge*
const out : *outgoing) {
3268 assert((prio + 1) * 2 > 0);
3269 prio = (prio + 1) * 2;
3270 priorities.push_back(prio);
3275#ifdef DEBUG_CONNECTION_GUESSING
3277 <<
" outgoing=" <<
toString(*outgoing)
3278 <<
" priorities1=" <<
toString(priorities)
3283 assert(priorities.size() > 0);
3285#ifdef DEBUG_CONNECTION_GUESSING
3287 std::cout <<
" priorities2=" <<
toString(priorities) <<
"\n";
3294 if (mainDirections.
empty()) {
3295 assert(dist < (
int)priorities.size());
3296 priorities[dist] *= 2;
3297#ifdef DEBUG_CONNECTION_GUESSING
3299 std::cout <<
" priorities3=" <<
toString(priorities) <<
"\n";
3304 priorities[dist] += 1;
3309 priorities[(int)priorities.size() - 1] /= 2;
3310#ifdef DEBUG_CONNECTION_GUESSING
3312 std::cout <<
" priorities6=" <<
toString(priorities) <<
"\n";
3316 && outgoing->size() > 2
3317 && availableLanes.size() == 2
3318 && (*outgoing)[dist]->getPriority() == (*outgoing)[0]->getPriority()) {
3320 priorities.back() /= 2;
3321#ifdef DEBUG_CONNECTION_GUESSING
3323 std::cout <<
" priorities7=" <<
toString(priorities) <<
"\n";
3330 priorities[dist] *= 2;
3331#ifdef DEBUG_CONNECTION_GUESSING
3333 std::cout <<
" priorities4=" <<
toString(priorities) <<
"\n";
3337 priorities[dist] *= 3;
3338#ifdef DEBUG_CONNECTION_GUESSING
3340 std::cout <<
" priorities5=" <<
toString(priorities) <<
"\n";
3350NBEdge::appendTurnaround(
bool noTLSControlled,
bool noFringe,
bool onlyDeadends,
bool onlyTurnlane,
bool noGeometryLike,
bool checkPermissions) {
3363 bool isDeadEnd =
true;
3365 if ((c.toEdge->getPermissions(c.toLane)
3373 if (onlyDeadends && !isDeadEnd) {
3376 const int fromLane = (int)
myLanes.size() - 1;
3386 if (checkPermissions) {
3410 if (noGeometryLike && !isDeadEnd) {
3419 if (turnIncoming.size() > 1) {
3445 if (pos < tolerance) {
3459 for (
int i = 0; i < lanes; i++) {
3461 assert(el.tlID ==
"");
3483 if (c.fromLane == fromLane && c.toEdge == toEdge && c.toLane == toLane && c.uncontrolled) {
3503 assert(fromLane < 0 || fromLane < (
int)
myLanes.size());
3505 if (fromLane >= 0 && toLane >= 0) {
3507 std::vector<Connection>::iterator i =
3515 connection.
tlID = tlID;
3524 bool hadError =
false;
3526 if ((*i).toEdge != toEdge) {
3529 if (fromLane >= 0 && fromLane != (*i).fromLane) {
3532 if (toLane >= 0 && toLane != (*i).toLane) {
3535 if ((*i).tlID ==
"") {
3537 (*i).tlLinkIndex = tlIndex;
3538 (*i).tlLinkIndex2 = tlIndex2;
3541 if ((*i).tlID != tlID && (*i).tlLinkIndex == tlIndex) {
3542 WRITE_WARNINGF(
TL(
"The lane '%' on edge '%' already had a traffic light signal."), i->fromLane,
getID());
3547 if (hadError && no == 0) {
3548 WRITE_WARNINGF(
TL(
"Could not set any signal of the tlLogic '%' (unknown group)."), tlID);
3573 ret =
myLanes[lane].shape.reverse();
3591 ret =
myLanes[lane].shape.reverse();
3602 reason =
"laneNumber";
3612 reason =
"bidi-rail";
3626 if (find(conn.begin(), conn.end(), possContinuation) == conn.end()) {
3627 reason =
"disconnected";
3638 reason =
"disconnected";
3644 if (conns.size() <
myLanes.size() - offset) {
3645 reason =
"some lanes disconnected";
3659 reason =
"priority";
3669 reason =
"spreadType";
3673 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3675 reason =
"lane " +
toString(i) +
" speed";
3677 }
else if (
myLanes[i].permissions != possContinuation->
myLanes[i].permissions) {
3678 reason =
"lane " +
toString(i) +
" permissions";
3680 }
else if (
myLanes[i].changeLeft != possContinuation->
myLanes[i].changeLeft ||
myLanes[i].changeRight != possContinuation->
myLanes[i].changeRight) {
3681 reason =
"lane " +
toString(i) +
" change restrictions";
3683 }
else if (
myLanes[i].width != possContinuation->
myLanes[i].width &&
3685 reason =
"lane " +
toString(i) +
" width";
3706 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3712 if (origID != origID2) {
3722 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3758 if ((*i).toEdge == e && (*i).tlID !=
"") {
3784 assert(distances.size() > 0);
3790NBEdge::addLane(
int index,
bool recomputeShape,
bool recomputeConnections,
bool shiftIndices) {
3791 assert(index <= (
int)
myLanes.size());
3795 int templateIndex = index > 0 ? index - 1 : index + 1;
3805 if (recomputeShape) {
3808 if (recomputeConnections) {
3809 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
3810 (*i)->invalidateConnections(
true);
3813 }
else if (shiftIndices) {
3816 if (c.fromLane >= index) {
3835 int newLaneNo = (int)
myLanes.size() + by;
3836 while ((
int)
myLanes.size() < newLaneNo) {
3846 assert(index < (
int)
myLanes.size());
3851 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
3852 (*i)->invalidateConnections(
true);
3855 }
else if (shiftIndices) {
3858 inc->removeFromConnections(
this, -1, index,
false,
true);
3866 int newLaneNo = (int)
myLanes.size() - by;
3867 assert(newLaneNo > 0);
3868 while ((
int)
myLanes.size() > newLaneNo) {
3886 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3890 assert(lane < (
int)
myLanes.size());
3891 myLanes[lane].permissions |= vclass;
3899 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3903 assert(lane < (
int)
myLanes.size());
3904 myLanes[lane].permissions &= ~vclass;
3912 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3916 assert(lane < (
int)
myLanes.size());
3917 myLanes[lane].preferred |= vclass;
3927 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3933 assert(lane < (
int)
myLanes.size());
3940 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3946 assert(lane < (
int)
myLanes.size());
3977 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4000 return myLanes[lane].laneStopOffset;
4010 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4016 assert(lane < (
int)
myLanes.size());
4017 myLanes[lane].endOffset = offset;
4035 }
else if (lane < (
int)
myLanes.size()) {
4036 if (!
myLanes[lane].laneStopOffset.isDefined() || overwrite) {
4041 myLanes[lane].laneStopOffset = offset;
4056 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4062 assert(lane < (
int)
myLanes.size());
4072 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4078 assert(lane < (
int)
myLanes.size());
4079 myLanes[lane].friction = friction;
4086 assert(lane < (
int)
myLanes.size());
4087 myLanes[lane].accelRamp = accelRamp;
4094 assert(lane < (
int)
myLanes.size());
4095 myLanes[lane].customShape = shape;
4102 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4107 assert(lane < (
int)
myLanes.size());
4108 myLanes[lane].permissions = permissions;
4116 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4121 assert(lane < (
int)
myLanes.size());
4122 myLanes[lane].preferred = permissions;
4130 assert(lane < (
int)
myLanes.size());
4131 myLanes[lane].changeLeft = changeLeft;
4132 myLanes[lane].changeRight = changeRight;
4140 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4145 assert(lane < (
int)
myLanes.size());
4146 return myLanes[lane].permissions;
4164 for (std::vector<Lane>::iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
4165 (*i).permissions =
SVCAll;
4201 for (
int i = start; i != end; i += direction) {
4217 for (
int i = start; i != end; i += direction) {
4231 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4232 if (
myLanes[i].permissions == permissions) {
4244 for (
int i = start; i != end; i += direction) {
4245 if (
myLanes[i].permissions != 0) {
4249 return end - direction;
4253std::set<SVCPermissions>
4255 std::set<SVCPermissions> result;
4259 for (
int i = iStart; i < iEnd; ++i) {
4269 if ((lane.permissions & permissions) == permissions) {
4298 std::cout <<
getID() <<
" angle=" <<
getAngleAtNode(node) <<
" convAngle=" << angle <<
"\n";
4316 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4321 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4355 if (lane.permissions == vclass) {
4379 myLanes[newIndex].permissions = vclass;
4380 myLanes[newIndex].width = fabs(width);
4390 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4391 (*it)->shiftToLanesToEdge(
this, 1);
4402 if (
myLanes[0].permissions != vclass) {
4412 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4413 (*it)->shiftToLanesToEdge(
this, 0);
4426 if ((*it).toEdge == to && (*it).toLane >= 0) {
4427 (*it).toLane += laneOff;
4436 const int i = (node ==
myTo ? -1 : 0);
4437 const int i2 = (node ==
myTo ? 0 : -1);
4442 const double neededOffset2 = neededOffset + (other->
getTotalWidth()) / 2;
4443 if (dist < neededOffset && dist2 < neededOffset2) {
4478 double avgEndOffset = 0;
4480 avgEndOffset += lane.endOffset;
4485 avgEndOffset /= (double)
myLanes.size();
4486 return MAX2(result - avgEndOffset, POSITION_EPS);
4492 if (laneIdx == -1) {
4493 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4500 if (std::find(oldIDs.begin(), oldIDs.end(), origID) == oldIDs.end()) {
4501 oldIDs.push_back(origID);
4521 if (con.fromLane >= 0 && con.toLane >= 0 && con.toEdge !=
nullptr &&
4523 & con.toEdge->getPermissions(con.toLane) & vClass) != 0)
4538 std::pair<const NBEdge*, const Connection*> pair(con.toEdge,
nullptr);
4542 }
else if ((con.fromLane >= 0) && (con.toLane >= 0) &&
4543 (con.toEdge !=
nullptr) &&
4544 ((
getPermissions(con.fromLane) & con.toEdge->getPermissions(con.toLane) & vClass) == vClass)) {
4546 if (con.getLength() > 0) {
4560 std::cout <<
" " <<
getID() <<
"_" << c.fromLane <<
"->" << c.toEdge->getID() <<
"_" << c.toLane <<
"\n";
4582 bool haveJoined =
false;
4587 const std::string newType =
myLanes[i].type +
"|" +
myLanes[i + 1].type;
4603 for (
NBEdge* edge : edges) {
4604 if ((edge->getPermissions() & permissions) != 0) {
4605 result.push_back(edge);
4614 if (cands.size() == 0) {
4618 NBEdge* best = cands.front();
4629 if (cands.size() == 0) {
4633 NBEdge* best = cands.front();
4644 NBEdge* opposite =
nullptr;
4650 if (cand->getToNode() ==
getFromNode() && !cand->getLanes().empty()) {
4651 const double lastWidthCand = cand->getLaneWidth(cand->getNumLanes() - 1);
4654 const double threshold = 1.42 * 0.5 * (lastWidth + lastWidthCand) + 0.5;
4657 if (distance < threshold) {
4662 if (opposite !=
nullptr) {
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGE(msg)
#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
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.
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_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ 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.
const std::map< NBEdge *, std::vector< int > > & getBuiltConnections() const
get built connections
void execute(const int lane, const int virtEdge)
executes a bresenham - step
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.
void mirrorX()
mirror coordinates along the x-axis
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
double getLaneSpeed(int lane) const
get lane speed
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false)
Adds a connection to another edge.
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
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
NBNode * getToNode() const
Returns the destination node of the edge.
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 ...
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.
const PositionVector & getGeometry() const
Returns the geometry 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.
std::vector< LinkDirection > decodeTurnSigns(int turnSigns)
decode bitset
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...
void preferVehicleClass(int lane, SUMOVehicleClass vclass)
prefer certain vehicle class
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 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)
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
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
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.
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 recheked.
@ 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.
const std::string & getID() const
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
std::vector< Connection > getConnectionsFromLane(int lane, NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
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.
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
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)
void assignInternalLaneLength(std::vector< Connection >::iterator i, int numLanes, double lengthSum, bool averageLength)
assign length to all lanes of an internal edge
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
int getNumLanesThatAllow(SVCPermissions permissions) const
get lane indices that allow the given permissions
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.
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
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.
const ConstRouterEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Returns the following edges for the given vClass.
const std::string & getStreetName() const
Returns the street name of this edge.
void setLaneShape(int lane, const PositionVector &shape)
sets a custom lane shape
double myLoadedLength
An optional length to use (-1 if not valid)
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
const NBEdge * getBidiEdge() const
NBNode * getFromNode() const
Returns the origin node of the edge.
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...
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 hasConnectionTo(NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain 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 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)
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.
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.
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
bool needsCont(const NBEdge *fromE, const NBEdge *otherFromE, const NBEdge::Connection &c, const NBEdge::Connection &otherC) 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.
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in 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...
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
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.
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 multple connections from the same edge target the same lane
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 Position & getPosition() const
const PositionVector & getShape() const
retrieve the junction shape
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.
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.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
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
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 ammount
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
bool hasElevation() const
return whether two positions differ in z-coordinate
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.
double speed
custom speed for connection
NBEdge * toEdge
The edge the connections yields in.
Connection(int fromLane_, NBEdge *toEdge_, int toLane_)
Constructor.
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.