54#define JOIN_TRAM_MAX_ANGLE 10
55#define JOIN_TRAM_MIN_LENGTH 3
59#define DEBUG_EDGE_ID ""
66 myVehicleClasses2Keep(0),
67 myVehicleClasses2Remove(0),
68 myNeedGeoTransformedPruningBoundary(false) {
83 if (oc.
isSet(
"keep-edges.input-file")) {
86 if (oc.
isSet(
"remove-edges.input-file")) {
89 if (oc.
isSet(
"keep-edges.explicit")) {
90 const std::vector<std::string> edges = oc.
getStringVector(
"keep-edges.explicit");
93 if (oc.
isSet(
"remove-edges.explicit")) {
94 const std::vector<std::string> edges = oc.
getStringVector(
"remove-edges.explicit");
97 if (oc.
exists(
"keep-edges.by-vclass") && oc.
isSet(
"keep-edges.by-vclass")) {
100 if (oc.
exists(
"remove-edges.by-vclass") && oc.
isSet(
"remove-edges.by-vclass")) {
103 if (oc.
exists(
"keep-edges.by-type") && oc.
isSet(
"keep-edges.by-type")) {
104 const std::vector<std::string> types = oc.
getStringVector(
"keep-edges.by-type");
107 if (oc.
exists(
"remove-edges.by-type") && oc.
isSet(
"remove-edges.by-type")) {
108 const std::vector<std::string> types = oc.
getStringVector(
"remove-edges.by-type");
112 if (oc.
isSet(
"keep-edges.in-boundary") || oc.
isSet(
"keep-edges.in-geo-boundary")) {
115 "keep-edges.in-boundary" :
"keep-edges.in-geo-boundary");
120 if (boundaryShape.size() < 2) {
121 throw ProcessError(
TL(
"Invalid boundary: need at least 2 coordinates"));
122 }
else if (boundaryShape.size() == 2) {
134 "keep-edges.in-boundary" :
"keep-edges.in-geo-boundary");
135 std::vector<double> poly;
136 for (std::vector<std::string>::iterator i = polyS.begin(); i != polyS.end(); ++i) {
139 if (poly.size() < 4) {
140 throw ProcessError(
TL(
"Invalid boundary: need at least 2 coordinates"));
141 }
else if (poly.size() % 2 != 0) {
143 }
else if (poly.size() == 4) {
150 for (std::vector<double>::iterator j = poly.begin(); j != poly.end();) {
164 for (
const auto& i :
myEdges) {
193 if (oc.
exists(
"dismiss-vclasses") && oc.
getBool(
"dismiss-vclasses")) {
261 WRITE_ERROR(
TL(
"Cannot prune edges using a geo-boundary because no projection has been loaded"));
282 EdgeCont::const_iterator i =
myEdges.find(
id);
284 if (retrieveExtracted) {
319 if (edge !=
nullptr) {
323 if ((
retrieve(
id +
"[0]") !=
nullptr) && (
retrieve(
id +
"[1]") !=
nullptr)) {
339 if (edge !=
nullptr) {
346 if (hintedge ==
nullptr) {
349 hints.push_back(hintedge);
352 for (
const NBEdge*
const currHint : hints) {
353 for (
NBEdge*
const poss_searched : candidates) {
354 const NBNode*
const node = incoming ? poss_searched->myTo : poss_searched->myFrom;
356 if (find(cont.begin(), cont.end(), currHint) != cont.end()) {
357 return poss_searched;
369 if (edge !=
nullptr) {
373 std::string tid =
id +
"[";
374 for (EdgeCont::const_iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
375 if ((*i).first.find(tid) == 0) {
376 maxLength =
MAX2(maxLength, (
int)(*i).first.length());
381 std::vector<std::string> names;
382 names.push_back(
id +
"[1]");
383 names.push_back(
id +
"[0]");
384 while (names.size() > 0) {
386 std::string cid = names.back();
391 if (edge ==
nullptr) {
392 if ((
int)cid.length() + 3 < maxLength) {
393 names.push_back(cid +
"[1]");
394 names.push_back(cid +
"[0]");
422 if (edge != prevExtracted->second) {
424 prevExtracted->second = edge;
439 if (
myEdges.count(newID) != 0) {
440 throw ProcessError(
TLF(
"Attempt to rename edge using existing id '%'", newID));
446 if (edge->
getLanes().back().oppositeID !=
"") {
448 if (oppo !=
nullptr) {
460 if (splits.empty()) {
463 const std::string origID = e->
getID();
469 maxNumLanes =
MAX2(maxNumLanes, (
int)
split.lanes.size());
472 std::vector<int> currLanes;
474 currLanes.push_back(l);
476 if (e->
getNumLanes() != (
int)splits.back().lanes.size()) {
484 std::string firstID =
"";
486 for (
const Split& exp : splits) {
487 assert(exp.lanes.size() != 0);
488 if (exp.pos > 0 && e->
getLoadedLength() + seen > exp.pos && exp.pos > seen) {
492 const std::string idBefore = exp.idBefore ==
"" ? e->
getID() : exp.idBefore;
493 const std::string idAfter = exp.idAfter ==
"" ? exp.nameID : exp.idAfter;
497 const bool ok =
splitAt(dc, e, exp.pos - seen, exp.node,
498 idBefore, idAfter, e->
getNumLanes(), (
int) exp.lanes.size(), exp.speed);
504 std::vector<int> newLanes = exp.lanes;
510 int rightMostP = currLanes[0];
511 int rightMostN = newLanes[0];
512 for (
int l = 0; l < (int) rightMostP - (
int) rightMostN; ++l) {
516 int leftMostP = currLanes.back();
517 int leftMostN = newLanes.back();
518 for (
int l = 0; l < (int) leftMostN - (
int) leftMostP; ++l) {
522 for (
int l = 0; l < maxNumLanes; ++l) {
523 if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) {
526 if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) {
535 if (exp.node->getIncomingEdges().size() > 1 || exp.node->getOutgoingEdges().size() > 1 || exp.node->getType() ==
SumoXMLNodeType::ZIPPER) {
536 for (
NBEdge* in : exp.node->getIncomingEdges()) {
537 in->invalidateConnections(
true);
542 currLanes = newLanes;
543 }
else if (exp.pos == 0) {
544 const int laneCountDiff = e->
getNumLanes() - (int)exp.lanes.size();
545 if (laneCountDiff < 0) {
550 currLanes = exp.lanes;
554 if (exp.speed != -1.) {
564 if (splits.front().pos != 0) {
568 for (
int lane = 0; lane < (int)e->
getNumLanes(); ++lane) {
569 start.
lanes.push_back(lane);
571 start.
offset = splits.front().offset;
573 splits.insert(splits.begin(), start);
576 int maxLeft =
split.lanes.back();
577 double offset =
split.offset;
578 if (maxLeft < maxNumLanes) {
585 int maxRight =
split.lanes.front();
612 const std::string& firstEdgeName,
613 const std::string& secondEdgeName,
614 int noLanesFirstEdge,
int noLanesSecondEdge,
615 const double speed,
const double friction,
616 const int changedLeft) {
627 return splitAt(dc, edge, pos, node, firstEdgeName, secondEdgeName,
628 noLanesFirstEdge, noLanesSecondEdge, speed, friction, changedLeft);
635 const std::string& firstEdgeName,
636 const std::string& secondEdgeName,
637 int noLanesFirstEdge,
int noLanesSecondEdge,
638 const double speed,
const double friction,
639 const int changedLeft) {
640 if (firstEdgeName != edge->
getID() &&
myEdges.count(firstEdgeName) != 0) {
641 WRITE_ERRORF(
TL(
"Could not insert edge '%' before split of edge '%'."), firstEdgeName, edge->
getID());
644 if (secondEdgeName == firstEdgeName || (secondEdgeName != edge->
getID() &&
myEdges.count(secondEdgeName) != 0)) {
645 WRITE_ERRORF(
TL(
"Could not insert edge '%' after split of edge '%'."), secondEdgeName, edge->
getID());
649 assert(changedLeft > -((
int)noLanesFirstEdge));
650 assert(changedLeft < (
int)noLanesSecondEdge);
653 double geomPos = pos;
660 std::pair<PositionVector, PositionVector> geoms = edge->
getGeometry().
splitAt(geomPos);
667 NBEdge* one =
new NBEdge(firstEdgeName, edge->
myFrom, node, edge, geoms.first, noLanesFirstEdge);
668 NBEdge* two =
new NBEdge(secondEdgeName, node, edge->
myTo, edge, geoms.second, noLanesSecondEdge);
671 if (firstEdgeName != origID) {
674 if (secondEdgeName != origID) {
682 if (friction != -1.) {
698 tld->replaceRemoved(edge, -1, one, -1,
false);
701 tld->replaceRemoved(edge, -1, two, -1,
true);
712 for (
int i2 = 0; i2 < (int)two->
getNumLanes(); i2++) {
731 const std::string oldID = edge->
getID();
744 std::set<EdgeSet> addLater;
745 for (std::set<EdgeSet>::iterator it = roundabouts.begin(); it != roundabouts.end(); ++it) {
747 if (roundaboutSet.count(orig) > 0) {
748 roundaboutSet.erase(orig);
749 roundaboutSet.insert(part1);
750 roundaboutSet.insert(part2);
752 addLater.insert(roundaboutSet);
755 roundabouts.insert(addLater.begin(), addLater.end());
760std::vector<std::string>
762 std::vector<std::string> ret;
763 for (EdgeCont::const_iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
764 ret.push_back((*i).first);
772 NBEdge* longest =
nullptr;
774 if (item.first->getID() == edgeID) {
775 if (longest ==
nullptr || longest->
getLoadedLength() < item.first->getLoadedLength()) {
776 longest =
const_cast<NBEdge*
>(item.first);
787 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
788 NBEdge* edge = (*i).second;
792 toRemove.push_back(edge);
795 for (EdgeVector::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
798 return (
int)toRemove.size();
806 for (
auto& item : edges) {
807 NBEdge* edge = item.second;
812 const std::string
id = edge->
getID();
814 for (
int i = 1; i < (int)geom.size() - 1; i++) {
815 offset += geom[i - 1].distanceTo(geom[i]);
816 std::string nodeID =
id +
"." +
toString((
int)offset);
817 if (!nc.
insert(nodeID, geom[i])) {
831 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
832 (*i).second->reduceGeometry(minDist);
839 if (maxAngle > 0 || minRadius > 0) {
844 item.second->checkGeometry(maxAngle, fixAngle, minRadius, fix || (fixRailways &&
isRailway(item.second->getPermissions())), silent);
853 for (EdgeCont::const_iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
854 (*i).second->clearControllingTLInformation();
861 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
862 (*i).second->sortOutgoingConnectionsByAngle();
869 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
870 (*i).second->computeEdge2Edges(noLeftMovers);
877 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
878 (*i).second->computeLanes2Edges();
886 for (
const auto& edgeIt :
myEdges) {
887 NBEdge*
const edge = edgeIt.second;
896 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
897 (*i).second->appendTurnaround(noTLSControlled, noFringe, onlyDeadends, onlyTurnlane, noGeometryLike,
true);
904 for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
905 myEdges[*it]->appendTurnaround(noTLSControlled,
false,
false,
false,
false,
false);
912 std::set<std::string> stopEdgeIDs;
913 for (
auto& stopItem : sc.
getStops()) {
914 stopEdgeIDs.insert(stopItem.second->getEdgeId());
917 NBEdge* edge = item.second;
919 && (stopEdgeIDs.count(item.first) > 0 ||
934 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
935 (*i).second->computeEdgeShape(smoothElevationThreshold);
938 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); i++) {
940 const std::string& oppositeID = edge->
getLanes().back().oppositeID;
941 if (oppositeID !=
"" && oppositeID !=
"-") {
942 NBEdge* oppEdge =
retrieve(oppositeID.substr(0, oppositeID.rfind(
"_")));
958 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
959 (*i).second->computeLaneShapes();
977 bool joinEdges =
true;
981 NBEdge* tpledge = *(edges.begin());
984 EdgeVector::const_iterator i;
985 int myPriority = (*edges.begin())->getPriority();
986 for (i = edges.begin(); i != edges.end(); i++) {
988 assert((*i)->getFromNode() == from);
989 assert((*i)->getToNode() == to);
991 nolanes += (*i)->getNumLanes();
993 if (i != edges.begin()) {
998 speed += (*i)->getSpeed();
1001 if (myPriority == (*i)->getPriority()) {
1002 priority = myPriority;
1009 speed /= (double)edges.size();
1016 for (i = edges.begin(); i != edges.end(); ++i) {
1017 const std::vector<NBEdge::Lane>& lanes = (*i)->getLanes();
1018 for (
int j = 0; j < (int)lanes.size(); ++j) {
1032 for (i = edges.begin(); i != edges.end(); i++) {
1034 for (EdgeVector::iterator j = ev.begin(); j != ev.end(); j++) {
1040 for (i = edges.begin(); i != edges.end(); i++) {
1042 currLane += (*i)->getNumLanes();
1046 for (i = edges.begin(); i != edges.end(); i++) {
1047 int noLanes = (*i)->getNumLanes();
1048 for (
int j = 0; j < noLanes; j++, currLane++) {
1055 for (i = edges.begin(); i != edges.end(); i++) {
1067 for (
const auto& edgeIt :
myEdges) {
1068 NBEdge*
const edge = edgeIt.second;
1071 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
1072 NBEdge* edge = i->second;
1080 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
1082 if (opposite !=
nullptr) {
1094 const std::string oppositeID = edgeID[0] ==
'-' ? edgeID.substr(1) :
"-" + edgeID;
1095 EdgeCont::const_iterator it =
myEdges.find(oppositeID);
1101 EdgeCont::const_iterator it =
myEdges.find(edgeID);
1108 KeepClear keepClear,
double contPos,
double visibility,
double speed,
double friction,
double length,
1109 const PositionVector& customShape,
bool uncontrolled,
bool warnOnly,
1112 speed, friction, length, customShape, uncontrolled, warnOnly, permissions, indirectLeft, edgeType, changeLeft, changeRight));
1137 for (std::vector<PostProcessConnection>::const_iterator i = item.second.begin(); i != item.second.end(); ++i) {
1140 if (from ==
nullptr || to ==
nullptr ||
1142 (*i).keepClear, (*i).contPos, (*i).visibility, (*i).speed, (*i).friction, (*i).customLength, (*i).customShape,
1143 (*i).uncontrolled, (*i).permissions, (*i).indirectLeft, (*i).edgeType, (*i).changeLeft, (*i).changeRight,
1145 const std::string msg =
"Could not insert connection between '" + (*i).from +
"' and '" + (*i).to +
"' after build.";
1146 if (warnOnly || (*i).warnOnly) {
1156 for (EdgeCont::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
1157 NBEdge* edge = it->second;
1160 std::vector<NBEdge::Connection> connections = edge->
getConnections();
1161 for (std::vector<NBEdge::Connection>::iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
1165 "' to edge '" + c.
toEdge->
getID() +
"' via junction '" + to->
getID() +
"'.");
1175 int len = (int)
id.length();
1177 for (EdgeCont::const_iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
1178 std::string curr = (*i).first;
1181 if ((
int)curr.length() <= len) {
1186 if (curr.substr(0, len) ==
id && curr[len] ==
'[') {
1187 ret.push_back((*i).second);
1191 std::string::size_type pos = curr.find(
id);
1193 if (pos == std::string::npos) {
1198 if (curr[pos - 1] !=
']' && curr[pos - 1] !=
'+') {
1203 if (pos +
id.length() < curr.length()) {
1204 if (curr[pos +
id.length()] !=
'[' && curr[pos +
id.length()] !=
'+') {
1209 ret.push_back((*i).second);
1218 std::set<NBEdge*> loadedRoundaboutEdges;
1220 loadedRoundaboutEdges.insert(it->begin(), it->end());
1224 std::set<NBEdge*> candidates;
1226 for (EdgeCont::const_iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
1232 candidates.insert(e);
1237 std::set<NBEdge*> visited;
1238 for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) {
1245 if (visited.count(e) > 0) {
1249 loopEdges.push_back(e);
1251#ifdef DEBUG_GUESS_ROUNDABOUT
1255#ifdef DEBUG_GUESS_ROUNDABOUT
1257 std::cout <<
" e=" << e->
getID() <<
" loopEdges=" <<
toString(loopEdges) <<
"\n";
1266#ifdef DEBUG_GUESS_ROUNDABOUT
1268 std::cout <<
" rbl\n";
1276#ifdef DEBUG_GUESS_ROUNDABOUT
1278 std::cout <<
" disabled\n";
1284 if (edges.size() < 2) {
1286#ifdef DEBUG_GUESS_ROUNDABOUT
1288 std::cout <<
" deadend\n";
1297#ifdef DEBUG_GUESS_ROUNDABOUT
1305 EdgeVector::const_iterator me = std::find(edges.begin(), edges.end(), e);
1315#ifdef DEBUG_GUESS_ROUNDABOUT
1317 std::cout <<
" noContinuation\n";
1327#ifdef DEBUG_GUESS_ROUNDABOUT
1329 std::cout <<
" e=" << e->
getID() <<
" left=" << left->
getID() <<
" nextLeft=" << nextLeft->
getID() <<
" angle=" << angle <<
" nextAngle=" << nextAngle <<
" eLength=" << e->
getLength() <<
" lLength=" << left->
getLength() <<
" dist=" << e->
getLaneShape(0).back().distanceTo2D(left->
getLaneShape(0).front()) <<
"\n";
1333 if (angle >= 90 && nextAngle < 45) {
1335#ifdef DEBUG_GUESS_ROUNDABOUT
1337 std::cout <<
" failed nextAngle=" << nextAngle <<
"\n";
1350 const double avgRadius = 0.5 * (edgeRadius + edgeRadius2);
1353 if (junctionRadius < 0.8 * avgRadius) {
1355#ifdef DEBUG_GUESS_ROUNDABOUT
1357 std::cout <<
" failed angle=" << angle <<
" eRadius=" << edgeRadius <<
" eRadius2=" << edgeRadius2 <<
" jRadius3=" << junctionRadius <<
"\n";
1365 EdgeVector::const_iterator loopClosed = std::find(loopEdges.begin(), loopEdges.end(), left);
1366 const int loopSize = (int)(loopEdges.end() - loopClosed);
1371 }
else if (loopSize < (
int)loopEdges.size()) {
1373 EdgeVector(loopEdges.begin() + (loopEdges.size() - loopSize), loopEdges.end()).swap(loopEdges);
1376 int attachments = 0;
1377 for (EdgeVector::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) {
1378 if ((*j)->getToNode()->getEdges().size() > 2) {
1382 if (attachments < 3) {
1384#ifdef DEBUG_GUESS_ROUNDABOUT
1386 std::cout <<
" attachments=" << attachments <<
"\n";
1393 if (visited.count(left) > 0) {
1397 loopEdges.push_back(left);
1403#ifdef DEBUG_GUESS_ROUNDABOUT
1405 std::cout <<
" formFactor=" <<
formFactor(loopEdges) <<
"\n";
1408 double loopLength = 0;
1409 for (
const NBEdge*
const le : loopEdges) {
1415 EdgeSet guessed(loopEdges.begin(), loopEdges.end());
1416 if (loadedRoundaboutEdges.count(loopEdges.front()) != 0) {
1419 if ((*it).count(loopEdges.front()) != 0) {
1429#ifdef DEBUG_GUESS_ROUNDABOUT
1431 std::cout <<
" foundRoundabout=" <<
toString(loopEdges) <<
"\n";
1437#ifdef DEBUG_GUESS_ROUNDABOUT
1447 std::set<NBEdge*> candidateEdges;
1448 for (
const auto& edge :
myEdges) {
1449 NBEdge*
const e = edge.second;
1451 candidateEdges.insert(e);
1454 std::set<NBEdge*> visited;
1456 for (
const auto& edgeIt : candidateEdges) {
1459 if (visited.count(e) > 0) {
1463 loopEdges.push_back(e);
1467 if (std::find(visited.begin(), visited.end(), e) != visited.end()) {
1468 if (loopEdges.size() > 1) {
1476 loopEdges.push_back(e);
1478 EdgeVector::const_iterator me = std::find_if(outgoingEdges.begin(), outgoingEdges.end(), [](
const NBEdge * outgoingEdge) {
1479 return outgoingEdge->getJunctionPriority(outgoingEdge->getToNode()) == NBEdge::JunctionPriority::ROUNDABOUT;
1481 if (me == outgoingEdges.end()) {
1495 std::set<EdgeSet> validRoundabouts;
1496 std::set<NBEdge*> validEdges;
1498 validEdges.insert(item.second);
1502 for (
NBEdge* cand : roundabout) {
1503 if (validEdges.count(cand) != 0) {
1504 validRoundabout.insert(cand);
1507 if (validRoundabout.size() > 0) {
1508 validRoundabouts.insert(validRoundabout);
1519 for (EdgeVector::const_iterator it = loopEdges.begin(); it != loopEdges.end(); ++it) {
1520 points.
append((*it)->getGeometry());
1522 double circumference = points.
length2D();
1523 return 4 *
M_PI * points.
area() / (circumference * circumference);
1527const std::set<EdgeSet>
1537 if (roundabout.size() > 0) {
1550 if (e->getToNode() == node) {
1567 std::vector<EdgeSet> rList;
1568 for (
const EdgeSet& r : roundabouts) {
1570 std::set_difference(r.begin(), r.end(), toRemove.begin(), toRemove.end(), std::inserter(r2, r2.end()));
1571 rList.push_back(r2);
1573 roundabouts.clear();
1574 roundabouts.insert(rList.begin(), rList.end());
1581 for (
NBEdge*
const edge : roundaboutSet) {
1583 NBNode*
const node = edge->getToNode();
1585 if (roundaboutSet.count(inEdge) > 0) {
1591 if (inEdge->getTurnDestination() !=
nullptr) {
1592 inEdge->removeFromConnections(inEdge->getTurnDestination(), -1);
1596 const std::vector<NBEdge::Connection> cons = inEdge->getConnections();
1598 if (con.toEdge && roundaboutSet.count(con.toEdge) == 0) {
1599 const double angle = fabs(
NBHelpers::normRelAngle(inEdge->getAngleAtNode(node), con.toEdge->getAngleAtNode(node)));
1601 inEdge->removeFromConnections(con.toEdge, -1);
1619 for (EdgeCont::iterator i =
myEdges.begin(); i !=
myEdges.end(); ++i) {
1663 int lanesCreated = 0;
1664 std::vector<std::string> edges;
1665 if (excludeOpt !=
"") {
1668 std::set<std::string> exclude(edges.begin(), edges.end());
1669 for (EdgeCont::iterator it =
myEdges.begin(); it !=
myEdges.end(); it++) {
1670 NBEdge* edge = it->second;
1672 exclude.count(edge->
getID()) == 0
1681 || (!fromPermissions && edge->
getSpeed() > minSpeed && edge->
getSpeed() <= maxSpeed)
1704 return lanesCreated;
1711 item.second->updateChangeRestrictions(ignoring);
1719 const auto nodeContainerCopy =
myEdges;
1721 for (
const auto& node : nodeContainerCopy) {
1722 node.second->setID(prefix + node.second->getID());
1723 myEdges[node.second->getID()] = node.second;
1731 if (!numericaIDs && !reservedIDs && prefix ==
"" && !startGiven) {
1734 std::vector<std::string> avoid;
1740 std::set<std::string> reserve;
1743 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1746 std::set<NBEdge*, ComparatorIdLess> toChange;
1747 for (EdgeCont::iterator it =
myEdges.begin(); it !=
myEdges.end(); it++) {
1749 toChange.insert(it->second);
1756 toChange.insert(it->second);
1759 if (reservedIDs && reserve.count(it->first) > 0) {
1760 toChange.insert(it->second);
1763 std::set<std::string> keep;
1766 for (
auto it = toChange.begin(); it != toChange.end();) {
1767 if (keep.count((*it)->getID()) != 0) {
1768 toChange.erase(it++);
1775 std::map<std::string, std::vector<std::shared_ptr<NBPTStop> > > stopsOnEdge;
1776 for (
const auto& item : sc.
getStops()) {
1777 stopsOnEdge[item.second->getEdgeId()].push_back(item.second);
1781 for (
NBEdge* edge : toChange) {
1784 for (
NBEdge* edge : toChange) {
1785 const std::string origID = edge->getID();
1787 edge->setOrigID(origID,
false);
1789 edge->setID(idSupplier.
getNext());
1790 myEdges[edge->getID()] = edge;
1791 for (std::shared_ptr<NBPTStop> stop : stopsOnEdge[origID]) {
1792 stop->setEdgeId(prefix + edge->getID(), *
this);
1795 if (prefix.empty()) {
1796 return (
int)toChange.size();
1801 for (
auto item : oldEdges) {
1803 rename(item.second, prefix + item.first);
1814 for (EdgeCont::const_iterator it =
myEdges.begin(); it !=
myEdges.end(); it++) {
1815 const NBEdge* e1 = it->second;
1821 for (EdgeCont::const_iterator it2 = it; it2 !=
myEdges.end(); it2++) {
1822 const NBEdge* e2 = it2->second;
1831 const double overlap = outline1.
getOverlapWith(outline2, zThreshold);
1832 if (overlap > threshold) {
1843 for (EdgeCont::const_iterator it =
myEdges.begin(); it !=
myEdges.end(); it++) {
1844 const NBEdge* edge = it->second;
1845 for (
int i = 0; i < (int)edge->
getNumLanes(); i++) {
1848 if (maxJump > 0.01) {
1850 }
else if (grade > threshold) {
1855 const std::vector<NBEdge::Connection>& connections = edge->
getConnections();
1856 for (std::vector<NBEdge::Connection>::const_iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
1860 if (maxJump > 0.01) {
1862 }
else if (grade > threshold) {
1873 int affectedEdges = 0;
1875 if (item.second->joinLanes(perms)) {
1879 return affectedEdges;
1885 if (a.first->getID() == b.first->getID()) {
1886 return a.second < b.second;
1888 return a.first->getID() < b.first->getID();
1895 std::vector<NBEdge*> tramEdges;
1896 std::vector<NBEdge*> targetEdges;
1899 if (
isTram(permissions)) {
1900 if (item.second->getNumLanes() == 1) {
1901 tramEdges.push_back(item.second);
1903 WRITE_WARNINGF(
TL(
"Not joining tram edge '%' with % lanes."), item.second->getID(), item.second->getNumLanes());
1906 targetEdges.push_back(item.second);
1909 if (tramEdges.empty() || targetEdges.empty()) {
1914 for (
NBEdge*
const edge : tramEdges) {
1915 const Boundary& bound = edge->getGeometry().getBoxBoundary();
1916 float min[2] = {
static_cast<float>(bound.
xmin()),
static_cast<float>(bound.
ymin()) };
1917 float max[2] = {
static_cast<float>(bound.
xmax()),
static_cast<float>(bound.
ymax()) };
1918 tramTree.
Insert(min, max, edge);
1923 for (
NBEdge*
const edge : targetEdges) {
1924 Boundary bound = edge->getGeometry().getBoxBoundary();
1925 bound.
grow(maxDist + edge->getTotalWidth());
1926 float min[2] = {
static_cast<float>(bound.
xmin()),
static_cast<float>(bound.
ymin()) };
1927 float max[2] = {
static_cast<float>(bound.
xmax()),
static_cast<float>(bound.
ymax()) };
1928 std::set<const Named*> near;
1930 tramTree.
Search(min, max, visitor);
1932 std::set<NBEdge*, ComparatorIdLess> nearby;
1933 for (
const Named* namedEdge : near) {
1934 nearby.insert(
const_cast<NBEdge*
>(
static_cast<const NBEdge*
>(namedEdge)));
1936 for (
NBEdge*
const tramEdge : nearby) {
1939 if (tramEdge->getToNode() == edge->getToNode()) {
1940 tramShape.
extrapolate(tramShape.back().distanceTo2D(edge->getGeometry().back()),
false,
true);
1942 double minEdgeDist = maxDist + 1;
1946 for (
int i = 0; i < edge->getNumLanes(); i++) {
1947 double maxLaneDist = -1;
1951 const double dist = tramShape.
distance2D(pos,
false);
1952#ifdef DEBUG_JOIN_TRAM
1961 maxLaneDist =
MAX2(maxLaneDist, dist);
1963 if (maxLaneDist >= 0 && maxLaneDist < minEdgeDist) {
1964 minEdgeDist = maxLaneDist;
1978 if (angleOK && offset2 > offset1) {
1979 std::pair<NBEdge*, int> key = std::make_pair(edge, minLane);
1980 if (matches.count(key) == 0) {
1981 matches[key] = tramEdge;
1983 WRITE_WARNINGF(
TL(
"Ambiguous tram edges '%' and '%' for lane '%'."), matches[key]->getID(), tramEdge->getID(), edge->getLaneID(minLane));
1985#ifdef DEBUG_JOIN_TRAM
1986 std::cout << edge->getLaneID(minLane) <<
" is close to tramEdge " << tramEdge->getID() <<
" maxLaneDist=" << minEdgeDist <<
" tramLength=" << tramEdge->getLength() <<
" edgeLength=" << edge->getLength() <<
" tramAngle=" << tramAngle <<
" edgeAngle=" << edge->getTotalAngle() <<
"\n";
1992 if (matches.size() == 0) {
1997 for (
NBEdge* tramEdge : tramEdges) {
1998 std::vector<std::pair<double, std::pair<NBEdge*, int> > > roads;
1999 for (
auto item : matches) {
2000 if (item.second == tramEdge) {
2001 NBEdge* road = item.first.first;
2002 int laneIndex = item.first.second;
2006 roads.push_back(std::make_pair(tramPos, item.first));
2009 if (roads.size() != 0) {
2011 sort(roads.begin(), roads.end());
2012#ifdef DEBUG_JOIN_TRAM
2013 std::cout <<
" tramEdge=" << tramEdge->getID() <<
" roads=";
2014 for (
auto item : roads) {
2015 std::cout << item.second.first->getLaneID(item.second.second) <<
",";
2017 std::cout <<
" offsets=";
2018 for (
auto item : roads) {
2019 std::cout << item.first <<
",";
2027 std::string tramEdgeID = tramEdge->getID();
2028 NBNode* tramFrom = tramEdge->getFromNode();
2030 const double tramLength = tramShape.
length();
2032 bool erasedLast =
false;
2033 for (
const auto& item : roads) {
2034 const double gap = item.first - pos;
2035 NBEdge* road = item.second.first;
2036 int laneIndex = item.second.second;
2038#ifdef DEBUG_JOIN_TRAM
2039 std::cout <<
" splitting tramEdge=" << tramEdge->
getID() <<
" at " << item.first <<
" (gap=" << gap <<
")\n";
2041 const std::string firstPartID = tramEdgeID +
"#" +
toString(tramPart++);
2047 incoming.push_back(firstPart);
2048 replacement.push_back(firstPart);
2052 replacement.push_back(road);
2055 tramEdge->reinitNodes(road->
getToNode(), tramEdge->getToNode());
2058#ifdef DEBUG_JOIN_TRAM
2059 std::cout <<
" shorted tramEdge=" << tramEdge->getID() <<
" (joined with roadEdge=" << road->
getID() <<
"\n";
2062#ifdef DEBUG_JOIN_TRAM
2063 std::cout <<
" erased tramEdge=" << tramEdge->getID() <<
"\n";
2070 road->
setOrigID(tramEdgeID,
true, laneIndex);
2072 for (
NBEdge* in : incoming) {
2073 if (
isTram(in->getPermissions()) && !in->isConnectedTo(road)) {
2075 in->reinitNodes(in->getFromNode(), road->
getFromNode());
2078#ifdef DEBUG_JOIN_TRAM
2079 std::cout <<
" erased incoming tramEdge=" << in->getID() <<
"\n";
2086 NBEdge* lastRoad = roads.back().second.first;
2090 for (
NBEdge* out : outEdges) {
2092 if (lastRoad->
getToNode() != out->getToNode()) {
2093 out->reinitNodes(lastRoad->
getToNode(), out->getToNode());
2096#ifdef DEBUG_JOIN_TRAM
2097 std::cout <<
" erased outgoing tramEdge=" << out->getID() <<
"\n";
2104 replacement.push_back(tramEdge);
2120 item.second->setNumericalID((
int)result.size());
2121 result.push_back(item.second);
2135 for (
const auto& item :
myEdges) {
2157 double maxLengthOut = 0;
2159 maxLengthOut =
MAX2(maxLengthOut, c.length + c.viaLength);
2161 double maxLengthIn = 0;
2164 maxLengthIn =
MAX2(maxLengthIn, c.length + c.viaLength);
2175 item.second->computeAngle();
2180std::set<std::string>
2182 std::set<std::string> result;
2184 if (item.second->getTypeID() !=
"") {
2185 result.insert(item.second->getTypeID());
2196 NBEdge* edge = item.second;
2199 toRemove.insert(edge);
2203 for (
NBEdge* edge : toRemove) {
2218 NBEdge* edge = item.second;
2221 toRemove.insert(edge);
2225 toRemove.insert(edge);
2229 for (
NBEdge* edge : toRemove) {
2244 NBEdge*
const edge = item.second;
2245 std::vector<int> indices;
2247 for (
const auto& lane : edge->
getLanes()) {
2249 indices.push_back(idx);
2254 toRemove.insert(edge);
2256 std::reverse(indices.begin(), indices.end());
2257 for (
const int i : indices) {
2263 for (
NBEdge* edge : toRemove) {
2277 std::map<std::string, std::vector<std::string> > node2edge;
2281 node2edge[nodeID].push_back(item.first);
2285 for (
auto item : nc) {
2287 auto itRN = node2edge.find(n->
getID());
2288 if (itRN != node2edge.end()) {
2289 bool rebuildConnections =
false;
2291 std::vector<std::string> edgeIDs = itRN->second;
2292 for (
const std::string& eID : edgeIDs) {
2294 assert(edge !=
nullptr);
2297 std::string idAfter = edge->
getID();
2299 size_t spos = idAfter.find(
"#");
2300 if (spos != std::string::npos && spos > 1) {
2301 idAfter = idAfter.substr(0, spos);
2309 rebuildConnections =
true;
2313 node2edge[nodeID].push_back(idAfter);
2318 if (rebuildConnections) {
2320 e->invalidateConnections(
true);
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
#define WRITE_ERRORF(...)
#define WRITE_WARNING(msg)
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
KeepClear
keepClear status of connections
std::vector< NBRouterEdge * > RouterEdgeVector
#define JOIN_TRAM_MIN_LENGTH
#define JOIN_TRAM_MAX_ANGLE
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
bool isTram(SVCPermissions permissions)
Returns whether an edge with the given permissions is a tram edge.
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_TRAM
vehicle is a light rail
@ SVC_PUBLIC_CLASSES
public transport
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
const std::string SUMO_PARAM_ORIGID
const std::string SUMO_PARAM_REMOVED_NODES
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
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
const double SUMO_const_halfLaneWidth
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class that stores a 2D geometrical boundary.
double ymin() const
Returns minimum y-coordinate.
double xmin() const
Returns minimum x-coordinate.
Boundary & grow(double by)
extends the boundary by the given amount
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns whether the boundary overlaps with the given polygon.
double ymax() const
Returns maximum y-coordinate.
double xmax() const
Returns maximum x-coordinate.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
static PositionVector parseShapeReporting(const std::string &shpdef, const std::string &objecttype, const char *objectid, bool &ok, bool allowEmpty, bool report=true)
Builds a PositionVector from a string representation, reporting occurred errors.
static const double INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
static double legacyDegree(const double angle, const bool positive=false)
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
std::string getNext()
Returns the next id.
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
A container for districts.
void removeFromSinksAndSources(NBEdge *const e)
Removes the given edge from the lists of sources and sinks in all stored districts.
Sorts splits by their position (increasing)
void patchRoundabouts(NBEdge *orig, NBEdge *part1, NBEdge *part2, std::set< EdgeSet > &roundabouts)
fix roundabout information after splitting an edge
void computeEdgeShapes(double smoothElevationThreshold=-1)
Computes the shapes of all edges stored in the container.
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
void computeEdge2Edges(bool noLeftMovers)
Computes for each edge the approached edges.
int guessRoundabouts()
Determines which edges belong to roundabouts and increases their priority.
bool myNeedGeoTransformedPruningBoundary
whether a geo transform has been applied to the pruning boundary
void sortOutgoingLanesConnections()
Sorts all lanes of all edges within the container by their direction.
void addRoundabout(const EdgeSet &roundabout)
add user specified roundabout
std::set< EdgeSet > myRoundabouts
Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout)
void appendRailwayTurnarounds(const NBPTStopCont &sc)
Appends turnarounds to all bidiRail edges with stops.
std::set< std::string > myEdges2Remove
Set of ids of edges which shall explicitly be removed.
std::set< std::string > myIgnoredEdges
The ids of ignored edges.
void updateAllChangeRestrictions(SVCPermissions ignoring)
modify all restrictions on lane changing for edges and connections
double myEdgesMinSpeed
The minimum speed an edge may have in order to be kept (default: -1)
void recheckPostProcessConnections()
Try to set any stored connections.
void extract(NBDistrictCont &dc, NBEdge *edge, bool remember=false)
Removes the given edge from the container like erase but does not delete it.
void processSplits(NBEdge *e, std::vector< Split > splits, NBNodeCont &nc, NBDistrictCont &dc, NBTrafficLightLogicCont &tlc)
process splits
EdgeVector getAllEdges() const
return all edges
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
std::set< std::string > myTypes2Keep
Set of edges types which shall be kept.
void recheckLanes()
Rechecks whether all lanes have a successor for each of the stored edges.
NBEdge * getOppositeByID(const std::string &edgeID) const
Returns the edge with negated id if it exists.
void checkGeometries(const double maxAngle, bool fixAngle, const double minRadius, bool fix, bool fixRailways, bool silent=false)
EdgeCont myExtractedEdges
The extracted edges which are kept for reference.
void reduceGeometries(const double minDist)
void recheckLaneSpread()
Rechecks whether the lane spread is proper.
bool ignoreFilterMatch(NBEdge *edge)
Returns true if this edge matches one of the removal criteria.
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
void cleanupRoundabouts()
void splitGeometry(NBDistrictCont &dc, NBNodeCont &nc)
Splits edges into multiple if they have a complex geometry.
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass, KeepClear keepClear, double contPos, double visibility, double speed, double friction, double length, const PositionVector &customShape, bool uncontrolled, bool warnOnly, SVCPermissions permissions=SVC_UNSPECIFIED, bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED)
Adds a connection which could not be set during loading.
std::set< std::string > getUsedTypes() const
return all edge types in used
void computeLanes2Edges()
Computes for each edge which lanes approach the next edges.
int extractRoundabouts()
Determines which edges have been marked as roundabouts and stores them internally.
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
RouterEdgeVector getAllRouterEdges() const
return all router edges
std::set< const NBEdge * > myWasSplit
the edges that were created as result of splitting
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
int joinTramEdges(NBDistrictCont &dc, NBPTStopCont &sc, NBPTLineCont &lc, double maxDist)
join tram edges into adjacent lanes
bool hasPostProcessConnection(const std::string &from, const std::string &to="")
add post process connections
EdgeCont myEdges
The instance of the dictionary (id->edge)
int removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
NBTypeCont & myTypeCont
The network builder; used to obtain type information.
void generateStreetSigns()
assigns street signs to edges based on toNode types
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
std::set< EdgeSet > myGuessedRoundabouts
Edges marked as belonging to a roundabout after guessing.
void computeAngles()
compute all edge angles
void clear()
Deletes all edges.
void guessOpposites()
Sets opposite lane information for geometrically close edges.
void markRoundabouts()
mark edge priorities and prohibit turn-arounds for all roundabout edges
std::set< std::string > myTypes2Remove
Set of edges types which shall be removed.
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
void removeRoundaboutEdges(const EdgeSet &toRemove)
remove edges from all stored roundabouts
PositionVector myPruningBoundary
Boundary within which an edge must be located in order to be kept.
int joinLanes(SVCPermissions perms)
join adjacent lanes with the given permissions
void checkOverlap(double threshold, double zThreshold) const
check whether edges overlap
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed)
int guessSpecialLanes(SUMOVehicleClass svc, double width, double minSpeed, double maxSpeed, bool fromPermissions, const std::string &excludeOpt, NBTrafficLightLogicCont &tlc)
add sidwalks to edges within the given limits or permissions and return the number of edges affected
EdgeVector getGeneratedFrom(const std::string &id) const
Returns the edges which have been built by splitting the edge of the given id.
void appendTurnarounds(bool noTLSControlled, bool noFringe, bool onlyDeadends, bool onlyTurnlane, bool noGeometryLike)
Appends turnarounds to all edges stored in the container.
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
void computeLaneShapes()
Computes the shapes of all lanes of all edges stored in the container.
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
std::map< std::string, NBEdge * > EdgeCont
The type of the dictionary where an edge may be found by its id.
void addPrefix(const std::string &prefix)
add prefix to all edges
void fixSplitCustomLength()
adapt custom lengths of split edges to account for intersection size
std::map< const NBEdge *, std::pair< NBEdge *, NBEdge * > > myEdgesSplit
the number of splits of edges during the building
NBEdge * getSplitBase(const std::string &edgeID) const
std::map< std::string, std::vector< PostProcessConnection > > myConnections
The list of connections to recheck.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
NBEdgeCont(NBTypeCont &tc)
Constructor.
std::set< NBEdge * > myEdgeCemetery
The edges which got extracted twice but may still be referenced somewhere TODO smart_ptr?
bool checkConsistency(const NBNodeCont &nc)
ensure that all edges have valid nodes
static double formFactor(const EdgeVector &loopEdges)
compute the form factor for a loop of edges
int removeLanesByWidth(NBDistrictCont &dc, const double minWidth)
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
int removeEdgesBySpeed(NBDistrictCont &dc)
return number of edges removed
int remapIDs(bool numericaIDs, bool reservedIDs, bool keptIDs, const std::string &prefix, NBPTStopCont &sc)
remap node IDs accoring to options –numerical-ids and –reserved-ids
void checkGrade(double threshold) const
check whether edges are to steep
int attachRemoved(NBNodeCont &nc, NBDistrictCont &dc, const double maxDist)
return number of edges split
int removeEdgesByPermissions(NBDistrictCont &dc)
bool myRemoveEdgesAfterLoading
Whether edges shall be joined and patched first, then removed.
The representation of a single edge during network building.
NBEdge * guessOpposite(bool reguess=false)
set oppositeID and return opposite edge if found
double getLength() const
Returns the computed length of the edge.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
const std::vector< Connection > & getConnections() const
Returns the connections.
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
void recheckOpposite(const NBEdgeCont &ec, bool fixOppositeLengths)
recheck whether all opposite and bidi settings are consistent
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
NBNode * getToNode() const
Returns the destination node of the edge.
PositionVector getCCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going counter-clock-wise around the given node
static const double UNSPECIFIED_FRICTION
unspecified lane friction
void incLaneNo(int by)
increment lane
Lane & getLaneStruct(int lane)
void setAverageLengthWithOpposite(double val)
patch average lane length in regard to the opposite edge
const PositionVector & getGeometry() const
Returns the geometry of the edge.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
void dismissVehicleClassInformation()
dimiss vehicle class information
EdgeBuildingStep getStep() const
The building step of this edge.
LaneSpreadFunction myLaneSpreadFunction
The information about how to spread the lanes.
bool hasLoadedLength() const
Returns whether a length was set explicitly.
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 setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
@ LANES2LANES_DONE
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
@ LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
double getSpeed() const
Returns the speed allowed on this edge.
const std::string & getID() const
double getDistance() const
get distance
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
std::vector< Lane > myLanes
Lane information.
int getNumLanes() const
Returns the number of lanes.
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
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)
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
bool isConnectedTo(const NBEdge *e, const bool ignoreTurnaround=false) const
Returns the information whethe a connection to the given edge has been added (or computed)
void addSign(NBSign sign)
add Sign
void deleteLane(int index, bool recompute, bool shiftIndices)
delete lane
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
std::string getLaneID(int lane) const
get lane ID
@ USER
The connection was given by the user.
@ VALIDATED
The connection was computed and validated.
@ COMPUTED
The connection was computed.
double getStartAngle() const
Returns the angle at the start of the edge (relative to the node shape center) The angle is computed ...
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection to a certain lane of a certain edge.
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
const std::string & getTypeID() const
get ID of type
const std::string & getStreetName() const
Returns the street name of this edge.
NBNode * getFromNode() const
Returns the origin node of the edge.
NBEdge * getTurnDestination(bool possibleDestination=false) const
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
bool isBidi() const
return whether this edge should be a bidi 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
double getEndAngle() const
Returns the angle at the end of the edge (relative to the node shape center) The angle is computed in...
void declareConnectionsAsLoaded(EdgeBuildingStep step=EdgeBuildingStep::LANES2LANES_USER)
declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has ...
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
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again
void setOrigID(const std::string origID, const bool append, const int laneIdx=-1)
set origID for all lanes or for a specific lane
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
void setLoadedLength(double val)
set loaded length
void decLaneNo(int by)
decrement lane
NBNode * myFrom
The source and the destination node.
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
static void loadPrefixedIDsFomFile(const std::string &file, const std::string prefix, std::set< std::string > &into)
Add prefixed ids defined in file.
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
static void loadEdgesFromFile(const std::string &file, std::set< std::string > &into)
Add edge ids defined in file (either ID or edge:ID per line) into the given set.
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
Container for nodes during the netbuilding process.
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
void markAsSplit(const NBNode *node)
mark a node as being created form a split
Represents a single node (junction) during network building.
void invalidateOutgoingConnections(bool reallowSetting=false)
invalidate outgoing connections
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 isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
void recheckVClassConnections(NBEdge *currentOutgoing)
ensure connectivity for all vClasses
SumoXMLNodeType getType() const
Returns the type of this node.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool addedConnections, bool removedConnections)
causes the traffic light to be computed anew
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
void replaceOutgoing(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurrences of the first edge within the list of outgoing by the second Connections are rema...
void setRoundabout()
update the type of this node as a roundabout
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurrences of the first edge within the list of incoming by the second Connections are rema...
const Position & getPosition() const
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
bool typeWasGuessed() const
return whether a priority road turns at this node
RoundaboutType getRoundaboutType() const
Returns roundabout type.
void removeDoubleEdges()
remove duble edges
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
void replaceEdge(const std::string &edgeID, const EdgeVector &replacement)
replace the edge with the given edge list in all lines
Container for public transport stops during the net building process.
void replaceEdge(const std::string &edgeID, const std::vector< NBEdge * > &replacement)
replace the edge with the closes edge on the given edge list in all stops
const std::map< std::string, std::shared_ptr< NBPTStop > > & getStops() const
Returns an unmodifiable reference to the stored pt stops.
A class representing a single street sign.
@ SIGN_TYPE_RIGHT_BEFORE_LEFT
@ SIGN_TYPE_LEFT_BEFORE_RIGHT
The base class for traffic light logic definitions.
A container for traffic light definitions and built programs.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces occurrences of the removed edge/lane in all definitions by the given edge.
A storage for available edgeTypes of edges.
bool getEdgeTypeShallBeDiscarded(const std::string &edgeType) const
Returns the information whether edges of this edgeType shall be discarded.
bool knows(const std::string &edgeType) const
Returns whether the named edgeType is in the container.
Allows to store the object; used as context while traveling the rtree in TraCI.
Base class for objects which have an id.
virtual void setID(const std::string &newID)
resets the id
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 RT-tree for efficient storing of SUMO's Named objects.
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
A storage for options typed value containers)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
std::string getValueString(const std::string &name) const
Returns the string-value of the named option (all options)
static OptionsCont & getOptions()
Retrieves the options.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
A point in 2D or 3D with translation and scaling methods.
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...
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
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::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
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
double getOverlapWith(const PositionVector &poly, double zThreshold) const
Returns the maximum overlaps between this and the given polygon (when not separated by at least zThre...
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
bool partialWithin(const AbstractPoly &poly, double offset=0) const
Returns the information whether this polygon lies partially within the given polygon.
double getMaxGrade(double &maxJump) const
double area() const
Returns the area (0 for non-closed)
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
std::vector< std::string > getVector()
return vector of strings
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
A structure which describes a connection between edges or lanes.
NBEdge * toEdge
The edge the connections yields in.
PositionVector viaShape
shape of via
std::string getDescription(const NBEdge *parent) const
get string describing this connection
PositionVector shape
shape of Connection
std::string oppositeID
An opposite lane ID, if given.
bool operator()(const std::pair< NBEdge *, int > &a, const std::pair< NBEdge *, int > &b) const
A structure representing a connection between two lanes.
A structure which describes changes of lane number or speed along the road.
int offsetFactor
direction in which to apply the offset (used by netgenerate for lefthand networks)
double offset
lateral offset to edge geometry
double pos
The position of this change.
std::vector< int > lanes
The lanes after this change.