62 #define EXTEND_CROSSING_ANGLE_THRESHOLD 35.0 // degrees
64 #define SPLIT_CROSSING_WIDTH_THRESHOLD 1.5 // meters
65 #define SPLIT_CROSSING_ANGLE_THRESHOLD 5 // degrees
68 #define MIN_WEAVE_LENGTH 20.0
75 #define DEBUG_NODE_ID "F"
76 #define DEBUGCOND (getID() == DEBUG_NODE_ID)
77 #define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUG_NODE_ID))
99 myApproaching(approaching),
100 myCurrentOutgoing(currentOutgoing),
101 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE) {
103 std::set<int> approachedLanes;
107 approachedLanes.insert(con.toLane);
115 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
121 && approachedLanes.count(i) == 0) {
134 assert((
int)myApproaching.size() > src);
136 NBEdge* incomingEdge = myApproaching[src];
140 if (myAvailableLanes.size() == 0) {
143 std::vector<int> approachingLanes = incomingEdge->
getConnectionLanes(myCurrentOutgoing, myIsBikeEdge || incomingEdge->getPermissions() ==
SVC_BICYCLE);
144 if (approachingLanes.size() == 0) {
147 #ifdef DEBUG_CONNECTION_GUESSING
149 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
153 std::deque<int>* approachedLanes = spread(approachingLanes, dest);
154 assert(approachedLanes->size() <= myAvailableLanes.size());
156 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
157 assert((
int)approachingLanes.size() > i);
158 int approached = myAvailableLanes[(*approachedLanes)[i]];
159 incomingEdge->setConnection(approachingLanes[i], myCurrentOutgoing, approached,
NBEdge::L2L_COMPUTED);
161 delete approachedLanes;
167 std::deque<int>* ret =
new std::deque<int>();
168 const int numLanes = (int)approachingLanes.size();
172 ret->push_back(dest);
176 const int numOutgoingLanes = (int)myAvailableLanes.size();
178 ret->push_back(dest);
182 while (noSet < numLanes) {
188 if (numOutgoingLanes == noSet) {
197 if (dest + loffset >= numOutgoingLanes) {
200 for (
int i = 0; i < (int)ret->size(); i++) {
201 (*ret)[i] = (*ret)[i] - 1;
206 ret->push_back(dest + loffset);
211 if (numOutgoingLanes == noSet) {
216 if (noSet < numLanes) {
219 if (dest < roffset) {
222 for (
int i = 0; i < (int)ret->size(); i++) {
223 (*ret)[i] = (*ret)[i] + 1;
226 ret->push_front(dest - roffset);
242 customShape(_customShape),
243 tlLinkIndex(_customTLIndex),
244 tlLinkIndex2(_customTLIndex2),
245 customTLIndex(_customTLIndex),
246 customTLIndex2(_customTLIndex2),
278 myPosition(position),
280 myDistrict(district),
281 myHaveCustomPoly(false),
283 myRadius(UNSPECIFIED_RADIUS),
284 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
287 myDiscardAllCrossings(false),
288 myCrossingsLoadedFromSumoNet(0),
289 myDisplacementError(0),
290 myIsBentPriority(false),
291 myTypeWasGuessed(false) {
305 bool updateEdgeGeometries) {
312 if (updateEdgeGeometries) {
316 (*i)->setGeometry(geom);
321 (*i)->setGeometry(geom);
334 wacs.shape.add(xoff, yoff, 0);
345 c->customShape.mirrorX();
352 wacs.shape.mirrorX();
378 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
388 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
390 if (dynamic_cast<NBLoadedSUMOTLDef*>(orig) !=
nullptr) {
391 dynamic_cast<NBLoadedSUMOTLDef*>(orig)->registerModifications(removedConnections, addedConnections);
392 }
else if (dynamic_cast<NBOwnTLDef*>(orig) ==
nullptr) {
394 const std::vector<NBNode*>& nodes = orig->
getNodes();
395 while (!nodes.empty()) {
396 newDef->
addNode(nodes.front());
397 nodes.front()->removeTrafficLight(orig);
410 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
437 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
489 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
492 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
508 double extrapolateBeg,
509 double extrapolateEnd,
511 int shapeFlag)
const {
515 #ifdef DEBUG_SMOOTH_GEOM
517 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
520 if (init.size() == 0) {
522 ret.push_back(begShape.back());
523 ret.push_back(endShape.front());
535 double extrapolateBeg,
536 double extrapolateEnd,
539 double straightThresh,
542 const Position beg = begShape.back();
543 const Position end = endShape.front();
547 #ifdef DEBUG_SMOOTH_GEOM
548 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
564 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
565 init.push_back(center);
570 endShapeBegLine.extrapolate2D(100,
true);
572 if (fabs(angle) <
M_PI / 4.) {
575 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
576 const double halfDistance = dist / 2;
577 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
578 #ifdef DEBUG_SMOOTH_GEOM
579 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
580 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
583 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
586 #ifdef DEBUG_SMOOTH_GEOM
587 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
588 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
589 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
590 <<
" displacementError=" << sin(displacementAngle) * dist
591 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
594 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
599 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
600 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
602 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
604 #ifdef DEBUG_SMOOTH_GEOM
605 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
606 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
607 <<
" halfDistance=" << halfDistance <<
"\n";
616 Position intersect = endShapeBegLine.intersectionPosition2D(begShapeEndLineRev);
618 #ifdef DEBUG_SMOOTH_GEOM
620 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
621 <<
" endShapeBegLine=" << endShapeBegLine
622 <<
" begShapeEndLineRev=" << begShapeEndLineRev
627 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
633 const double minControlLength =
MIN2((
double)1.0, dist / 2);
636 const bool lengthenBeg = distBeg <= minControlLength;
637 const bool lengthenEnd = distEnd <= minControlLength;
638 if (lengthenBeg && lengthenEnd) {
639 #ifdef DEBUG_SMOOTH_GEOM
640 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
641 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
643 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
651 init.push_back(endShapeBegLine.positionAtOffset2D(100 - extrapolateEnd));
652 }
else if (lengthenBeg || lengthenEnd) {
654 init.push_back(endShapeBegLine.positionAtOffset2D(100 - minControlLength));
661 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
664 :
MIN2(0.6, 16 / dist));
665 init.push_back(begShapeEndLineRev.
positionAtOffset2D(100 -
MIN2(distBeg * factor / 1.2, dist * factor / 1.8)));
666 init.push_back(endShapeBegLine.positionAtOffset2D(100 -
MIN2(distEnd * factor / 1.2, dist * factor / 1.8)));
670 init.push_back(endShapeBegLine.positionAtOffset2D(100 -
MIN2(distEnd / 1.4, dist / 2)));
674 const double z2 = endShapeBegLine.positionAtOffset2D(endShapeBegLine.nearest_offset_to_point2D(intersect)).z();
675 const double z3 = 0.5 * (beg.
z() + end.
z());
679 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
684 intersect.
set(intersect.
x(), intersect.
y(), z);
685 init.push_back(intersect);
707 if (useCustomShape) {
710 if (startBorder.size() == 0) {
711 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
714 if (tmp.size() < 2) {
716 useCustomShape =
false;
720 tmp[0] = fromShape.back();
721 }
else if (recordError !=
nullptr) {
722 const double offset = tmp[0].distanceTo2D(fromShape.back());
728 if (endBorder.size() == 0) {
729 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
732 if (ret.size() < 2) {
734 useCustomShape =
false;
737 ret[-1] = toShape.front();
738 }
else if (recordError !=
nullptr) {
739 const double offset = ret[-1].distanceTo2D(toShape.front());
746 if (!useCustomShape) {
754 #ifdef DEBUG_SMOOTH_GEOM
756 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
761 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
793 for (
int i = 0; i < con.
toLane; ++i) {
797 for (
int i = 0; i < con.
fromLane; ++i) {
807 fromShape.
move2side(inCenter - outCenter);
860 const bool bothLeft = thisLeft && otherLeft;
861 if (fromE == otherFromE && !thisRight) {
868 if (c.
tlID !=
"" && !bothLeft) {
871 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
896 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
898 if ((*i)->getNodes().size() > 1) {
900 (*i)->removeNode(
this);
901 (*i)->setParticipantsInformation();
902 (*i)->setTLControllingInformation();
940 }
else if (numConnections == 0) {
1014 if (mismatchThreshold >= 0
1041 #ifdef DEBUG_CONNECTION_GUESSING
1043 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a\n";
1052 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1080 #ifdef DEBUG_CONNECTION_GUESSING
1082 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1091 std::swap(in1, in2);
1092 std::swap(in1Offset, in2Offset);
1119 #ifdef DEBUG_CONNECTION_GUESSING
1121 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1126 std::swap(out1, out2);
1127 std::swap(out1Offset, out2Offset);
1144 #ifdef DEBUG_CONNECTION_GUESSING
1146 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1155 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1171 #ifdef DEBUG_CONNECTION_GUESSING
1173 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f\n";
1184 inOffset += reduction;
1185 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1201 const int numApproaching = (int)approaching.size();
1202 if (numApproaching != 0) {
1206 #ifdef DEBUG_CONNECTION_GUESSING
1208 std::cout <<
"l2l node=" <<
getID() <<
" bresenham:\n";
1210 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1211 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1212 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1217 int bikeLaneTarget = currentOutgoing->getSpecialLane(
SVC_BICYCLE);
1226 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1227 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1232 unsatisfied &= ~satisfied;
1235 if (unsatisfied != 0) {
1236 #ifdef DEBUG_CONNECTION_GUESSING
1238 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1242 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1243 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1244 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); ++toLane) {
1245 const SVCPermissions satisfied = incoming->getPermissions(fromLane) & currentOutgoing->getPermissions(toLane) & unsatisfied;
1246 if (satisfied != 0 && !incoming->getLaneStruct(fromLane).connectionsDone) {
1248 #ifdef DEBUG_CONNECTION_GUESSING
1250 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1253 unsatisfied &= ~satisfied;
1259 #ifdef DEBUG_CONNECTION_GUESSING
1261 if (unsatisfied != 0) {
1262 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1275 bool builtConnection =
false;
1276 for (
int i = 0; i < (int)incoming->getNumLanes(); i++) {
1278 && incoming->getConnectionsFromLane(i, currentOutgoing).size() == 0) {
1280 if (bikeLaneTarget >= 0) {
1282 builtConnection =
true;
1285 for (
int i2 = 0; i2 < (int)currentOutgoing->getNumLanes(); i2++) {
1286 if ((currentOutgoing->getPermissions(i2) &
SVC_BICYCLE) != 0) {
1290 builtConnection =
true;
1297 if (!builtConnection && bikeLaneTarget >= 0
1298 && incoming->getConnectionsFromLane(-1, currentOutgoing, bikeLaneTarget).size() == 0) {
1301 int end = (int)incoming->getNumLanes();
1304 std::swap(start, end);
1307 for (
int i = start; i < end; i += inc) {
1308 if ((incoming->getPermissions(i) &
SVC_BICYCLE) != 0) {
1321 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1322 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1324 (*i)->removeFromConnections((*k).toEdge);
1335 incoming->markAsInLane2LaneState();
1339 #ifdef DEBUG_CONNECTION_GUESSING
1341 std::cout <<
"final connections at " <<
getID() <<
"\n";
1343 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1344 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1345 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1355 while (seen < minLength) {
1372 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1377 approaching.clear();
1378 for (; *i != currentOutgoing;) {
1380 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1381 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1382 if (connLanes.size() != 0) {
1383 approaching.push_back(*i);
1413 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1415 laneOff += (*i)->getNumLanes();
1445 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1447 laneOff += (*i)->getNumLanes();
1462 int whichLaneOff,
int byLaneOff) {
1466 bool changed =
false;
1468 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1471 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1485 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1487 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1488 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1548 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1549 edges.erase(find(edges.begin(), edges.end(), e));
1551 if (edges.size() == 0) {
1566 if (mayDrive.
getFrom() ==
nullptr ||
1567 mayDrive.
getTo() ==
nullptr ||
1568 mustStop.
getFrom() ==
nullptr ||
1569 mustStop.
getTo() ==
nullptr) {
1571 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1575 conn.push_back(mayDrive);
1582 int size = (int) edgeid.length();
1584 std::string
id = (*i)->
getID();
1585 if (
id.substr(0, size) == edgeid) {
1595 int size = (int) edgeid.length();
1597 std::string
id = (*i)->
getID();
1598 if (
id.substr(0, size) == edgeid) {
1623 if (removeFromConnections) {
1625 (*i)->removeFromConnections(edge);
1630 (*i)->replaceRemoved(edge, -1,
nullptr, -1);
1639 EdgeVector::const_iterator i;
1641 NBNode* conn = (*i)->getFromNode();
1644 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1648 NBNode* conn = (*i)->getToNode();
1651 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1655 if (pos.
x() == 0 && pos.
y() == 0) {
1667 (*i)->invalidateConnections();
1675 (*i)->invalidateConnections();
1687 if (to ==
nullptr) {
1702 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane,
1704 if (from != prohibitorFrom) {
1728 lefthand = !lefthand;
1735 if ((!lefthand && fromLane <= prohibitorFromLane) ||
1736 (lefthand && fromLane >= prohibitorFromLane)) {
1739 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (double)360.0);
1740 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (double)360.0);
1750 bool lefthand)
const {
1752 if (from != from2 || to == to2 || fromLane == fromLane2) {
1760 bool result =
false;
1762 if (fromLane < fromLane2) {
1764 while (*it != to2) {
1772 while (*it != to2) {
1804 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
1814 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
1815 bool regardNonSignalisedLowerPriority)
const {
1817 possProhibitedFrom, possProhibitedTo,
1818 regardNonSignalisedLowerPriority);
1824 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
1833 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1834 bool changed =
true;
1840 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1845 bool blockedChanged =
false;
1847 NBConnectionVector::const_iterator j;
1848 for (j = blocked.begin(); j != blocked.end(); j++) {
1850 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
1851 blockedChanged =
true;
1855 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1857 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
1861 }
else if (sblocked.
getFrom() == removed) {
1862 assert(sblocked.
getTo() != removed);
1863 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1866 }
else if (sblocked.
getTo() == removed) {
1867 assert(sblocked.
getFrom() != removed);
1868 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1875 if (blockedChanged) {
1876 blockedConnectionsNew[blocker] = newBlocked;
1881 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
1886 }
else if (blocker.
getFrom() == removed) {
1887 assert(blocker.
getTo() != removed);
1889 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1892 }
else if (blocker.
getTo() == removed) {
1893 assert(blocker.
getFrom() != removed);
1895 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1899 blockedConnectionsNew[blocker] = blocked;
1912 EdgeVector::const_iterator i = itOut;
1913 while (*i != incoming) {
1919 if ((*i)->getFromNode() !=
this) {
1927 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
1938 if (outgoing ==
nullptr) {
1956 if (abs((
int) angle) + 1 < 45) {
1959 if (outCW !=
nullptr) {
1961 if (fabs(angle2) < fabs(angle)) {
1962 if (fabs(angle2 - angle) > 5) {
1963 if (angle2 > angle) {
1972 if (outCCW !=
nullptr) {
1974 if (fabs(angle2) < fabs(angle)) {
1975 if (fabs(angle2 - angle) > 5) {
1976 if (angle2 > angle) {
1993 if (outCW !=
nullptr) {
2004 if (outCCW !=
nullptr) {
2015 bool mayDefinitelyPass,
const std::string& tlID)
const {
2022 if (outgoing ==
nullptr) {
2034 if (!mayDefinitelyPass
2035 &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)
2060 reason =
"rail_signal";
2064 reason =
"crossing";
2067 EdgeVector::const_iterator i;
2072 reason =
"edges incompatible: " + reason;
2076 reason =
"turnaround";
2084 std::set<NBNode*> origSet;
2086 origSet.insert((*i)->getFromNode());
2088 if (origSet.size() < 2) {
2096 if (opposite !=
nullptr) {
2100 if (!(*i)->expandableBy(continuation, reason)) {
2101 reason =
"edges incompatible: " + reason;
2107 reason =
"not opposites";
2114 reason =
"intersection";
2119 std::vector<std::pair<NBEdge*, NBEdge*> >
2122 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2126 std::pair<NBEdge*, NBEdge*>(
2134 assert(opposite != 0);
2136 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2154 (*i)->resetNodeBorder(
this);
2163 if ((*i)->getToNode() == n) {
2178 back_inserter(edges));
2180 back_inserter(edges));
2181 for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
2192 for (EdgeVector::const_iterator k = edges2.begin(); k != edges2.end(); ++k) {
2193 if ((*k)->getFromNode()->isDistrict() || (*k)->getToNode()->isDistrict()) {
2210 #ifdef DEBUG_PED_STRUCTURES
2219 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
2223 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2224 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2226 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2228 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2229 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2232 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2233 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2238 int firstSidewalk = -1;
2239 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2240 if (normalizedLanes[i].second) {
2245 int hadCandidates = 0;
2246 std::vector<int> connectedCandidates;
2247 if (firstSidewalk != -1) {
2249 std::vector<std::pair<NBEdge*, bool> > tmp;
2250 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2251 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2252 normalizedLanes = tmp;
2255 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2256 NBEdge* edge = normalizedLanes[i].first;
2257 const bool allowsPed = normalizedLanes[i].second;
2259 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2261 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2262 candidates.push_back(edge);
2263 }
else if (allowsPed) {
2264 if (candidates.size() > 0) {
2270 connectedCandidates.push_back(n);
2277 if (hadCandidates > 0 && candidates.size() > 0) {
2283 connectedCandidates.push_back(n);
2289 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2291 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2293 if (connectedCandidates.back() <= connectedCandidates.front()) {
2294 numGuessed -= connectedCandidates.back();
2297 numGuessed -= connectedCandidates.front();
2303 std::cout <<
"guessedCrossings:\n";
2305 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2315 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2317 if (candidates.size() == 0) {
2319 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2324 double prevAngle = -100000;
2325 for (
int i = 0; i < (int)candidates.size(); ++i) {
2326 NBEdge* edge = candidates[i];
2331 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2337 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2346 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2351 double prevAngle = -100000;
2352 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2353 double angle = (*it)->getCrossingAngle(
this);
2354 if (it != candidates.begin()) {
2355 NBEdge* prev = *(it - 1);
2360 double intermediateWidth = 0;
2363 prevPos = prev->
getLanes()[laneI].shape[-1];
2366 prevPos = prev->
getLanes()[laneI].shape[0];
2371 currPos = curr->
getLanes()[laneI].shape[0];
2374 currPos = curr->
getLanes()[laneI].shape[-1];
2380 <<
" prevAngle=" << prevAngle
2381 <<
" angle=" << angle
2382 <<
" intermediateWidth=" << intermediateWidth
2395 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2406 std::sort(edges.begin(), edges.end());
2410 EdgeVector edgesOfCrossing = crossing->edges;
2411 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2412 if (edgesOfCrossing == edges) {
2422 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2423 if (!normalizedLanes[i].second) {
2437 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2438 if (crossing->valid) {
2439 WRITE_WARNING(
"Discarding invalid crossing '" + crossing->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(crossing->edges) +
"' (no walkingarea found).");
2442 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2443 if (it_nc != wa.nextCrossings.end()) {
2444 wa.nextCrossings.erase(it_nc);
2447 crossing->valid =
false;
2448 crossing->prevWalkingArea =
"";
2449 crossing->nextWalkingArea =
"";
2454 std::vector<NBNode::Crossing*>
2456 std::vector<Crossing*> result;
2459 result.push_back(c);
2496 int noInternalNoSplits = 0;
2498 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2499 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2500 if ((*k).toEdge ==
nullptr) {
2503 noInternalNoSplits++;
2509 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2516 #ifdef DEBUG_PED_STRUCTURES
2520 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2536 c->nextWalkingArea =
"";
2537 c->prevWalkingArea =
"";
2540 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2546 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2549 double maxAngleDiff = 0;
2550 int maxAngleDiffIndex = 0;
2551 for (
int i = 0; i < (int) edges.size(); i++) {
2553 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2558 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2560 if (diff > maxAngleDiff) {
2561 maxAngleDiff = diff;
2562 maxAngleDiffIndex = i;
2565 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2567 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2569 std::cout <<
" rotatedEdges=" <<
toString(edges);
2573 std::reverse(edges.begin(), edges.end());
2575 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2579 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2580 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2581 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2582 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2584 WRITE_WARNING(
"Discarding invalid crossing '" + c->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(c->edges) +
"' (no vehicle lanes to cross).");
2586 }
else if (c->customShape.size() != 0) {
2587 c->shape = c->customShape;
2589 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2590 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2599 WRITE_WARNING(
"Discarding invalid crossing '" + c->id +
"' at junction '" +
getID() +
"' with edges '" +
toString(c->edges) +
"' (Invalid shape).");
2602 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2603 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2613 #ifdef DEBUG_PED_STRUCTURES
2619 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2626 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2627 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2629 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2631 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2635 normalizedLanes.push_back(std::make_pair(edge, l));
2638 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2643 normalizedLanes.push_back(std::make_pair(edge, l));
2649 std::vector<std::pair<int, int> > waIndices;
2651 NBEdge* prevEdge = normalizedLanes.back().first;
2652 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2653 NBEdge* edge = normalizedLanes[i].first;
2661 waIndices.push_back(std::make_pair(start, i - start));
2671 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2676 const int waNumLanes = (int)normalizedLanes.size() - start;
2677 if (waIndices.size() == 0) {
2678 waIndices.push_back(std::make_pair(start, waNumLanes));
2680 std::cout <<
" single wa, end at wrap-around\n";
2683 if (waIndices.front().first == 0) {
2684 NBEdge* edge = normalizedLanes.front().first;
2685 NBEdge* prevEdge = normalizedLanes.back().first;
2688 waIndices.push_back(std::make_pair(start, waNumLanes));
2690 std::cout <<
" do not wrap around, turn-around in between\n";
2694 waIndices.front().first = start;
2695 waIndices.front().second = waNumLanes + waIndices.front().second;
2697 std::cout <<
" wrapping around\n";
2702 waIndices.push_back(std::make_pair(start, waNumLanes));
2704 std::cout <<
" end at wrap-around\n";
2710 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2711 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2712 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2716 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2717 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2718 const int start = waIndices[i].first;
2719 const int prev = start > 0 ? start - 1 : (int)normalizedLanes.size() - 1;
2720 const int count = waIndices[i].second;
2721 const int end = (start + count) % normalizedLanes.size();
2725 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << start <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2727 double endCrossingWidth = 0;
2728 double startCrossingWidth = 0;
2732 bool connectsCrossing =
false;
2733 std::vector<Position> connectedPoints;
2736 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
2738 if (c->edges.back() == normalizedLanes[end].first
2739 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
2741 if (c->nextWalkingArea !=
"") {
2743 +
"'; crossing '" + c->id
2744 +
"' targets '" + c->nextWalkingArea
2745 +
"' and '" + wa.
id +
"'.");
2748 c->nextWalkingArea = wa.
id;
2751 endCrossingWidth = c->width;
2752 endCrossingShape = c->shape;
2754 connectsCrossing =
true;
2755 connectedPoints.push_back(c->shape[-1]);
2759 std::cout <<
" crossing " << c->id <<
" ends\n";
2762 if (c->edges.front() == normalizedLanes[prev].first
2763 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
2765 if (c->prevWalkingArea !=
"") {
2767 +
"'; crossing '" + c->id
2768 +
"' is targeted by '" + c->prevWalkingArea
2769 +
"' and '" + wa.
id +
"'.");
2772 c->prevWalkingArea = wa.
id;
2776 startCrossingWidth = c->width;
2777 startCrossingShape = c->shape;
2779 connectsCrossing =
true;
2780 connectedPoints.push_back(c->shape[0]);
2784 std::cout <<
" crossing " << c->id <<
" starts\n";
2787 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
2788 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
2789 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[start].first->getID()
2790 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
2793 if (count < 2 && !connectsCrossing) {
2796 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
2801 std::set<NBEdge*, ComparatorIdLess> connected;
2802 for (
int j = 0; j < count; ++j) {
2803 const int nlI = (start + j) % normalizedLanes.size();
2804 NBEdge* edge = normalizedLanes[nlI].first;
2807 if (connected.count(edge) == 0) {
2815 connected.insert(edge);
2822 if (buildExtensions) {
2824 if (startCrossingShape.size() > 0) {
2826 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
2828 startCrossingShape.
move2side(startCrossingWidth / 2);
2830 startCrossingShape.
move2side(-startCrossingWidth);
2834 if (endCrossingShape.size() > 0) {
2836 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
2838 endCrossingShape.
move2side(endCrossingWidth / 2);
2840 endCrossingShape.
move2side(-endCrossingWidth);
2845 && normalizedLanes.size() == 2) {
2847 NBEdge* e1 = *connected.begin();
2848 NBEdge* e2 = *(++connected.begin());
2851 std::cout <<
" not building a walkingarea since normal connections exist\n";
2857 if (cornerDetail > 0) {
2858 int smoothEnd = end;
2859 int smoothPrev = prev;
2861 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
2862 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
2864 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
2865 if (smoothPrev == 0) {
2866 smoothPrev = (int)normalizedLanes.size() - 1;
2871 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
2872 begShape = begShape.
reverse();
2874 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
2875 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
2876 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
2879 if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
2883 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
2887 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
2888 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
2889 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
2890 if (curve.size() > 2) {
2891 curve.erase(curve.begin());
2893 if (endCrossingWidth > 0) {
2894 wa.
shape.pop_back();
2896 if (startCrossingWidth > 0) {
2906 if (wacs.shape.size() != 0 &&
includes(connected, wacs.edges)) {
2907 wa.
shape = wacs.shape;
2913 double lengthSum = 0;
2914 int combinations = 0;
2915 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
2916 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
2926 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
2929 if (combinations > 0) {
2935 std::vector<Crossing*> validCrossings =
getCrossings();
2936 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
2938 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
2940 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
2955 wa.
shape.push_back(tmp[-1]);
2957 wa.
shape.push_back(tmp[-1]);
2961 wa.
shape.push_back(tmp[0]);
2963 wa.
shape.push_back(tmp[0]);
2966 std::set<NBEdge*, ComparatorIdLess> crossed(prev.
edges.begin(), prev.
edges.end());
2967 crossed.insert(next.
edges.begin(), next.
edges.end());
2970 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(crossed, wacs.edges)) {
2971 wa.
shape = wacs.shape;
2980 std::cout <<
" build wa=" << wa.
id <<
"\n";
2988 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
2990 for (
const NBEdge* e : sub) {
2991 if (super.count(const_cast<NBEdge*>(e)) == 0) {
3010 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
3011 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
3012 if (it1 != edges.end() && it2 != edges.end()) {
3028 while (it != it_end) {
3029 result.push_back(*it);
3039 wacs.
edges.insert(edges.begin(), edges.end());
3052 if (incoming.size() == 1 && outgoing.size() == 1) {
3055 if (incoming.size() == 2 && outgoing.size() == 2) {
3058 NBEdge* in0 = incoming[0];
3059 NBEdge* in1 = incoming[1];
3060 NBEdge* out0 = outgoing[0];
3061 NBEdge* out1 = outgoing[1];
3066 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
3070 if (
MAX2(angle0, angle1) <= 160) {
3091 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
3102 EdgeSet edgeSet(edges.begin(), edges.end());
3104 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
3105 if (edgeSet == edgeSet2) {
3122 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
3128 EdgeSet edgeSet(edges.begin(), edges.end());
3130 EdgeSet edgeSet2(it->edges.begin(), it->edges.end());
3131 if (edgeSet == edgeSet2) {
3138 throw ProcessError(
"Request for unknown crossing for the given Edges");
3145 bool usedCustom =
false;
3147 c->tlLinkIndex = startIndex++;
3149 if (c->customTLIndex != -1) {
3150 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
3151 c->tlLinkIndex = c->customTLIndex;
3153 c->tlLinkIndex2 = c->customTLIndex2;
3165 result += (int)edge->getConnections().size();
3178 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
3179 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
3215 std::cout <<
" angles:\n";
3216 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3217 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3219 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3224 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
3226 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
3228 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
3239 assert(
id[0] ==
':');
3240 std::string::size_type sep_index =
id.rfind(
'_');
3241 if (sep_index == std::string::npos) {
3242 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3245 sep_index =
id.substr(0, sep_index).rfind(
'_');
3246 if (sep_index == std::string::npos) {
3247 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3250 return id.substr(1, sep_index - 1);
3260 if (turnDest !=
nullptr) {
3281 if ((*i)->rightOnRedConflict(index, foeIndex)) {
3304 std::vector<NBEdge*>::iterator j;
3305 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3308 if (allEdges.size() > 1 && j != allEdges.end()) {
3313 NBEdge* firstOfAll = allEdges.front();
3314 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3315 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3321 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3322 if (firstOfIncoming !=
nullptr) {
3323 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3325 if (firstOfOutgoing !=
nullptr) {
3326 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3328 #ifdef DEBUG_EDGE_SORTING
3330 std::cout <<
"sortedEdges:\n";
3331 for (
NBEdge* e : allEdges) {
3332 std::cout <<
" " << e->
getID()
3333 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3334 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3341 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3342 std::vector<NBEdge*>::const_iterator in, out;
3343 std::vector<NBEdge*> allTmp;
3344 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3345 if ((*in)->isTurningDirectionAt(*out)) {
3346 allTmp.push_back(*in);
3347 allTmp.push_back(*out);
3352 if (allTmp.size() == allEdges.size()) {
3365 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3369 e->computeEdgeShape();
3374 std::vector<std::pair<Position, std::string> >
3377 std::vector<std::pair<Position, std::string> >result;
3379 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3380 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
3382 for (
const auto& pair : result) {
3383 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
3389 result.push_back(std::make_pair(pos, origID));