60#define DEBUGCOND (getID() == DEBUGID)
63#define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUGID))
99 return viaID +
"_" +
toString(internalViaLaneIndex);
114 mayDefinitelyPass(mayDefinitelyPass_),
131 connectionsDone(false) {
144 assert((
int)myTransitions.size() > virtEdge);
146 NBEdge* succEdge = myTransitions[virtEdge];
147 std::vector<int> lanes;
151 std::map<NBEdge*, std::vector<int> >::iterator i =
myConnections.find(succEdge);
159 std::vector<int>::iterator j = std::find(lanes.begin(), lanes.end(), lane);
160 if (j == lanes.end()) {
162 lanes.push_back(lane);
175 const NBEdge* straight =
nullptr;
176 for (
const NBEdge*
const out : outgoing) {
178 for (
const int l : availableLanes) {
179 if ((parent->
myLanes[l].permissions & outPerms) != 0) {
180 if (straight ==
nullptr || sorter(out, straight)) {
187 if (straight ==
nullptr) {
190 myStraightest = (int)std::distance(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), straight));
193 assert(outgoing.size() > 0);
195#ifdef DEBUG_CONNECTION_GUESSING
197 std::cout <<
" MainDirections edge=" << parent->
getID() <<
" straightest=" << straight->
getID() <<
" dir=" <<
toString(straightestDir) <<
"\n";
209 if (outgoing.back()->getJunctionPriority(to) == 1) {
213 if (outgoing.back()->getPriority() > straight->
getPriority() ||
214 outgoing.back()->getNumLanes() > straight->
getNumLanes()) {
231 return myDirs.empty();
237 return std::find(myDirs.begin(), myDirs.end(), d) != myDirs.end();
257 std::string type,
double speed,
double friction,
int nolanes,
258 int priority,
double laneWidth,
double endOffset,
280 init(nolanes,
false,
"");
285 std::string type,
double speed,
double friction,
int nolanes,
286 int priority,
double laneWidth,
double endOffset,
289 const std::string& streetName,
290 const std::string& origID,
291 bool tryIgnoreNodePositions) :
295 myFrom(from), myTo(to),
296 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
297 myPriority(priority), mySpeed(speed), myFriction(friction),
299 myTurnDestination(nullptr),
300 myPossibleTurnDestination(nullptr),
301 myFromJunctionPriority(-1), myToJunctionPriority(-1),
302 myGeom(geom), myLaneSpreadFunction(spread), myEndOffset(endOffset),
303 myLaneWidth(laneWidth),
304 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
305 myAmInTLS(false), myAmMacroscopicConnector(false),
306 myStreetName(streetName),
308 mySignalNode(nullptr),
312 init(nolanes, tryIgnoreNodePositions, origID);
319 myType(tpl->getTypeID()),
320 myFrom(from), myTo(to),
321 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
322 myPriority(tpl->getPriority()), mySpeed(tpl->getSpeed()),
323 myFriction(tpl->getFriction()),
325 myTurnDestination(nullptr),
326 myPossibleTurnDestination(nullptr),
327 myFromJunctionPriority(-1), myToJunctionPriority(-1),
329 myLaneSpreadFunction(tpl->getLaneSpreadFunction()),
330 myEndOffset(tpl->getEndOffset()),
331 myEdgeStopOffset(tpl->getEdgeStopOffset()),
332 myLaneWidth(tpl->getLaneWidth()),
333 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
335 myAmMacroscopicConnector(false),
336 myStreetName(tpl->getStreetName()),
337 mySignalPosition(to == tpl->myTo ? tpl->mySignalPosition :
Position::
INVALID),
338 mySignalNode(to == tpl->myTo ? tpl->mySignalNode : nullptr),
340 myIsBidi(tpl->myIsBidi),
350 myLanes[i].updateParameters(tpl->
myLanes[tplIndex].getParametersMap());
351 if (to == tpl->
myTo) {
366 myFrom(nullptr), myTo(nullptr),
367 myStartAngle(0), myEndAngle(0), myTotalAngle(0),
368 myPriority(0), mySpeed(0), myFriction(UNSPECIFIED_FRICTION),
370 myTurnDestination(nullptr),
371 myPossibleTurnDestination(nullptr),
372 myFromJunctionPriority(-1), myToJunctionPriority(-1),
377 myLoadedLength(UNSPECIFIED_LOADED_LENGTH),
379 myAmMacroscopicConnector(false),
381 mySignalNode(nullptr) {
387 double speed,
double friction,
int nolanes,
int priority,
389 const std::string& streetName,
391 bool tryIgnoreNodePositions) {
413 const std::vector<Lane> oldLanes =
myLanes;
414 init(nolanes, tryIgnoreNodePositions, oldLanes.empty() ?
"" : oldLanes[0].getParameter(
SUMO_PARAM_ORIGID));
415 for (
int i = 0; i < (int)nolanes; ++i) {
417 myLanes[i] = oldLanes[
MIN2(i, (
int)oldLanes.size() - 1)];
439 if (from ==
nullptr || to ==
nullptr) {
463NBEdge::init(
int noLanes,
bool tryIgnoreNodePositions,
const std::string& origID) {
486 if (!tryIgnoreNodePositions ||
myGeom.size() < 2) {
511 assert(
myGeom.size() >= 2);
513 if ((
int)
myLanes.size() > noLanes) {
515 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
520 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
521 for (
int lane = noLanes; lane < (int)
myLanes.size(); ++lane) {
522 (*i)->removeFromConnections(
this, -1, lane);
527 for (
int i = 0; i < noLanes; i++) {
533#ifdef DEBUG_CONNECTION_GUESSING
535 std::cout <<
"init edge=" <<
getID() <<
"\n";
537 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
540 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
555 lane.customShape.add(xoff, yoff, 0);
559 (*i).customShape.add(xoff, yoff, 0);
595 for (
int i = 0; i < (int)
myLanes.size(); i++) {
597 myLanes[i].customShape.mirrorX();
601 c.viaShape.mirrorX();
602 c.customShape.mirrorX();
637 assert(node ==
myTo);
649 assert(
myGeom.size() >= 2);
652 }
else if (node ==
myTo) {
691 assert(node ==
myTo);
720 if (rectangularCut) {
721 const double extend = 100;
725 border.push_back(p2);
727 if (border.size() == 2) {
732 assert(node ==
myTo);
736#ifdef DEBUG_NODE_BORDER
739 <<
" rect=" << rectangularCut
740 <<
" p=" << p <<
" p2=" << p2
741 <<
" border=" << border
754 assert(node ==
myTo);
765 assert(node ==
myTo);
820#ifdef DEBUG_CUT_LANES
822 std::cout <<
getID() <<
" cutFrom=" << shape <<
"\n";
825 if (shape.size() < 2) {
827 const double oldLength = old.
length();
828 shape = old.
getSubpart(oldLength - 2 * POSITION_EPS, oldLength);
829#ifdef DEBUG_CUT_LANES
831 std::cout <<
getID() <<
" cutFromFallback=" << shape <<
"\n";
836#ifdef DEBUG_CUT_LANES
838 std::cout <<
getID() <<
" cutTo=" << shape <<
"\n";
842 if (shape.
length() < POSITION_EPS) {
843 if (old.
length() < 2 * POSITION_EPS) {
846 const double midpoint = old.
length() / 2;
848 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
849 assert(shape.size() >= 2);
850 assert(shape.
length() > 0);
851#ifdef DEBUG_CUT_LANES
853 std::cout <<
getID() <<
" fallBackShort=" << shape <<
"\n";
863 tmp.push_back(shape[0]);
864 tmp.push_back(shape[-1]);
866 if (tmp.
length() < POSITION_EPS) {
868 if (old.
length() < 2 * POSITION_EPS) {
871 const double midpoint = old.
length() / 2;
873 shape = old.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
874 assert(shape.size() >= 2);
875 assert(shape.
length() > 0);
877#ifdef DEBUG_CUT_LANES
879 std::cout <<
getID() <<
" fallBackReversed=" << shape <<
"\n";
883 const double midpoint = shape.
length() / 2;
885 shape = shape.
getSubpart(midpoint - POSITION_EPS, midpoint + POSITION_EPS);
886 if (shape.
length() < POSITION_EPS) {
891#ifdef DEBUG_CUT_LANES
893 std::cout <<
getID() <<
" fallBackReversed2=" << shape <<
" mid=" << midpoint <<
"\n";
898 const double z = (shape[0].z() + shape[1].z()) / 2;
914 const double d = cut[0].distanceTo2D(cut[1]);
915 const double dZ = fabs(cut[0].z() - cut[1].z());
916 if (dZ / smoothElevationThreshold > d) {
922 const double d = cut[-1].distanceTo2D(cut[-2]);
923 const double dZ = fabs(cut[-1].z() - cut[-2].z());
924 if (dZ / smoothElevationThreshold > d) {
935 for (
int i = 0; i < (int)
myLanes.size(); i++) {
939 double avgLength = 0;
940 for (
int i = 0; i < (int)
myLanes.size(); i++) {
941 avgLength +=
myLanes[i].shape.length();
950 if (nodeShape.size() == 0) {
959 assert(pbv.size() > 0);
967 const double delta = ns[0].z() - laneShape[0].z();
969 if (fabs(delta) > 2 * POSITION_EPS && (!startNode->
geometryLike() || pb < 1)) {
974 assert(ns.size() >= 2);
979 assert(pbv.size() > 0);
984 const double delta = np.
z() - laneShape[0].z();
986 if (fabs(delta) > 2 * POSITION_EPS && !startNode->
geometryLike()) {
1045 reverse = lane.customShape.
reverse();
1047 lane.customShape = reverse.
reverse();
1052 lane.customShape.removeDoublePoints(minDist,
true, 0, 0,
true);
1064 std::vector<double> angles;
1066 for (
int i = 0; i < (int)
myGeom.size() - 1; ++i) {
1072 for (
int i = 0; i < (int)angles.size() - 1; ++i) {
1075 if (maxAngle > 0 && relAngle > maxAngle) {
1077 WRITE_MESSAGEF(
TL(
"Removing sharp angle of % degrees at edge '%', segment %."),
1080 if (bidi !=
nullptr) {
1085 }
else if (!silent) {
1092 if (i == 0 || i == (
int)angles.size() - 2) {
1093 const bool start = i == 0;
1095 const double r = tan(0.5 * (
M_PI - relAngle)) * dist;
1097 if (minRadius > 0 && r < minRadius) {
1099 WRITE_MESSAGEF(
TL(
"Removing sharp turn with radius % at the % of edge '%'."),
1102 if (bidi !=
nullptr) {
1107 }
else if (!silent) {
1127 if (dest !=
nullptr &&
myTo != dest->
myFrom) {
1130 if (dest ==
nullptr) {
1138 if (overrideRemoval) {
1141 if (it->toEdge == dest) {
1158 bool mayUseSameDestination,
1159 bool mayDefinitelyPass,
1170 const std::string& edgeType,
1186 return setConnection(from, dest, toLane, type, mayUseSameDestination, mayDefinitelyPass, keepClear, contPos, visibility, speed, friction, length,
1187 customShape, uncontrolled, permissions, indirectLeft, edgeType, changeLeft, changeRight, postProcess);
1193 NBEdge* dest,
int toLane,
1195 bool invalidatePrevious,
1196 bool mayDefinitelyPass) {
1197 if (invalidatePrevious) {
1201 for (
int i = 0; i < no && ok; i++) {
1211 bool mayUseSameDestination,
1212 bool mayDefinitelyPass,
1223 const std::string& edgeType,
1251 if ((*i).toEdge == destEdge && ((*i).fromLane == -1 || (*i).toLane == -1)) {
1255 permissions = (*i).permissions;
1263 if (mayDefinitelyPass) {
1296 if ((it->fromLane < 0 || it->fromLane == lane)
1297 && (it->toEdge ==
nullptr || it->toEdge == destEdge)
1298 && (it->toLane < 0 || it->toLane == destLane)) {
1309std::vector<NBEdge::Connection>
1311 std::vector<NBEdge::Connection> ret;
1313 if ((lane < 0 || c.fromLane == lane)
1314 && (to ==
nullptr || to == c.toEdge)
1315 && (toLane < 0 || toLane == c.toLane)) {
1326 if (c.fromLane == fromLane && c.toEdge == to && c.toLane == toLane) {
1331 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1338 if (c.fromLane == fromLane && c.toEdge == to && c.toLane == toLane) {
1343 +
" to " + to->
getID() +
"_" +
toString(toLane) +
" not found");
1374 if (find(outgoing.begin(), outgoing.end(), (*i).toEdge) == outgoing.end()) {
1375 outgoing.push_back((*i).toEdge);
1380 if (it->fromLane < 0 && it->toLane < 0) {
1382 EdgeVector::iterator forbidden = std::find(outgoing.begin(), outgoing.end(), it->toEdge);
1383 if (forbidden != outgoing.end()) {
1384 outgoing.erase(forbidden);
1389 int size = (int) outgoing.size();
1391 edges->reserve(size);
1392 for (EdgeVector::const_iterator i = outgoing.begin(); i != outgoing.end(); i++) {
1395 edges->push_back(outedge);
1407 if (find(ret.begin(), ret.end(), (*i).toEdge) == ret.end()) {
1408 ret.push_back((*i).toEdge);
1419 for (EdgeVector::const_iterator i = candidates.begin(); i != candidates.end(); i++) {
1420 if ((*i)->isConnectedTo(
this)) {
1430 std::vector<int> ret;
1433 if (c.toEdge == currentOutgoing
1436 ret.push_back(c.fromLane);
1459 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
1464 for (EdgeVector::iterator j = connected.begin(); j != connected.end(); j++) {
1474 const bool keepPossibleTurns) {
1476 const int fromLaneRemoved = adaptToLaneRemoval && fromLane >= 0 ? fromLane : -1;
1477 const int toLaneRemoved = adaptToLaneRemoval && toLane >= 0 ? toLane : -1;
1480 if ((toEdge ==
nullptr || c.
toEdge == toEdge)
1481 && (fromLane < 0 || c.
fromLane == fromLane)
1482 && (toLane < 0 || c.
toLane == toLane)) {
1485 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1492 if (fromLaneRemoved >= 0 && c.
fromLane > fromLaneRemoved) {
1495 for (std::set<NBTrafficLightDefinition*>::iterator it = tldefs.begin(); it != tldefs.end(); it++) {
1496 for (NBConnectionVector::iterator tlcon = (*it)->getControlledLinks().begin(); tlcon != (*it)->getControlledLinks().end(); ++tlcon) {
1507 if (toLaneRemoved >= 0 && c.
toLane > toLaneRemoved && (toEdge ==
nullptr || c.
toEdge == toEdge)) {
1523#ifdef DEBUG_CONNECTION_GUESSING
1525 std::cout <<
"removeFromConnections " <<
getID() <<
"_" << fromLane <<
"->" << toEdge->
getID() <<
"_" << toLane <<
"\n";
1527 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
1530 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
1542 if ((i->toEdge == connectionToRemove.
toEdge) && (i->fromLane == connectionToRemove.
fromLane) && (i->toLane == connectionToRemove.
toLane)) {
1557 if (reallowSetting) {
1569 if ((*i).toEdge == which) {
1571 (*i).toLane += laneOff;
1582 std::map<int, int> laneMap;
1586 bool wasConnected =
false;
1588 if ((*i).toEdge != which) {
1591 wasConnected =
true;
1592 if ((*i).fromLane != -1) {
1593 int fromLane = (*i).fromLane;
1594 laneMap[(*i).toLane] = fromLane;
1595 if (minLane == -1 || minLane > fromLane) {
1598 if (maxLane == -1 || maxLane < fromLane) {
1603 if (!wasConnected) {
1607 std::vector<NBEdge::Connection> conns = origConns;
1609 for (std::vector<NBEdge::Connection>::iterator i = conns.begin(); i != conns.end(); ++i) {
1610 if ((*i).toEdge == which || (*i).toEdge ==
this
1612 || std::find(origTargets.begin(), origTargets.end(), (*i).toEdge) != origTargets.end()) {
1613#ifdef DEBUG_REPLACECONNECTION
1615 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID()
1616 <<
" origTargets=" <<
toString(origTargets) <<
" newTarget=" << i->toEdge->getID() <<
" skipped\n";
1626 int fromLane = (*i).fromLane;
1628 if (laneMap.find(fromLane) == laneMap.end()) {
1629 if (fromLane >= 0 && fromLane <= minLane) {
1632 for (
auto& item : laneMap) {
1633 if (item.first < fromLane) {
1634 item.second =
MIN2(item.second, minLane);
1638 if (fromLane >= 0 && fromLane >= maxLane) {
1641 for (
auto& item : laneMap) {
1642 if (item.first > fromLane) {
1643 item.second =
MAX2(item.second, maxLane);
1648 toUse = laneMap[fromLane];
1653#ifdef DEBUG_REPLACECONNECTION
1655 std::cout <<
" replaceInConnections edge=" <<
getID() <<
" which=" << which->
getID() <<
" origTargets=" <<
toString(origTargets)
1656 <<
" origFrom=" << fromLane <<
" laneMap=" <<
joinToString(laneMap,
":",
",") <<
" minLane=" << minLane <<
" maxLane=" << maxLane
1657 <<
" newTarget=" << i->toEdge->getID() <<
" fromLane=" << toUse <<
" toLane=" << i->toLane <<
"\n";
1661 i->contPos, i->visibility, i->speed, i->friction, i->customLength, i->customShape, i->uncontrolled);
1686#ifdef DEBUG_CONNECTION_CHECKING
1687 std::cout <<
" moveConnectionToLeft " <<
getID() <<
" lane=" << lane <<
"\n";
1695 std::vector<Connection>::iterator i =
myConnections.begin() + index;
1704#ifdef DEBUG_CONNECTION_CHECKING
1705 std::cout <<
" moveConnectionToRight " <<
getID() <<
" lane=" << lane <<
"\n";
1721 const int numPoints = oc.
getInt(
"junctions.internal-link-detail");
1722 const bool joinTurns = oc.
getBool(
"junctions.join-turns");
1723 const double limitTurnSpeed = oc.
getFloat(
"junctions.limit-turn-speed");
1724 const double limitTurnSpeedMinAngle =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle"));
1725 const double limitTurnSpeedMinAngleRail =
DEG2RAD(oc.
getFloat(
"junctions.limit-turn-speed.min-angle.railway"));
1726 const double limitTurnSpeedWarnStraight = oc.
getFloat(
"junctions.limit-turn-speed.warn.straight");
1727 const double limitTurnSpeedWarnTurn = oc.
getFloat(
"junctions.limit-turn-speed.warn.turn");
1728 const bool higherSpeed = oc.
getBool(
"junctions.higher-speed");
1729 const double interalJunctionVehicleWidth = oc.
getFloat(
"internal-junctions.vehicle-width");
1730 const double defaultContPos = oc.
getFloat(
"default.connection.cont-pos");
1732 std::string innerID =
":" + n.
getID();
1733 NBEdge* toEdge =
nullptr;
1734 int edgeIndex = linkIndex;
1735 int internalLaneIndex = 0;
1737 double lengthSum = 0;
1738 int avoidedIntersectingLeftOriginLane = std::numeric_limits<int>::max();
1739 bool averageLength =
true;
1740 double maxCross = 0.;
1744 if (con.
toEdge ==
nullptr) {
1751 if (con.
toEdge != toEdge) {
1754 edgeIndex = linkIndex;
1756 internalLaneIndex = 0;
1761 averageLength = !isTurn || joinTurns;
1765 std::vector<int> foeInternalLinks;
1772 std::pair<double, std::vector<int> > crossingPositions(-1, std::vector<int>());
1773 std::set<std::string> tmpFoeIncomingLanes;
1776 std::vector<PositionVector> otherShapes;
1778 const double width1OppositeLeft = 0;
1780 for (
const Connection& k2 : i2->getConnections()) {
1781 if (k2.toEdge ==
nullptr) {
1786 double width2 = k2.toEdge->getLaneWidth(k2.toLane);
1787 if (k2.toEdge->getPermissions(k2.toLane) !=
SVC_BICYCLE) {
1790 const bool foes = n.
foes(
this, con.
toEdge, i2, k2.toEdge);
1793 const bool avoidIntersectCandidate = !foes &&
bothLeftTurns(dir, i2, dir2);
1794 bool oppositeLeftIntersect = avoidIntersectCandidate &&
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2);
1799 && k2.customShape.size() == 0
1800 && (oppositeLeftIntersect || (avoidedIntersectingLeftOriginLane < con.
fromLane && avoidIntersectCandidate))
1801 && ((i2->getPermissions(k2.fromLane) & warn) != 0
1802 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0)) {
1808 oppositeLeftIntersect =
haveIntersection(n, shape, i2, k2, numPoints, width1OppositeLeft, width2, shapeFlag);
1809 if (oppositeLeftIntersect
1814 if (avoidedIntersectingLeftOriginLane == std::numeric_limits<int>::max()
1815 || avoidedIntersectingLeftOriginLane < con.
fromLane) {
1818 const double minDV =
firstIntersection(shape, otherShape, width1OppositeLeft, width2,
1819 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1820 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1822 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1823 crossingPositions.first = minDV;
1829 avoidedIntersectingLeftOriginLane = con.
fromLane;
1835 const bool isBicycleLeftTurn = k2.indirectLeft || (dir2 ==
LinkDirection::LEFT && (i2->getPermissions(k2.fromLane) & k2.toEdge->getPermissions(k2.toLane)) ==
SVC_BICYCLE);
1838 crossingPositions.second.push_back(index);
1840 otherShapes.push_back(otherShape);
1843 "Could not compute intersection of conflicting internal lanes at node '" +
myTo->
getID() +
"'", secondIntersection);
1844 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1846 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1847 crossingPositions.first = minDV;
1859 if (foes || rightTurnConflict || oppositeLeftIntersect || mergeConflict || indirectTurnConflit || bidiConflict) {
1860 foeInternalLinks.push_back(index);
1863 if (oppositeLeftIntersect &&
getID() > i2->getID()
1866 && (i2->getPermissions(k2.fromLane) & warn) != 0
1867 && (k2.toEdge->getPermissions(k2.toLane) & warn) != 0
1871 WRITE_WARNINGF(
TL(
"Intersecting left turns at junction '%' from lane '%' and lane '%' (increase junction radius to avoid this)."),
1876 if ((n.
forbids(i2, k2.toEdge,
this, con.
toEdge, signalised) || rightTurnConflict || indirectTurnConflit || mergeResponse)
1878 tmpFoeIncomingLanes.insert(i2->getID() +
"_" +
toString(k2.fromLane));
1880 if (bothPrio && oppositeLeftIntersect &&
getID() < i2->getID()) {
1884 tmpFoeIncomingLanes.insert(
":" +
toString(index));
1889 if (dir ==
LinkDirection::TURN && crossingPositions.first < 0 && crossingPositions.second.size() != 0 && shape.
length() > 2. * POSITION_EPS) {
1895 std::vector<NBNode::Crossing*> crossings = n.
getCrossings();
1896 for (
auto c : crossings) {
1898 for (EdgeVector::const_iterator it_e = crossing.
edges.begin(); it_e != crossing.
edges.end(); ++it_e) {
1899 const NBEdge* edge = *it_e;
1901 if ((
this == edge || con.
toEdge == edge) && !
isRailway(conPermissions)) {
1902 foeInternalLinks.push_back(index);
1903 if (con.
toEdge == edge &&
1909 if (minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS) {
1911 if (crossingPositions.first < 0 || crossingPositions.first > minDV) {
1912 crossingPositions.first = minDV;
1916 crossingPositions.first = 0;
1931 crossingPositions.first = -1;
1934 crossingPositions.first = con.
contPos;
1953 if (limitTurnSpeed > 0) {
1958 const double angle =
MAX2(0.0, angleRaw - (fromRail ? limitTurnSpeedMinAngleRail : limitTurnSpeedMinAngle));
1959 const double length = shape.
length2D();
1962 if (angle > 0 && length > 1) {
1965 const double limit = sqrt(limitTurnSpeed * radius);
1966 const double reduction = con.
vmax - limit;
1974 dirType =
"roundabout";
1976 WRITE_WARNINGF(
TL(
"Speed of % connection '%' reduced by % due to turning radius of % (length=%, angle=%)."),
1983 assert(con.
vmax > 0);
1998 assert(shape.size() >= 2);
2000 con.
id = innerID +
"_" +
toString(edgeIndex);
2001 const double shapeLength = shape.
length();
2002 double firstLength = shapeLength;
2004 if (crossingPositions.first > 0 && crossingPositions.first < shapeLength) {
2005 std::pair<PositionVector, PositionVector>
split = shape.
splitAt(crossingPositions.first);
2007 con.
foeIncomingLanes = std::vector<std::string>(tmpFoeIncomingLanes.begin(), tmpFoeIncomingLanes.end());
2013 con.
viaID = innerID +
"_" +
toString(splitIndex + noInternalNoSplits);
2022 ++internalLaneIndex;
2027 lengthSum += (shapeLength != 0 ? firstLength / shapeLength : 1) * con.
customLength;
2029 lengthSum += firstLength;
2041 double maxCross = 0.;
2043 for (
int prevIndex = 1; prevIndex <= numLanes; prevIndex++) {
2057 if (!averageLength) {
2078 double intersect = std::numeric_limits<double>::max();
2079 if (v2.
length() < POSITION_EPS) {
2096 bool skip = secondIntersection;
2102 intersect =
MIN2(intersect, cand);
2104 skip = secondIntersection;
2110 intersect =
MIN2(intersect, cand);
2112 skip = secondIntersection;
2118 intersect =
MIN2(intersect, cand);
2120 skip = secondIntersection;
2126 intersect =
MIN2(intersect, cand);
2142 if (otherFrom ==
this) {
2151 double width1,
double width2,
int shapeFlag)
const {
2154 return minDV < shape.
length() - POSITION_EPS && minDV > POSITION_EPS;
2173#ifdef DEBUG_JUNCTIONPRIO
2178#ifdef DEBUG_JUNCTIONPRIO
2190 assert(atNode ==
myTo);
2201 assert(atNode ==
myTo);
2220 assert(atNode ==
myTo);
2228 if (!onlyPossible) {
2243 return myLanes[lane].friction;
2256 if (lane.changeLeft !=
SVCAll) {
2257 lane.changeLeft = ignoring;
2259 if (lane.changeRight !=
SVCAll) {
2260 lane.changeRight = ignoring;
2265 con.changeLeft = ignoring;
2268 con.changeRight = ignoring;
2281 std::vector<double> offsets(
myLanes.size(), 0.);
2283 for (
int i = (
int)
myLanes.size() - 2; i >= 0; --i) {
2285 offsets[i] = offset;
2289 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2295 offset = laneWidth / 2.;
2306 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2307 offsets[i] += offset;
2311 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
2312 if (
myLanes[i].customShape.size() != 0) {
2348 if ((hasFromShape || hasToShape) &&
getNumLanes() > 0) {
2381 if (suspiciousFromShape) {
2382 std::cout <<
"suspiciousFromShape len=" << shape.
length() <<
" startA=" <<
myStartAngle <<
" startA2=" << myStartAngle2 <<
" startA3=" << myStartAngle3
2384 <<
" fromCenter=" << fromCenter
2386 <<
" refStart=" << referencePosStart
2389 if (suspiciousToShape) {
2390 std::cout <<
"suspiciousToShape len=" << shape.
length() <<
" endA=" <<
myEndAngle <<
" endA2=" << myEndAngle2 <<
" endA3=" << myEndAngle3
2392 <<
" toCenter=" << toCenter
2394 <<
" refEnd=" << referencePosEnd
2400 if (suspiciousFromShape && shape.
length() > 1) {
2411 if (suspiciousToShape && shape.
length() > 1) {
2425 <<
" fromCenter=" << fromCenter <<
" toCenter=" << toCenter
2426 <<
" refStart=" << referencePosStart <<
" refEnd=" << referencePosEnd <<
" shape=" << shape
2427 <<
" hasFromShape=" << hasFromShape
2428 <<
" hasToShape=" << hasToShape
2454 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2455 if ((*i).permissions !=
SVCAll) {
2465 std::vector<Lane>::const_iterator i =
myLanes.begin();
2468 for (; i !=
myLanes.end(); ++i) {
2469 if (i->permissions != firstLanePermissions) {
2479 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2489 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2490 if (i->friction !=
myLanes.begin()->friction) {
2499 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2500 if (i->width !=
myLanes.begin()->width) {
2510 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2511 if (i->type !=
myLanes.begin()->type) {
2521 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2522 if (i->endOffset !=
myLanes.begin()->endOffset) {
2532 for (
const auto& lane :
myLanes) {
2533 if (lane.laneStopOffset.isDefined()) {
2545 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2556 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2557 if (i->customShape.size() > 0) {
2567 for (std::vector<Lane>::const_iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
2568 if (i->getParametersMap().size() > 0) {
2578 if (lane.changeLeft !=
SVCAll || lane.changeRight !=
SVCAll) {
2604#ifdef DEBUG_CONNECTION_GUESSING
2606 std::cout <<
"computeEdge2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
" noLeftMovers=" << noLeftMovers <<
"\n";
2608 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2611 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2626 if (fromRail &&
isRailway(out->getPermissions())) {
2630 }
else if (angle > 90) {
2638 if (radius < minRadius) {
2660#ifdef DEBUG_CONNECTION_GUESSING
2662 std::cout <<
"computeLanes2Edges edge=" <<
getID() <<
" step=" << (int)
myStep <<
"\n";
2664 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2667 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2676 if ((*i).toEdge ==
nullptr) {
2703std::vector<LinkDirection>
2705 std::vector<LinkDirection> result;
2706 for (
int i = 0; i < 8; i++) {
2708 if ((turnSigns & (1 << (i + shift))) != 0) {
2717 if (dirs.size() > 0) {
2718 if (std::find(dirs.begin(), dirs.end(), dir) == dirs.end()) {
2728#ifdef DEBUG_TURNSIGNS
2729 std::cout <<
"applyTurnSigns edge=" <<
getID() <<
"\n";
2732 std::vector<const NBEdge*> targets;
2733 std::map<const NBEdge*, std::vector<int> > toLaneMap;
2735 if (
myLanes[c.fromLane].turnSigns != 0) {
2736 if (std::find(targets.begin(), targets.end(), c.toEdge) == targets.end()) {
2737 targets.push_back(c.toEdge);
2739 toLaneMap[c.toEdge].push_back(c.toLane);
2743 for (
auto& item : toLaneMap) {
2744 std::sort(item.second.begin(), item.second.end());
2748 std::map<LinkDirection, int> signCons;
2751 allDirs |= lane.turnSigns;
2761 targets.push_back(
nullptr);
2767 std::map<LinkDirection, const NBEdge*> dirMap;
2768#ifdef DEBUG_TURNSIGNS
2769 std::cout <<
" numDirs=" << signedDirs.size() <<
" numTargets=" << targets.size() <<
"\n";
2771 if (signedDirs.size() > targets.size()) {
2772 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed directions but only % targets"),
getID(), signedDirs.size(), targets.size());
2774 }
else if (signedDirs.size() < targets.size()) {
2777 std::vector<LinkDirection> sumoDirs;
2778 for (
const NBEdge* to : targets) {
2782 bool checkMore =
true;
2783 while (signedDirs.size() < targets.size() && checkMore) {
2786 if (sumoDirs.back() != signedDirs.back()) {
2788 sumoDirs.pop_back();
2794 while (signedDirs.size() < targets.size() && checkMore) {
2796 if (sumoDirs.front() != signedDirs.front()) {
2797 targets.erase(targets.begin());
2798 sumoDirs.erase(sumoDirs.begin());
2804 while (signedDirs.size() < targets.size() && i < (int)targets.size()) {
2805 if (targets[i] !=
nullptr && (targets[i]->
getPermissions() & defaultPermissions) == 0) {
2806 targets.erase(targets.begin() + i);
2807 sumoDirs.erase(sumoDirs.begin() + i);
2812 if (signedDirs.size() != targets.size()) {
2813 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());
2818 for (
int i = 0; i < (int)signedDirs.size(); i++) {
2819 dirMap[signedDirs[i]] = targets[i];
2822 for (
auto item : signCons) {
2827 const NBEdge* to = dirMap[dir];
2829 if (candidates == 0) {
2830 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because the target edge '%' has no suitable lanes"),
getID(), to->
getID());
2833 std::vector<int>& knownTargets = toLaneMap[to];
2834 if ((
int)knownTargets.size() < item.second) {
2835 if (candidates < item.second) {
2836 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because there are % signed connections with directions '%' but target edge '%' has only % suitable lanes"),
2854 while ((
int)knownTargets.size() < item.second && i != iEnd) {
2856 if (std::find(knownTargets.begin(), knownTargets.end(), i) == knownTargets.end()) {
2857 knownTargets.push_back(i);
2862 if ((
int)knownTargets.size() != item.second) {
2863 WRITE_WARNINGF(
TL(
"Cannot apply turn sign information for edge '%' because not enough target lanes could be determined for direction '%'"),
getID(),
toString(dir));
2866 std::sort(knownTargets.begin(), knownTargets.end());
2869 std::map<const NBEdge*, int> toLaneIndex;
2871 const int turnSigns =
myLanes[i].turnSigns;
2873 if (turnSigns != 0) {
2876 if (it->fromLane == i) {
2883 int allSigns = (turnSigns
2908 if (to !=
nullptr) {
2909 if (toLaneIndex.count(to) == 0) {
2911 int toLane = toLaneMap[to][0];
2924#ifdef DEBUG_TURNSIGNS
2925 std::cout <<
" target=" << to->
getID() <<
" initial toLane=" << toLane <<
"\n";
2927 toLaneIndex[to] = toLane;
2929#ifdef DEBUG_TURNSIGNS
2938 if (toLaneIndex[to] < to->getNumLanes() - 1
2939 && (to->getPermissions(toLaneIndex[to] + 1) & fromP) != 0) {
2941 }
else if (toLaneIndex[to] < to->getNumLanes() - 2
2942 && (to->getPermissions(toLaneIndex[to] + 2) & fromP) != 0) {
2944 toLaneIndex[to] += 2;
2958#ifdef DEBUG_CONNECTION_GUESSING
2960 std::cout <<
"recheckLanes (initial) edge=" <<
getID() <<
"\n";
2962 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
2965 std::cout <<
" connToDelete " << c.getDescription(
this) <<
"\n";
2973 std::vector<int> connNumbersPerLane(
myLanes.size(), 0);
2975 if ((*i).toEdge ==
nullptr || (*i).fromLane < 0 || (*i).toLane < 0) {
2978 if ((*i).fromLane >= 0) {
2979 ++connNumbersPerLane[(*i).fromLane];
2985#ifdef DEBUG_TURNSIGNS
2986 if (
myLanes.back().turnSigns != 0) {
2987 std::cout <<
getID() <<
" hasTurnSigns\n";
2999 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3002 bool hasDeadEnd =
true;
3004 for (
int i2 = i - 1; hasDeadEnd && i2 >= 0; i2--) {
3008 if (connNumbersPerLane[i2] > 1) {
3009 connNumbersPerLane[i2]--;
3010 for (
int i3 = i2; i3 != i; i3++) {
3020 for (
int i2 = i + 1; hasDeadEnd && i2 <
getNumLanes(); i2++) {
3024 if (connNumbersPerLane[i2] > 1) {
3025 connNumbersPerLane[i2]--;
3026 for (
int i3 = i2; i3 != i; i3--) {
3036 int passengerLanes = 0;
3037 int passengerTargetLanes = 0;
3045 for (
const Lane& lane : out->getLanes()) {
3047 passengerTargetLanes++;
3052 if (passengerLanes > 0 && passengerLanes <= passengerTargetLanes) {
3057 if (rightCons.size() > 0) {
3060 int toLane = rc.
toLane + 1;
3064#ifdef DEBUG_CONNECTION_CHECKING
3065 std::cout <<
" recheck1 setConnection " <<
getID() <<
"_" << i <<
"->" << to->
getID() <<
"_" << toLane <<
"\n";
3081#ifdef DEBUG_CONNECTION_CHECKING
3082 std::cout <<
" recheck2 setConnection " <<
getID() <<
"_" << i <<
"->" << to->
getID() <<
"_" << (toLane + 1) <<
"\n";
3095 if (leftCons.size() > 0) {
3096 NBEdge* to = leftCons.front().toEdge;
3097 int toLane = leftCons.front().toLane - 1;
3101#ifdef DEBUG_CONNECTION_CHECKING
3102 std::cout <<
" recheck3 setConnection " <<
getID() <<
"_" << i <<
"->" << to->
getID() <<
"_" << toLane <<
"\n";
3111#ifdef ADDITIONAL_WARNINGS
3129 if (incoming.size() > 1) {
3130 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3132 bool connected =
false;
3133 for (std::vector<NBEdge*>::const_iterator in = incoming.begin(); in != incoming.end(); ++in) {
3134 if ((*in)->hasConnectionTo(
this, i)) {
3148 for (
int i = 0; i < (int)
myLanes.size(); i++) {
3150 if ((connNumbersPerLane[i] == 0 || ((lane.
accelRamp || (i > 0 &&
myLanes[i - 1].accelRamp && connNumbersPerLane[i - 1] > 0))
3155 if (forbiddenLeft && (i == 0 || forbiddenRight)) {
3158 }
else if (forbiddenRight && (i ==
getNumLanes() - 1 || (i > 0 &&
myLanes[i - 1].accelRamp))) {
3165#ifdef ADDITIONAL_WARNINGS
3172 bool hasAlternative =
false;
3174 if (c.fromLane == c2.fromLane && c.toEdge == c2.toEdge
3175 && (c.toEdge->getPermissions(c2.toLane) &
SVC_PASSENGER) != 0) {
3176 hasAlternative =
true;
3179 if (!hasAlternative) {
3180 WRITE_WARNING(
"Road lane ends on bikeLane for connection " + c.getDescription(
this));
3186#ifdef DEBUG_CONNECTION_GUESSING
3188 std::cout <<
"recheckLanes (final) edge=" <<
getID() <<
"\n";
3190 std::cout <<
" conn " << c.getDescription(
this) <<
"\n";
3207 for (
int i = 0; i < leftmostLane; i++) {
3208 const std::string& oppositeID =
getLanes()[i].oppositeID;
3209 NBEdge* oppEdge = ec.
retrieve(oppositeID.substr(0, oppositeID.rfind(
"_")));
3210 if (oppositeID !=
"" && oppositeID !=
"-") {
3211 if (
getLanes().back().oppositeID ==
"" && oppEdge !=
nullptr) {
3213 WRITE_WARNINGF(
TL(
"Moving opposite lane '%' from invalid lane '%' to lane index %."), oppositeID,
getLaneID(i), leftmostLane);
3220 const std::string& oppositeID =
getLanes().back().oppositeID;
3221 if (oppositeID !=
"" && oppositeID !=
"-") {
3222 NBEdge* oppEdge = ec.
retrieve(oppositeID.substr(0, oppositeID.rfind(
"_")));
3223 if (oppEdge ==
nullptr) {
3228 WRITE_WARNINGF(
TL(
"Opposite lane '%' does not reverse-connect the same nodes as edge '%'!"), oppositeID,
getID());
3233 WRITE_WARNINGF(
TL(
"Adapting invalid opposite lane '%' for edge '%' to '%'."), oppositeID,
getID(), oppEdgeLeftmost);
3237 const std::string leftmostID =
getLaneID(leftmostLane);
3239 WRITE_WARNINGF(
TL(
"Adapting missing opposite lane '%' for edge '%'."), leftmostID, oppEdge->
getID());
3244 if (oppOppEdge ==
nullptr) {
3249 WRITE_ERRORF(
TL(
"Opposite edge '%' does not reverse-connect the same nodes as edge '%'!"), oppEdge->
getID(), oppOppEdge->
getID());
3261 if (fixOppositeLengths) {
3263 WRITE_WARNINGF(
TL(
"Averaging edge lengths for lane '%' (length %) and edge '%' (length %)."),
3269 ") differs in length from edge '" +
getID() +
"' (length " +
3286 if (startOffset + l.endOffset >
getLength()) {
3287 WRITE_WARNINGF(
TL(
"Invalid endOffset % at lane '%' with length % (startOffset %)."),
3289 }
else if (l.speed < 0.) {
3291 }
else if (l.speed == 0.) {
3305#ifdef DEBUG_CONNECTION_CHECKING
3306 std::cout <<
" remove pedCon " << c.
getDescription(
this) <<
"\n";
3309 }
else if (common == 0) {
3312 const int origToLane = c.
toLane;
3314 int toLane = origToLane;
3327 toLane = origToLane;
3340#ifdef DEBUG_CONNECTION_CHECKING
3341 std::cout <<
" remove " << c.
getDescription(
this) <<
" with no alternative target\n";
3349#ifdef DEBUG_CONNECTION_CHECKING
3350 std::cout <<
" remove " << c.
getDescription(
this) <<
" (rail turnaround)\n";
3361 if (outgoing->size() == 0) {
3367#ifdef DEBUG_CONNECTION_GUESSING
3369 std::cout <<
" divideOnEdges " <<
getID() <<
" outgoing=" <<
toString(*outgoing) <<
"\n";
3374 std::vector<int> availableLanes;
3375 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3377 availableLanes.push_back(i);
3380 if (availableLanes.size() > 0) {
3384 availableLanes.clear();
3385 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3390 availableLanes.push_back(i);
3392 if (availableLanes.size() > 0) {
3396 availableLanes.clear();
3397 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3402 availableLanes.push_back(i);
3404 if (availableLanes.size() > 0) {
3408 availableLanes.clear();
3409 for (
int i = 0; i < (int)
myLanes.size(); ++i) {
3414 availableLanes.push_back(i);
3416 if (availableLanes.size() > 0) {
3420 bool explicitTurnaround =
false;
3423 if ((*i).fromLane == -1) {
3425 explicitTurnaround =
true;
3426 turnaroundPermissions = (*i).permissions;
3430 if (c.toLane == -1 && c.toEdge == (*i).toEdge) {
3432 c.permissions = (*i).permissions;
3441 if (explicitTurnaround) {
3452 if (priorities.empty()) {
3455#ifdef DEBUG_CONNECTION_GUESSING
3457 std::cout <<
"divideSelectedLanesOnEdges " <<
getID() <<
" out=" <<
toString(*outgoing) <<
" prios=" <<
toString(priorities) <<
" avail=" <<
toString(availableLanes) <<
"\n";
3461 const int numOutgoing = (int)outgoing->size();
3462 std::vector<int> resultingLanesFactor;
3463 resultingLanesFactor.reserve(numOutgoing);
3464 int minResulting = std::numeric_limits<int>::max();
3465 for (
int i = 0; i < numOutgoing; i++) {
3467 const int res = priorities[i] * (int)availableLanes.size();
3468 resultingLanesFactor.push_back(res);
3469 if (minResulting > res && res > 0) {
3481 transition.reserve(numOutgoing);
3482 for (
int i = 0; i < numOutgoing; i++) {
3484 assert(i < (
int)resultingLanesFactor.size());
3485 const int tmpNum = (resultingLanesFactor[i] + minResulting - 1) / minResulting;
3486 numVirtual += tmpNum;
3487 for (
int j = 0; j < tmpNum; j++) {
3488 transition.push_back((*outgoing)[i]);
3491#ifdef DEBUG_CONNECTION_GUESSING
3493 std::cout <<
" minResulting=" << minResulting <<
" numVirtual=" << numVirtual <<
" availLanes=" <<
toString(availableLanes) <<
" resLanes=" <<
toString(resultingLanesFactor) <<
" transition=" <<
toString(transition) <<
"\n";
3502 for (
NBEdge*
const target : *outgoing) {
3503 assert(l2eConns.find(target) != l2eConns.end());
3504 for (
const int j : l2eConns.find(target)->second) {
3505 const int fromIndex = availableLanes[j];
3506 if ((
getPermissions(fromIndex) & target->getPermissions()) == 0) {
3520 int targetLanes = target->getNumLanes();
3524 if (numConsToTarget >= targetLanes) {
3527 if (
myLanes[fromIndex].connectionsDone) {
3530#ifdef DEBUG_CONNECTION_GUESSING
3532 std::cout <<
" connectionsDone from " <<
getID() <<
"_" << fromIndex <<
": ";
3534 std::cout << c.getDescription(
this) <<
", ";
3542#ifdef DEBUG_CONNECTION_GUESSING
3544 std::cout <<
" request connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->getID() <<
"\n";
3557 const int numOutgoing = (int) outgoing->size();
3558 NBEdge* target =
nullptr;
3559 NBEdge* rightOfTarget =
nullptr;
3560 NBEdge* leftOfTarget =
nullptr;
3562 for (
int i = 0; i < numOutgoing; i++) {
3563 if (maxPrio < priorities[i]) {
3566 maxPrio = priorities[i];
3567 target = (*outgoing)[i];
3568 rightOfTarget = i == 0 ? outgoing->back() : (*outgoing)[i - 1];
3569 leftOfTarget = i + 1 == numOutgoing ? outgoing->front() : (*outgoing)[i + 1];
3573 if (target ==
nullptr) {
3581 const int numDesiredConsToTarget =
MIN2(targetLanes, (
int)availableLanes.size());
3582#ifdef DEBUG_CONNECTION_GUESSING
3584 std::cout <<
" checking extra lanes for target=" << target->
getID() <<
" cons=" << numConsToTarget <<
" desired=" << numDesiredConsToTarget <<
"\n";
3587 std::vector<int>::const_iterator it_avail = availableLanes.begin();
3588 while (numConsToTarget < numDesiredConsToTarget && it_avail != availableLanes.end()) {
3589 const int fromIndex = *it_avail;
3598 && !
myLanes[fromIndex].connectionsDone
3600#ifdef DEBUG_CONNECTION_GUESSING
3602 std::cout <<
" candidate from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3611#ifdef DEBUG_CONNECTION_GUESSING
3613 std::cout <<
" request additional connection from " <<
getID() <<
"_" << fromIndex <<
" to " << target->
getID() <<
"\n";
3619#ifdef DEBUG_CONNECTION_GUESSING
3624 <<
" rightOfTarget=" << rightOfTarget->
getID()
3625 <<
" leftOfTarget=" << leftOfTarget->
getID()
3636const std::vector<int>
3638 std::vector<int> priorities;
3645 priorities.reserve(outgoing->size());
3646 for (
const NBEdge*
const out : *outgoing) {
3648 assert((prio + 1) * 2 > 0);
3649 prio = (prio + 1) * 2;
3650 priorities.push_back(prio);
3655#ifdef DEBUG_CONNECTION_GUESSING
3657 <<
" outgoing=" <<
toString(*outgoing)
3658 <<
" priorities1=" <<
toString(priorities)
3663 assert(priorities.size() > 0);
3665#ifdef DEBUG_CONNECTION_GUESSING
3667 std::cout <<
" priorities2=" <<
toString(priorities) <<
"\n";
3674 if (mainDirections.
empty()) {
3675 assert(dist < (
int)priorities.size());
3676 priorities[dist] *= 2;
3677#ifdef DEBUG_CONNECTION_GUESSING
3679 std::cout <<
" priorities3=" <<
toString(priorities) <<
"\n";
3684 priorities[dist] += 1;
3689 priorities[(int)priorities.size() - 1] /= 2;
3690#ifdef DEBUG_CONNECTION_GUESSING
3692 std::cout <<
" priorities6=" <<
toString(priorities) <<
"\n";
3696 && outgoing->size() > 2
3697 && availableLanes.size() == 2
3698 && (*outgoing)[dist]->getPriority() == (*outgoing)[0]->getPriority()) {
3700 priorities.back() /= 2;
3701#ifdef DEBUG_CONNECTION_GUESSING
3703 std::cout <<
" priorities7=" <<
toString(priorities) <<
"\n";
3710 priorities[dist] *= 2;
3711#ifdef DEBUG_CONNECTION_GUESSING
3713 std::cout <<
" priorities4=" <<
toString(priorities) <<
"\n";
3717 priorities[dist] *= 3;
3718#ifdef DEBUG_CONNECTION_GUESSING
3720 std::cout <<
" priorities5=" <<
toString(priorities) <<
"\n";
3730NBEdge::appendTurnaround(
bool noTLSControlled,
bool noFringe,
bool onlyDeadends,
bool onlyTurnlane,
bool noGeometryLike,
bool checkPermissions) {
3743 bool isDeadEnd =
true;
3745 if ((c.toEdge->getPermissions(c.toLane)
3753 if (onlyDeadends && !isDeadEnd) {
3766 if (checkPermissions) {
3790 if (noGeometryLike && !isDeadEnd) {
3799 if (turnIncoming.size() > 1) {
3825 if (pos < tolerance) {
3839 for (
int i = 0; i < lanes; i++) {
3841 assert(el.tlID ==
"");
3863 if (c.fromLane == fromLane && c.toEdge == toEdge && c.toLane == toLane && c.uncontrolled) {
3883 assert(fromLane < 0 || fromLane < (
int)
myLanes.size());
3885 if (fromLane >= 0 && toLane >= 0) {
3887 std::vector<Connection>::iterator i =
3895 connection.
tlID = tlID;
3904 bool hadError =
false;
3906 if ((*i).toEdge != toEdge) {
3909 if (fromLane >= 0 && fromLane != (*i).fromLane) {
3912 if (toLane >= 0 && toLane != (*i).toLane) {
3915 if ((*i).tlID ==
"") {
3917 (*i).tlLinkIndex = tlIndex;
3918 (*i).tlLinkIndex2 = tlIndex2;
3921 if ((*i).tlID != tlID && (*i).tlLinkIndex == tlIndex) {
3922 WRITE_WARNINGF(
TL(
"The lane '%' on edge '%' already had a traffic light signal."), i->fromLane,
getID());
3927 if (hadError && no == 0) {
3928 WRITE_WARNINGF(
TL(
"Could not set any signal of the tlLogic '%' (unknown group)."), tlID);
3982 reason =
"laneNumber";
3992 reason =
"bidi-rail";
4006 if (find(conn.begin(), conn.end(), possContinuation) == conn.end()) {
4007 reason =
"disconnected";
4018 reason =
"disconnected";
4024 if (conns.size() <
myLanes.size() - offset) {
4025 reason =
"some lanes disconnected";
4038 if (maxJunctionSize >= 0) {
4039 const double junctionSize =
myGeom.back().distanceTo2D(possContinuation->
myGeom.front());
4040 if (junctionSize > maxJunctionSize + POSITION_EPS) {
4041 reason =
"junction size (" +
toString(junctionSize) +
") > max-junction-size (" +
toString(maxJunctionSize) +
")";
4047 reason =
"priority";
4057 reason =
"routingType";
4062 reason =
"spreadType";
4066 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4068 reason =
"lane " +
toString(i) +
" speed";
4070 }
else if (
myLanes[i].permissions != possContinuation->
myLanes[i].permissions) {
4071 reason =
"lane " +
toString(i) +
" permissions";
4073 }
else if (
myLanes[i].changeLeft != possContinuation->
myLanes[i].changeLeft ||
myLanes[i].changeRight != possContinuation->
myLanes[i].changeRight) {
4074 reason =
"lane " +
toString(i) +
" change restrictions";
4076 }
else if (
myLanes[i].width != possContinuation->
myLanes[i].width &&
4078 reason =
"lane " +
toString(i) +
" width";
4099 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4105 if (origID != origID2) {
4115 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4150 if (!result.empty() && !removed.empty()) {
4154 if (!result.empty()) {
4163 if ((*i).toEdge == e && (*i).tlID !=
"") {
4189 assert(distances.size() > 0);
4195NBEdge::addLane(
int index,
bool recomputeShape,
bool recomputeConnections,
bool shiftIndices) {
4196 assert(index <= (
int)
myLanes.size());
4200 int templateIndex = index > 0 ? index - 1 : index + 1;
4210 if (recomputeShape) {
4213 if (recomputeConnections) {
4214 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
4215 (*i)->invalidateConnections(
true);
4218 }
else if (shiftIndices) {
4221 if (c.fromLane >= index) {
4228 if (c.toEdge ==
this && c.toLane >= index) {
4240 int newLaneNo = (int)
myLanes.size() + by;
4241 while ((
int)
myLanes.size() < newLaneNo) {
4251 assert(index < (
int)
myLanes.size());
4256 for (EdgeVector::const_iterator i = incs.begin(); i != incs.end(); ++i) {
4257 (*i)->invalidateConnections(
true);
4260 }
else if (shiftIndices) {
4263 inc->removeFromConnections(
this, -1, index,
false,
true);
4271 int newLaneNo = (int)
myLanes.size() - by;
4272 assert(newLaneNo > 0);
4273 while ((
int)
myLanes.size() > newLaneNo) {
4291 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4295 assert(lane < (
int)
myLanes.size());
4296 myLanes[lane].permissions |= vclass;
4304 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4308 assert(lane < (
int)
myLanes.size());
4309 myLanes[lane].permissions &= ~vclass;
4317 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4321 assert(lane < (
int)
myLanes.size());
4322 myLanes[lane].permissions |= vclasses;
4323 myLanes[lane].preferred |= vclasses;
4333 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4339 assert(lane < (
int)
myLanes.size());
4346 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4352 assert(lane < (
int)
myLanes.size());
4383 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4406 return myLanes[lane].laneStopOffset;
4416 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4422 assert(lane < (
int)
myLanes.size());
4423 myLanes[lane].endOffset = offset;
4441 }
else if (lane < (
int)
myLanes.size()) {
4442 if (!
myLanes[lane].laneStopOffset.isDefined() || overwrite) {
4447 myLanes[lane].laneStopOffset = offset;
4462 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4468 assert(lane < (
int)
myLanes.size());
4478 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4484 assert(lane < (
int)
myLanes.size());
4485 myLanes[lane].friction = friction;
4492 assert(lane < (
int)
myLanes.size());
4493 myLanes[lane].accelRamp = accelRamp;
4500 assert(lane < (
int)
myLanes.size());
4501 myLanes[lane].customShape = shape;
4508 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4513 assert(lane < (
int)
myLanes.size());
4514 myLanes[lane].permissions = permissions;
4522 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4527 assert(lane < (
int)
myLanes.size());
4528 myLanes[lane].preferred = permissions;
4536 assert(lane < (
int)
myLanes.size());
4537 myLanes[lane].changeLeft = changeLeft;
4538 myLanes[lane].changeRight = changeRight;
4546 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4551 assert(lane < (
int)
myLanes.size());
4552 return myLanes[lane].permissions;
4570 for (std::vector<Lane>::iterator i =
myLanes.begin(); i !=
myLanes.end(); ++i) {
4571 (*i).permissions =
SVCAll;
4607 for (
int i = start; i != end; i += direction) {
4623 for (
int i = start; i != end; i += direction) {
4637 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4638 if (
myLanes[i].permissions == permissions) {
4650 for (
int i = start; i != end; i += direction) {
4651 if (
myLanes[i].permissions != 0) {
4655 return end - direction;
4659std::set<SVCPermissions>
4661 std::set<SVCPermissions> result;
4665 for (
int i = iStart; i < iEnd; ++i) {
4675 if ((allPermissions && (lane.permissions & permissions) == permissions)
4676 || (!allPermissions && (lane.permissions & permissions) != 0)) {
4705 std::cout <<
getID() <<
" angle=" <<
getAngleAtNode(node) <<
" convAngle=" << angle <<
"\n";
4723 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4728 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4762 if (lane.permissions == vclass) {
4783 if (newIndex == 0) {
4789 myLanes[newIndex].permissions = vclass;
4790 myLanes[newIndex].width = fabs(width);
4800 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4801 (*it)->shiftToLanesToEdge(
this, 1);
4812 if (
myLanes[0].permissions != vclass) {
4822 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
4823 (*it)->shiftToLanesToEdge(
this, 0);
4836 if ((*it).toEdge == to && (*it).toLane >= 0) {
4837 (*it).toLane += laneOff;
4849 const int i = (node ==
myTo ? -1 : 0);
4850 const int i2 = (node ==
myTo ? 0 : -1);
4857 const double missing = neededOffset - dist;
4858 const double missing2 = neededOffset2 - dist2;
4860 if (missing > 0 && missing2 > 0) {
4861 shift =
MIN2(missing, missing2);
4862 }
else if (missing2) {
4903 double avgEndOffset = 0;
4905 avgEndOffset += lane.endOffset;
4910 avgEndOffset /= (double)
myLanes.size();
4911 return MAX2(result - avgEndOffset, POSITION_EPS);
4917 if (laneIdx == -1) {
4918 for (
int i = 0; i < (int)
myLanes.size(); i++) {
4925 if (std::find(oldIDs.begin(), oldIDs.end(), origID) == oldIDs.end()) {
4926 oldIDs.push_back(origID);
4946 if (con.fromLane >= 0 && con.toLane >= 0 && con.toEdge !=
nullptr &&
4948 & con.toEdge->getPermissions(con.toLane) & vClass) != 0)
4963 std::pair<const NBEdge*, const Connection*> pair(con.toEdge,
nullptr);
4967 }
else if ((con.fromLane >= 0) && (con.toLane >= 0) &&
4968 (con.toEdge !=
nullptr) &&
4969 ((
getPermissions(con.fromLane) & con.toEdge->getPermissions(con.toLane) & vClass) == vClass)) {
4971 if (con.getLength() > 0) {
4985 std::cout <<
" " <<
getID() <<
"_" << c.fromLane <<
"->" << c.toEdge->getID() <<
"_" << c.toLane <<
"\n";
4991 if (c.toEdge ==
this) {
4992 std::cout <<
" " << inc->getID() <<
"_" << c.fromLane <<
"->" << c.toEdge->getID() <<
"_" << c.toLane <<
"\n";
5007 bool haveJoined =
false;
5012 const std::string newType =
myLanes[i].type +
"|" +
myLanes[i + 1].type;
5028 for (
NBEdge* edge : edges) {
5029 if ((edge->getPermissions() & permissions) != 0) {
5030 result.push_back(edge);
5039 if (cands.size() == 0) {
5043 NBEdge* best = cands.front();
5054 if (cands.size() == 0) {
5058 NBEdge* best = cands.front();
5069 NBEdge* opposite =
nullptr;
5075 if (cand->getToNode() ==
getFromNode() && !cand->getLanes().empty()) {
5076 const NBEdge::Lane& candLastLane = cand->getLanes().back();
5078 const double lastWidthCand = cand->getLaneWidth(cand->getNumLanes() - 1);
5081 const double threshold = 1.42 * 0.5 * (lastWidth + lastWidthCand) + 0.5;
5084 if (distance < threshold) {
5090 if (opposite !=
nullptr) {
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGEF(...)
#define WRITE_ERRORF(...)
#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 permissions is a (exclusive) railway edge.
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permissions is a forbidden edge.
bool isBikepath(SVCPermissions permissions)
Returns whether an edge with the given permissions is a bicycle edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_DELIVERY
vehicle is a small delivery vehicle
@ SVC_TRAM
vehicle is a light rail
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
@ RIGHT
At the rightmost side of the lane.
const std::string SUMO_PARAM_ORIGID
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
const std::string SUMO_PARAM_REMOVED_NODES
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ PARTRIGHT
The link is a partial right direction.
@ NODIR
The link has no direction (is a dead end link)
double roundDecimalToEven(double x, int precision)
round to the given number of decimal digits (bankers rounding)
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
Storage for edges, including some functionality operating on multiple edges.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
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 updateRemovedNodes(const std::string &removed)
update parameter with removed nodes
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
static std::vector< LinkDirection > decodeTurnSigns(int turnSigns, int shift=0)
decode bitset
void mirrorX()
mirror coordinates along the x-axis
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
set preferred Vehicle Class
static const int TURN_SIGN_SHIFT_BUS
shift values for decoding turn signs
double getLaneSpeed(int lane) const
get lane speed
static const int TURN_SIGN_SHIFT_BICYCLE
NBEdge * guessOpposite(bool reguess=false)
set oppositeID and return opposite edge if found
void setPermittedChanging(int lane, SVCPermissions changeLeft, SVCPermissions changeRight)
set allowed classes for changing to the left and right from the given lane
double getLength() const
Returns the computed length of the edge.
double myLaneWidth
This width of this edge's lanes.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
std::vector< Connection > myConnectionsToDelete
List of connections marked for delayed removal.
const EdgeVector * getConnectedSorted()
Returns the list of outgoing edges without the turnaround sorted in clockwise direction.
double getDistancAt(double pos) const
get distance at the given offset
double myEndOffset
This edges's offset to the intersection begin (will be applied to all lanes)
int myToJunctionPriority
The priority normalised for the node the edge is incoming in.
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
StopOffset myEdgeStopOffset
A vClass specific stop offset - assumed of length 0 (unspecified) or 1. For the latter case the int i...
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
double getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
void addBikeLane(double width)
add a bicycle lane of the given width and shift existing connctions
bool expandableBy(NBEdge *possContinuation, std::string &reason) const
Check if Node is expandable.
double getLaneFriction(int lane) const
get lane friction of specified lane
void recheckOpposite(const NBEdgeCont &ec, bool fixOppositeLengths)
recheck whether all opposite and bidi settings are consistent
const ConstRouterEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING, bool ignoreTransientPermissions=false) const
Returns the following edges for the given vClass.
void init(int noLanes, bool tryIgnoreNodePositions, const std::string &origID)
Initialization routines common to all constructors.
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
double mySpeed
The maximal speed.
bool hasLaneSpecificFriction() const
whether lanes differ in friction
double getLaneWidth() const
Returns the default width of lanes of this edge.
PositionVector getCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going clock-wise around the given node
NBNode * getToNode() const
Returns the destination node of the edge.
void checkGeometry(const double maxAngle, bool fixAngle, const double minRadius, bool fix, bool silent)
Check the angles of successive geometry segments.
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
Lane & getLaneStruct(int lane)
const Connection & getConnection(int fromLane, const NBEdge *to, int toLane) const
Returns the specified connection (unmodifiable) This method goes through "myConnections" and returns ...
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
void removeInvalidConnections()
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.
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)
moves a connection one place to the left;
void updateChangeRestrictions(SVCPermissions ignoring)
modify all existing restrictions on lane changing
void restoreBikelane(std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore an previously added BikeLane
Position getEndpointAtNode(const NBNode *node) const
NBEdge * getStraightContinuation(SVCPermissions permissions) const
return the straightest follower edge for the given permissions or nullptr (never returns turn-arounds...
bool hasLoadedLength() const
Returns whether a length was set explicitly.
void resetEndpointAtNode(const NBNode *node)
void restoreSidewalk(std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore an previously added sidewalk
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false, SVCPermissions permission=SVC_UNSPECIFIED)
Adds a connection to another edge.
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, const bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
void divideSelectedLanesOnEdges(const EdgeVector *outgoing, const std::vector< int > &availableLanes)
divide selected lanes on edges
bool setEdgeStopOffset(int lane, const StopOffset &offset, bool overwrite=false)
set lane and vehicle class specific stopOffset (negative lane implies set for all lanes)
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
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 rechecked.
@ LANES2LANES_DONE
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
@ LANES2EDGES
Lanes to edges - relationships are computed/loaded.
@ LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
@ INIT
The edge has been loaded, nothing is computed yet.
NBEdge * getStraightPredecessor(SVCPermissions permissions) const
return the straightest predecessor edge for the given permissions or nullptr (never returns turn-arou...
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
double getSpeed() const
Returns the speed allowed on this edge.
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
bool shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap and return whether geometry was changed
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
void roundSpeed()
ensure consistency between input and output speed
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.
std::vector< Connection > getConnectionsFromLane(int lane, const NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
bool hasAccelLane() const
whether one of the lanes is an acceleration lane
bool myIsBidi
whether this edge is part of a non-rail bidi edge pair
static double firstIntersection(const PositionVector &v1, const PositionVector &v2, double width1, double width2, const std::string &error="", bool secondIntersection=false)
compute the first intersection point between the given lane geometries considering their rspective wi...
PositionVector myToBorder
void extendGeometryAtNode(const NBNode *node, double maxExtent)
linearly extend the geometry at the given node
void setFriction(int lane, double friction)
set lane specific friction (negative lane implies set for all lanes)
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
static const double ANGLE_LOOKAHEAD
the distance at which to take the default angle
int getNumLanesThatAllow(SVCPermissions permissions, bool allPermissions=true) const
void reduceGeometry(const double minDist)
Removes points with a distance lesser than the given.
static NBEdge DummyEdge
Dummy edge to use when a reference must be supplied in the no-arguments constructor (FOX technicality...
bool joinLanes(SVCPermissions perms)
join adjacent lanes with the given permissions
void resetNodeBorder(const NBNode *node)
void markAsInLane2LaneState()
mark edge as in lane to state lane
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
return true if certain connection must be controlled by TLS
void addRestrictedLane(double width, SUMOVehicleClass vclass)
add a lane of the given width, restricted to the given class and shift existing connections
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
double myLength
The length of the edge.
NBEdge::Lane getFirstNonPedestrianLane(int direction) const
get first non-pedestrian lane
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
const std::vector< int > prepareEdgePriorities(const EdgeVector *outgoing, const std::vector< int > &availableLanes)
recomputes the edge priorities and manipulates them for a distribution of lanes on edges which is mor...
int myIndex
the index of the edge in the list of all edges. Set by NBEdgeCont and requires re-set whenever the li...
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
PositionVector cutAtIntersection(const PositionVector &old) const
cut shape at the intersection shapes
Position geometryPositionAtOffset(double offset) const
return position taking into account loaded length
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
bool canMoveConnection(const Connection &con, int newFromLane) const
whether the connection can originate on newFromLane
double getInternalLaneWidth(const NBNode &node, const NBEdge::Connection &connection, const NBEdge::Lane &successor, bool isVia) const
Returns the width of the internal lane associated with the connection.
void allowVehicleClass(int lane, SUMOVehicleClass vclass)
set allowed class for the given lane or for all lanes if -1 is given
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
double getMaxLaneOffset()
get max lane offset
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
NBEdge * myPossibleTurnDestination
The edge that would be the turn destination if there was one.
const PositionVector & getNodeBorder(const NBNode *node) const
const NBNode * mySignalNode
bool hasLaneSpecificWidth() const
whether lanes differ in width
void moveConnectionToRight(int lane)
moves a connection one place to the right; @noteAttention! no checking for field validity
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
void reshiftPosition(double xoff, double yoff)
Applies an offset to the edge.
static const int TURN_SIGN_SHIFT_TAXI
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
std::string getLaneID(int lane) const
get lane ID
bool myIsOffRamp
whether this edge is an Off-Ramp or leads to one
static const double UNSPECIFIED_SPEED
unspecified lane speed
Lane2LaneInfoType
Modes of setting connections between lanes.
@ USER
The connection was given by the user.
@ VALIDATED
The connection was computed and validated.
@ COMPUTED
The connection was computed.
double getFriction() const
Returns the friction on this edge.
static PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode, PositionVector nodeShape)
std::string getSidewalkID()
get the lane id for the canonical sidewalk lane
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 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)
static void updateTurnPermissions(SVCPermissions &perm, LinkDirection dir, SVCPermissions spec, std::vector< LinkDirection > dirs)
void sortOutgoingConnectionsByAngle()
sorts the outgoing connections by their angle relative to their junction
bool applyTurnSigns()
apply loaded turn sign information
bool haveIntersection(const NBNode &n, const PositionVector &shape, const NBEdge *otherFrom, const NBEdge::Connection &otherCon, int numPoints, double width1, double width2, int shapeFlag=0) const
void preferVehicleClass(int lane, SVCPermissions vclasses)
prefer certain vehicle classes for the given lane or for all lanes if -1 is given (ensures also permi...
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
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.
void roundGeometry()
ensure consistency between input and output geometries
std::string myRoutingType
The routing type of the edge.
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing, bool withBikes=true, bool withBusLanes=true) const
Returns the list of lanes that may be used to reach the given edge.
bool myAmInTLS
Information whether this is lies within a joined tls.
void setTurningDestination(NBEdge *e, bool onlyPossible=false)
Sets the turing destination at the given edge.
bool hasDefaultGeometryEndpointAtNode(const NBNode *node) const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
NBEdge * myTurnDestination
The turn destination edge (if a connection exists)
int getPriority() const
Returns the priority of the edge.
void computeEdgeShape(double smoothElevationThreshold=-1)
Recomputeds the lane shapes to terminate at the node shape For every lane the intersection with the f...
double assignInternalLaneLength(std::vector< Connection >::iterator i, int numLanes, double lengthSum, bool averageLength)
assign length to all lanes of an internal edge
static const double UNSPECIFIED_WIDTH
unspecified lane width
bool hasRestrictedLane(SUMOVehicleClass vclass) const
returns whether any lane already allows the given vclass exclusively
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
const StopOffset & getLaneStopOffset(int lane) const
Returns the stop offset to the specified lane's end.
void debugPrintConnections(bool outgoing=true, bool incoming=false) const
debugging helper to print all connections
Position mySignalPosition
the position of a traffic light signal on this edge
void replaceInConnections(NBEdge *which, NBEdge *by, int laneOff)
replace in current connections of edge
bool lanesWereAssigned() const
Check if lanes were assigned.
void restoreRestrictedLane(SUMOVehicleClass vclass, std::vector< NBEdge::Lane > oldLanes, PositionVector oldGeometry, std::vector< NBEdge::Connection > oldConnections)
restore a restricted lane
double getEndOffset() const
Returns the offset to the destination node.
bool isRailDeadEnd() const
whether this edge is a railway edge that does not continue
double myFriction
The current friction.
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
static const double UNSPECIFIED_OFFSET
unspecified lane offset
void sortOutgoingConnectionsByIndex()
sorts the outgoing connections by their from-lane-index and their to-lane-index
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again
int myFromJunctionPriority
The priority normalised for the node the edge is outgoing of.
bool addLane2LaneConnections(int fromLane, NBEdge *dest, int toLane, int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
void setOrigID(const std::string origID, const bool append, const int laneIdx=-1)
set origID for all lanes or for a specific lane
PositionVector computeLaneShape(int lane, double offset) const
Computes the shape for the given lane.
bool allowsChangingLeft(int lane, SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
static int getLaneIndexFromLaneID(const std::string laneID)
bool hasConnectionTo(const NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
bool hasCustomLaneShape() const
whether one of the lanes has a custom shape
bool hasLaneParams() const
whether one of the lanes has parameters set
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
double getShapeEndAngle() const
Returns the angle at the end of the edge.
bool prohibitsChanging() const
whether one of the lanes prohibits lane changing
void setLoadedLength(double val)
set loaded length
PositionVector myGeom
The geometry for the edge.
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
void decLaneNo(int by)
decrement lane
NBNode * myFrom
The source and the destination node.
void append(NBEdge *continuation)
append another edge
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
double getFinalLength() const
get length that will be assigned to the lanes in the final network
void shortenGeometryAtNode(const NBNode *node, double reduction)
linearly extend the geometry at the given node
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
int myPriority
The priority of the edge.
std::string myStreetName
The street name (or whatever arbitrary string you wish to attach)
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
int getFirstNonPedestrianNonBicycleLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN, SVC_BICYCLE and 0
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
A definition of a pedestrian crossing.
PositionVector shape
The crossing's shape.
bool priority
whether the pedestrians have priority
EdgeVector edges
The edges being crossed.
double width
This crossing's width.
Represents a single node (junction) during network building.
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
static const int AVOID_INTERSECTING_LEFT_TURNS
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
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, bool checkOnlyTLS=false) const
whether an internal junction should be built at from and respect other
FringeType getFringeType() const
Returns fringe type.
static const int BACKWARD
SumoXMLNodeType getType() const
Returns the type of this node.
bool isTrafficLight() const
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.
bool bidiConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether the foe connections is oncoming on the same lane
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0, int shapeFlag=0) const
Compute a smooth curve between the given geometries.
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
bool mergeConflict(const NBEdge *from, const NBEdge::Connection &con, const NBEdge *prohibitorFrom, const NBEdge::Connection &prohibitorCon, bool foes) const
whether multiple connections from the same edge target the same lane
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.
bool hasParameter(const std::string &key) const
Returns whether the parameter is set.
void mergeParameters(const Parameterised::Map &mapArg, const std::string separator=" ", bool uniqueValues=true)
Adds or appends all given parameters from the map.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
const Parameterised::Map & getParametersMap() const
Returns the inner key/value map.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void updateParameters(const Parameterised::Map &mapArg)
Adds or updates all given parameters from the map.
A point in 2D or 3D with translation and scaling methods.
static const Position INVALID
used to indicate that a position is valid
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
void add(const Position &pos)
Adds the given position to this one.
void setz(double z)
set position z
double z() const
Returns the z-position.
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position (in radians bet...
void sety(double y)
set position y
double y() const
Returns the y-position.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double beginEndAngle() const
returns the angle in radians of the line connecting the first and the last position
double length() const
Returns the length.
void round(int precision, bool avoidDegeneration=true)
round all coordinates to the given precision
void ensureMinLength(int precision)
ensure minimum length so that the geometry will not degenerate to 0-length on writing with the given ...
void push_front_noDoublePos(const Position &p)
insert in front a non double position
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void add(double xoff, double yoff, double zoff)
void closePolygon()
ensures that the last position equals the first
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0, double deg=90) const
return orthogonal through p (extending this vector if necessary)
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
bool almostSame(const PositionVector &v2, double maxDiv=POSITION_EPS) const
check if the two vectors have the same length and pairwise similar positions
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
PositionVector smoothedZFront(double dist=std::numeric_limits< double >::max()) const
returned vector that is smoothed at the front (within dist)
double angleAt2D(int pos) const
get angle in certain position of position vector (in radians between -M_PI and M_PI)
bool hasElevation() const
return whether two positions differ in z-coordinate
static const PositionVector EMPTY
empty Vector
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
Position getCentroid() const
Returns the centroid (closes the polygon if unclosed)
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
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
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point.
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
bool isDefined() const
check if stopOffset was defined
double getOffset() const
get offset
std::vector< std::string > getVector()
return vector of strings
Some static methods for string processing.
static std::string convertUmlaute(std::string str)
Converts german "Umlaute" to their latin-version.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static T maxValue(const std::vector< T > &v)
A structure which describes a connection between edges or lanes.
bool indirectLeft
Whether this connection is an indirect left turn.
int fromLane
The lane the connections starts at.
std::string viaID
if Connection have a via, ID of it
int toLane
The lane the connections yields in.
std::vector< int > foeInternalLinks
FOE Internal links.
Connection(int fromLane_, NBEdge *toEdge_, int toLane_, const bool mayDefinitelyPass_=false)
Constructor.
std::string getInternalViaLaneID() const
get ID of internal lane (second part)
double speed
custom speed for connection
NBEdge * toEdge
The edge the connections yields in.
double customLength
custom length for connection
double vmax
maximum velocity
PositionVector customShape
custom shape for connection
PositionVector viaShape
shape of via
std::string getDescription(const NBEdge *parent) const
get string describing this connection
double contPos
custom position for internal junction on this connection
std::string getInternalLaneID() const
get ID of internal lane
int internalLaneIndex
The lane index of this internal lane within the internal edge.
std::string tlID
The id of the traffic light that controls this connection.
int tlLinkIndex2
The index of the internal junction within the controlling traffic light (optional)
double length
computed length (average of all internal lane shape lengths that share an internal edge)
PositionVector shape
shape of Connection
std::string id
id of Connection
std::vector< std::string > foeIncomingLanes
FOE Incomings lanes.
bool haveVia
check if Connection have a Via
int tlLinkIndex
The index of this connection within the controlling traffic light.
double viaLength
the length of the via shape (maybe customized)
static ConstRouterEdgePairVector myViaSuccessors
An (internal) definition of a single lane of an edge.
double width
This lane's width.
std::string oppositeID
An opposite lane ID, if given.
SVCPermissions changeRight
List of vehicle types that are allowed to change right from this lane.
SVCPermissions changeLeft
List of vehicle types that are allowed to change Left from this lane.
Lane(NBEdge *e, const std::string &_origID)
constructor
bool accelRamp
Whether this lane is an acceleration lane.
PositionVector shape
The lane's shape.