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),
287 bool updateEdgeGeometries) {
294 if (updateEdgeGeometries) {
298 (*i)->setGeometry(geom);
303 (*i)->setGeometry(geom);
316 wacs.shape.add(xoff, yoff, 0);
330 (*it_wa).shape.mirrorX();
356 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
366 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
368 if (dynamic_cast<NBLoadedSUMOTLDef*>(orig) !=
nullptr) {
369 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
370 }
else if (dynamic_cast<NBOwnTLDef*>(orig) ==
nullptr) {
372 const std::vector<NBNode*>& nodes = orig->
getNodes();
373 while (!nodes.empty()) {
374 newDef->
addNode(nodes.front());
375 nodes.front()->removeTrafficLight(orig);
388 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
415 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
464 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
480 double extrapolateBeg,
481 double extrapolateEnd,
483 int shapeFlag)
const {
487 #ifdef DEBUG_SMOOTH_GEOM 489 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
492 if (init.size() == 0) {
494 ret.push_back(begShape.back());
495 ret.push_back(endShape.front());
498 return bezier(init, numPoints).smoothedZFront();
507 double extrapolateBeg,
508 double extrapolateEnd,
511 double straightThresh,
514 const Position beg = begShape.back();
515 const Position end = endShape.front();
519 #ifdef DEBUG_SMOOTH_GEOM 520 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
536 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
537 init.push_back(center);
542 endShapeBegLine.extrapolate2D(100,
true);
544 if (fabs(angle) <
M_PI / 4.) {
547 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
548 const double halfDistance = dist / 2;
549 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
550 #ifdef DEBUG_SMOOTH_GEOM 551 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
552 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
555 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
558 #ifdef DEBUG_SMOOTH_GEOM 559 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
560 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
561 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
562 <<
" displacementError=" << sin(displacementAngle) * dist
563 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
566 if (recordError !=
nullptr) {
571 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
572 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
574 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
576 #ifdef DEBUG_SMOOTH_GEOM 577 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
578 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
579 <<
" halfDistance=" << halfDistance <<
"\n";
588 Position intersect = endShapeBegLine.intersectionPosition2D(begShapeEndLineRev);
590 #ifdef DEBUG_SMOOTH_GEOM 592 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
593 <<
" endShapeBegLine=" << endShapeBegLine
594 <<
" begShapeEndLineRev=" << begShapeEndLineRev
599 if (recordError !=
nullptr) {
605 const double minControlLength =
MIN2((
double)1.0, dist / 2);
608 const bool lengthenBeg = distBeg <= minControlLength;
609 const bool lengthenEnd = distEnd <= minControlLength;
610 if (lengthenBeg && lengthenEnd) {
611 #ifdef DEBUG_SMOOTH_GEOM 612 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
613 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
615 if (recordError !=
nullptr) {
623 init.push_back(endShapeBegLine.positionAtOffset2D(100 - extrapolateEnd));
624 }
else if (lengthenBeg || lengthenEnd) {
626 init.push_back(endShapeBegLine.positionAtOffset2D(100 - minControlLength));
630 init.push_back(endShapeBegLine.positionAtOffset2D(100 - 10.0));
634 init.push_back(endShapeBegLine.positionAtOffset2D(100 - 10.0));
638 const double z2 = endShapeBegLine.positionAtOffset2D(endShapeBegLine.nearest_offset_to_point2D(intersect)).z();
639 const double z3 = 0.5 * (beg.
z() + end.
z());
643 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
648 intersect.
set(intersect.
x(), intersect.
y(), z);
649 init.push_back(intersect);
671 if (useCustomShape) {
674 if (startBorder.size() == 0) {
675 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
678 if (tmp.size() < 2) {
680 useCustomShape =
false;
684 tmp[0] = fromShape.back();
685 }
else if (recordError !=
nullptr) {
686 const double offset = tmp[0].distanceTo2D(fromShape.back());
692 if (endBorder.size() == 0) {
693 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
696 if (ret.size() < 2) {
698 useCustomShape =
false;
701 ret[-1] = toShape.front();
702 }
else if (recordError !=
nullptr) {
703 const double offset = ret[-1].distanceTo2D(toShape.front());
710 if (!useCustomShape) {
721 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
724 if (lane.endOffset > 0) {
749 for (
int i = 0; i < con.
toLane; ++i) {
753 for (
int i = 0; i < con.
fromLane; ++i) {
763 fromShape.
move2side(inCenter - outCenter);
803 if (thisRight && !rightTurnConflict) {
806 if (!(
foes(otherFromE, otherToE, fromE, toE) ||
myRequest ==
nullptr || rightTurnConflict)) {
816 const bool bothLeft = thisLeft && otherLeft;
817 if (fromE == otherFromE && !thisRight) {
824 if (c.
tlID !=
"" && !bothLeft) {
827 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
852 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
854 if ((*i)->getNodes().size() > 1) {
856 (*i)->removeNode(
this);
857 (*i)->setParticipantsInformation();
858 (*i)->setTLControllingInformation();
896 }
else if (numConnections == 0) {
966 if (mismatchThreshold >= 0
999 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1030 std::swap(in1, in2);
1031 std::swap(in1Offset, in2Offset);
1060 std::swap(out1, out2);
1061 std::swap(out1Offset, out2Offset);
1084 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1108 inOffset += reduction;
1109 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1121 EdgeVector::reverse_iterator i;
1123 NBEdge* currentOutgoing = *i;
1126 const int numApproaching = (int)approaching->size();
1127 if (numApproaching != 0) {
1141 const std::vector<NBEdge::Connection>& elv = incoming->
getConnections();
1142 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1144 if (c.
toEdge == currentOutgoing) {
1147 unsatisfied &= ~satisfied;
1150 if (unsatisfied != 0) {
1153 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1155 for (
int toLane = 0; toLane < currentOutgoing->
getNumLanes(); ++toLane) {
1160 unsatisfied &= ~satisfied;
1177 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1178 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1180 (*i)->removeFromConnections((*k).toEdge);
1191 (*i)->markAsInLane2LaneState();
1208 while (seen < minLength) {
1224 EdgeVector::const_iterator i = find(
myAllEdges.begin(),
1230 for (; *i != currentOutgoing;) {
1232 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1233 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1234 if (connLanes.size() != 0) {
1235 approaching->push_back(*i);
1266 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1268 laneOff += (*i)->getNumLanes();
1298 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1300 laneOff += (*i)->getNumLanes();
1315 int whichLaneOff,
int byLaneOff) {
1319 bool changed =
false;
1321 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1324 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1338 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1340 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1341 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1401 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1402 edges.erase(find(edges.begin(), edges.end(), e));
1404 if (edges.size() == 0) {
1419 if (mayDrive.
getFrom() ==
nullptr ||
1420 mayDrive.
getTo() ==
nullptr ||
1421 mustStop.
getFrom() ==
nullptr ||
1422 mustStop.
getTo() ==
nullptr) {
1424 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1428 conn.push_back(mayDrive);
1435 int size = (int) edgeid.length();
1437 std::string
id = (*i)->
getID();
1438 if (
id.substr(0, size) == edgeid) {
1448 int size = (int) edgeid.length();
1450 std::string
id = (*i)->
getID();
1451 if (
id.substr(0, size) == edgeid) {
1476 if (removeFromConnections) {
1478 (*i)->removeFromConnections(edge);
1483 (*i)->replaceRemoved(edge, -1,
nullptr, -1);
1492 EdgeVector::const_iterator i;
1494 NBNode* conn = (*i)->getFromNode();
1497 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1501 NBNode* conn = (*i)->getToNode();
1504 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1508 if (pos.
x() == 0 && pos.
y() == 0) {
1520 (*i)->invalidateConnections();
1528 (*i)->invalidateConnections();
1540 if (to ==
nullptr) {
1555 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane,
1557 if (from != prohibitorFrom) {
1581 lefthand = !lefthand;
1588 if ((!lefthand && fromLane <= prohibitorFromLane) ||
1589 (lefthand && fromLane >= prohibitorFromLane)) {
1592 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (double)360.0);
1593 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (double)360.0);
1603 bool lefthand)
const {
1605 if (from != from2 || to == to2 || fromLane == fromLane2) {
1613 bool result =
false;
1615 if (fromLane < fromLane2) {
1617 while (*it != to2) {
1625 while (*it != to2) {
1657 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
1667 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
1668 bool regardNonSignalisedLowerPriority)
const {
1670 possProhibitedFrom, possProhibitedTo,
1671 regardNonSignalisedLowerPriority);
1677 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
1686 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1687 bool changed =
true;
1693 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1698 bool blockedChanged =
false;
1700 NBConnectionVector::const_iterator j;
1701 for (j = blocked.begin(); j != blocked.end(); j++) {
1703 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
1704 blockedChanged =
true;
1708 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1710 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
1714 }
else if (sblocked.
getFrom() == removed) {
1715 assert(sblocked.
getTo() != removed);
1716 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1719 }
else if (sblocked.
getTo() == removed) {
1720 assert(sblocked.
getFrom() != removed);
1721 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1728 if (blockedChanged) {
1729 blockedConnectionsNew[blocker] = newBlocked;
1734 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
1739 }
else if (blocker.
getFrom() == removed) {
1740 assert(blocker.
getTo() != removed);
1742 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1745 }
else if (blocker.
getTo() == removed) {
1746 assert(blocker.
getFrom() != removed);
1748 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1752 blockedConnectionsNew[blocker] = blocked;
1766 if (outgoing ==
nullptr) {
1779 if (abs((
int) angle) + 1 < 45) {
1781 EdgeVector::const_iterator i =
1789 if (fabs(angle2) < fabs(angle) && fabs(angle2 - angle) > 5.) {
1790 if (angle2 > angle) {
1807 EdgeVector::const_iterator i =
1814 while ((*i) != incoming) {
1815 if ((*i)->getFromNode() ==
this 1817 && (vehPerm & (*i)->getPermissions()) != 0) {
1830 EdgeVector::const_iterator i =
1837 while ((*i) != incoming) {
1838 if ((*i)->getFromNode() ==
this 1840 && (vehPerm & (*i)->getPermissions()) != 0) {
1856 bool mayDefinitelyPass,
const std::string& tlID)
const {
1863 if (outgoing ==
nullptr) {
1875 if ((!incoming->
isInternal() &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)) && !mayDefinitelyPass) {
1896 reason =
"rail_signal";
1900 reason =
"crossing";
1903 EdgeVector::const_iterator i;
1908 reason =
"edges incompatible: " + reason;
1912 reason =
"turnaround";
1920 std::set<NBNode*> origSet;
1922 origSet.insert((*i)->getFromNode());
1924 if (origSet.size() < 2) {
1932 if (opposite !=
nullptr) {
1936 if (!(*i)->expandableBy(continuation, reason)) {
1937 reason =
"edges incompatible: " + reason;
1943 reason =
"not opposites";
1950 reason =
"intersection";
1955 std::vector<std::pair<NBEdge*, NBEdge*> >
1958 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
1962 std::pair<NBEdge*, NBEdge*>(
1970 assert(opposite != 0);
1972 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
1990 (*i)->resetNodeBorder(
this);
1999 if ((*i)->getToNode() == n) {
2014 back_inserter(edges));
2016 back_inserter(edges));
2017 for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
2028 for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
2029 if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
2046 #ifdef DEBUG_PED_STRUCTURES 2055 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
2059 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2060 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2062 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2064 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2065 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2068 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2069 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2074 int firstSidewalk = -1;
2075 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2076 if (normalizedLanes[i].second) {
2081 int hadCandidates = 0;
2082 std::vector<int> connectedCandidates;
2083 if (firstSidewalk != -1) {
2085 std::vector<std::pair<NBEdge*, bool> > tmp;
2086 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2087 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2088 normalizedLanes = tmp;
2091 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2092 NBEdge* edge = normalizedLanes[i].first;
2093 const bool allowsPed = normalizedLanes[i].second;
2095 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2097 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2098 candidates.push_back(edge);
2099 }
else if (allowsPed) {
2100 if (candidates.size() > 0) {
2106 connectedCandidates.push_back(n);
2113 if (hadCandidates > 0 && candidates.size() > 0) {
2119 connectedCandidates.push_back(n);
2125 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2127 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2129 if (connectedCandidates.back() <= connectedCandidates.front()) {
2130 numGuessed -= connectedCandidates.back();
2133 numGuessed -= connectedCandidates.front();
2139 std::cout <<
"guessedCrossings:\n";
2141 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2151 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2153 if (candidates.size() == 0) {
2155 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2160 double prevAngle = -100000;
2161 for (
int i = 0; i < (int)candidates.size(); ++i) {
2162 NBEdge* edge = candidates[i];
2167 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2173 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2182 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2187 double prevAngle = -100000;
2188 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2189 double angle = (*it)->getCrossingAngle(
this);
2190 if (it != candidates.begin()) {
2191 NBEdge* prev = *(it - 1);
2196 double intermediateWidth = 0;
2199 prevPos = prev->
getLanes()[laneI].shape[-1];
2202 prevPos = prev->
getLanes()[laneI].shape[0];
2207 currPos = curr->
getLanes()[laneI].shape[0];
2210 currPos = curr->
getLanes()[laneI].shape[-1];
2216 <<
" prevAngle=" << prevAngle
2217 <<
" angle=" << angle
2218 <<
" intermediateWidth=" << intermediateWidth
2231 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2242 std::sort(edges.begin(), edges.end());
2246 EdgeVector edgesOfCrossing = crossing->edges;
2247 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2248 if (edgesOfCrossing == edges) {
2258 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2259 if (!normalizedLanes[i].second) {
2273 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2274 if (crossing->valid) {
2275 WRITE_WARNING(
"Discarding invalid crossing '" + crossing->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(crossing->edges) +
"' (no walkingarea found).");
2278 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2279 if (it_nc != wa.nextCrossings.end()) {
2280 wa.nextCrossings.erase(it_nc);
2283 crossing->valid =
false;
2284 crossing->prevWalkingArea =
"";
2285 crossing->nextWalkingArea =
"";
2290 std::vector<NBNode::Crossing*>
2292 std::vector<Crossing*> result;
2295 result.push_back(c);
2313 myCrossings.clear();
2332 int noInternalNoSplits = 0;
2334 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2335 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2336 if ((*k).toEdge ==
nullptr) {
2339 noInternalNoSplits++;
2345 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2352 #ifdef DEBUG_PED_STRUCTURES 2356 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2372 c->nextWalkingArea =
"";
2373 c->prevWalkingArea =
"";
2376 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2382 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2385 double maxAngleDiff = 0;
2386 int maxAngleDiffIndex = 0;
2387 for (
int i = 0; i < (int) edges.size(); i++) {
2389 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2394 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2396 if (diff > maxAngleDiff) {
2397 maxAngleDiff = diff;
2398 maxAngleDiffIndex = i;
2401 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2403 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2405 std::cout <<
" rotatedEdges=" <<
toString(edges);
2409 std::reverse(edges.begin(), edges.end());
2411 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2415 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2416 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2417 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2418 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2420 WRITE_WARNING(
"Discarding invalid crossing '" + c->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(c->edges) +
"' (no vehicle lanes to cross).");
2422 }
else if (c->customShape.size() != 0) {
2423 c->shape = c->customShape;
2425 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2426 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2435 WRITE_WARNING(
"Discarding invalid crossing '" + c->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(c->edges) +
"' (Invalid shape).");
2438 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2439 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2449 #ifdef DEBUG_PED_STRUCTURES 2455 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2462 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2463 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2465 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2467 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2471 normalizedLanes.push_back(std::make_pair(edge, l));
2474 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2479 normalizedLanes.push_back(std::make_pair(edge, l));
2485 std::vector<std::pair<int, int> > waIndices;
2487 NBEdge* prevEdge = normalizedLanes.back().first;
2488 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2489 NBEdge* edge = normalizedLanes[i].first;
2497 waIndices.push_back(std::make_pair(start, i - start));
2507 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2512 const int waNumLanes = (int)normalizedLanes.size() - start;
2513 if (waIndices.size() == 0) {
2514 waIndices.push_back(std::make_pair(start, waNumLanes));
2516 std::cout <<
" single wa, end at wrap-around\n";
2519 if (waIndices.front().first == 0) {
2520 NBEdge* edge = normalizedLanes.front().first;
2521 NBEdge* prevEdge = normalizedLanes.back().first;
2524 waIndices.push_back(std::make_pair(start, waNumLanes));
2526 std::cout <<
" do not wrap around, turn-around in between\n";
2530 waIndices.front().first = start;
2531 waIndices.front().second = waNumLanes + waIndices.front().second;
2533 std::cout <<
" wrapping around\n";
2538 waIndices.push_back(std::make_pair(start, waNumLanes));
2540 std::cout <<
" end at wrap-around\n";
2546 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2547 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2548 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2552 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2553 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2554 const int start = waIndices[i].first;
2555 const int prev = start > 0 ? start - 1 : (int)normalizedLanes.size() - 1;
2556 const int count = waIndices[i].second;
2557 const int end = (start + count) % normalizedLanes.size();
2561 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << start <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2563 double endCrossingWidth = 0;
2564 double startCrossingWidth = 0;
2568 bool connectsCrossing =
false;
2569 std::vector<Position> connectedPoints;
2572 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
2574 if (c->edges.back() == normalizedLanes[end].first
2575 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
2577 if (c->nextWalkingArea !=
"") {
2579 +
"'; crossing '" + c->id
2580 +
"' targets '" + c->nextWalkingArea
2581 +
"' and '" + wa.
id +
"'.");
2584 c->nextWalkingArea = wa.
id;
2587 endCrossingWidth = c->width;
2588 endCrossingShape = c->shape;
2590 connectsCrossing =
true;
2591 connectedPoints.push_back(c->shape[-1]);
2595 std::cout <<
" crossing " << c->id <<
" ends\n";
2598 if (c->edges.front() == normalizedLanes[prev].first
2599 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
2601 if (c->prevWalkingArea !=
"") {
2603 +
"'; crossing '" + c->id
2604 +
"' is targeted by '" + c->prevWalkingArea
2605 +
"' and '" + wa.
id +
"'.");
2608 c->prevWalkingArea = wa.
id;
2612 startCrossingWidth = c->width;
2613 startCrossingShape = c->shape;
2615 connectsCrossing =
true;
2616 connectedPoints.push_back(c->shape[0]);
2620 std::cout <<
" crossing " << c->id <<
" starts\n";
2623 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
2624 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
2625 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[start].first->getID()
2626 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
2629 if (count < 2 && !connectsCrossing) {
2632 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
2637 std::set<NBEdge*, ComparatorIdLess> connected;
2638 for (
int j = 0; j < count; ++j) {
2639 const int nlI = (start + j) % normalizedLanes.size();
2640 NBEdge* edge = normalizedLanes[nlI].first;
2643 if (connected.count(edge) == 0) {
2651 connected.insert(edge);
2658 if (buildExtensions) {
2660 if (startCrossingShape.size() > 0) {
2662 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
2664 startCrossingShape.
move2side(startCrossingWidth / 2);
2666 startCrossingShape.
move2side(-startCrossingWidth);
2670 if (endCrossingShape.size() > 0) {
2672 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
2674 endCrossingShape.
move2side(endCrossingWidth / 2);
2676 endCrossingShape.
move2side(-endCrossingWidth);
2681 && normalizedLanes.size() == 2) {
2683 NBEdge* e1 = *connected.begin();
2684 NBEdge* e2 = *(++connected.begin());
2687 std::cout <<
" not building a walkingarea since normal connections exist\n";
2693 if (cornerDetail > 0) {
2694 int smoothEnd = end;
2695 int smoothPrev = prev;
2697 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
2698 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
2700 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
2701 if (smoothPrev == 0) {
2702 smoothPrev = (int)normalizedLanes.size() - 1;
2707 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
2708 begShape = begShape.
reverse();
2710 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
2711 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
2712 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
2715 if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
2719 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
2723 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
2724 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
2725 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
2726 if (curve.size() > 2) {
2727 curve.erase(curve.begin());
2729 if (endCrossingWidth > 0) {
2730 wa.
shape.pop_back();
2732 if (startCrossingWidth > 0) {
2742 if (wacs.shape.size() != 0 &&
includes(connected, wacs.edges)) {
2743 wa.
shape = wacs.shape;
2749 double lengthSum = 0;
2750 int combinations = 0;
2751 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
2752 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
2762 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
2765 if (combinations > 0) {
2771 std::vector<Crossing*> validCrossings =
getCrossings();
2772 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
2774 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
2776 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
2791 wa.
shape.push_back(tmp[-1]);
2793 wa.
shape.push_back(tmp[-1]);
2797 wa.
shape.push_back(tmp[0]);
2799 wa.
shape.push_back(tmp[0]);
2802 std::set<NBEdge*, ComparatorIdLess> crossed(prev.
edges.begin(), prev.
edges.end());
2803 crossed.insert(next.
edges.begin(), next.
edges.end());
2806 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(crossed, wacs.edges)) {
2807 wa.
shape = wacs.shape;
2816 std::cout <<
" build wa=" << wa.
id <<
"\n";
2824 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
2826 for (
const NBEdge* e : sub) {
2827 if (super.count(const_cast<NBEdge*>(e)) == 0) {
2846 EdgeVector::const_iterator it1 = find(edges.begin(), edges.end(), e1);
2847 EdgeVector::const_iterator it2 = find(edges.begin(), edges.end(), e2);
2848 if (it1 != edges.end() && it2 != edges.end()) {
2864 while (it != it_end) {
2865 result.push_back(*it);
2875 wacs.
edges.insert(edges.begin(), edges.end());
2901 if (
MAX2(angle0, angle1) <= 160) {
2923 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
2934 EdgeSet edgeSet(edges.begin(), edges.end());
2936 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
2937 if (edgeSet == edgeSet2) {
2954 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
2960 EdgeSet edgeSet(edges.begin(), edges.end());
2962 EdgeSet edgeSet2(it->edges.begin(), it->edges.end());
2963 if (edgeSet == edgeSet2) {
2970 throw ProcessError(
"Request for unknown crossing for the given Edges");
2977 bool usedCustom =
false;
2979 c->tlLinkIndex = startIndex++;
2981 if (c->customTLIndex != -1) {
2982 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
2983 c->tlLinkIndex = c->customTLIndex;
2985 c->tlLinkIndex2 = c->customTLIndex2;
2997 result += (int)edge->getConnections().size();
3010 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
3011 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
3047 std::cout <<
" angles:\n";
3048 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3049 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3051 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3056 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
3058 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
3060 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
3071 assert(
id[0] ==
':');
3072 std::string::size_type sep_index =
id.rfind(
'_');
3073 if (sep_index == std::string::npos) {
3074 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3077 sep_index =
id.substr(0, sep_index).rfind(
'_');
3078 if (sep_index == std::string::npos) {
3079 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3082 return id.substr(1, sep_index - 1);
3092 if (turnDest !=
nullptr) {
3113 if ((*i)->rightOnRedConflict(index, foeIndex)) {
3136 std::vector<NBEdge*>::iterator j;
3137 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3140 if (allEdges.size() > 1 && j != allEdges.end()) {
3145 NBEdge* firstOfAll = allEdges.front();
3146 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3147 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3153 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3154 if (firstOfIncoming !=
nullptr) {
3155 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3157 if (firstOfOutgoing !=
nullptr) {
3158 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3160 #ifdef DEBUG_EDGE_SORTING 3162 std::cout <<
"sortedEdges:\n";
3163 for (
NBEdge* e : allEdges) {
3164 std::cout <<
" " << e->
getID()
3165 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3166 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3173 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3174 std::vector<NBEdge*>::const_iterator in, out;
3175 std::vector<NBEdge*> allTmp;
3176 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3177 if ((*in)->isTurningDirectionAt(*out)) {
3178 allTmp.push_back(*in);
3179 allTmp.push_back(*out);
3184 if (allTmp.size() == allEdges.size()) {
3197 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3201 e->computeEdgeShape();
3206 std::vector<Position>
3209 std::vector<Position> result;
3211 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3220 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
check if two position is almost the sme as other
double length2D() const
Returns the length.
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 writeLogic(OutputDevice &into) const
void append(const PositionVector &v, double sameThreshold=2.0)
PositionVector getOrthogonal(const Position &p, double extend, bool before, double length=1.0) const
return orthogonal through p (extending this vector if necessary)
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.
void computeLogic2(bool checkLaneFoes)
compute right-of-way logic for all lane-to-lane connections
RightOfWay myRightOfWay
how to compute right of way for this node
#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.
static PositionVector startShapeAt(const PositionVector &laneShape, const NBNode *startNode, PositionVector nodeShape)
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
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
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.
const std::string & getFoes(int linkIndex) const
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.
void computeLogic(const bool checkLaneFoes)
writes the XML-representation of the logic as a bitset-logic XML representation
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.
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.
bool writeLogic(OutputDevice &into) const
writes the XML-representation of the logic as a bitset-logic XML representation
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.
const std::string & getResponse(int linkIndex) const
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.
class for maintaining associations between enums and xml-strings
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.
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
const PositionVector & getNodeBorder(const NBNode *node)
static const int FOUR_CONTROL_POINTS
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)
const std::string getFoes(int linkIndex) const
SumoXMLNodeType getType() const
Returns the type of this node.
bool isNAN() const
check if PositionVector is NAN
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 isInternal() const
Returns whether this edge was marked as being within an intersection.
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.
const std::string getResponse(int linkIndex) const
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
static bool includes(const std::set< NBEdge *, ComparatorIdLess > &super, const std::set< const NBEdge *, ComparatorIdLess > &sub)
returns whether sub is a subset of super
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