63 #define EXTEND_CROSSING_ANGLE_THRESHOLD 35.0 // degrees 65 #define SPLIT_CROSSING_WIDTH_THRESHOLD 1.5 // meters 66 #define SPLIT_CROSSING_ANGLE_THRESHOLD 5 // degrees 69 #define MIN_WEAVE_LENGTH 20.0 75 #define DEBUGCOND (getID() == "C") 76 #define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == "disabled")) 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);
228 customShape(_customShape),
229 tlLinkIndex(_customTLIndex),
230 tlLinkIndex2(_customTLIndex2),
231 customTLIndex(_customTLIndex),
232 customTLIndex2(_customTLIndex2),
285 bool updateEdgeGeometries) {
292 if (updateEdgeGeometries) {
296 (*i)->setGeometry(geom);
301 (*i)->setGeometry(geom);
314 wacs.shape.add(xoff, yoff, 0);
328 (*it_wa).shape.mirrorX();
354 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
364 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
366 if (dynamic_cast<NBLoadedSUMOTLDef*>(orig) != 0) {
367 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
368 }
else if (dynamic_cast<NBOwnTLDef*>(orig) == 0) {
370 const std::vector<NBNode*>& nodes = orig->
getNodes();
371 while (!nodes.empty()) {
372 newDef->
addNode(nodes.front());
373 nodes.front()->removeTrafficLight(orig);
386 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
413 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
462 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
478 double extrapolateBeg,
479 double extrapolateEnd,
481 int shapeFlag)
const {
485 #ifdef DEBUG_SMOOTH_GEOM 487 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
490 if (init.size() == 0) {
492 ret.push_back(begShape.back());
493 ret.push_back(endShape.front());
496 return bezier(init, numPoints).smoothedZFront();
505 double extrapolateBeg,
506 double extrapolateEnd,
509 double straightThresh,
512 const Position beg = begShape.back();
513 const Position end = endShape.front();
517 #ifdef DEBUG_SMOOTH_GEOM 518 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
534 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
535 init.push_back(center);
540 endShapeBegLine.extrapolate2D(100,
true);
542 if (fabs(angle) <
M_PI / 4.) {
545 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
546 const double halfDistance = dist / 2;
547 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
548 #ifdef DEBUG_SMOOTH_GEOM 549 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
550 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
553 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
556 #ifdef DEBUG_SMOOTH_GEOM 557 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
558 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
559 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
560 <<
" displacementError=" << sin(displacementAngle) * dist
561 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
564 if (recordError != 0) {
569 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
570 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
572 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
574 #ifdef DEBUG_SMOOTH_GEOM 575 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
576 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
577 <<
" halfDistance=" << halfDistance <<
"\n";
586 Position intersect = endShapeBegLine.intersectionPosition2D(begShapeEndLineRev);
588 #ifdef DEBUG_SMOOTH_GEOM 590 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
591 <<
" endShapeBegLine=" << endShapeBegLine
592 <<
" begShapeEndLineRev=" << begShapeEndLineRev
597 if (recordError != 0) {
603 const double minControlLength =
MIN2((
double)1.0, dist / 2);
606 const bool lengthenBeg = distBeg <= minControlLength;
607 const bool lengthenEnd = distEnd <= minControlLength;
608 if (lengthenBeg && lengthenEnd) {
609 #ifdef DEBUG_SMOOTH_GEOM 610 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
611 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
613 if (recordError != 0) {
621 init.push_back(endShapeBegLine.positionAtOffset2D(100 - extrapolateEnd));
622 }
else if (lengthenBeg || lengthenEnd) {
624 init.push_back(endShapeBegLine.positionAtOffset2D(100 - minControlLength));
628 init.push_back(endShapeBegLine.positionAtOffset2D(100 - 10.0));
632 init.push_back(endShapeBegLine.positionAtOffset2D(100 - 10.0));
636 const double z2 = endShapeBegLine.positionAtOffset2D(endShapeBegLine.nearest_offset_to_point2D(intersect)).z();
637 const double z3 = 0.5 * (beg.
z() + end.
z());
641 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
646 intersect.
set(intersect.
x(), intersect.
y(), z);
647 init.push_back(intersect);
679 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
709 for (
int i = 0; i < con.
toLane; ++i) {
713 for (
int i = 0; i < con.
fromLane; ++i) {
723 fromShape.
move2side(inCenter - outCenter);
763 if (thisRight && !rightTurnConflict) {
766 if (!(
foes(otherFromE, otherToE, fromE, toE) ||
myRequest == 0 || rightTurnConflict)) {
776 const bool bothLeft = thisLeft && otherLeft;
777 if (fromE == otherFromE && !thisRight) {
784 if (c.
tlID !=
"" && !bothLeft) {
787 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
812 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
814 if ((*i)->getNodes().size() > 1) {
816 (*i)->removeNode(
this);
817 (*i)->setParticipantsInformation();
818 (*i)->setTLControllingInformation();
856 }
else if (numConnections == 0) {
898 if (mismatchThreshold >= 0
931 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
963 std::swap(in1Offset, in2Offset);
992 std::swap(out1, out2);
993 std::swap(out1Offset, out2Offset);
1016 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1040 inOffset += reduction;
1041 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1053 EdgeVector::reverse_iterator i;
1055 NBEdge* currentOutgoing = *i;
1058 const int numApproaching = (int)approaching->size();
1059 if (numApproaching != 0) {
1073 const std::vector<NBEdge::Connection>& elv = incoming->
getConnections();
1074 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1076 if (c.
toEdge == currentOutgoing) {
1079 unsatisfied &= ~satisfied;
1082 if (unsatisfied != 0) {
1085 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1087 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1092 unsatisfied &= ~satisfied;
1109 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1110 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1112 (*i)->removeFromConnections((*k).toEdge);
1123 (*i)->markAsInLane2LaneState();
1140 while (seen < minLength) {
1156 EdgeVector::const_iterator i = find(
myAllEdges.begin(),
1162 for (; *i != currentOutgoing;) {
1164 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1165 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1166 if (connLanes.size() != 0) {
1167 approaching->push_back(*i);
1198 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1200 laneOff += (*i)->getNumLanes();
1230 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1232 laneOff += (*i)->getNumLanes();
1247 int whichLaneOff,
int byLaneOff) {
1251 bool changed =
false;
1253 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1256 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1270 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1272 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1273 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1333 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1334 edges.erase(find(edges.begin(), edges.end(), e));
1336 if (edges.size() == 0) {
1351 if (mayDrive.
getFrom() == 0 ||
1352 mayDrive.
getTo() == 0 ||
1354 mustStop.
getTo() == 0) {
1356 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1360 conn.push_back(mayDrive);
1367 int size = (int) edgeid.length();
1369 std::string
id = (*i)->
getID();
1370 if (
id.substr(0, size) == edgeid) {
1380 int size = (int) edgeid.length();
1382 std::string
id = (*i)->
getID();
1383 if (
id.substr(0, size) == edgeid) {
1408 if (removeFromConnections) {
1410 (*i)->removeFromConnections(edge);
1415 (*i)->replaceRemoved(edge, -1, 0, -1);
1424 EdgeVector::const_iterator i;
1426 NBNode* conn = (*i)->getFromNode();
1429 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1433 NBNode* conn = (*i)->getToNode();
1436 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1440 if (pos.
x() == 0 && pos.
y() == 0) {
1452 (*i)->invalidateConnections();
1460 (*i)->invalidateConnections();
1487 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane,
1489 if (from != prohibitorFrom) {
1513 lefthand = !lefthand;
1520 if ((!lefthand && fromLane <= prohibitorFromLane) ||
1521 (lefthand && fromLane >= prohibitorFromLane)) {
1524 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (double)360.0);
1525 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (double)360.0);
1535 bool lefthand)
const {
1537 if (from != from2 || to == to2 || fromLane == fromLane2) {
1545 bool result =
false;
1547 if (fromLane < fromLane2) {
1549 while (*it != to2) {
1557 while (*it != to2) {
1589 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
1599 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
1600 bool regardNonSignalisedLowerPriority)
const {
1602 possProhibitedFrom, possProhibitedTo,
1603 regardNonSignalisedLowerPriority);
1609 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
1618 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1619 bool changed =
true;
1625 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1630 bool blockedChanged =
false;
1632 NBConnectionVector::const_iterator j;
1633 for (j = blocked.begin(); j != blocked.end(); j++) {
1635 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
1636 blockedChanged =
true;
1640 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1642 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
1646 }
else if (sblocked.
getFrom() == removed) {
1647 assert(sblocked.
getTo() != removed);
1648 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1651 }
else if (sblocked.
getTo() == removed) {
1652 assert(sblocked.
getFrom() != removed);
1653 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1660 if (blockedChanged) {
1661 blockedConnectionsNew[blocker] = newBlocked;
1666 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
1671 }
else if (blocker.
getFrom() == removed) {
1672 assert(blocker.
getTo() != removed);
1674 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1677 }
else if (blocker.
getTo() == removed) {
1678 assert(blocker.
getFrom() != removed);
1680 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1684 blockedConnectionsNew[blocker] = blocked;
1698 if (outgoing == 0) {
1711 if (abs((
int) angle) + 1 < 45) {
1713 EdgeVector::const_iterator i =
1721 if (fabs(angle2) < fabs(angle) && fabs(angle2 - angle) > 5.) {
1722 if (angle2 > angle) {
1739 EdgeVector::const_iterator i =
1746 while ((*i) != incoming) {
1747 if ((*i)->getFromNode() ==
this 1749 && (vehPerm & (*i)->getPermissions()) != 0) {
1762 EdgeVector::const_iterator i =
1769 while ((*i) != incoming) {
1770 if ((*i)->getFromNode() ==
this 1772 && (vehPerm & (*i)->getPermissions()) != 0) {
1788 bool mayDefinitelyPass,
const std::string& tlID)
const {
1795 if (outgoing == 0) {
1807 if ((!incoming->
isInnerEdge() &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)) && !mayDefinitelyPass) {
1828 reason =
"rail_signal";
1832 reason =
"crossing";
1835 EdgeVector::const_iterator i;
1840 reason =
"edges incompatible: " + reason;
1844 reason =
"turnaround";
1852 std::set<NBNode*> origSet;
1854 origSet.insert((*i)->getFromNode());
1856 if (origSet.size() < 2) {
1864 if (opposite != 0) {
1868 if (!(*i)->expandableBy(continuation, reason)) {
1869 reason =
"edges incompatible: " + reason;
1875 reason =
"not opposites";
1882 reason =
"intersection";
1887 std::vector<std::pair<NBEdge*, NBEdge*> >
1890 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
1894 std::pair<NBEdge*, NBEdge*>(
1902 assert(opposite != 0);
1904 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
1922 (*i)->resetNodeBorder(
this);
1931 if ((*i)->getToNode() == n) {
1946 back_inserter(edges));
1948 back_inserter(edges));
1949 for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
1960 for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
1961 if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
1978 #ifdef DEBUG_PED_STRUCTURES 1987 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
1991 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
1992 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
1994 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
1996 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
1997 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2000 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2001 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2006 int firstSidewalk = -1;
2007 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2008 if (normalizedLanes[i].second) {
2013 int hadCandidates = 0;
2014 std::vector<int> connectedCandidates;
2015 if (firstSidewalk != -1) {
2017 std::vector<std::pair<NBEdge*, bool> > tmp;
2018 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2019 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2020 normalizedLanes = tmp;
2023 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2024 NBEdge* edge = normalizedLanes[i].first;
2025 const bool allowsPed = normalizedLanes[i].second;
2027 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2029 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2030 candidates.push_back(edge);
2031 }
else if (allowsPed) {
2032 if (candidates.size() > 0) {
2038 connectedCandidates.push_back(n);
2045 if (hadCandidates > 0 && candidates.size() > 0) {
2051 connectedCandidates.push_back(n);
2057 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2059 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2061 if (connectedCandidates.back() <= connectedCandidates.front()) {
2062 numGuessed -= connectedCandidates.back();
2065 numGuessed -= connectedCandidates.front();
2071 std::cout <<
"guessedCrossings:\n";
2073 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2083 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2085 if (candidates.size() == 0) {
2087 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2092 double prevAngle = -100000;
2093 for (
int i = 0; i < (int)candidates.size(); ++i) {
2094 NBEdge* edge = candidates[i];
2099 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2105 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2114 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2119 double prevAngle = -100000;
2120 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2121 double angle = (*it)->getCrossingAngle(
this);
2122 if (it != candidates.begin()) {
2123 NBEdge* prev = *(it - 1);
2128 double intermediateWidth = 0;
2131 prevPos = prev->
getLanes()[laneI].shape[-1];
2134 prevPos = prev->
getLanes()[laneI].shape[0];
2139 currPos = curr->
getLanes()[laneI].shape[0];
2142 currPos = curr->
getLanes()[laneI].shape[-1];
2148 <<
" prevAngle=" << prevAngle
2149 <<
" angle=" << angle
2150 <<
" intermediateWidth=" << intermediateWidth
2163 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2174 std::sort(edges.begin(), edges.end());
2178 EdgeVector edgesOfCrossing = crossing->edges;
2179 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2180 if (edgesOfCrossing == edges) {
2190 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2191 if (!normalizedLanes[i].second) {
2205 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2206 if (crossing->valid) {
2207 WRITE_WARNING(
"Discarding invalid crossing '" + crossing->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(crossing->edges) +
"' (no walkingarea found).");
2210 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2211 if (it_nc != wa.nextCrossings.end()) {
2212 wa.nextCrossings.erase(it_nc);
2215 crossing->valid =
false;
2216 crossing->prevWalkingArea =
"";
2217 crossing->nextWalkingArea =
"";
2222 std::vector<NBNode::Crossing*>
2224 std::vector<Crossing*> result;
2227 result.push_back(c);
2245 myCrossings.clear();
2264 int noInternalNoSplits = 0;
2266 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2267 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2268 if ((*k).toEdge == 0) {
2271 noInternalNoSplits++;
2277 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2284 #ifdef DEBUG_PED_STRUCTURES 2288 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2304 c->nextWalkingArea =
"";
2305 c->prevWalkingArea =
"";
2308 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2314 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2317 double maxAngleDiff = 0;
2318 int maxAngleDiffIndex = 0;
2319 for (
int i = 0; i < (int) edges.size(); i++) {
2321 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2326 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2328 if (diff > maxAngleDiff) {
2329 maxAngleDiff = diff;
2330 maxAngleDiffIndex = i;
2333 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2335 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2337 std::cout <<
" rotatedEdges=" <<
toString(edges);
2341 std::reverse(edges.begin(), edges.end());
2343 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2347 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2348 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2349 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2350 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2352 WRITE_WARNING(
"Discarding invalid crossing '" + c->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(c->edges) +
"' (no vehicle lanes to cross).");
2354 }
else if (c->customShape.size() != 0) {
2355 c->shape = c->customShape;
2357 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2358 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2365 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2366 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2375 #ifdef DEBUG_PED_STRUCTURES 2381 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2388 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2389 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2391 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2393 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2397 normalizedLanes.push_back(std::make_pair(edge, l));
2400 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2405 normalizedLanes.push_back(std::make_pair(edge, l));
2411 std::vector<std::pair<int, int> > waIndices;
2413 NBEdge* prevEdge = normalizedLanes.back().first;
2414 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2415 NBEdge* edge = normalizedLanes[i].first;
2423 waIndices.push_back(std::make_pair(start, i - start));
2433 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2438 const int waNumLanes = (int)normalizedLanes.size() - start;
2439 if (waIndices.size() == 0) {
2440 waIndices.push_back(std::make_pair(start, waNumLanes));
2442 std::cout <<
" single wa, end at wrap-around\n";
2445 if (waIndices.front().first == 0) {
2446 NBEdge* edge = normalizedLanes.front().first;
2447 NBEdge* prevEdge = normalizedLanes.back().first;
2450 waIndices.push_back(std::make_pair(start, waNumLanes));
2452 std::cout <<
" do not wrap around, turn-around in between\n";
2456 waIndices.front().first = start;
2457 waIndices.front().second = waNumLanes + waIndices.front().second;
2459 std::cout <<
" wrapping around\n";
2464 waIndices.push_back(std::make_pair(start, waNumLanes));
2466 std::cout <<
" end at wrap-around\n";
2472 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2473 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2474 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2478 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2479 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2480 const int start = waIndices[i].first;
2481 const int prev = start > 0 ? start - 1 : (int)normalizedLanes.size() - 1;
2482 const int count = waIndices[i].second;
2483 const int end = (start + count) % normalizedLanes.size();
2487 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << start <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2489 double endCrossingWidth = 0;
2490 double startCrossingWidth = 0;
2494 bool connectsCrossing =
false;
2495 std::vector<Position> connectedPoints;
2498 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
2500 if (c->edges.back() == normalizedLanes[end].first
2501 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
2503 if (c->nextWalkingArea !=
"") {
2505 +
"'; crossing '" + c->id
2506 +
"' targets '" + c->nextWalkingArea
2507 +
"' and '" + wa.
id +
"'.");
2510 c->nextWalkingArea = wa.
id;
2513 endCrossingWidth = c->width;
2514 endCrossingShape = c->shape;
2516 connectsCrossing =
true;
2517 connectedPoints.push_back(c->shape[-1]);
2521 std::cout <<
" crossing " << c->id <<
" ends\n";
2524 if (c->edges.front() == normalizedLanes[prev].first
2525 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
2527 if (c->prevWalkingArea !=
"") {
2529 +
"'; crossing '" + c->id
2530 +
"' is targeted by '" + c->prevWalkingArea
2531 +
"' and '" + wa.
id +
"'.");
2534 c->prevWalkingArea = wa.
id;
2538 startCrossingWidth = c->width;
2539 startCrossingShape = c->shape;
2541 connectsCrossing =
true;
2542 connectedPoints.push_back(c->shape[0]);
2546 std::cout <<
" crossing " << c->id <<
" starts\n";
2549 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
2550 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
2551 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[start].first->getID()
2552 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
2555 if (count < 2 && !connectsCrossing) {
2558 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
2563 std::set<NBEdge*> connected;
2564 for (
int j = 0; j < count; ++j) {
2565 const int nlI = (start + j) % normalizedLanes.size();
2566 NBEdge* edge = normalizedLanes[nlI].first;
2569 if (connected.count(edge) == 0) {
2577 connected.insert(edge);
2584 if (buildExtensions) {
2586 if (startCrossingShape.size() > 0) {
2588 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
2590 startCrossingShape.
move2side(startCrossingWidth / 2);
2592 startCrossingShape.
move2side(-startCrossingWidth);
2596 if (endCrossingShape.size() > 0) {
2598 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
2600 endCrossingShape.
move2side(endCrossingWidth / 2);
2602 endCrossingShape.
move2side(-endCrossingWidth);
2607 && normalizedLanes.size() == 2) {
2609 NBEdge* e1 = *connected.begin();
2610 NBEdge* e2 = *(++connected.begin());
2613 std::cout <<
" not building a walkingarea since normal connections exist\n";
2619 if (cornerDetail > 0) {
2620 int smoothEnd = end;
2621 int smoothPrev = prev;
2623 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
2624 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
2626 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
2627 if (smoothPrev == 0) {
2628 smoothPrev = (int)normalizedLanes.size() - 1;
2633 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
2634 begShape = begShape.
reverse();
2636 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
2637 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
2638 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
2642 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
2643 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
2644 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
2645 if (curve.size() > 2) {
2646 curve.erase(curve.begin());
2648 if (endCrossingWidth > 0) {
2649 wa.
shape.pop_back();
2651 if (startCrossingWidth > 0) {
2661 if (wacs.shape.size() != 0 && std::includes(connected.begin(), connected.end(), wacs.edges.begin(), wacs.edges.end())) {
2662 wa.
shape = wacs.shape;
2668 double lengthSum = 0;
2669 int combinations = 0;
2670 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
2671 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
2681 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
2684 if (combinations > 0) {
2690 std::vector<Crossing*> validCrossings =
getCrossings();
2691 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
2693 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
2695 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
2710 wa.
shape.push_back(tmp[-1]);
2712 wa.
shape.push_back(tmp[-1]);
2716 wa.
shape.push_back(tmp[0]);
2718 wa.
shape.push_back(tmp[0]);
2722 crossed.insert(crossed.end(), next.
edges.begin(), next.
edges.end());
2723 std::sort(crossed.begin(), crossed.end());
2726 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 && std::includes(crossed.begin(), crossed.end(), wacs.edges.begin(), wacs.edges.end())) {
2727 wa.
shape = wacs.shape;
2736 std::cout <<
" build wa=" << wa.
id <<
"\n";
2754 EdgeVector::const_iterator it1 = find(edges.begin(), edges.end(), e1);
2755 EdgeVector::const_iterator it2 = find(edges.begin(), edges.end(), e2);
2756 if (it1 != edges.end() && it2 != edges.end()) {
2772 while (it != it_end) {
2773 result.push_back(*it);
2783 wacs.
edges.insert(edges.begin(), edges.end());
2809 if (
MAX2(angle0, angle1) <= 160) {
2831 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
2842 EdgeSet edgeSet(edges.begin(), edges.end());
2844 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
2845 if (edgeSet == edgeSet2) {
2862 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
2868 EdgeSet edgeSet(edges.begin(), edges.end());
2870 EdgeSet edgeSet2(it->edges.begin(), it->edges.end());
2871 if (edgeSet == edgeSet2) {
2878 throw ProcessError(
"Request for unknown crossing for the given Edges");
2885 bool usedCustom =
false;
2887 c->tlLinkIndex = startIndex++;
2889 if (c->customTLIndex != -1) {
2890 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
2891 c->tlLinkIndex = c->customTLIndex;
2893 c->tlLinkIndex2 = c->customTLIndex2;
2905 result += (int)edge->getConnections().size();
2918 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2919 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2955 std::cout <<
" angles:\n";
2956 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
2957 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
2959 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
2964 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
2966 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
2968 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
2979 assert(
id[0] ==
':');
2980 std::string::size_type sep_index =
id.rfind(
'_');
2981 if (sep_index == std::string::npos) {
2982 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
2985 sep_index =
id.substr(0, sep_index).rfind(
'_');
2986 if (sep_index == std::string::npos) {
2987 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
2990 return id.substr(1, sep_index - 1);
3000 if (turnDest != 0) {
3021 if ((*i)->rightOnRedConflict(index, foeIndex)) {
3044 std::vector<NBEdge*>::iterator j;
3045 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3048 if (allEdges.size() > 1 && j != allEdges.end()) {
3053 NBEdge* firstOfAll = allEdges.front();
3054 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3055 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3061 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3062 if (firstOfIncoming != 0) {
3063 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3065 if (firstOfOutgoing != 0) {
3066 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3068 #ifdef DEBUG_EDGE_SORTING 3070 std::cout <<
"sortedEdges:\n";
3071 for (
NBEdge* e : allEdges) {
3072 std::cout <<
" " << e->
getID()
3073 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3074 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3081 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3082 std::vector<NBEdge*>::const_iterator in, out;
3083 std::vector<NBEdge*> allTmp;
3084 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3085 if ((*in)->isTurningDirectionAt(*out)) {
3086 allTmp.push_back(*in);
3087 allTmp.push_back(*out);
3092 if (allTmp.size() == allEdges.size()) {
3105 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3109 e->computeEdgeShape();
3114 std::vector<Position>
3117 std::vector<Position> result;
3119 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3128 result.push_back(pos);
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.
bool almostSame(const Position &p2, double maxDiv=POSITION_EPS) const
checki if two position is almost the sme as other
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.
double getRadius() const
get computed radius for node
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...
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 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, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED)
Adds a connection to a certain lane of a certain edge.
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
void displaceShapeAtWidthChange(const NBEdge *from, const NBEdge::Connection &con, PositionVector &fromShape, PositionVector &toShape) const
displace lane shapes to account for change in lane width at this node
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.
static bool isLongEnough(NBEdge *out, double minLength)
check if is long enough
void buildBitfieldLogic()
builds the bitset-representation of the logic
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
#define UNUSED_PARAMETER(x)
Crossing(const NBNode *_node, const EdgeVector &_edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector &_customShape)
constructor
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.
static const int AVOID_WIDE_RIGHT_TURN
flags for controlling shape generation
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)...
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
bool tlsContConflict(const NBEdge *from, const NBEdge::Connection &c, const NBEdge *foeFrom, const NBEdge::Connection &foe) const
whether the connection must yield if the foe remains on the intersection after its phase ends ...
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.
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.
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.
bool turnFoes(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *from2, const NBEdge *to2, int fromLane2, bool lefthand=false) const
return whether the given laneToLane connection originate from the same edge and are in conflict due t...
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
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width ...
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.
std::set< const NBEdge *, ComparatorIdLess > 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.
static PositionVector bezierControlPoints(const PositionVector &begShape, const PositionVector &endShape, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, bool &ok, NBNode *recordError=0, double straightThresh=DEG2RAD(5), int shapeFlag=0)
get bezier control points
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.
An upper class for objects with additional parameters.
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
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.
bool setCrossingTLIndices(const std::string &tlID, int startIndex)
void avoidOverlap()
fix overlap
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.
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
const PositionVector & getShape() const
retrieve the junction shape
double getSpeed() const
Returns the speed allowed on this edge.
NBNode::Crossing * addCrossing(EdgeVector edges, double width, bool priority, int tlIndex=-1, int tlIndex2=-1, const PositionVector &customShape=PositionVector::EMPTY, bool fromSumoNet=false)
add a pedestrian crossing to this node
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
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 there 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.
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset, int threshold=-1)
patches loaded signal plans by modifying lane indices above threshold by the given offset ...
~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
std::vector< Position > getEndPoints() const
return list of unique endpoint coordinates of all edges at this node
static const int FOUR_CONTROL_POINTS
void writeLogic(std::string key, OutputDevice &into, const bool checkLaneFoes) const
writes the XML-representation of the logic as a bitset-logic XML representation
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)
SumoXMLNodeType getType() const
Returns the type of this node.
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)
bool haveVia
check if Connection have a Via
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
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, double extrapolateBeg, double extrapolateEnd, NBNode *recordError=0, int shapeFlag=0) const
Compute a smooth curve between the given geometries.
void discardWalkingareas()
discard previously built walkingareas (required for repeated computation by netedit) ...
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
static const int AVOID_WIDE_LEFT_TURN
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