55 #define DEBUGCOND (getID() == DEBUGID)
58 #define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUGID))
103 mayDefinitelyPass(false),
116 uncontrolled(false) {
121 double visibility_,
double speed_,
double length_,
bool haveVia_,
bool uncontrolled_,
const PositionVector& customShape_,
122 SVCPermissions permissions_,
bool indirectLeft_,
const std::string& edgeType_,
129 mayDefinitelyPass(mayDefinitelyPass_),
130 keepClear(keepClear_),
132 visibility(visibility_),
134 customLength(length_),
135 customShape(customShape_),
136 permissions(permissions_),
137 changeLeft(changeLeft_),
138 changeRight(changeRight_),
139 indirectLeft(indirectLeft_),
145 uncontrolled(uncontrolled_)
159 connectionsDone(false) {
172 assert((
int)myTransitions.size() > virtEdge);
174 NBEdge* succEdge = myTransitions[virtEdge];
175 std::vector<int> lanes;
179 std::map<NBEdge*, std::vector<int> >::iterator i =
myConnections.find(succEdge);
187 std::vector<int>::iterator j = std::find(lanes.begin(), lanes.end(), lane);
188 if (j == lanes.end()) {
190 lanes.push_back(lane);
203 const NBEdge* straight =
nullptr;
204 for (
const NBEdge*
const out : outgoing) {
206 for (
const int l : availableLanes) {
207 if ((parent->
myLanes[l].permissions & outPerms) != 0) {
208 if (straight ==
nullptr || sorter(out, straight)) {
215 if (straight ==
nullptr) {
218 myStraightest = (int)std::distance(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), straight));
221 assert(outgoing.size() > 0);
223 #ifdef DEBUG_CONNECTION_GUESSING
225 std::cout <<
" MainDirections edge=" << parent->
getID() <<
" straightest=" << straight->
getID() <<
" dir=" <<
toString(straightestDir) <<
"\n";
237 if (outgoing.back()->getJunctionPriority(to) == 1) {
241 if (outgoing.back()->getPriority() > straight->
getPriority() ||
242 outgoing.back()->getNumLanes() > straight->
getNumLanes()) {
259 return myDirs.empty();
265 return std::find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
285 std::string type,
double speed,
int nolanes,
286 int priority,
double laneWidth,
double endOffset,
307 init(nolanes,
false,
"");
312 std::string type,
double speed,
int nolanes,
313 int priority,
double laneWidth,
double endOffset,
316 const std::string& streetName,
317 const std::string& origID,
318 bool tryIgnoreNodePositions) :
322 myFrom(from), myTo(to),
323 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
324 myPriority(priority), mySpeed(speed),
326 myTurnDestination(nullptr),
327 myPossibleTurnDestination(nullptr),
328 myFromJunctionPriority(-1), myToJunctionPriority(-1),
329 myGeom(geom), myLaneSpreadFunction(spread), myEndOffset(endOffset),
330 myLaneWidth(laneWidth),
331 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
332 myAmInTLS(false), myAmMacroscopicConnector(false),
333 myStreetName(streetName),
335 mySignalNode(nullptr),
338 init(nolanes, tryIgnoreNodePositions, origID);
345 myType(tpl->getTypeID()),
346 myFrom(from), myTo(to),
347 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
348 myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
350 myTurnDestination(nullptr),
351 myPossibleTurnDestination(nullptr),
352 myFromJunctionPriority(-1), myToJunctionPriority(-1),
354 myLaneSpreadFunction(tpl->getLaneSpreadFunction()),
355 myEndOffset(tpl->getEndOffset()),
356 myEdgeStopOffset(tpl->getEdgeStopOffset()),
357 myLaneWidth(tpl->getLaneWidth()),
358 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
360 myAmMacroscopicConnector(false),
361 myStreetName(tpl->getStreetName()),
362 mySignalPosition(to == tpl->myTo ? tpl->mySignalPosition :
Position::
INVALID),
363 mySignalNode(to == tpl->myTo ? tpl->mySignalNode : nullptr) {
370 myLanes[i].updateParameters(tpl->
myLanes[tplIndex].getParametersMap());
371 if (to == tpl->
myTo) {
386 myFrom(nullptr), myTo(nullptr),
387 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
388 myPriority(0), mySpeed(0),
390 myTurnDestination(nullptr),
391 myPossibleTurnDestination(nullptr),
392 myFromJunctionPriority(-1), myToJunctionPriority(-1),
397 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
399 myAmMacroscopicConnector(false),
401 mySignalNode(nullptr) {
407 double speed,
int nolanes,
int priority,
409 const std::string& streetName,
411 bool tryIgnoreNodePositions) {
433 const std::vector<Lane> oldLanes =
myLanes;
434 init(nolanes, tryIgnoreNodePositions, oldLanes.empty() ?
"" : oldLanes[0].getParameter(
SUMO_PARAM_ORIGID));
435 for (
int i = 0; i < (int)nolanes; ++i) {
437 myLanes[i] = oldLanes[
MIN2(i, (
int)oldLanes.size() - 1)];
456 if (from ==
nullptr || to ==
nullptr) {
457 throw ProcessError(
"At least one of edge's '" +
myID +
"' nodes is not known.");
480 NBEdge::init(
int noLanes,
bool tryIgnoreNodePositions,
const std::string& origID) {
485 throw ProcessError(
"At least one of edge's '" +
myID +
"' nodes is not known.");
494 if (!tryIgnoreNodePositions ||
myGeom.size() < 2) {
517 assert(
myGeom.size() >= 2);
519 if ((
int)
myLanes.size() > noLanes) {
521 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
526 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
527 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
528 (*i)->removeFromConnections(
this, -1, lane);
533 for (
int i = 0; i < noLanes; i++) {
539 #ifdef DEBUG_CONNECTION_GUESSING
541 std::cout <<
"init edge=" <<
getID() <<
"\n";
543 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
546 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
561 lane.customShape.add(xoff, yoff, 0);
565 (*i).customShape.add(xoff, yoff, 0);
580 for (
int i = 0; i < (int)
myLanes.size(); i++) {
582 myLanes[i].customShape.mirrorX();
586 c.viaShape.mirrorX();
587 c.customShape.mirrorX();
622 assert(node ==
myTo);
657 assert(node ==
myTo);
686 if (rectangularCut) {
687 const double extend = 100;
691 border.push_back(p2);
693 if (border.size() == 2) {
694 double edgeWidth = 0;
695 for (
int i = 0; i < (int)
myLanes.size(); i++) {
702 assert(node ==
myTo);
706 #ifdef DEBUG_NODE_BORDER
709 <<
" rect=" << rectangularCut
710 <<
" p=" << p <<
" p2=" << p2
711 <<
" border=" << border
724 assert(node ==
myTo);
735 assert(node ==
myTo);
771 if (shape.size() < 2) {
773 const double oldLength = old.
length();
774 shape = old.
getSubpart(oldLength - 2 * POSITION_EPS, oldLength);
778 if (shape.
length() < POSITION_EPS) {
779 if (old.
length() < 2 * POSITION_EPS) {
782 const double midpoint = old.
length() / 2;
784 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
785 assert(shape.size() >= 2);
786 assert(shape.
length() > 0);
794 tmp.push_back(shape[0]);
795 tmp.push_back(shape[-1]);
797 if (tmp.
length() < POSITION_EPS) {
799 if (old.
length() < 2 * POSITION_EPS) {
802 const double midpoint = old.
length() / 2;
804 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
805 assert(shape.size() >= 2);
806 assert(shape.
length() > 0);
809 const double midpoint = shape.
length() / 2;
811 shape = shape.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
812 if (shape.
length() < POSITION_EPS) {
819 const double z = (shape[0].z() + shape[1].z()) / 2;
835 const double d = cut[0].distanceTo2D(cut[1]);
836 const double dZ = fabs(cut[0].z() - cut[1].z());
837 if (dZ / smoothElevationThreshold > d) {
843 const double d = cut[-1].distanceTo2D(cut[-2]);
844 const double dZ = fabs(cut[-1].z() - cut[-2].z());
845 if (dZ / smoothElevationThreshold > d) {
856 for (
int i = 0; i < (int)
myLanes.size(); i++) {
860 double avgLength = 0;
861 for (
int i = 0; i < (int)
myLanes.size(); i++) {
862 avgLength +=
myLanes[i].shape.length();
871 if (nodeShape.size() == 0) {
880 assert(pbv.size() > 0);
888 const double delta = ns[0].z() - laneShape[0].z();
890 if (fabs(delta) > 2 * POSITION_EPS && (!startNode->
geometryLike() || pb < 1)) {
895 assert(ns.size() >= 2);
900 assert(pbv.size() > 0);
905 const double delta = np.
z() - laneShape[0].z();
907 if (fabs(delta) > 2 * POSITION_EPS && !startNode->
geometryLike()) {
966 reverse = lane.customShape.
reverse();
968 lane.customShape = reverse.
reverse();
973 lane.customShape.removeDoublePoints(minDist,
true, 0, 0,
true);
985 std::vector<double> angles;
987 for (
int i = 0; i < (int)
myGeom.size() - 1; ++i) {
992 for (
int i = 0; i < (int)angles.size() - 1; ++i) {
995 if (maxAngle > 0 && relAngle > maxAngle && !silent) {
1001 if (i == 0 || i == (
int)angles.size() - 2) {
1002 const bool start = i == 0;
1004 const double r = tan(0.5 * (
M_PI - relAngle)) * dist;
1006 if (minRadius > 0 && r < minRadius) {
1009 (start ?
"start" :
"end") +
" of edge '" +
getID() +
"'.");
1013 }
else if (!silent) {
1015 toString(start ?
"start" :
"end") +
" of edge '%'.", r,
getID());
1033 if (dest !=
nullptr &&
myTo != dest->
myFrom) {
1036 if (dest ==
nullptr) {
1042 if (overrideRemoval) {
1045 if (it->toEdge == dest) {
1062 bool mayUseSameDestination,
1063 bool mayDefinitelyPass,
1073 const std::string& edgeType,
1089 return setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass, keepClear, contPos, visibility, speed, length,
1090 customShape, uncontrolled, permissions, indirectLeft, edgeType, changeLeft, changeRight, postProcess);
1096 NBEdge* dest,
int toLane,
1098 bool invalidatePrevious,
1099 bool mayDefinitelyPass) {
1100 if (invalidatePrevious) {
1104 for (
int i = 0; i < no && ok; i++) {
1114 bool mayUseSameDestination,
1115 bool mayDefinitelyPass,
1125 const std::string& edgeType,
1153 if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
1160 if (mayDefinitelyPass) {
1192 if ((it->fromLane < 0 || it->fromLane == lane)
1193 && (it->toEdge ==
nullptr || it->toEdge == destEdge)
1194 && (it->toLane < 0 || it->toLane == destLane)) {
1205 std::vector<NBEdge::Connection>
1207 std::vector<NBEdge::Connection> ret;
1209 if ((lane < 0 || c.fromLane == lane)
1210 && (to ==
nullptr || to == c.toEdge)
1211 && (toLane < 0 || toLane == c.toLane)) {
1223 (*i).fromLane == fromLane
1224 && (*i).toEdge == to
1225 && (*i).toLane == toLane) {
1230 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1237 (*i).fromLane == fromLane
1238 && (*i).toEdge == to
1239 && (*i).toLane == toLane) {
1244 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1275 if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
1276 outgoing.push_back((*i).toEdge);
1281 if (it->fromLane < 0 && it->toLane < 0) {
1283 EdgeVector::iterator forbidden = std::find(outgoing.begin(), outgoing.end(), it->toEdge);
1284 if (forbidden != outgoing.end()) {
1285 outgoing.erase(forbidden);
1290 int size = (int) outgoing.size();
1292 edges->reserve(size);
1293 for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
1296 edges->push_back(outedge);
1308 if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
1309 ret.push_back((*i).toEdge);
1320 for (EdgeVector::const_iterator i = candidates.begin(); i != candidates.end(); i++) {
1321 if ((*i)->isConnectedTo(
this)) {
1331 std::vector<int> ret;
1335 ret.push_back(c.fromLane);
1358 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
1363 for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
1373 const bool keepPossibleTurns) {
1375 const int fromLaneRemoved = adaptToLaneRemoval && fromLane >= 0 ? fromLane : -1;
1376 const int toLaneRemoved = adaptToLaneRemoval && toLane >= 0 ? toLane : -1;
1379 if ((toEdge ==
nullptr || c.
toEdge == toEdge)
1380 && (fromLane < 0 || c.
fromLane == fromLane)
1381 && (toLane < 0 || c.
toLane == toLane)) {
1384 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1391 if (fromLaneRemoved >= 0 && c.
fromLane > fromLaneRemoved) {
1394 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1395 for (NBConnectionVector::iterator tlcon = (*it)->getControlledLinks().begin(); tlcon != (*it)->getControlledLinks().end(); ++tlcon) {
1406 if (toLaneRemoved >= 0 && c.
toLane > toLaneRemoved && (toEdge ==
nullptr || c.
toEdge == toEdge)) {
1422 #ifdef DEBUG_CONNECTION_GUESSING
1424 std::cout <<
"removeFromConnections " <<
getID() <<
"_" << fromLane <<
"->" << toEdge->
getID() <<
"_" << toLane <<
"\n";
1426 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
1429 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
1441 if ((i->toEdge == connectionToRemove.
toEdge) && (i->fromLane == connectionToRemove.
fromLane) && (i->toLane == connectionToRemove.
toLane)) {
1456 if (reallowSetting) {
1468 if ((*i).toEdge == which) {
1470 (*i).toLane += laneOff;
1481 std::map<int, int> laneMap;
1485 bool wasConnected =
false;
1487 if ((*i).toEdge != which) {
1490 wasConnected =
true;
1491 if ((*i).fromLane != -1) {
1492 int fromLane = (*i).fromLane;
1493 laneMap[(*i).toLane] = fromLane;
1494 if (minLane == -1 || minLane > fromLane) {
1497 if (maxLane == -1 || maxLane < fromLane) {
1502 if (!wasConnected) {
1506 std::vector<NBEdge::Connection> conns = origConns;
1508 for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
1509 if ((*i).toEdge == which || (*i).toEdge ==
this
1511 || std::find(origTargets.begin(), origTargets.end(), (*i).toEdge) != origTargets.end()) {
1512 #ifdef DEBUG_REPLACECONNECTION
1514 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID()
1515 <<
" origTargets=" <<
toString(origTargets) <<
" newTarget=" << i->toEdge->getID() <<
" skipped\n";
1525 int fromLane = (*i).fromLane;
1527 if (laneMap.find(fromLane) == laneMap.end()) {
1528 if (fromLane >= 0 && fromLane <= minLane) {
1531 for (
auto& item : laneMap) {
1532 if (item.first < fromLane) {
1533 item.second =
MIN2(item.second, minLane);
1537 if (fromLane >= 0 && fromLane >= maxLane) {
1540 for (
auto& item : laneMap) {
1541 if (item.first > fromLane) {
1542 item.second =
MAX2(item.second, maxLane);
1547 toUse = laneMap[fromLane];
1552 #ifdef DEBUG_REPLACECONNECTION
1554 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID() <<
" origTargets=" <<
toString(origTargets)
1555 <<
" origFrom=" << fromLane <<
" laneMap=" <<
joinToString(laneMap,
":",
",") <<
" minLane=" << minLane <<
" maxLane=" << maxLane
1556 <<
" newTarget=" << i->toEdge->getID() <<
" fromLane=" << toUse <<
" toLane=" << i->toLane <<
"\n";
1560 i->contPos, i->visibility, i->speed, i->customLength, i->customShape, i->uncontrolled);
1591 std::vector<Connection>::iterator i =
myConnections.begin() + index;
1614 const int numPoints = oc.
getInt(
"junctions.internal-link-detail");
1615 const bool joinTurns = oc.
getBool(
"junctions.join-turns");
1616 const double limitTurnSpeed = oc.
getFloat(
"junctions.limit-turn-speed");
1617 const double limitTurnSpeedMinAngle =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle"));
1618 const double limitTurnSpeedMinAngleRail =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle.railway"));
1619 const double limitTurnSpeedWarnStraight = oc.
getFloat(
"junctions.limit-turn-speed.warn.straight");
1620 const double limitTurnSpeedWarnTurn = oc.
getFloat(
"junctions.limit-turn-speed.warn.turn");
1621 const bool higherSpeed = oc.
getBool(
"junctions.higher-speed");
1622 const double interalJunctionVehicleWidth = oc.
getFloat(
"internal-junctions.vehicle-width");
1624 std::string innerID =
":" + n.
getID();
1625 NBEdge* toEdge =
nullptr;
1626 int edgeIndex = linkIndex;
1627 int internalLaneIndex = 0;
1629 double lengthSum = 0;
1630 int avoidedIntersectingLeftOriginLane = std::numeric_limits<int>::max();
1631 bool averageLength =
true;
1635 if (con.
toEdge ==
nullptr) {
1642 if (con.
toEdge != toEdge) {
1645 edgeIndex = linkIndex;
1647 internalLaneIndex = 0;
1652 averageLength = !isTurn || joinTurns;
1656 std::vector<int> foeInternalLinks;
1663 std::pair<double, std::vector<int> > crossingPositions(-1, std::vector<int>());
1664 std::set<std::string> tmpFoeIncomingLanes;
1672 std::vector<PositionVector> otherShapes;
1674 const double width1OppositeLeft = 0;
1676 for (
const Connection& k2 : i2->getConnections()) {
1677 if (k2.toEdge ==
nullptr) {
1682 double width2 = k2.toEdge->getLaneWidth(k2.toLane);
1683 if (k2.toEdge->getPermissions(k2.toLane) !=
SVC_BICYCLE) {
1686 const bool foes = n.
foes(
this, con.
toEdge, i2, k2.toEdge);
1689 const bool avoidIntersectCandidate = !foes &&
bothLeftTurns(dir, i2, dir2);
1690 bool oppositeLeftIntersect = avoidIntersectCandidate &&
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2);
1695 && k2.customShape.size() == 0
1696 && (oppositeLeftIntersect || (avoidedIntersectingLeftOriginLane < con.
fromLane && avoidIntersectCandidate))
1697 && ((i2->getPermissions(k2.fromLane) & warn) != 0
1698 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0)) {
1704 oppositeLeftIntersect =
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2, shapeFlag);
1705 if (oppositeLeftIntersect
1710 if (avoidedIntersectingLeftOriginLane == std::numeric_limits<int>::max()
1711 || avoidedIntersectingLeftOriginLane < con.
fromLane) {
1714 const double minDV =
firstIntersection(shape, otherShape, width1OppositeLeft, width2,
1715 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1716 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1718 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1719 crossingPositions.first = minDV;
1725 avoidedIntersectingLeftOriginLane = con.
fromLane;
1731 const bool isBicycleLeftTurn = k2.indirectLeft || (dir2 ==
LinkDirection::LEFT && (i2->getPermissions(k2.fromLane) & k2.toEdge->getPermissions(k2.toLane)) ==
SVC_BICYCLE);
1734 crossingPositions.second.push_back(index);
1736 otherShapes.push_back(otherShape);
1739 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1740 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1742 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1743 crossingPositions.first = minDV;
1752 if (foes || rightTurnConflict || oppositeLeftIntersect || mergeConflict || indirectTurnConflit) {
1753 foeInternalLinks.push_back(index);
1756 if (oppositeLeftIntersect &&
getID() > i2->getID()
1759 && (i2->getPermissions(k2.fromLane) & warn) != 0
1760 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0
1764 WRITE_WARNINGF(
"Intersecting left turns at junction '%' from lane '%' and lane '%' (increase junction radius to avoid this).",
1770 tmpFoeIncomingLanes.insert(i2->getID() +
"_" +
toString(k2.fromLane));
1772 if (bothPrio && oppositeLeftIntersect &&
getID() < i2->getID()) {
1776 tmpFoeIncomingLanes.insert(
":" +
toString(index));
1782 std::vector<NBNode::Crossing*> crossings = n.
getCrossings();
1783 for (
auto c : crossings) {
1785 for (EdgeVector::const_iterator it_e = crossing.
edges.begin(); it_e != crossing.
edges.end(); ++it_e) {
1786 const NBEdge* edge = *it_e;
1788 if (
this == edge || con.
toEdge == edge) {
1789 foeInternalLinks.push_back(index);
1790 if (con.
toEdge == edge &&
1796 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1798 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1799 crossingPositions.first = minDV;
1808 if (dir ==
LinkDirection::TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0 && shape.
length() > 2. * POSITION_EPS) {
1822 crossingPositions.first = -1;
1825 crossingPositions.first = con.
contPos;
1844 if (limitTurnSpeed > 0) {
1849 const double angle =
MAX2(0.0, angleRaw - (fromRail ? limitTurnSpeedMinAngleRail : limitTurnSpeedMinAngle));
1850 const double length = shape.
length2D();
1853 if (angle > 0 && length > 1) {
1856 const double limit = sqrt(limitTurnSpeed * radius);
1857 const double reduction = con.
vmax - limit;
1865 dirType =
"roundabout";
1867 WRITE_WARNINGF(
"Speed of % connection '%' reduced by % due to turning radius of % (length=%, angle=%).",
1874 assert(con.
vmax > 0);
1886 assert(shape.size() >= 2);
1888 con.
id = innerID +
"_" +
toString(edgeIndex);
1889 if (crossingPositions.first >= 0 && crossingPositions.first < shape.
length()) {
1890 std::pair<PositionVector, PositionVector>
split = shape.
splitAt(crossingPositions.first);
1892 con.
foeIncomingLanes = std::vector<std::string>(tmpFoeIncomingLanes.begin(), tmpFoeIncomingLanes.end());
1894 con.
viaID = innerID +
"_" +
toString(splitIndex + noInternalNoSplits);
1902 ++internalLaneIndex;
1921 for (
int prevIndex = 1; prevIndex <= numLanes; prevIndex++) {
1925 if (averageLength) {
1926 c.
length =
MAX2(minLength, lengthSum / numLanes);
1935 const double a = firstLength / (firstLength + c.
viaLength);
1945 double intersect = std::numeric_limits<double>::max();
1946 if (v2.
length() < POSITION_EPS) {
1963 bool skip = secondIntersection;
1969 intersect =
MIN2(intersect, cand);
1971 skip = secondIntersection;
1977 intersect =
MIN2(intersect, cand);
1979 skip = secondIntersection;
1985 intersect =
MIN2(intersect, cand);
1987 skip = secondIntersection;
1993 intersect =
MIN2(intersect, cand);
2009 if (otherFrom ==
this) {
2018 double width1,
double width2,
int shapeFlag)
const {
2021 return minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS;
2040 #ifdef DEBUG_JUNCTIONPRIO
2045 #ifdef DEBUG_JUNCTIONPRIO
2058 assert(atNode ==
myTo);
2073 assert(atNode ==
myTo);
2081 if (!onlyPossible) {
2102 if (lane.changeLeft !=
SVCAll) {
2103 lane.changeLeft = ignoring;
2105 if (lane.changeRight !=
SVCAll) {
2106 lane.changeRight = ignoring;
2111 con.changeLeft = ignoring;
2114 con.changeRight = ignoring;
2127 std::vector<double> offsets(
myLanes.size(), 0.);
2129 for (
int i = (
int)
myLanes.size() - 2; i >= 0; --i) {
2131 offsets[i] = offset;
2135 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2153 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2154 offsets[i] += offset;
2158 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2159 if (
myLanes[i].customShape.size() != 0) {
2195 if ((hasFromShape || hasToShape) &&
getNumLanes() > 0) {
2228 if (suspiciousFromShape) {
2229 std::cout <<
" len=" << shape.
length() <<
" startA=" <<
myStartAngle <<
" startA2=" << myStartAngle2 <<
" startA3=" << myStartAngle3
2231 <<
" fromCenter=" << fromCenter
2233 <<
" refStart=" << referencePosStart
2236 if (suspiciousToShape) {
2237 std::cout <<
" len=" << shape.
length() <<
" endA=" <<
myEndAngle <<
" endA2=" << myEndAngle2 <<
" endA3=" << myEndAngle3
2239 <<
" toCenter=" << toCenter
2241 <<
" refEnd=" << referencePosEnd
2247 if (suspiciousFromShape && shape.
length() > 1) {
2258 if (suspiciousToShape && shape.
length() > 1) {
2272 <<
" fromCenter=" << fromCenter <<
" toCenter=" << toCenter
2273 <<
" refStart=" << referencePosStart <<
" refEnd=" << referencePosEnd <<
" shape=" << shape
2274 <<
" hasFromShape=" << hasFromShape
2275 <<
" hasToShape=" << hasToShape
2301 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2302 if ((*i).permissions !=
SVCAll) {
2312 std::vector<Lane>::const_iterator i =
myLanes.begin();
2315 for (; i !=
myLanes.end(); ++i) {
2316 if (i->permissions != firstLanePermissions) {
2326 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2337 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2338 if (i->width !=
myLanes.begin()->width) {
2348 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2349 if (i->type !=
myLanes.begin()->type) {
2359 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2360 if (i->endOffset !=
myLanes.begin()->endOffset) {
2370 for (
const auto& lane :
myLanes) {
2371 if (lane.laneStopOffset.isDefined()) {
2383 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2394 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2395 if (i->customShape.size() > 0) {
2405 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2406 if (i->getParametersMap().size() > 0) {
2416 if (lane.changeLeft !=
SVCAll || lane.changeRight !=
SVCAll) {
2442 #ifdef DEBUG_CONNECTION_GUESSING
2444 std::cout <<
"computeEdge2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
"\n";
2446 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2449 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2460 for (EdgeVector::const_iterator i = o.begin(); i != o.end(); ++i) {
2465 if (fromRail &&
isRailway((*i)->getPermissions()) &&
2482 #ifdef DEBUG_CONNECTION_GUESSING
2484 std::cout <<
"computeLanes2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
"\n";
2486 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2489 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2515 std::vector<LinkDirection>
2517 std::vector<LinkDirection> result;
2518 for (
int i = 0; i < 8; i++) {
2520 if ((turnSigns & (1 << i)) != 0) {
2530 std::vector<const NBEdge*> targets;
2531 std::map<const NBEdge*, std::vector<int> > toLaneMap;
2533 if (
myLanes[c.fromLane].turnSigns != 0) {
2534 if (std::find(targets.begin(), targets.end(), c.toEdge) == targets.end()) {
2535 targets.push_back(c.toEdge);
2537 toLaneMap[c.toEdge].push_back(c.toLane);
2541 for (
auto& item : toLaneMap) {
2542 std::sort(item.second.begin(), item.second.end());
2546 std::map<LinkDirection, int> signCons;
2549 allDirs |= lane.turnSigns;
2555 targets.push_back(
nullptr);
2560 std::map<LinkDirection, const NBEdge*> dirMap;
2561 if (signedDirs.size() > targets.size()) {
2562 WRITE_WARNINGF(
"Cannot apply turn sign information for edge '%' because there are % signed directions but only % targets",
getID(), signedDirs.size(), targets.size());
2564 }
else if (signedDirs.size() < targets.size()) {
2567 std::vector<LinkDirection> sumoDirs;
2568 for (
const NBEdge* to : targets) {
2572 bool checkMore =
true;
2573 while (signedDirs.size() < targets.size() && checkMore) {
2576 if (sumoDirs.back() != signedDirs.back()) {
2578 sumoDirs.pop_back();
2584 while (signedDirs.size() < targets.size() && checkMore) {
2586 if (sumoDirs.front() != signedDirs.front()) {
2587 targets.erase(targets.begin());
2588 sumoDirs.erase(sumoDirs.begin());
2594 while (signedDirs.size() < targets.size() && i < (
int)targets.size()) {
2596 targets.erase(targets.begin() + i);
2597 sumoDirs.erase(sumoDirs.begin() + i);
2602 if (signedDirs.size() != targets.size()) {
2603 WRITE_WARNINGF(
"Cannot apply turn sign information for edge '%' because there are % signed directions and % targets (after target pruning)",
getID(), signedDirs.size(), targets.size());
2608 for (
int i = 0; i < (int)signedDirs.size(); i++) {
2609 dirMap[signedDirs[i]] = targets[i];
2612 for (
auto item : signCons) {
2617 const NBEdge* to = dirMap[dir];
2618 std::vector<int>& knownTargets = toLaneMap[to];
2619 if ((
int)knownTargets.size() < item.second) {
2621 if (candidates < item.second) {
2622 WRITE_WARNINGF(
"Cannot apply turn sign information for edge '%' because there are % signed connections with directions '%' but target edge '%' has only % suitable lanes",
2640 while ((
int)knownTargets.size() < item.second && i != iEnd) {
2642 if (std::find(knownTargets.begin(), knownTargets.end(), i) == knownTargets.end()) {
2643 knownTargets.push_back(i);
2648 if ((
int)knownTargets.size() != item.second) {
2649 WRITE_WARNINGF(
"Cannot apply turn sign information for edge '%' because not enough target lanes could be determined for direction '%'",
getID(),
toString(dir));
2652 std::sort(knownTargets.begin(), knownTargets.end());
2656 std::map<const NBEdge*, int> toLaneIndex;
2658 const int turnSigns =
myLanes[i].turnSigns;
2660 if (turnSigns != 0) {
2663 if (it->fromLane == i) {
2672 if (to !=
nullptr) {
2686 #ifdef DEBUG_CONNECTION_GUESSING
2688 std::cout <<
"recheckLanes (initial) edge=" <<
getID() <<
"\n";
2690 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2693 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2701 std::vector<int> connNumbersPerLane(
myLanes.size(), 0);
2703 if ((*i).toEdge ==
nullptr || (*i).fromLane < 0 || (*i).toLane < 0) {
2706 if ((*i).fromLane >= 0) {
2707 ++connNumbersPerLane[(*i).fromLane];
2722 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2725 bool hasDeadEnd =
true;
2727 for (
int i2 = i - 1; hasDeadEnd && i2 >= 0; i2--) {
2731 if (connNumbersPerLane[i2] > 1) {
2732 connNumbersPerLane[i2]--;
2733 for (
int i3 = i2; i3 != i; i3++) {
2743 for (
int i2 = i + 1; hasDeadEnd && i2 <
getNumLanes(); i2++) {
2747 if (connNumbersPerLane[i2] > 1) {
2748 connNumbersPerLane[i2]--;
2749 for (
int i3 = i2; i3 != i; i3--) {
2767 }
else if (common == 0) {
2770 const int origToLane = c.
toLane;
2772 int toLane = origToLane;
2785 toLane = origToLane;
2817 if (incoming.size() > 1) {
2818 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2820 bool connected =
false;
2821 for (std::vector<NBEdge*>::const_iterator in = incoming.begin(); in != incoming.end(); ++in) {
2822 if ((*in)->hasConnectionTo(
this, i)) {
2836 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2838 if ((connNumbersPerLane[i] == 0 || ((lane.
accelRamp || (i > 0 &&
myLanes[i - 1].accelRamp && connNumbersPerLane[i - 1] > 0))
2843 if (forbiddenLeft && (i == 0 || forbiddenRight)) {
2846 }
else if (forbiddenRight && (i ==
getNumLanes() - 1 || (i > 0 &&
myLanes[i - 1].accelRamp))) {
2853 #ifdef ADDITIONAL_WARNINGS
2860 bool hasAlternative =
false;
2862 if (c.fromLane == c2.fromLane && c.toEdge == c2.toEdge
2863 && (c.toEdge->getPermissions(c2.toLane) &
SVC_PASSENGER) != 0) {
2864 hasAlternative =
true;
2867 if (!hasAlternative) {
2868 WRITE_WARNING(
"Road lane ends on bikeLane for connection " + c.getDescription(
this));
2873 int passengerLanes = 0;
2874 int passengerTargetLanes = 0;
2882 for (
const Lane& lane : out->getLanes()) {
2884 passengerTargetLanes++;
2889 if (passengerLanes <= passengerTargetLanes) {
2891 connNumbersPerLane = std::vector<int>(
myLanes.size(), 0);
2893 connNumbersPerLane[c.fromLane]++;
2895 for (
int i = 0; i < (int)
myLanes.size(); i++) {
2904 #ifdef DEBUG_CONNECTION_GUESSING
2906 std::cout <<
"recheckLanes (final) edge=" <<
getID() <<
"\n";
2908 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2918 if (outgoing->size() == 0) {
2924 #ifdef DEBUG_CONNECTION_GUESSING
2926 std::cout <<
" divideOnEdges " <<
getID() <<
" outgoing=" <<
toString(*outgoing) <<
"\n";
2931 std::vector<int> availableLanes;
2932 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2934 availableLanes.push_back(i);
2937 if (availableLanes.size() > 0) {
2941 availableLanes.clear();
2942 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2947 availableLanes.push_back(i);
2949 if (availableLanes.size() > 0) {
2953 availableLanes.clear();
2954 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2959 availableLanes.push_back(i);
2961 if (availableLanes.size() > 0) {
2965 availableLanes.clear();
2966 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2971 availableLanes.push_back(i);
2973 if (availableLanes.size() > 0) {
2977 bool explicitTurnaround =
false;
2979 if ((*i).fromLane == -1) {
2981 explicitTurnaround =
true;
2988 if (explicitTurnaround) {
2998 if (priorities.empty()) {
3001 #ifdef DEBUG_CONNECTION_GUESSING
3003 std::cout <<
"divideSelectedLanesOnEdges " <<
getID() <<
" out=" <<
toString(*outgoing) <<
" prios=" <<
toString(priorities) <<
" avail=" <<
toString(availableLanes) <<
"\n";
3007 const int numOutgoing = (int)outgoing->size();
3008 std::vector<int> resultingLanesFactor;
3009 resultingLanesFactor.reserve(numOutgoing);
3010 int minResulting = std::numeric_limits<int>::max();
3011 for (
int i = 0; i < numOutgoing; i++) {
3013 const int res = priorities[i] * (int)availableLanes.size();
3014 resultingLanesFactor.push_back(res);
3015 if (minResulting > res && res > 0) {
3027 transition.reserve(numOutgoing);
3028 for (
int i = 0; i < numOutgoing; i++) {
3030 assert(i < (
int)resultingLanesFactor.size());
3031 const int tmpNum = (resultingLanesFactor[i] + minResulting - 1) / minResulting;
3032 numVirtual += tmpNum;
3033 for (
int j = 0; j < tmpNum; j++) {
3034 transition.push_back((*outgoing)[i]);
3037 #ifdef DEBUG_CONNECTION_GUESSING
3039 std::cout <<
" minResulting=" << minResulting <<
" numVirtual=" << numVirtual <<
" availLanes=" <<
toString(availableLanes) <<
" resLanes=" <<
toString(resultingLanesFactor) <<
" transition=" <<
toString(transition) <<
"\n";
3048 for (
NBEdge*
const target : *outgoing) {
3049 assert(l2eConns.find(target) != l2eConns.end());
3050 for (
const int j : l2eConns.find(target)->second) {
3051 const int fromIndex = availableLanes[j];
3052 if ((
getPermissions(fromIndex) & target->getPermissions()) == 0) {
3066 int targetLanes = target->getNumLanes();
3070 if (numConsToTarget >= targetLanes) {
3073 if (
myLanes[fromIndex].connectionsDone) {
3076 #ifdef DEBUG_CONNECTION_GUESSING
3078 std::cout <<
" connectionsDone from " <<
getID() <<
"_" << fromIndex <<
": ";
3080 std::cout << c.getDescription(
this) <<
", ";
3088 #ifdef DEBUG_CONNECTION_GUESSING
3090 std::cout <<
" request connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->getID() <<
"\n";
3103 const int numOutgoing = (int) outgoing->size();
3104 NBEdge* target =
nullptr;
3105 NBEdge* rightOfTarget =
nullptr;
3106 NBEdge* leftOfTarget =
nullptr;
3108 for (
int i = 0; i < numOutgoing; i++) {
3109 if (maxPrio < priorities[i]) {
3112 maxPrio = priorities[i];
3113 target = (*outgoing)[i];
3114 rightOfTarget = i == 0 ? outgoing->back() : (*outgoing)[i - 1];
3115 leftOfTarget = i + 1 == numOutgoing ? outgoing->front() : (*outgoing)[i + 1];
3119 if (target ==
nullptr) {
3127 const int numDesiredConsToTarget =
MIN2(targetLanes, (
int)availableLanes.size());
3128 #ifdef DEBUG_CONNECTION_GUESSING
3130 std::cout <<
" checking extra lanes for target=" << target->
getID() <<
" cons=" << numConsToTarget <<
" desired=" << numDesiredConsToTarget <<
"\n";
3133 std::vector<int>::const_iterator it_avail = availableLanes.begin();
3134 while (numConsToTarget < numDesiredConsToTarget && it_avail != availableLanes.end()) {
3135 const int fromIndex = *it_avail;
3144 && !
myLanes[fromIndex].connectionsDone
3146 #ifdef DEBUG_CONNECTION_GUESSING
3148 std::cout <<
" candidate from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3157 #ifdef DEBUG_CONNECTION_GUESSING
3159 std::cout <<
" request additional connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3165 #ifdef DEBUG_CONNECTION_GUESSING
3170 <<
" rightOfTarget=" << rightOfTarget->
getID()
3171 <<
" leftOfTarget=" << leftOfTarget->
getID()
3182 const std::vector<int>
3184 std::vector<int> priorities;
3191 priorities.reserve(outgoing->size());
3192 for (
const NBEdge*
const out : *outgoing) {
3194 assert((prio + 1) * 2 > 0);
3195 prio = (prio + 1) * 2;
3196 priorities.push_back(prio);
3201 #ifdef DEBUG_CONNECTION_GUESSING
3203 <<
" outgoing=" <<
toString(*outgoing)
3204 <<
" priorities1=" <<
toString(priorities)
3209 assert(priorities.size() > 0);
3211 #ifdef DEBUG_CONNECTION_GUESSING
3213 std::cout <<
" priorities2=" <<
toString(priorities) <<
"\n";
3220 if (mainDirections.
empty()) {
3221 assert(dist < (
int)priorities.size());
3222 priorities[dist] *= 2;
3223 #ifdef DEBUG_CONNECTION_GUESSING
3225 std::cout <<
" priorities3=" <<
toString(priorities) <<
"\n";
3230 priorities[dist] += 1;
3235 priorities[(int)priorities.size() - 1] /= 2;
3236 #ifdef DEBUG_CONNECTION_GUESSING
3238 std::cout <<
" priorities6=" <<
toString(priorities) <<
"\n";
3242 && outgoing->size() > 2
3243 && availableLanes.size() == 2
3244 && (*outgoing)[dist]->getPriority() == (*outgoing)[0]->getPriority()) {
3246 priorities.back() /= 2;
3247 #ifdef DEBUG_CONNECTION_GUESSING
3249 std::cout <<
" priorities7=" <<
toString(priorities) <<
"\n";
3256 priorities[dist] *= 2;
3257 #ifdef DEBUG_CONNECTION_GUESSING
3259 std::cout <<
" priorities4=" <<
toString(priorities) <<
"\n";
3263 priorities[dist] *= 3;
3264 #ifdef DEBUG_CONNECTION_GUESSING
3266 std::cout <<
" priorities5=" <<
toString(priorities) <<
"\n";
3276 NBEdge::appendTurnaround(
bool noTLSControlled,
bool noFringe,
bool onlyDeadends,
bool onlyTurnlane,
bool noGeometryLike,
bool checkPermissions) {
3289 bool isDeadEnd =
true;
3291 if ((c.toEdge->getPermissions(c.toLane)
3299 if (onlyDeadends && !isDeadEnd) {
3302 const int fromLane = (int)
myLanes.size() - 1;
3312 if (checkPermissions) {
3336 if (noGeometryLike && !isDeadEnd) {
3345 if (turnIncoming.size() > 1) {
3371 if (pos < tolerance) {
3385 for (
int i = 0; i < lanes; i++) {
3387 for (std::vector<NBEdge::Connection>::iterator j = elv.begin(); j != elv.end(); j++) {
3389 assert(el.
tlID ==
"");
3411 if (c.fromLane == fromLane && c.toEdge == toEdge && c.toLane == toLane && c.uncontrolled) {
3431 assert(fromLane < 0 || fromLane < (
int)
myLanes.size());
3433 if (fromLane >= 0 && toLane >= 0) {
3435 std::vector<Connection>::iterator i =
3443 connection.
tlID = tlID;
3452 bool hadError =
false;
3454 if ((*i).toEdge != toEdge) {
3457 if (fromLane >= 0 && fromLane != (*i).fromLane) {
3460 if (toLane >= 0 && toLane != (*i).toLane) {
3463 if ((*i).tlID ==
"") {
3465 (*i).tlLinkIndex = tlIndex;
3466 (*i).tlLinkIndex2 = tlIndex2;
3469 if ((*i).tlID != tlID && (*i).tlLinkIndex == tlIndex) {
3470 WRITE_WARNINGF(
"The lane '%' on edge '%' already had a traffic light signal.", i->fromLane,
getID());
3475 if (hadError && no == 0) {
3476 WRITE_WARNINGF(
"Could not set any signal of the tlLogic '%' (unknown group).", tlID);
3501 ret =
myLanes[lane].shape.reverse();
3519 ret =
myLanes[lane].shape.reverse();
3530 reason =
"laneNumber";
3540 reason =
"bidi-rail";
3554 if (find(conn.begin(), conn.end(), possContinuation) == conn.end()) {
3555 reason =
"disconnected";
3566 reason =
"disconnected";
3572 if (conns.size() <
myLanes.size() - offset) {
3573 reason =
"some lanes disconnected";
3587 reason =
"priority";
3597 reason =
"spreadType";
3601 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3603 reason =
"lane " +
toString(i) +
" speed";
3605 }
else if (
myLanes[i].permissions != possContinuation->
myLanes[i].permissions) {
3606 reason =
"lane " +
toString(i) +
" permissions";
3608 }
else if (
myLanes[i].width != possContinuation->
myLanes[i].width &&
3610 reason =
"lane " +
toString(i) +
" width";
3627 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3633 if (origID != origID2) {
3643 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3675 if ((*i).toEdge == e && (*i).tlID !=
"") {
3701 assert(distances.size() > 0);
3707 NBEdge::addLane(
int index,
bool recomputeShape,
bool recomputeConnections,
bool shiftIndices) {
3708 assert(index <= (
int)
myLanes.size());
3712 int templateIndex = index > 0 ? index - 1 : index + 1;
3721 if (recomputeShape) {
3724 if (recomputeConnections) {
3725 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
3726 (*i)->invalidateConnections(
true);
3729 }
else if (shiftIndices) {
3732 if (c.fromLane >= index) {
3751 int newLaneNo = (int)
myLanes.size() + by;
3752 while ((
int)
myLanes.size() < newLaneNo) {
3762 assert(index < (
int)
myLanes.size());
3767 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
3768 (*i)->invalidateConnections(
true);
3771 }
else if (shiftIndices) {
3774 inc->removeFromConnections(
this, -1, index,
false,
true);
3782 int newLaneNo = (int)
myLanes.size() - by;
3783 assert(newLaneNo > 0);
3784 while ((
int)
myLanes.size() > newLaneNo) {
3802 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3806 assert(lane < (
int)
myLanes.size());
3807 myLanes[lane].permissions |= vclass;
3815 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3819 assert(lane < (
int)
myLanes.size());
3820 myLanes[lane].permissions &= ~vclass;
3828 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3832 assert(lane < (
int)
myLanes.size());
3833 myLanes[lane].preferred |= vclass;
3843 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3849 assert(lane < (
int)
myLanes.size());
3856 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3862 assert(lane < (
int)
myLanes.size());
3878 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3901 return myLanes[lane].laneStopOffset;
3911 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3917 assert(lane < (
int)
myLanes.size());
3918 myLanes[lane].endOffset = offset;
3936 }
else if (lane < (
int)
myLanes.size()) {
3937 if (!
myLanes[lane].laneStopOffset.isDefined() || overwrite) {
3942 myLanes[lane].laneStopOffset = offset;
3957 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3963 assert(lane < (
int)
myLanes.size());
3971 assert(lane < (
int)
myLanes.size());
3972 myLanes[lane].accelRamp = accelRamp;
3979 assert(lane < (
int)
myLanes.size());
3980 myLanes[lane].customShape = shape;
3987 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3992 assert(lane < (
int)
myLanes.size());
3993 myLanes[lane].permissions = permissions;
4001 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4006 assert(lane < (
int)
myLanes.size());
4007 myLanes[lane].preferred = permissions;
4015 assert(lane < (
int)
myLanes.size());
4016 myLanes[lane].changeLeft = changeLeft;
4017 myLanes[lane].changeRight = changeRight;
4025 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4030 assert(lane < (
int)
myLanes.size());
4031 return myLanes[lane].permissions;
4049 for (std::vector<Lane>::iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
4050 (*i).permissions =
SVCAll;
4086 for (
int i = start; i != end; i += direction) {
4102 for (
int i = start; i != end; i += direction) {
4116 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4117 if (
myLanes[i].permissions == permissions) {
4129 for (
int i = start; i != end; i += direction) {
4130 if (
myLanes[i].permissions != 0) {
4134 return end - direction;
4138 std::set<SVCPermissions>
4140 std::set<SVCPermissions> result;
4144 for (
int i = iStart; i < iEnd; ++i) {
4154 if ((lane.permissions & permissions) == permissions) {
4183 std::cout <<
getID() <<
" angle=" <<
getAngleAtNode(node) <<
" convAngle=" << angle <<
"\n";
4201 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4206 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4240 if (lane.permissions == vclass) {
4264 myLanes[newIndex].permissions = vclass;
4265 myLanes[newIndex].width = fabs(width);
4275 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4276 (*it)->shiftToLanesToEdge(
this, 1);
4287 if (
myLanes[0].permissions != vclass) {
4297 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4298 (*it)->shiftToLanesToEdge(
this, 0);
4311 if ((*it).toEdge == to && (*it).toLane >= 0) {
4312 (*it).toLane += laneOff;
4321 const int i = (node ==
myTo ? -1 : 0);
4322 const int i2 = (node ==
myTo ? 0 : -1);
4328 if (dist < neededOffset && dist2 < neededOffset2) {
4363 double avgEndOffset = 0;
4365 avgEndOffset += lane.endOffset;
4370 avgEndOffset /=
myLanes.size();
4371 return MAX2(result - avgEndOffset, POSITION_EPS);
4377 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4382 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4395 if (con.fromLane >= 0 && con.toLane >= 0 && con.toEdge !=
nullptr &&
4397 & con.toEdge->getPermissions(con.toLane) & vClass) != 0)
4412 std::pair<const NBEdge*, const Connection*> pair(con.toEdge,
nullptr);
4416 }
else if ((con.fromLane >= 0) && (con.toLane >= 0) &&
4417 (con.toEdge !=
nullptr) &&
4418 ((
getPermissions(con.fromLane) & con.toEdge->getPermissions(con.toLane) & vClass) == vClass)) {
4420 if (con.getLength() > 0) {
4434 std::cout <<
" " <<
getID() <<
"_" << c.fromLane <<
"->" << c.toEdge->getID() <<
"_" << c.toLane <<
"\n";
4456 bool haveJoined =
false;
4461 const std::string newType =
myLanes[i].type +
"|" +
myLanes[i + 1].type;
4477 for (
NBEdge* edge : edges) {
4478 if ((edge->getPermissions() & permissions) != 0) {
4479 result.push_back(edge);
4488 if (cands.size() == 0) {
4492 NBEdge* best = cands.front();
4503 if (cands.size() == 0) {
4507 NBEdge* best = cands.front();
4518 NBEdge* opposite =
nullptr;
4524 if (cand->getToNode() ==
getFromNode() && !cand->getLanes().empty()) {
4525 const double lastWidthCand = cand->getLaneWidth(cand->getNumLanes() - 1);
4528 const double threshold = 1.42 * 0.5 * (lastWidth + lastWidthCand) + 0.5;
4531 if (distance < threshold) {
4536 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.
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_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_laneWidthAndOffset
const double SUMO_const_laneOffset
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 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
void buildInnerEdges(const NBNode &n, int noInternalNoSplits, int &linkIndex, int &splitIndex)
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 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.
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.
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
void setOrigID(const std::string origID)
set origID for all lanes
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 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.
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
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 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.
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 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 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 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
void reinit(NBNode *from, NBNode *to, const std::string &type, double speed, int nolanes, int priority, PositionVector geom, double width, double endOffset, const std::string &streetName, LaneSpreadFunction spread, bool tryIgnoreNodePositions=false)
Resets initial values.
std::vector< Connection > getConnectionsFromLane(int lane, NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
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.
bool hasAccelLane() const
whether one of the lanes is an acceleration lane
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
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 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 extendGeometryAtNode(const NBNode *node, double maxExtent)
linearly extend the geometry at the given node
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
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.
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 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.
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
double myStartAngle
The angles of the edge.
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
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.
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
Connection getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection This method goes through "myConnections" and returns the specified o...
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.
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) 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
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 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
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
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
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.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void updateParameters(const std::map< std::string, std::string > &mapArg)
Adds or updates all given parameters from the map.
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value 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
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.
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.