69 #define EXTEND_CROSSING_ANGLE_THRESHOLD 35.0 // degrees 71 #define SPLIT_CROSSING_WIDTH_THRESHOLD 1.5 // meters 72 #define SPLIT_CROSSING_ANGLE_THRESHOLD 5 // degrees 75 #define MIN_WEAVE_LENGTH 20.0 79 #define DEBUGCOND true 96 myApproaching(approaching), myCurrentOutgoing(currentOutgoing) {
100 std::set<int> approachedLanes;
102 const std::vector<NBEdge::Connection> conns = (*it)->getConnections();
103 for (std::vector<NBEdge::Connection>::const_iterator it_con = conns.begin(); it_con != conns.end(); ++it_con) {
105 approachedLanes.insert((*it_con).toLane);
113 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
116 && approachedLanes.count(i) == 0) {
131 NBEdge* incomingEdge = (*myApproaching)[src];
135 std::vector<int> approachingLanes =
137 assert(approachingLanes.size() != 0);
138 std::deque<int>* approachedLanes =
spread(approachingLanes, dest);
141 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
142 assert((
int)approachingLanes.size() > i);
147 delete approachedLanes;
154 std::deque<int>* ret =
new std::deque<int>();
155 int noLanes = (int) approachingLanes.size();
159 ret->push_back(dest);
165 ret->push_back(dest);
169 while (noSet < noLanes) {
175 if (noOutgoingLanes == noSet) {
184 if (dest + loffset >= noOutgoingLanes) {
187 for (
int i = 0; i < (int)ret->size(); i++) {
188 (*ret)[i] = (*ret)[i] - 1;
193 ret->push_back(dest + loffset);
198 if (noOutgoingLanes == noSet) {
203 if (noSet < noLanes) {
206 if (dest < roffset) {
209 for (
int i = 0; i < (int)ret->size(); i++) {
210 (*ret)[i] = (*ret)[i] + 1;
213 ret->push_front(dest - roffset);
227 customShape(_customShape),
228 tlLinkNo(_customTLIndex),
229 customTLIndex(_customTLIndex),
274 bool updateEdgeGeometries) {
281 if (updateEdgeGeometries) {
285 (*i)->setGeometry(geom);
290 (*i)->setGeometry(geom);
314 (*it_wa).shape.mirrorX();
340 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
350 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
352 if (dynamic_cast<NBLoadedSUMOTLDef*>(orig) != 0) {
353 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
354 }
else if (dynamic_cast<NBOwnTLDef*>(orig) == 0) {
356 const std::vector<NBNode*>& nodes = orig->
getNodes();
357 while (!nodes.empty()) {
358 newDef->
addNode(nodes.front());
359 nodes.front()->removeTrafficLight(orig);
372 (*it)->shiftTLConnectionLaneIndex(edge, offset);
399 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
448 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
464 double extrapolateBeg,
465 double extrapolateEnd,
466 NBNode* recordError)
const {
470 #ifdef DEBUG_SMOOTH_GEOM 472 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
475 if (init.size() == 0) {
477 ret.push_back(begShape.back());
478 ret.push_back(endShape.front());
481 return bezier(init, numPoints).smoothedZFront();
490 double extrapolateBeg,
491 double extrapolateEnd,
494 double straightThresh) {
496 const Position beg = begShape.back();
497 const Position end = endShape.front();
501 #ifdef DEBUG_SMOOTH_GEOM 502 if (
DEBUGCOND) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
518 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
519 init.push_back(center);
524 endShapeBegLine.extrapolate2D(100,
true);
526 if (fabs(angle) <
M_PI / 4.) {
529 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
530 const double halfDistance = dist / 2;
531 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
532 #ifdef DEBUG_SMOOTH_GEOM 533 if (
DEBUGCOND) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
534 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
537 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
540 #ifdef DEBUG_SMOOTH_GEOM 541 if (
DEBUGCOND) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
542 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
543 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
544 <<
" displacementError=" << sin(displacementAngle) * dist
545 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
548 if (recordError != 0) {
553 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
554 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
556 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
558 #ifdef DEBUG_SMOOTH_GEOM 559 if (
DEBUGCOND) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
560 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
561 <<
" halfDistance=" << halfDistance <<
"\n";
570 Position intersect = endShapeBegLine.intersectionPosition2D(begShapeEndLineRev);
572 #ifdef DEBUG_SMOOTH_GEOM 574 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect <<
"\n";
578 if (recordError != 0) {
584 const double minControlLength =
MIN2((
double)1.0, dist / 2);
585 const bool lengthenBeg = intersect.
distanceTo2D(beg) <= minControlLength;
586 const bool lengthenEnd = intersect.
distanceTo2D(end) <= minControlLength;
587 if (lengthenBeg && lengthenEnd) {
588 #ifdef DEBUG_SMOOTH_GEOM 589 if (
DEBUGCOND) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
592 if (recordError != 0) {
598 }
else if (lengthenBeg || lengthenEnd) {
600 init.push_back(endShapeBegLine.positionAtOffset2D(100 - minControlLength));
604 const double z2 = endShapeBegLine.positionAtOffset2D(endShapeBegLine.nearest_offset_to_point2D(intersect)).z();
605 const double z3 = 0.5 * (beg.
z() + end.
z());
609 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
614 intersect.
set(intersect.
x(), intersect.
y(), z);
615 init.push_back(intersect);
665 if (thisRight && !rightTurnConflict) {
668 if (!(
foes(otherFromE, otherToE, fromE, toE) ||
myRequest == 0 || rightTurnConflict)) {
678 const bool bothLeft = thisLeft && otherLeft;
679 if (fromE == otherFromE && !thisRight) {
686 if (c.
tlID !=
"" && !bothLeft) {
689 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
704 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
706 if ((*i)->getNodes().size() > 1) {
708 (*i)->removeNode(
this);
709 (*i)->setParticipantsInformation();
710 (*i)->setTLControllingInformation();
748 }
else if (numConnections == 0) {
787 if (mismatchThreshold >= 0
820 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
852 std::swap(in1Offset, in2Offset);
881 std::swap(out1, out2);
882 std::swap(out1Offset, out2Offset);
905 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
929 inOffset += reduction;
930 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
942 EdgeVector::reverse_iterator i;
944 NBEdge* currentOutgoing = *i;
947 const int numApproaching = (int)approaching->size();
948 if (numApproaching != 0) {
962 const std::vector<NBEdge::Connection>& elv = incoming->
getConnections();
963 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
965 if (c.
toEdge == currentOutgoing) {
968 unsatisfied &= ~satisfied;
971 if (unsatisfied != 0) {
974 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
976 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
981 unsatisfied &= ~satisfied;
998 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
999 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1001 (*i)->removeFromConnections((*k).toEdge);
1012 (*i)->markAsInLane2LaneState();
1029 while (seen < minLength) {
1045 EdgeVector::const_iterator i = find(
myAllEdges.begin(),
1051 for (; *i != currentOutgoing;) {
1053 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1054 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1055 if (connLanes.size() != 0) {
1056 approaching->push_back(*i);
1087 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1089 laneOff += (*i)->getNumLanes();
1119 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1121 laneOff += (*i)->getNumLanes();
1136 int whichLaneOff,
int byLaneOff) {
1140 bool changed =
false;
1142 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1145 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1159 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1161 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1162 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1222 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1223 edges.erase(find(edges.begin(), edges.end(), e));
1225 if (edges.size() == 0) {
1240 if (mayDrive.
getFrom() == 0 ||
1241 mayDrive.
getTo() == 0 ||
1243 mustStop.
getTo() == 0) {
1245 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1249 conn.push_back(mayDrive);
1256 int size = (int) edgeid.length();
1258 std::string
id = (*i)->
getID();
1259 if (
id.substr(0, size) == edgeid) {
1269 int size = (int) edgeid.length();
1271 std::string
id = (*i)->
getID();
1272 if (
id.substr(0, size) == edgeid) {
1297 if (removeFromConnections) {
1299 (*i)->removeFromConnections(edge);
1304 (*i)->replaceRemoved(edge, -1, 0, -1);
1313 EdgeVector::const_iterator i;
1315 NBNode* conn = (*i)->getFromNode();
1318 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1322 NBNode* conn = (*i)->getToNode();
1325 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1329 if (pos.
x() == 0 && pos.
y() == 0) {
1341 (*i)->invalidateConnections();
1349 (*i)->invalidateConnections();
1376 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane,
1378 if (from != prohibitorFrom) {
1402 lefthand = !lefthand;
1409 if ((!lefthand && fromLane <= prohibitorFromLane) ||
1410 (lefthand && fromLane >= prohibitorFromLane)) {
1413 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (double)360.0);
1414 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (double)360.0);
1432 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
1442 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
1443 bool regardNonSignalisedLowerPriority)
const {
1445 possProhibitedFrom, possProhibitedTo,
1446 regardNonSignalisedLowerPriority);
1452 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
1461 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1462 bool changed =
true;
1468 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1473 bool blockedChanged =
false;
1475 NBConnectionVector::const_iterator j;
1476 for (j = blocked.begin(); j != blocked.end(); j++) {
1478 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
1479 blockedChanged =
true;
1483 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1485 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
1489 }
else if (sblocked.
getFrom() == removed) {
1490 assert(sblocked.
getTo() != removed);
1491 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1494 }
else if (sblocked.
getTo() == removed) {
1495 assert(sblocked.
getFrom() != removed);
1496 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1503 if (blockedChanged) {
1504 blockedConnectionsNew[blocker] = newBlocked;
1509 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
1514 }
else if (blocker.
getFrom() == removed) {
1515 assert(blocker.
getTo() != removed);
1517 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1520 }
else if (blocker.
getTo() == removed) {
1521 assert(blocker.
getFrom() != removed);
1523 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1527 blockedConnectionsNew[blocker] = blocked;
1541 if (outgoing == 0) {
1555 if (abs((
int) angle) + 1 < 45) {
1562 EdgeVector::const_iterator i =
1569 while ((*i) != incoming) {
1583 EdgeVector::const_iterator i =
1590 while ((*i) != incoming) {
1607 bool mayDefinitelyPass,
const std::string& tlID)
const {
1614 if (outgoing == 0) {
1626 if ((!incoming->
isInnerEdge() &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)) && !mayDefinitelyPass) {
1647 reason =
"crossing";
1650 EdgeVector::const_iterator i;
1655 reason =
"edges incompatible: " + reason;
1659 reason =
"turnaround";
1667 std::set<NBNode*> origSet;
1669 origSet.insert((*i)->getFromNode());
1671 if (origSet.size() < 2) {
1679 if (opposite != 0) {
1683 if (!(*i)->expandableBy(continuation, reason)) {
1684 reason =
"edges incompatible: " + reason;
1690 reason =
"not opposites";
1697 reason =
"intersection";
1702 std::vector<std::pair<NBEdge*, NBEdge*> >
1705 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
1709 std::pair<NBEdge*, NBEdge*>(
1717 assert(opposite != 0);
1719 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
1737 (*i)->resetNodeBorder(
this);
1746 if ((*i)->getToNode() == n) {
1761 back_inserter(edges));
1763 back_inserter(edges));
1764 for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
1775 for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
1776 if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
1793 #ifdef DEBUG_PED_STRUCTURES 1802 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
1806 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
1807 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
1809 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
1811 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
1812 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
1815 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
1816 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
1821 int firstSidewalk = -1;
1822 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
1823 if (normalizedLanes[i].second) {
1828 int hadCandidates = 0;
1829 std::vector<int> connectedCandidates;
1830 if (firstSidewalk != -1) {
1832 std::vector<std::pair<NBEdge*, bool> > tmp;
1833 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
1834 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
1835 normalizedLanes = tmp;
1838 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
1839 NBEdge* edge = normalizedLanes[i].first;
1840 const bool allowsPed = normalizedLanes[i].second;
1842 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
1844 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
1845 candidates.push_back(edge);
1846 }
else if (allowsPed) {
1847 if (candidates.size() > 0) {
1853 connectedCandidates.push_back(n);
1860 if (hadCandidates > 0 && candidates.size() > 0) {
1866 connectedCandidates.push_back(n);
1872 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
1874 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
1876 if (connectedCandidates.back() <= connectedCandidates.front()) {
1877 numGuessed -= connectedCandidates.back();
1880 numGuessed -= connectedCandidates.front();
1886 std::cout <<
"guessedCrossings:\n";
1888 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
1898 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
1900 if (candidates.size() == 0) {
1902 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
1907 double prevAngle = -100000;
1908 for (
int i = 0; i < (int)candidates.size(); ++i) {
1909 NBEdge* edge = candidates[i];
1914 std::cout <<
"no crossing added (found angle difference of " << fabs(angle - prevAngle) <<
" at i=" << i <<
"\n";
1920 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
1926 if (candidates.size() == 1) {
1929 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
1934 double prevAngle = -100000;
1935 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
1936 double angle = (*it)->getCrossingAngle(
this);
1937 if (it != candidates.begin()) {
1938 NBEdge* prev = *(it - 1);
1943 double intermediateWidth = 0;
1946 prevPos = prev->
getLanes()[laneI].shape[-1];
1949 prevPos = prev->
getLanes()[laneI].shape[0];
1954 currPos = curr->
getLanes()[laneI].shape[0];
1957 currPos = curr->
getLanes()[laneI].shape[-1];
1963 <<
" prevAngle=" << prevAngle
1964 <<
" angle=" << angle
1965 <<
" intermediateWidth=" << intermediateWidth
1978 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
1989 std::sort(edges.begin(), edges.end());
1993 EdgeVector edgesOfCrossing = crossing->edges;
1994 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
1995 if (edgesOfCrossing == edges) {
2005 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2006 if (!normalizedLanes[i].second) {
2020 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2021 if (crossing->valid) {
2022 WRITE_WARNING(
"Discarding invalid crossing '" + crossing->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(crossing->edges) +
"' (no walkingarea found).");
2025 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2026 if (it_nc != wa.nextCrossings.end()) {
2027 wa.nextCrossings.erase(it_nc);
2030 crossing->valid =
false;
2031 crossing->prevWalkingArea =
"";
2032 crossing->nextWalkingArea =
"";
2037 std::vector<NBNode::Crossing*>
2039 std::vector<Crossing*> result;
2042 result.push_back(c);
2060 myCrossings.clear();
2072 int noInternalNoSplits = 0;
2074 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2075 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2076 if ((*k).toEdge == 0) {
2079 noInternalNoSplits++;
2085 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2092 #ifdef DEBUG_PED_STRUCTURES 2096 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2110 c->nextWalkingArea =
"";
2111 c->prevWalkingArea =
"";
2114 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2120 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2123 double maxAngleDiff = 0;
2124 int maxAngleDiffIndex = 0;
2125 for (
int i = 0; i < (int) edges.size(); i++) {
2127 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2132 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2134 if (diff > maxAngleDiff) {
2135 maxAngleDiff = diff;
2136 maxAngleDiffIndex = i;
2139 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2141 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2143 std::cout <<
" rotatedEdges=" <<
toString(edges);
2147 std::reverse(edges.begin(), edges.end());
2149 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2153 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2154 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2155 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2156 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2158 WRITE_WARNING(
"Discarding invalid crossing '" + c->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(c->edges) +
"' (no vehicle lanes to cross).");
2160 }
else if (c->customShape.size() != 0) {
2161 c->shape = c->customShape;
2163 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2164 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2171 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2172 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2181 #ifdef DEBUG_PED_STRUCTURES 2187 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2194 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2195 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2197 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2199 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2203 normalizedLanes.push_back(std::make_pair(edge, l));
2206 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2211 normalizedLanes.push_back(std::make_pair(edge, l));
2217 std::vector<std::pair<int, int> > waIndices;
2219 NBEdge* prevEdge = normalizedLanes.back().first;
2220 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2221 NBEdge* edge = normalizedLanes[i].first;
2229 waIndices.push_back(std::make_pair(start, i - start));
2239 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2244 const int waNumLanes = (int)normalizedLanes.size() - start;
2245 if (waIndices.size() == 0) {
2246 waIndices.push_back(std::make_pair(start, waNumLanes));
2248 std::cout <<
" single wa, end at wrap-around\n";
2251 if (waIndices.front().first == 0) {
2252 NBEdge* edge = normalizedLanes.front().first;
2253 NBEdge* prevEdge = normalizedLanes.back().first;
2256 waIndices.push_back(std::make_pair(start, waNumLanes));
2258 std::cout <<
" do not wrap around, turn-around in between\n";
2262 waIndices.front().first = start;
2263 waIndices.front().second = waNumLanes + waIndices.front().second;
2265 std::cout <<
" wrapping around\n";
2270 waIndices.push_back(std::make_pair(start, waNumLanes));
2272 std::cout <<
" end at wrap-around\n";
2278 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2279 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2280 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2284 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2285 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2286 const int start = waIndices[i].first;
2287 const int prev = start > 0 ? start - 1 : (int)normalizedLanes.size() - 1;
2288 const int count = waIndices[i].second;
2289 const int end = (start + count) % normalizedLanes.size();
2293 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << start <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2295 double endCrossingWidth = 0;
2296 double startCrossingWidth = 0;
2300 bool connectsCrossing =
false;
2301 std::vector<Position> connectedPoints;
2304 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
2306 if (c->edges.back() == normalizedLanes[end].first
2307 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
2309 if (c->nextWalkingArea !=
"") {
2311 +
"'; crossing '" + c->id
2312 +
"' targets '" + c->nextWalkingArea
2313 +
"' and '" + wa.
id +
"'.");
2316 c->nextWalkingArea = wa.
id;
2319 endCrossingWidth = c->width;
2320 endCrossingShape = c->shape;
2322 connectsCrossing =
true;
2323 connectedPoints.push_back(c->shape[-1]);
2327 std::cout <<
" crossing " << c->id <<
" ends\n";
2330 if (c->edges.front() == normalizedLanes[prev].first
2331 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
2333 if (c->prevWalkingArea !=
"") {
2335 +
"'; crossing '" + c->id
2336 +
"' is targeted by '" + c->prevWalkingArea
2337 +
"' and '" + wa.
id +
"'.");
2340 c->prevWalkingArea = wa.
id;
2344 startCrossingWidth = c->width;
2345 startCrossingShape = c->shape;
2347 connectsCrossing =
true;
2348 connectedPoints.push_back(c->shape[0]);
2352 std::cout <<
" crossing " << c->id <<
" starts\n";
2355 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
2356 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
2357 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[start].first->getID()
2358 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
2361 if (count < 2 && !connectsCrossing) {
2364 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
2369 std::set<NBEdge*> connected;
2370 for (
int j = 0; j < count; ++j) {
2371 const int nlI = (start + j) % normalizedLanes.size();
2372 NBEdge* edge = normalizedLanes[nlI].first;
2375 if (connected.count(edge) == 0) {
2383 connected.insert(edge);
2390 if (buildExtensions) {
2392 if (startCrossingShape.size() > 0) {
2394 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
2396 startCrossingShape.
move2side(startCrossingWidth / 2);
2398 startCrossingShape.
move2side(-startCrossingWidth);
2402 if (endCrossingShape.size() > 0) {
2404 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
2406 endCrossingShape.
move2side(endCrossingWidth / 2);
2408 endCrossingShape.
move2side(-endCrossingWidth);
2413 && normalizedLanes.size() == 2) {
2415 NBEdge* e1 = *connected.begin();
2416 NBEdge* e2 = *(++connected.begin());
2419 std::cout <<
" not building a walkingarea since normal connections exist\n";
2425 if (cornerDetail > 0) {
2426 int smoothEnd = end;
2427 int smoothPrev = prev;
2429 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
2430 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
2432 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
2433 if (smoothPrev == 0) {
2434 smoothPrev = (int)normalizedLanes.size() - 1;
2439 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
2440 begShape = begShape.
reverse();
2442 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
2443 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
2444 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
2448 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
2449 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
2450 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
2451 if (curve.size() > 2) {
2452 curve.erase(curve.begin());
2454 if (endCrossingWidth > 0) {
2455 wa.
shape.pop_back();
2457 if (startCrossingWidth > 0) {
2467 if (wacs.shape.size() != 0 && std::includes(connected.begin(), connected.end(), wacs.edges.begin(), wacs.edges.end())) {
2468 wa.
shape = wacs.shape;
2474 double lengthSum = 0;
2475 int combinations = 0;
2476 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
2477 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
2487 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
2490 if (combinations > 0) {
2496 std::vector<Crossing*> validCrossings =
getCrossings();
2497 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
2499 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
2501 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
2505 WRITE_WARNING(
"Invalid pedestrian topology: crossing '" + prev.
id +
"' has no target.");
2516 wa.
shape.push_back(tmp[-1]);
2518 wa.
shape.push_back(tmp[-1]);
2522 wa.
shape.push_back(tmp[0]);
2524 wa.
shape.push_back(tmp[0]);
2528 crossed.insert(crossed.end(), next.
edges.begin(), next.
edges.end());
2529 std::sort(crossed.begin(), crossed.end());
2532 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 && std::includes(crossed.begin(), crossed.end(), wacs.edges.begin(), wacs.edges.end())) {
2533 wa.
shape = wacs.shape;
2542 std::cout <<
" build wa=" << wa.
id <<
"\n";
2560 EdgeVector::const_iterator it1 = find(edges.begin(), edges.end(), e1);
2561 EdgeVector::const_iterator it2 = find(edges.begin(), edges.end(), e2);
2562 if (it1 != edges.end() && it2 != edges.end()) {
2578 while (it != it_end) {
2579 result.push_back(*it);
2589 wacs.
edges.insert(edges.begin(), edges.end());
2615 if (
MAX2(angle0, angle1) <= 160) {
2646 EdgeSet edgeSet(edges.begin(), edges.end());
2648 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
2649 if (edgeSet == edgeSet2) {
2666 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
2673 c->tlLinkNo = startIndex++;
2675 if (c->customTLIndex != -1) {
2676 c->tlLinkNo = c->customTLIndex;
2688 result += (int)edge->getConnections().size();
2701 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2702 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2738 std::cout <<
" angles:\n";
2739 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
2740 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
2742 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
2747 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
2749 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
2751 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
2762 assert(
id[0] ==
':');
2763 std::string::size_type sep_index =
id.rfind(
'_');
2764 if (sep_index == std::string::npos) {
2765 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
2768 sep_index =
id.substr(0, sep_index).rfind(
'_');
2769 if (sep_index == std::string::npos) {
2770 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
2773 return id.substr(1, sep_index - 1);
2783 if (turnDest != 0) {
2804 if ((*i)->rightOnRedConflict(index, foeIndex)) {
2828 std::vector<NBEdge*>::iterator j;
2829 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
2832 if (allEdges.size() > 1 && j != allEdges.end()) {
2836 NBEdge* firstOfAll = allEdges.front();
2837 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
2838 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
2844 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
2845 if (firstOfIncoming != 0) {
2846 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
2848 if (firstOfOutgoing != 0) {
2849 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
2854 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
2855 std::vector<NBEdge*>::const_iterator in, out;
2856 std::vector<NBEdge*> allTmp;
2857 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
2858 if ((*in)->isTurningDirectionAt(*out)) {
2859 allTmp.push_back(*in);
2860 allTmp.push_back(*out);
2865 if (allTmp.size() == allEdges.size()) {
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
bool gDebugFlag1
global utility flags for debugging
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point...
std::pair< int, int > getSizes() const
returns the number of the junction's lanes and the number of the junction's links in respect...
int getConnectionIndex(const NBEdge *from, const NBEdge::Connection &con) const
return the index of the given connection
The link is a partial left direction.
void replaceOutgoing(const EdgeVector &which, NBEdge *const by)
Replaces outgoing edges from the vector (source) by the given edge.
A structure which describes a connection between edges or lanes.
std::vector< WalkingAreaCustomShape > myWalkingAreaCustomShapes
Vector of custom walking areas shapes.
LinkState getLinkState(const NBEdge *incoming, NBEdge *outgoing, int fromLane, int toLane, bool mayDefinitelyPass, const std::string &tlID) const
get link state
int toLane
The lane the connections yields in.
void setRoundabout()
update the type of this node as a roundabout
int numNormalConnections() const
return the number of lane-to-lane connections at this junction (excluding crossings) ...
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.
ApproachingDivider(EdgeVector *approaching, NBEdge *currentOutgoing)
Constructor.
PositionVector shape
The lane's shape.
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
int buildCrossings()
build pedestrian crossings
void append(const PositionVector &v, double sameThreshold=2.0)
double z() const
Returns the z-position.
bool isInStringVector(const std::string &optionName, const std::string &itemName)
Returns the named option is a list of string values containing the specified item.
Sorts incoming and outgoing edges clockwise around the given node.
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) ...
NBEdge * toEdge
The edge the connections yields in.
#define EXTEND_CROSSING_ANGLE_THRESHOLD
Sorts crossings by minimum clockwise clockwise edge angle. Use the ordering found in myAllEdges of th...
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset)
patches loaded signal plans by modifying lane indices
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
std::string id
the (edge)-id of this crossing
void add(const Position &pos)
Adds the given position to this one.
PositionVector myPoly
the (outer) shape of the junction
void execute(const int src, const int dest)
the bresenham-callback
bool isConnectedTo(const NBEdge *e) const
Returns the information whethe a connection to the given edge has been added (or computed) ...
A loaded (complete) traffic light logic.
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
bool isDistrict() const
check if node is a district
SumoXMLNodeType myType
The type of the junction.
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
A container for traffic light definitions and built programs.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
int minPrevCrossingEdges
minimum number of edges crossed by incoming crossings
PositionVector computeInternalLaneShape(NBEdge *fromE, const NBEdge::Connection &con, int numPoints, NBNode *recordError=0) const
Compute the shape for an internal lane.
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
Some static methods for string processing.
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
int myCrossingsLoadedFromSumoNet
number of crossings loaded from a sumo net
This class computes shapes of junctions.
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
This is an uncontrolled, minor link, has to stop.
double length
This lane's width.
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
const double SUMO_const_laneWidth
bool mustBrake(const NBEdge *const from, const NBEdge *const to, int fromLane, int toLane, bool includePedCrossings) const
Returns the information whether the described flow must let any other flow pass.
double y() const
Returns the y-position.
void addIncomingEdge(NBEdge *edge)
adds an incoming edge
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
The representation of a single edge during network building.
TrafficLightType getType() const
get the algorithm type (static etc..)
static double getCCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle counter-clockwise.
Class to sort edges by their angle in relation to the given edge.
bool replaceTo(NBEdge *which, NBEdge *by)
replaces the to-edge by the one given
The link is a 180 degree turn.
static const double UNSPECIFIED_RADIUS
unspecified lane width
double x() const
Returns the x-position.
A container for districts.
The base class for traffic light logic definitions.
Crossing(const NBNode *_node, const EdgeVector &_edges, double _width, bool _priority, int _customTLIndex, const PositionVector &_customShape)
constructor
static bool isLongEnough(NBEdge *out, double minLength)
check if is long enough
void buildBitfieldLogic()
bool isInnerEdge() const
Returns whether this edge was marked as being within an intersection.
void removeDoubleEdges()
remove duble edges
double angleTo2D(const Position &other) const
returns the angle in the plane of the vector pointing from here to the other position ...
bool hasCustomShape
whether this walkingArea has a custom shape
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light ...
NBEdge * getTurnDestination(bool possibleDestination=false) const
Crossing * getCrossing(const std::string &id) const
return the crossing with the given id
PositionVector shape
The crossing's shape.
#define SPLIT_CROSSING_ANGLE_THRESHOLD
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
PositionVector reverse() const
reverse position vector
void buildWalkingAreas(int cornerDetail)
build pedestrian walking areas and set connections from/to walkingAreas
double endOffset
This lane's offset to the intersection begin.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
This is an uncontrolled, right-before-left link.
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
void remapConnections(const EdgeVector &incoming)
Remaps the connection in a way that allows the removal of it.
std::string id
the (edge)-id of this walkingArea
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
bool connectionsDone
Whether connection information for this lane is already completed.
const std::string & getID() const
Returns the id.
void mirrorX()
mirror coordinates along the x-axis
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
std::vector< int > getConnectionLanes(NBEdge *currentOutgoing) const
Returns the list of lanes that may be used to reach the given edge.
Lane & getLaneStruct(int lane)
void set(double x, double y)
set positions x and y
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
void setCustomShape(const PositionVector &shape)
set the junction shape
The link is controlled by a tls which is off, not blinking, may pass.
NBConnectionProhibits myBlockedConnections
The container for connection block dependencies.
This is an uncontrolled, all-way stop link.
void addOutgoingEdge(NBEdge *edge)
adds an outgoing edge
std::string getDescription(const NBEdge *parent) const
get string describing this connection
static const double UNSPECIFIED_WIDTH
unspecified lane width
void replaceOutgoing(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of outgoing by the second Connections are remap...
This is an uncontrolled, zipper-merge link.
The link is a (hard) left direction.
PositionVector customShape
custom shape for connection
#define WRITE_WARNING(msg)
void sortEdges(bool useNodeShape)
sort all edge containers for this node
The connection was computed and validated.
static OptionsCont & getOptions()
Retrieves the options.
Position getCenter() const
Returns a position that is guaranteed to lie within the node shape.
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane, bool lefthand=false)
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)
NBRequest * myRequest
Node requests.
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
double area() const
Returns the area (0 for non-closed)
The link is a straight direction.
SUMOTime getOffset()
Returns the offset.
NBDistrict * myDistrict
The district the node is the centre of.
A class representing a single district.
bool mustBrake(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
An (internal) definition of a single lane of an edge.
static bool mustBrakeForCrossing(const NBNode *node, const NBEdge *const from, const NBEdge *const to, const NBNode::Crossing &crossing)
Returns the information whether the described flow must brake for the given crossing.
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool removedConnections, bool addedConnections)
causes the traffic light to be computed anew
void computeLanes2Lanes()
computes the connections of lanes to edges
static void swapWhenReversed(const NBNode *const n, const std::vector< NBEdge *>::iterator &i1, const std::vector< NBEdge *>::iterator &i2)
Assures correct order for same-angle opposite-direction edges.
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
bool isTLControlled() const
Returns whether this node is controlled by any tls.
bool writeLogic(OutputDevice &into, const bool checkLaneFoes) const
writes the XML-representation of the logic as a bitset-logic XML representation
void invalidateIncomingConnections()
invalidate incoming connections
void push_front_noDoublePos(const Position &p)
insert in front a non double position
void removeCrossing(const EdgeVector &edges)
remove a pedestrian crossing from this node (identified by its edges)
void computeNodeShape(double mismatchThreshold)
Compute the junction shape for this node.
std::set< const NBEdge * > edges
bool replaceFrom(NBEdge *which, NBEdge *by)
replaces the from-edge by the one given
std::set< NBEdge * > EdgeSet
container for unique edges
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
std::string prevWalkingArea
the lane-id of the previous walkingArea
NBEdge * getPossiblySplittedIncoming(const std::string &edgeid)
get possibly splitted incoming edge
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
int checkCrossing(EdgeVector candidates)
static const int FORWARD
edge directions (for pedestrian related stuff)
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
std::string tlID
The id of the traffic light that controls this connection.
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.
void setCrossingTLIndices(const std::string &tlID, int startIndex)
set tl indices of this nodes crossing starting at the given index
This is an uncontrolled, minor link, has to brake.
int getNumLanes() const
Returns the number of lanes.
int fromLane
The lane the connections starts at.
int minNextCrossingEdges
minimum number of edges crossed by nextCrossings
A point in 2D or 3D with translation and scaling methods.
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 buildCrossingsAndWalkingAreas()
build crossings, and walkingareas. Also removes invalid loaded crossings if wished ...
static double getCWAngleDiff(double angle1, double angle2)
Returns the distance of second angle from first angle clockwise.
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
bool crossingBetween(const NBEdge *e1, const NBEdge *e2) const
return true if the given edges are connected by a crossing
bool hasConnectionTo(NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
void invalidateOutgoingConnections()
invalidate outgoing connections
void removeJoinedTrafficLights()
remove all traffic light definitions that are part of a joined tls
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
void removeTrafficLights()
Removes all references to traffic lights that control this tls.
EdgeVector * getEdgesThatApproach(NBEdge *currentOutgoing)
returns a list of edges which are connected to the given outgoing edge
bool geometryLike() const
whether this is structurally similar to a geometry node
std::set< NBTrafficLightDefinition * > myTrafficLights
traffic lights of node
Storage for edges, including some functionality operating on multiple edges.
The link is a (hard) right direction.
std::string getSidewalkID()
get the lane id for the canonical sidewalk lane
EdgeBuildingStep getStep() const
The building step of this edge.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
bool myDiscardAllCrossings
whether to discard all pedestrian crossings
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
void discardAllCrossings(bool rejectAll)
discard all current (and optionally future) crossings
void replaceInConnectionProhibitions(NBEdge *which, NBEdge *by, int whichLaneOff, int byLaneOff)
replace incoming connections prohibitions
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
PositionVector compute()
Computes the shape of the assigned junction.
double myRadius
the turning radius (for all corners) at this node in m.
The link is a partial right direction.
double width
This lane's width.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::set< SVCPermissions > getPermissionVariants(int iStart, int iEnd) const
return all permission variants within the specified lane range [iStart, iEnd[
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
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.
void move2side(double amount)
move position vector to side using certain ammount
void addCrossing(EdgeVector edges, double width, bool priority, int tlIndex=-1, const PositionVector &customShape=PositionVector::EMPTY, bool fromSumoNet=false)
add a pedestrian crossing to this node
virtual void removeNode(NBNode *node)
Removes the given node from the list of controlled nodes.
EdgeVector myIncomingEdges
Vector of incoming edges.
bool checkIsRemovableReporting(std::string &reason) const
check if node is removable and return reason if not
Base class for objects which have an id.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
std::vector< NBConnection > NBConnectionVector
Definition of a connection vector.
void avoidOverlap()
fix overlap
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0) const
Compute a smooth curve between the given geometries.
NBEdge * getPossiblySplittedOutgoing(const std::string &edgeid)
get possibly splitted outgoing edge
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
const PositionVector & getShape() const
retrieve the junction shape
double getSpeed() const
Returns the speed allowed on this edge.
NBEdge * getTo() const
returns the to-edge (end of the connection)
EdgeVector myOutgoingEdges
Vector of outgoing edges.
std::vector< Crossing * > myCrossings
Vector of crossings.
void addWalkingAreaShape(EdgeVector edges, const PositionVector &shape)
add custom shape for walkingArea
NBEdge * myCurrentOutgoing
The approached current edge.
double getLaneWidth() const
Returns the default width of lanes of this edge.
double myDisplacementError
geometry error after computation of internal lane shapes
static const int BACKWARD
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY)
Adds a connection to a certain lane of a certain edge.
std::string myID
The name of the object.
void extrapolate(const double val, const bool onlyFirst=false, const bool onlyLast=false)
extrapolate position vector
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
double width
This crossing's width.
bool myHaveCustomPoly
whether this nodes shape was set by the user
Position myPosition
The position the node lies at.
double length() const
Returns the length.
bool checkCrossingDuplicated(EdgeVector edges)
return true if already exist a crossing with the same edges as the input
std::map< NBConnection, NBConnectionVector > NBConnectionProhibits
Definition of a container for connection block dependencies Includes a list of all connections which ...
int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
~ApproachingDivider()
Destructor.
std::vector< WalkingArea > myWalkingAreas
Vector of walking areas.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const std::vector< Connection > & getConnections() const
Returns the connections.
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
bool isNearDistrict() const
if node is near district
bool myKeepClear
whether the junction area must be kept clear
std::vector< int > myAvailableLanes
The available lanes to which connections shall be built.
double getCrossingAngle(NBNode *node)
return the angle for computing pedestrian crossings at the given node
The link is controlled by a tls which is off and blinks, has to brake.
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
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.
void buildInnerEdges()
build internal lanes, pedestrian crossings and walking areas
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
A definition of a pedestrian walking area.
EdgeVector * myApproaching
The list of edges that approach the current edge.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
A storage for options typed value containers)
double angleAt2D(int pos) const
get angle in certain position of position vector
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Position getEmptyDir() const
Returns something like the most unused direction Should only be used to add source or sink nodes...
This is an uncontrolled, major link, may pass.
bool needsCont(const NBEdge *fromE, const NBEdge *otherFromE, const NBEdge::Connection &c, const NBEdge::Connection &otherC) const
whether an internal junction should be built at from and respect other
double getStartAngle() const
Returns the angle at the start of the edge (relative to the node shape center) The angle is computed ...
int numAvailableLanes() const
@ get number of avaliable lanes
EdgeVector getEdgesSortedByAngleAtNodeCenter() const
returns the list of all edges sorted clockwise by getAngleAtNodeToCenter
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
The connection was computed.
const Position & getPosition() const
EdgeVector edges
The edges being crossed.
Represents a single node (junction) during network building.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
Lanes to lanes - relationships are computed; no recheck is necessary/wished.
The link is a 180 degree turn (left-hand network)
int guessCrossings()
guess pedestrian crossings and return how many were guessed
A definition of a pedestrian crossing.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
void replaceInConnections(NBEdge *which, NBEdge *by, int laneOff)
replace in current connections of edge
void addSortedLinkFoes(const NBConnection &mayDrive, const NBConnection &mustStop)
add shorted link FOES
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
Static storage of an output device and its base (abstract) implementation.
static void compute(BresenhamCallBack *callBack, const int val1, const int val2)
Computes lane-2-lane connections.
bool mustBrakeForCrossing(const NBEdge *const from, const NBEdge *const to, const Crossing &crossing) const
Returns the information whether the described flow must brake for the given crossing.
NBEdge * getOppositeIncoming(NBEdge *e) const
returns the opposite incoming edge of certain edge
std::vector< std::string > nextCrossings
the lane-id of the next crossing(s)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
Computes whether the given connection is a left mover across the junction.
#define SPLIT_CROSSING_WIDTH_THRESHOLD
NBNode * getFromNode() const
Returns the origin node of the edge.
void computeLogic(const NBEdgeCont &ec, OptionsCont &oc)
computes the node's type, logic and traffic light
void mul(double val)
Multiplies both positions with the given value.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
A traffic light logics which must be computed (only nodes/edges are given)
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
void add(double xoff, double yoff, double zoff)
std::string nextWalkingArea
the lane-id of the next walkingArea
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::deque< int > * spread(const std::vector< int > &approachingLanes, int dest) const
the method that spreads the wished number of lanes from the the lane given by the bresenham-call to b...
void closePolygon()
ensures that the last position equals the first
Lanes to edges - relationships are computed/loaded.
bool checkIsRemovable() const
check if node is removable
NBNode(const std::string &id, const Position &position, SumoXMLNodeType type)
Constructor.
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5))
get bezier control points
NBNode * getToNode() const
Returns the destination node of the edge.
std::vector< std::string > prevSidewalks
the lane-id of the previous sidewalk lane or ""
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
bool valid
whether this crossing is valid (and can be written to the net.xml). This is needed for netedit becaus...
void shiftPositionAtNode(NBNode *node, NBEdge *opposite)
shift geometry at the given node to avoid overlap
std::vector< std::string > nextSidewalks
the lane-id of the next sidewalk lane or ""
static void nextCCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
bool isSimpleContinuation(bool checkLaneNumbers=true) const
check if node is a simple continuation
void reshiftPosition(double xoff, double yoff)
Applies an offset to the node.
void remapRemoved(NBTrafficLightLogicCont &tc, NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
remap removed
PositionVector shape
The polygonal shape.
static const Position INVALID
used to indicate that a position is valid
double getEndAngle() const
Returns the angle at the end of the edge (relative to the node shape center) The angle is computed in...
void replaceIncoming(const EdgeVector &which, NBEdge *const by)
Replaces incoming edges from the vector (sinks) by the given edge.
The link has no direction (is a dead end link)
double width
This lane's width.
bool forbidsPedestriansAfter(std::vector< std::pair< NBEdge *, bool > > normalizedLanes, int startIndex)
return whether there is a non-sidewalk lane after the given index;
void bezier(int npts, double b[], int cpts, double p[])
void sub(double dx, double dy)
Substracts the given position from this one.
EdgeVector edgesBetween(const NBEdge *e1, const NBEdge *e2) const
return all edges that lie clockwise between the given edges
static std::string getNodeIDFromInternalLane(const std::string id)
returns the node id for internal lanes, crossings and walkingareas