61 #define EXTEND_CROSSING_ANGLE_THRESHOLD 35.0 // degrees
63 #define SPLIT_CROSSING_WIDTH_THRESHOLD 1.5 // meters
64 #define SPLIT_CROSSING_ANGLE_THRESHOLD 5 // degrees
67 #define MIN_WEAVE_LENGTH 20.0
74 #define DEBUG_NODE_ID "F"
75 #define DEBUGCOND (getID() == DEBUG_NODE_ID)
76 #define DEBUGCOND2(obj) ((obj != 0 && (obj)->getID() == DEBUG_NODE_ID))
98 myApproaching(approaching),
99 myCurrentOutgoing(currentOutgoing),
100 myIsBikeEdge(currentOutgoing->getPermissions() ==
SVC_BICYCLE) {
102 std::set<int> approachedLanes;
106 approachedLanes.insert(con.toLane);
114 for (
int i = 0; i < currentOutgoing->
getNumLanes(); ++i) {
120 && approachedLanes.count(i) == 0) {
133 assert((
int)myApproaching.size() > src);
135 NBEdge* incomingEdge = myApproaching[src];
139 if (myAvailableLanes.size() == 0) {
143 if (approachingLanes.size() == 0) {
146 #ifdef DEBUG_CONNECTION_GUESSING
148 std::cout <<
"Bre:ex src=" << src <<
" dest=" << dest <<
" in=" << incomingEdge->
getID() <<
" apLanes=" <<
toString(approachingLanes) <<
"\n";
152 std::deque<int>* approachedLanes = spread(approachingLanes, dest);
153 assert(approachedLanes->size() <= myAvailableLanes.size());
155 for (
int i = 0; i < (int)approachedLanes->size(); i++) {
156 assert((
int)approachingLanes.size() > i);
157 int approached = myAvailableLanes[(*approachedLanes)[i]];
160 delete approachedLanes;
166 std::deque<int>* ret =
new std::deque<int>();
167 const int numLanes = (int)approachingLanes.size();
171 ret->push_back(dest);
175 const int numOutgoingLanes = (int)myAvailableLanes.size();
177 ret->push_back(dest);
181 while (noSet < numLanes) {
187 if (numOutgoingLanes == noSet) {
196 if (dest + loffset >= numOutgoingLanes) {
199 for (
int i = 0; i < (int)ret->size(); i++) {
200 (*ret)[i] = (*ret)[i] - 1;
205 ret->push_back(dest + loffset);
210 if (numOutgoingLanes == noSet) {
215 if (noSet < numLanes) {
218 if (dest < roffset) {
221 for (
int i = 0; i < (int)ret->size(); i++) {
222 (*ret)[i] = (*ret)[i] + 1;
225 ret->push_front(dest - roffset);
241 customShape(_customShape),
242 tlLinkIndex(_customTLIndex),
243 tlLinkIndex2(_customTLIndex2),
244 customTLIndex(_customTLIndex),
245 customTLIndex2(_customTLIndex2),
277 myPosition(position),
279 myDistrict(district),
280 myHaveCustomPoly(false),
282 myRadius(UNSPECIFIED_RADIUS),
283 myKeepClear(
OptionsCont::getOptions().getBool(
"default.junctions.keep-clear")),
286 myDiscardAllCrossings(false),
287 myCrossingsLoadedFromSumoNet(0),
288 myDisplacementError(0),
289 myIsBentPriority(false),
290 myTypeWasGuessed(false) {
304 bool updateEdgeGeometries) {
311 if (updateEdgeGeometries) {
315 (*i)->setGeometry(geom);
320 (*i)->setGeometry(geom);
333 wacs.shape.add(xoff, yoff, 0);
336 c->customShape.add(xoff, yoff, 0);
347 c->customShape.mirrorX();
354 wacs.shape.mirrorX();
380 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
390 for (std::set<NBTrafficLightDefinition*>::iterator it = oldDefs.begin(); it != oldDefs.end(); ++it) {
393 dynamic_cast<NBLoadedSUMOTLDef*
>(orig)->registerModifications(removedConnections, addedConnections);
394 }
else if (
dynamic_cast<NBOwnTLDef*
>(orig) ==
nullptr) {
396 const std::vector<NBNode*>& nodes = orig->
getNodes();
397 while (!nodes.empty()) {
398 newDef->
addNode(nodes.front());
399 nodes.front()->removeTrafficLight(orig);
412 (*it)->shiftTLConnectionLaneIndex(edge, offset, threshold);
439 remapRemoved(tc, dummy, incomingConnected, outgoingConnected);
491 if (checkLaneNumbers && in->
getNumLanes() != (*opposite)->getNumLanes()) {
494 if (checkWidth && in->
getTotalWidth() != (*opposite)->getTotalWidth()) {
510 double extrapolateBeg,
511 double extrapolateEnd,
513 int shapeFlag)
const {
517 #ifdef DEBUG_SMOOTH_GEOM
519 std::cout <<
"computeSmoothShape node " <<
getID() <<
" init=" << init <<
"\n";
522 if (init.size() == 0) {
524 ret.push_back(begShape.back());
525 ret.push_back(endShape.front());
537 double extrapolateBeg,
538 double extrapolateEnd,
541 double straightThresh,
544 const Position beg = begShape.back();
545 const Position end = endShape.front();
549 #ifdef DEBUG_SMOOTH_GEOM
550 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end
566 center.
sub(beg.
y() - end.
y(), end.
x() - beg.
x());
567 init.push_back(center);
574 if (fabs(angle) <
M_PI / 4.) {
577 const double bendDeg =
RAD2DEG(fabs(displacementAngle - angle));
578 const double halfDistance = dist / 2;
579 if (fabs(displacementAngle) <= straightThresh && fabs(angle) <= straightThresh) {
580 #ifdef DEBUG_SMOOTH_GEOM
581 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints identified straight line beg=" << beg <<
" end=" << end
582 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle) <<
"\n";
585 }
else if (bendDeg > 22.5 && pow(bendDeg / 45, 2) / dist > 0.13) {
588 #ifdef DEBUG_SMOOTH_GEOM
589 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found extreme s-curve, falling back to straight line beg=" << beg <<
" end=" << end
590 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
591 <<
" dist=" << dist <<
" bendDeg=" << bendDeg <<
" bd2=" << pow(bendDeg / 45, 2)
592 <<
" displacementError=" << sin(displacementAngle) * dist
593 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
"\n";
596 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
601 const double endLength = begShape[-2].distanceTo2D(begShape[-1]);
602 const double off1 = endLength +
MIN2(extrapolateBeg, halfDistance);
604 const double off2 = 100. -
MIN2(extrapolateEnd, halfDistance);
606 #ifdef DEBUG_SMOOTH_GEOM
607 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints found s-curve beg=" << beg <<
" end=" << end
608 <<
" angle=" <<
RAD2DEG(angle) <<
" displacementAngle=" <<
RAD2DEG(displacementAngle)
609 <<
" halfDistance=" << halfDistance <<
"\n";
620 #ifdef DEBUG_SMOOTH_GEOM
622 std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
623 <<
" endShapeBegLine=" << endShapeBegLine
624 <<
" begShapeEndLineRev=" << begShapeEndLineRev
629 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
635 const double minControlLength =
MIN2((
double)1.0, dist / 2);
638 const bool lengthenBeg = distBeg <= minControlLength;
639 const bool lengthenEnd = distEnd <= minControlLength;
640 if (lengthenBeg && lengthenEnd) {
641 #ifdef DEBUG_SMOOTH_GEOM
642 if (
DEBUGCOND2(recordError)) std::cout <<
" bezierControlPoints failed beg=" << beg <<
" end=" << end <<
" intersect=" << intersect
643 <<
" distBeg=" << distBeg <<
" distEnd=" << distEnd <<
"\n";
645 if (recordError !=
nullptr && (shapeFlag &
SCURVE_IGNORE) == 0) {
654 }
else if (lengthenBeg || lengthenEnd) {
663 || (angle >
DEG2RAD(95) && (distBeg > 20 || distEnd > 20)))) {
666 :
MIN2(0.6, 16 / dist));
667 init.push_back(begShapeEndLineRev.
positionAtOffset2D(100 -
MIN2(distBeg * factor / 1.2, dist * factor / 1.8)));
668 init.push_back(endShapeBegLine.
positionAtOffset2D(100 -
MIN2(distEnd * factor / 1.2, dist * factor / 1.8)));
677 const double z3 = 0.5 * (beg.
z() + end.
z());
681 if ((z1 <= z3 && z2 <= z3) || (z1 >= z3 && z2 >= z3)) {
686 intersect.
set(intersect.
x(), intersect.
y(), z);
687 init.push_back(intersect);
709 if (useCustomShape) {
712 if (startBorder.size() == 0) {
713 startBorder = fromShape.
getOrthogonal(fromShape.back(), 1,
true);
716 if (tmp.size() < 2) {
718 useCustomShape =
false;
722 tmp[0] = fromShape.back();
723 }
else if (recordError !=
nullptr) {
724 const double offset = tmp[0].distanceTo2D(fromShape.back());
730 if (endBorder.size() == 0) {
731 endBorder = toShape.
getOrthogonal(toShape.front(), 1,
false);
734 if (ret.size() < 2) {
736 useCustomShape =
false;
739 ret[-1] = toShape.front();
740 }
else if (recordError !=
nullptr) {
741 const double offset = ret[-1].distanceTo2D(toShape.front());
748 if (!useCustomShape) {
756 #ifdef DEBUG_SMOOTH_GEOM
758 std::cout <<
"computeInternalLaneShape node " <<
getID() <<
" fromE=" << fromE->
getID() <<
" toE=" << con.
toEdge->
getID() <<
"\n";
763 extrapolateBeg, extrapolateEnd, recordError, shapeFlag);
795 for (
int i = 0; i < con.
toLane; ++i) {
799 for (
int i = 0; i < con.
fromLane; ++i) {
809 fromShape.
move2side(inCenter - outCenter);
862 const bool bothLeft = thisLeft && otherLeft;
863 if (fromE == otherFromE && !thisRight) {
870 if (c.
tlID !=
"" && !bothLeft) {
873 if ((*it)->needsCont(fromE, toE, otherFromE, otherToE)) {
898 for (std::set<NBTrafficLightDefinition*>::const_iterator i = trafficLights.begin(); i != trafficLights.end(); ++i) {
900 if ((*i)->getNodes().size() > 1) {
902 (*i)->removeNode(
this);
903 (*i)->setParticipantsInformation();
904 (*i)->setTLControllingInformation();
935 WRITE_WARNINGF(
"Junction '%' is too complicated (% connections, max %); will be set to %.",
937 }
else if (numConnections == 0) {
1011 if (mismatchThreshold >= 0
1038 #ifdef DEBUG_CONNECTION_GUESSING
1040 std::cout <<
"l2l node=" <<
getID() <<
" specialCase a\n";
1049 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1077 #ifdef DEBUG_CONNECTION_GUESSING
1079 std::cout <<
"l2l node=" <<
getID() <<
" specialCase b\n";
1088 std::swap(in1, in2);
1089 std::swap(in1Offset, in2Offset);
1116 #ifdef DEBUG_CONNECTION_GUESSING
1118 std::cout <<
"l2l node=" <<
getID() <<
" specialCase c\n";
1123 std::swap(out1, out2);
1124 std::swap(out1Offset, out2Offset);
1141 #ifdef DEBUG_CONNECTION_GUESSING
1143 std::cout <<
"l2l node=" <<
getID() <<
" specialCase d\n";
1152 for (
int i = inOffset; i < in->
getNumLanes(); ++i) {
1168 #ifdef DEBUG_CONNECTION_GUESSING
1170 std::cout <<
"l2l node=" <<
getID() <<
" specialCase f\n";
1181 inOffset += reduction;
1182 for (
int i = outOffset; i < out->
getNumLanes(); ++i) {
1198 const int numApproaching = (int)approaching.size();
1199 if (numApproaching != 0) {
1203 #ifdef DEBUG_CONNECTION_GUESSING
1205 std::cout <<
"l2l node=" <<
getID() <<
" bresenham:\n";
1207 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1208 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1209 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1214 int bikeLaneTarget = currentOutgoing->getSpecialLane(
SVC_BICYCLE);
1223 const std::vector<NBEdge::Connection>& elv = incoming->getConnections();
1224 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1229 unsatisfied &= ~satisfied;
1232 if (unsatisfied != 0) {
1233 #ifdef DEBUG_CONNECTION_GUESSING
1235 std::cout <<
" unsatisfied modes from edge=" << incoming->
getID() <<
" toEdge=" << currentOutgoing->getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1239 while (unsatisfied != 0 && fromLane < incoming->getNumLanes()) {
1240 if ((incoming->getPermissions(fromLane) & unsatisfied) != 0) {
1241 for (
int toLane = 0; toLane < currentOutgoing->getNumLanes(); ++toLane) {
1242 const SVCPermissions satisfied = incoming->getPermissions(fromLane) & currentOutgoing->getPermissions(toLane) & unsatisfied;
1243 if (satisfied != 0 && !incoming->getLaneStruct(fromLane).connectionsDone) {
1245 #ifdef DEBUG_CONNECTION_GUESSING
1247 std::cout <<
" new connection from=" << fromLane <<
" to=" << currentOutgoing->getID() <<
"_" << toLane <<
" satisfies=" <<
getVehicleClassNames(satisfied) <<
"\n";
1250 unsatisfied &= ~satisfied;
1256 #ifdef DEBUG_CONNECTION_GUESSING
1258 if (unsatisfied != 0) {
1259 std::cout <<
" still unsatisfied modes from edge=" << incoming->getID() <<
" toEdge=" << currentOutgoing->getID() <<
" deadModes=" <<
getVehicleClassNames(unsatisfied) <<
"\n";
1272 bool builtConnection =
false;
1273 for (
int i = 0; i < (int)incoming->getNumLanes(); i++) {
1275 && incoming->getConnectionsFromLane(i, currentOutgoing).size() == 0) {
1277 if (bikeLaneTarget >= 0) {
1279 builtConnection =
true;
1282 for (
int i2 = 0; i2 < (int)currentOutgoing->getNumLanes(); i2++) {
1283 if ((currentOutgoing->getPermissions(i2) &
SVC_BICYCLE) != 0) {
1287 builtConnection =
true;
1294 if (!builtConnection && bikeLaneTarget >= 0
1295 && incoming->getConnectionsFromLane(-1, currentOutgoing, bikeLaneTarget).size() == 0) {
1298 int end = (int)incoming->getNumLanes();
1301 std::swap(start, end);
1304 for (
int i = start; i < end; i += inc) {
1305 if ((incoming->getPermissions(i) &
SVC_BICYCLE) != 0) {
1318 const std::vector<NBEdge::Connection> cons = (*i)->getConnections();
1319 for (std::vector<NBEdge::Connection>::const_iterator k = cons.begin(); k != cons.end(); ++k) {
1321 (*i)->removeFromConnections((*k).toEdge);
1332 incoming->markAsInLane2LaneState();
1336 #ifdef DEBUG_CONNECTION_GUESSING
1338 std::cout <<
"final connections at " <<
getID() <<
"\n";
1340 const std::vector<NBEdge::Connection>& elv = e->getConnections();
1341 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
1342 std::cout <<
" " << e->getID() <<
"_" << (*k).fromLane <<
" -> " << (*k).toEdge->getID() <<
"_" << (*k).toLane <<
"\n";
1352 while (seen < minLength) {
1369 EdgeVector::const_iterator i = std::find(
myAllEdges.begin(),
1374 approaching.clear();
1375 for (; *i != currentOutgoing;) {
1377 if ((*i)->getToNode() ==
this && (*i)->getTurnDestination() != currentOutgoing) {
1378 std::vector<int> connLanes = (*i)->getConnectionLanes(currentOutgoing);
1379 if (connLanes.size() != 0) {
1380 approaching.push_back(*i);
1410 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1412 laneOff += (*i)->getNumLanes();
1442 for (EdgeVector::const_iterator i = which.begin(); i != which.end(); i++) {
1444 laneOff += (*i)->getNumLanes();
1459 int whichLaneOff,
int byLaneOff) {
1463 bool changed =
false;
1465 if (c.
replaceFrom(which, whichLaneOff, by, byLaneOff)) {
1468 if (c.
replaceTo(which, whichLaneOff, by, byLaneOff)) {
1482 for (NBConnectionVector::iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
1484 sprohibiting.
replaceFrom(which, whichLaneOff, by, byLaneOff);
1485 sprohibiting.
replaceTo(which, whichLaneOff, by, byLaneOff);
1545 if (find(edges.begin(), edges.end(), e) != edges.end()) {
1546 edges.erase(find(edges.begin(), edges.end(), e));
1548 if (edges.size() == 0) {
1563 if (mayDrive.
getFrom() ==
nullptr ||
1564 mayDrive.
getTo() ==
nullptr ||
1565 mustStop.
getFrom() ==
nullptr ||
1566 mustStop.
getTo() ==
nullptr) {
1568 WRITE_WARNING(
"Something went wrong during the building of a connection...");
1572 conn.push_back(mayDrive);
1579 int size = (int) edgeid.length();
1581 std::string
id = (*i)->
getID();
1582 if (
id.substr(0, size) == edgeid) {
1592 int size = (int) edgeid.length();
1594 std::string
id = (*i)->
getID();
1595 if (
id.substr(0, size) == edgeid) {
1620 if (removeFromConnections) {
1622 (*i)->removeFromConnections(edge);
1627 (*i)->replaceRemoved(edge, -1,
nullptr, -1);
1636 EdgeVector::const_iterator i;
1638 NBNode* conn = (*i)->getFromNode();
1641 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1645 NBNode* conn = (*i)->getToNode();
1648 toAdd.
mul((
double) 1.0 / sqrt(toAdd.
x()*toAdd.
x() + toAdd.
y()*toAdd.
y()));
1652 if (pos.
x() == 0 && pos.
y() == 0) {
1664 (*i)->invalidateConnections();
1672 (*i)->invalidateConnections();
1684 if (to ==
nullptr) {
1699 const NBEdge* prohibitorFrom,
const NBEdge* prohibitorTo,
int prohibitorFromLane,
1701 if (from != prohibitorFrom) {
1725 lefthand = !lefthand;
1732 if ((!lefthand && fromLane <= prohibitorFromLane) ||
1733 (lefthand && fromLane >= prohibitorFromLane)) {
1736 const double toAngleAtNode = fmod(to->
getStartAngle() + 180, (
double)360.0);
1737 const double prohibitorToAngleAtNode = fmod(prohibitorTo->
getStartAngle() + 180, (
double)360.0);
1747 bool lefthand)
const {
1749 if (from != from2 || to == to2 || fromLane == fromLane2) {
1757 bool result =
false;
1759 if (fromLane < fromLane2) {
1761 while (*it != to2) {
1769 while (*it != to2) {
1801 std::vector<NBEdge*>::const_iterator i = std::find(
myAllEdges.begin(),
myAllEdges.end(), from);
1811 const NBEdge*
const possProhibitedFrom,
const NBEdge*
const possProhibitedTo,
1812 bool regardNonSignalisedLowerPriority)
const {
1814 possProhibitedFrom, possProhibitedTo,
1815 regardNonSignalisedLowerPriority);
1821 const NBEdge*
const from2,
const NBEdge*
const to2)
const {
1830 assert(find(incoming.begin(), incoming.end(), removed) == incoming.end());
1831 bool changed =
true;
1837 for (NBConnectionProhibits::iterator i = blockedConnectionsTmp.begin(); i != blockedConnectionsTmp.end(); i++) {
1842 bool blockedChanged =
false;
1844 NBConnectionVector::const_iterator j;
1845 for (j = blocked.begin(); j != blocked.end(); j++) {
1847 if (sblocked.
getFrom() == removed || sblocked.
getTo() == removed) {
1848 blockedChanged =
true;
1852 for (j = blocked.begin(); blockedChanged && j != blocked.end(); j++) {
1854 if (sblocked.
getFrom() == removed && sblocked.
getTo() == removed) {
1858 }
else if (sblocked.
getFrom() == removed) {
1859 assert(sblocked.
getTo() != removed);
1860 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1863 }
else if (sblocked.
getTo() == removed) {
1864 assert(sblocked.
getFrom() != removed);
1865 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1872 if (blockedChanged) {
1873 blockedConnectionsNew[blocker] = newBlocked;
1878 if (blocker.
getFrom() == removed && blocker.
getTo() == removed) {
1883 }
else if (blocker.
getFrom() == removed) {
1884 assert(blocker.
getTo() != removed);
1886 for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); k++) {
1889 }
else if (blocker.
getTo() == removed) {
1890 assert(blocker.
getFrom() != removed);
1892 for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); k++) {
1896 blockedConnectionsNew[blocker] = blocked;
1909 EdgeVector::const_iterator i = itOut;
1910 while (*i != incoming) {
1916 if ((*i)->getFromNode() !=
this) {
1924 if ((vehPerm & (*i)->getPermissions()) != 0 || vehPerm == 0) {
1935 if (outgoing ==
nullptr) {
1953 if (abs((
int) angle) + 1 < 45) {
1956 if (outCW !=
nullptr) {
1958 if (fabs(angle2) < fabs(angle)) {
1959 if (fabs(angle2 - angle) > 5) {
1960 if (angle2 > angle) {
1969 if (outCCW !=
nullptr) {
1971 if (fabs(angle2) < fabs(angle)) {
1972 if (fabs(angle2 - angle) > 5) {
1973 if (angle2 > angle) {
1990 if (outCW !=
nullptr) {
2001 if (outCCW !=
nullptr) {
2012 bool mayDefinitelyPass,
const std::string& tlID)
const {
2019 if (outgoing ==
nullptr) {
2031 if (!mayDefinitelyPass
2032 &&
mustBrake(incoming, outgoing, fromlane, toLane,
true)
2057 reason =
"rail_signal";
2061 reason =
"crossing";
2064 EdgeVector::const_iterator i;
2069 reason =
"edges incompatible: " + reason;
2073 reason =
"turnaround";
2081 std::set<NBNode*> origSet;
2083 origSet.insert((*i)->getFromNode());
2085 if (origSet.size() < 2) {
2093 if (opposite !=
nullptr) {
2097 if (!(*i)->expandableBy(continuation, reason)) {
2098 reason =
"edges incompatible: " + reason;
2104 reason =
"not opposites";
2111 reason =
"intersection";
2116 std::vector<std::pair<NBEdge*, NBEdge*> >
2119 std::vector<std::pair<NBEdge*, NBEdge*> > ret;
2123 std::pair<NBEdge*, NBEdge*>(
2131 assert(opposite != 0);
2133 ret.push_back(std::pair<NBEdge*, NBEdge*>(*i, continuation));
2151 (*i)->resetNodeBorder(
this);
2160 if (e->getToNode() == n && e->getPermissions() != 0) {
2174 const NBNode*
const other = t->getToNode() ==
this ? t->getFromNode() : t->getToNode();
2176 if (k->getFromNode()->isDistrict() || k->getToNode()->isDistrict()) {
2193 #ifdef DEBUG_PED_STRUCTURES
2202 std::cout <<
"guess crossings for " <<
getID() <<
"\n";
2206 std::vector<std::pair<NBEdge*, bool> > normalizedLanes;
2207 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2209 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2211 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2212 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2215 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2216 normalizedLanes.push_back(std::make_pair(edge, ((*it_l).permissions &
SVC_PEDESTRIAN) != 0));
2221 int firstSidewalk = -1;
2222 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2223 if (normalizedLanes[i].second) {
2228 int hadCandidates = 0;
2229 std::vector<int> connectedCandidates;
2230 if (firstSidewalk != -1) {
2232 std::vector<std::pair<NBEdge*, bool> > tmp;
2233 copy(normalizedLanes.begin() + firstSidewalk, normalizedLanes.end(), std::back_inserter(tmp));
2234 copy(normalizedLanes.begin(), normalizedLanes.begin() + firstSidewalk, std::back_inserter(tmp));
2235 normalizedLanes = tmp;
2238 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2239 NBEdge* edge = normalizedLanes[i].first;
2240 const bool allowsPed = normalizedLanes[i].second;
2242 std::cout <<
" cands=" <<
toString(candidates) <<
" edge=" << edge->
getID() <<
" allowsPed=" << allowsPed <<
"\n";
2244 if (!allowsPed && (candidates.size() == 0 || candidates.back() != edge)) {
2245 candidates.push_back(edge);
2246 }
else if (allowsPed) {
2247 if (candidates.size() > 0) {
2253 connectedCandidates.push_back(n);
2260 if (hadCandidates > 0 && candidates.size() > 0) {
2266 connectedCandidates.push_back(n);
2272 std::cout <<
" hadCandidates=" << hadCandidates <<
" connectedCandidates=" <<
toString(connectedCandidates) <<
"\n";
2274 if (hadCandidates == 2 && connectedCandidates.size() == 2) {
2276 if (connectedCandidates.back() <= connectedCandidates.front()) {
2277 numGuessed -= connectedCandidates.back();
2280 numGuessed -= connectedCandidates.front();
2286 std::cout <<
"guessedCrossings:\n";
2288 std::cout <<
" edges=" <<
toString(crossing->edges) <<
"\n";
2298 std::cout <<
"checkCrossing candidates=" <<
toString(candidates) <<
"\n";
2300 if (candidates.size() == 0) {
2302 std::cout <<
"no crossing added (numCandidates=" << candidates.size() <<
")\n";
2307 double prevAngle = -100000;
2308 for (
int i = 0; i < (int)candidates.size(); ++i) {
2309 NBEdge* edge = candidates[i];
2314 std::cout <<
"no crossing added (found angle difference of " << fabs(
NBHelpers::relAngle(angle, prevAngle)) <<
" at i=" << i <<
"\n";
2320 std::cout <<
"no crossing added (uncontrolled, edge with speed > " << edge->
getSpeed() <<
")\n";
2329 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2334 double prevAngle = -100000;
2335 for (EdgeVector::iterator it = candidates.begin(); it != candidates.end(); ++it) {
2336 double angle = (*it)->getCrossingAngle(
this);
2337 if (it != candidates.begin()) {
2338 NBEdge* prev = *(it - 1);
2343 double intermediateWidth = 0;
2346 prevPos = prev->
getLanes()[laneI].shape[-1];
2349 prevPos = prev->
getLanes()[laneI].shape[0];
2354 currPos = curr->
getLanes()[laneI].shape[0];
2357 currPos = curr->
getLanes()[laneI].shape[-1];
2363 <<
" prevAngle=" << prevAngle
2364 <<
" angle=" << angle
2365 <<
" intermediateWidth=" << intermediateWidth
2378 std::cout <<
"adding crossing: " <<
toString(candidates) <<
"\n";
2389 std::sort(edges.begin(), edges.end());
2393 EdgeVector edgesOfCrossing = crossing->edges;
2394 std::sort(edgesOfCrossing.begin(), edgesOfCrossing.end());
2395 if (edgesOfCrossing == edges) {
2405 for (
int i = startIndex; i < (int)normalizedLanes.size(); ++i) {
2406 if (!normalizedLanes[i].second) {
2420 if (crossing->prevWalkingArea ==
"" || crossing->nextWalkingArea ==
"" || !crossing->valid) {
2421 if (crossing->valid) {
2422 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no walkingarea found).",
2426 std::vector<std::string>::iterator it_nc = std::find(wa.nextCrossings.begin(), wa.nextCrossings.end(), crossing->id);
2427 if (it_nc != wa.nextCrossings.end()) {
2428 wa.nextCrossings.erase(it_nc);
2431 crossing->valid =
false;
2432 crossing->prevWalkingArea =
"";
2433 crossing->nextWalkingArea =
"";
2438 std::vector<NBNode::Crossing*>
2440 std::vector<Crossing*> result;
2443 result.push_back(c);
2480 int noInternalNoSplits = 0;
2482 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
2483 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
2484 if ((*k).toEdge ==
nullptr) {
2487 noInternalNoSplits++;
2493 (*i)->buildInnerEdges(*
this, noInternalNoSplits, lno, splitNo);
2500 #ifdef DEBUG_PED_STRUCTURES
2504 std::cout <<
"build crossings for " <<
getID() <<
":\n";
2520 c->nextWalkingArea =
"";
2521 c->prevWalkingArea =
"";
2524 std::cout <<
" crossing=" << c->id <<
" edges=" <<
toString(edges);
2530 std::cout <<
" sortedEdges=" <<
toString(edges) <<
"\n";
2533 double maxAngleDiff = 0;
2534 int maxAngleDiffIndex = 0;
2535 for (
int i = 0; i < (int) edges.size(); i++) {
2537 edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this));
2542 std::cout <<
" i=" << i <<
" a1=" << edges[i]->getAngleAtNodeToCenter(
this) <<
" a2=" << edges[(i + 1) % edges.size()]->getAngleAtNodeToCenter(
this) <<
" diff=" << diff <<
"\n";
2544 if (diff > maxAngleDiff) {
2545 maxAngleDiff = diff;
2546 maxAngleDiffIndex = i;
2549 if (maxAngleDiff > 2 && maxAngleDiff < 360 - 2) {
2551 std::rotate(edges.begin(), edges.begin() + (maxAngleDiffIndex + 1) % edges.size(), edges.end());
2553 std::cout <<
" rotatedEdges=" <<
toString(edges);
2557 std::reverse(edges.begin(), edges.end());
2559 std::cout <<
" finalEdges=" <<
toString(edges) <<
"\n";
2563 const int begDir = (edges.front()->getFromNode() ==
this ?
FORWARD :
BACKWARD);
2564 const int endDir = (edges.back()->getToNode() ==
this ?
FORWARD :
BACKWARD);
2565 if (edges.front()->getFirstNonPedestrianLaneIndex(begDir) < 0
2566 || edges.back()->getFirstNonPedestrianLaneIndex(endDir) < 0) {
2568 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (no vehicle lanes to cross).", c->id,
getID(),
toString(c->edges));
2570 }
else if (c->customShape.size() != 0) {
2571 c->shape = c->customShape;
2573 NBEdge::Lane crossingBeg = edges.front()->getFirstNonPedestrianLane(begDir);
2574 NBEdge::Lane crossingEnd = edges.back()->getFirstNonPedestrianLane(endDir);
2583 WRITE_WARNINGF(
"Discarding invalid crossing '%' at junction '%' with edges [%] (invalid shape).", c->id,
getID(),
toString(c->edges));
2586 c->shape.push_back(crossingBeg.
shape[begDir ==
FORWARD ? 0 : -1]);
2587 c->shape.push_back(crossingEnd.
shape[endDir ==
FORWARD ? -1 : 0]);
2597 #ifdef DEBUG_PED_STRUCTURES
2603 std::cout <<
"build walkingAreas for " <<
getID() <<
":\n";
2610 std::vector<std::pair<NBEdge*, NBEdge::Lane> > normalizedLanes;
2611 for (EdgeVector::const_iterator it = allEdges.begin(); it != allEdges.end(); ++it) {
2613 const std::vector<NBEdge::Lane>& lanes = edge->
getLanes();
2615 for (std::vector<NBEdge::Lane>::const_reverse_iterator it_l = lanes.rbegin(); it_l != lanes.rend(); ++it_l) {
2619 normalizedLanes.push_back(std::make_pair(edge, l));
2622 for (std::vector<NBEdge::Lane>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); ++it_l) {
2627 normalizedLanes.push_back(std::make_pair(edge, l));
2633 std::vector<std::pair<int, int> > waIndices;
2635 NBEdge* prevEdge = normalizedLanes.back().first;
2636 for (
int i = 0; i < (int)normalizedLanes.size(); ++i) {
2637 NBEdge* edge = normalizedLanes[i].first;
2645 waIndices.push_back(std::make_pair(start, i - start));
2655 <<
" waI=" << waIndices.size() <<
" crossingBetween=" <<
crossingBetween(edge, prevEdge) <<
"\n";
2660 const int waNumLanes = (int)normalizedLanes.size() - start;
2661 if (waIndices.size() == 0) {
2662 waIndices.push_back(std::make_pair(start, waNumLanes));
2664 std::cout <<
" single wa, end at wrap-around\n";
2667 if (waIndices.front().first == 0) {
2668 NBEdge* edge = normalizedLanes.front().first;
2669 NBEdge* prevEdge = normalizedLanes.back().first;
2672 waIndices.push_back(std::make_pair(start, waNumLanes));
2674 std::cout <<
" do not wrap around, turn-around in between\n";
2678 waIndices.front().first = start;
2679 waIndices.front().second = waNumLanes + waIndices.front().second;
2681 std::cout <<
" wrapping around\n";
2686 waIndices.push_back(std::make_pair(start, waNumLanes));
2688 std::cout <<
" end at wrap-around\n";
2694 std::cout <<
" normalizedLanes=" << normalizedLanes.size() <<
" waIndices:\n";
2695 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2696 std::cout <<
" " << waIndices[i].first <<
", " << waIndices[i].second <<
"\n";
2700 for (
int i = 0; i < (int)waIndices.size(); ++i) {
2701 const bool buildExtensions = waIndices[i].second != (int)normalizedLanes.size();
2702 const int start = waIndices[i].first;
2703 const int prev = start > 0 ? start - 1 : (int)normalizedLanes.size() - 1;
2704 const int count = waIndices[i].second;
2705 const int end = (start + count) % normalizedLanes.size();
2709 std::cout <<
"build walkingArea " << wa.
id <<
" start=" << start <<
" end=" << end <<
" count=" << count <<
" prev=" << prev <<
":\n";
2711 double endCrossingWidth = 0;
2712 double startCrossingWidth = 0;
2716 bool connectsCrossing =
false;
2717 std::vector<Position> connectedPoints;
2720 std::cout <<
" crossing=" << c->id <<
" sortedEdges=" <<
toString(c->edges) <<
"\n";
2722 if (c->edges.back() == normalizedLanes[end].first
2723 && (normalizedLanes[end].second.permissions &
SVC_PEDESTRIAN) == 0) {
2725 if (c->nextWalkingArea !=
"") {
2726 WRITE_WARNINGF(
"Invalid pedestrian topology at junction '%'; crossing '%' targets '%' and '%'.",
2727 getID(), c->id, c->nextWalkingArea, wa.
id);
2730 c->nextWalkingArea = wa.
id;
2733 endCrossingWidth = c->width;
2734 endCrossingShape = c->shape;
2736 connectsCrossing =
true;
2737 connectedPoints.push_back(c->shape[-1]);
2741 std::cout <<
" crossing " << c->id <<
" ends\n";
2744 if (c->edges.front() == normalizedLanes[prev].first
2745 && (normalizedLanes[prev].second.permissions &
SVC_PEDESTRIAN) == 0) {
2747 if (c->prevWalkingArea !=
"") {
2748 WRITE_WARNINGF(
"Invalid pedestrian topology at junction '%'; crossing '%' is targeted by '%' and '%'.",
2749 getID(), c->id, c->prevWalkingArea, wa.
id);
2752 c->prevWalkingArea = wa.
id;
2756 startCrossingWidth = c->width;
2757 startCrossingShape = c->shape;
2759 connectsCrossing =
true;
2760 connectedPoints.push_back(c->shape[0]);
2764 std::cout <<
" crossing " << c->id <<
" starts\n";
2767 if (
gDebugFlag1) std::cout <<
" check connections to crossing " << c->id
2768 <<
" cFront=" << c->edges.front()->getID() <<
" cBack=" << c->edges.back()->getID()
2769 <<
" wEnd=" << normalizedLanes[end].first->getID() <<
" wStart=" << normalizedLanes[start].first->getID()
2770 <<
" wStartPrev=" << normalizedLanes[prev].first->getID()
2773 if (count < 2 && !connectsCrossing) {
2776 std::cout <<
" not relevant for walking: count=" << count <<
" connectsCrossing=" << connectsCrossing <<
"\n";
2781 std::set<NBEdge*, ComparatorIdLess> connected;
2782 for (
int j = 0; j < count; ++j) {
2783 const int nlI = (start + j) % normalizedLanes.size();
2784 NBEdge* edge = normalizedLanes[nlI].first;
2787 if (connected.count(edge) == 0) {
2795 connected.insert(edge);
2802 if (buildExtensions) {
2804 if (startCrossingShape.size() > 0) {
2806 std::cout <<
" extension at startCrossing shape=" << startCrossingShape <<
"\n";
2808 startCrossingShape.
move2side(startCrossingWidth / 2);
2810 startCrossingShape.
move2side(-startCrossingWidth);
2814 if (endCrossingShape.size() > 0) {
2816 std::cout <<
" extension at endCrossing shape=" << endCrossingShape <<
"\n";
2818 endCrossingShape.
move2side(endCrossingWidth / 2);
2820 endCrossingShape.
move2side(-endCrossingWidth);
2825 && normalizedLanes.size() == 2) {
2827 NBEdge* e1 = *connected.begin();
2828 NBEdge* e2 = *(++connected.begin());
2831 std::cout <<
" not building a walkingarea since normal connections exist\n";
2837 if (cornerDetail > 0) {
2838 int smoothEnd = end;
2839 int smoothPrev = prev;
2841 if (endCrossingWidth > 0 && normalizedLanes[smoothEnd].second.permissions == 0) {
2842 smoothEnd = (smoothEnd + 1) % normalizedLanes.size();
2844 if (startCrossingWidth > 0 && normalizedLanes[smoothPrev].second.permissions == 0) {
2845 if (smoothPrev == 0) {
2846 smoothPrev = (int)normalizedLanes.size() - 1;
2851 PositionVector begShape = normalizedLanes[smoothEnd].second.shape;
2852 begShape = begShape.
reverse();
2854 begShape.
move2side(normalizedLanes[smoothEnd].second.width / 2);
2855 PositionVector endShape = normalizedLanes[smoothPrev].second.shape;
2856 endShape.
move2side(normalizedLanes[smoothPrev].second.width / 2);
2859 if ((normalizedLanes[smoothEnd].first->getPermissions() & normalizedLanes[smoothPrev].first->getPermissions() &
2863 const double extend =
MIN2(10.0, begShape.back().distanceTo2D(endShape.front()) / 2);
2867 <<
" end=" << smoothEnd <<
" prev=" << smoothPrev
2868 <<
" endCrossingWidth=" << endCrossingWidth <<
" startCrossingWidth=" << startCrossingWidth
2869 <<
" begShape=" << begShape <<
" endShape=" << endShape <<
" smooth curve=" << curve <<
"\n";
2870 if (curve.size() > 2) {
2871 curve.erase(curve.begin());
2873 if (endCrossingWidth > 0) {
2874 wa.
shape.pop_back();
2876 if (startCrossingWidth > 0) {
2886 if (wacs.shape.size() != 0 &&
includes(connected, wacs.edges)) {
2887 wa.
shape = wacs.shape;
2893 double lengthSum = 0;
2894 int combinations = 0;
2895 for (std::vector<Position>::const_iterator it1 = connectedPoints.begin(); it1 != connectedPoints.end(); ++it1) {
2896 for (std::vector<Position>::const_iterator it2 = connectedPoints.begin(); it2 != connectedPoints.end(); ++it2) {
2906 std::cout <<
" combinations=" << combinations <<
" connectedPoints=" << connectedPoints <<
"\n";
2909 if (combinations > 0) {
2915 std::vector<Crossing*> validCrossings =
getCrossings();
2916 for (std::vector<Crossing*>::iterator it = validCrossings.begin(); it != validCrossings.end(); ++it) {
2918 Crossing& next = (it != validCrossings.begin() ? **(it - 1) :** (validCrossings.end() - 1));
2920 std::cout <<
" checkIntermediate: prev=" << prev.
id <<
" next=" << next.
id <<
" prev.nextWA=" << prev.
nextWalkingArea <<
"\n";
2935 wa.
shape.push_back(tmp[-1]);
2937 wa.
shape.push_back(tmp[-1]);
2941 wa.
shape.push_back(tmp[0]);
2943 wa.
shape.push_back(tmp[0]);
2946 std::set<NBEdge*, ComparatorIdLess> crossed(prev.
edges.begin(), prev.
edges.end());
2947 crossed.insert(next.
edges.begin(), next.
edges.end());
2950 if (wacs.shape.size() != 0 && wacs.edges.size() > 1 &&
includes(crossed, wacs.edges)) {
2951 wa.
shape = wacs.shape;
2960 std::cout <<
" build wa=" << wa.
id <<
"\n";
2968 const std::set<const NBEdge*, ComparatorIdLess>& sub) {
2970 for (
const NBEdge* e : sub) {
2971 if (super.count(
const_cast<NBEdge*
>(e)) == 0) {
2990 EdgeVector::const_iterator it1 = std::find(edges.begin(), edges.end(), e1);
2991 EdgeVector::const_iterator it2 = std::find(edges.begin(), edges.end(), e2);
2992 if (it1 != edges.end() && it2 != edges.end()) {
3008 while (it != it_end) {
3009 result.push_back(*it);
3019 wacs.
edges.insert(edges.begin(), edges.end());
3032 if (incoming.size() == 1 && outgoing.size() == 1) {
3035 if (incoming.size() == 2 && outgoing.size() == 2) {
3038 NBEdge* in0 = incoming[0];
3039 NBEdge* in1 = incoming[1];
3040 NBEdge* out0 = outgoing[0];
3041 NBEdge* out1 = outgoing[1];
3046 for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
3050 if (
MAX2(angle0, angle1) <= 160) {
3071 Crossing* c =
new Crossing(
this, edges, width, priority, tlIndex, tlIndex2, customShape);
3082 EdgeSet edgeSet(edges.begin(), edges.end());
3084 EdgeSet edgeSet2((*it)->edges.begin(), (*it)->edges.end());
3085 if (edgeSet == edgeSet2) {
3102 throw ProcessError(
"Request for unknown crossing '" +
id +
"'");
3108 EdgeSet edgeSet(edges.begin(), edges.end());
3110 EdgeSet edgeSet2(it->edges.begin(), it->edges.end());
3111 if (edgeSet == edgeSet2) {
3118 throw ProcessError(
"Request for unknown crossing for the given Edges");
3125 bool usedCustom =
false;
3127 c->tlLinkIndex = startIndex++;
3129 if (c->customTLIndex != -1) {
3130 usedCustom |= (c->tlLinkIndex != c->customTLIndex);
3131 c->tlLinkIndex = c->customTLIndex;
3133 c->tlLinkIndex2 = c->customTLIndex2;
3145 result += (int)edge->getConnections().size();
3158 const std::vector<NBEdge::Connection>& elv = (*i)->getConnections();
3159 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
3195 std::cout <<
" angles:\n";
3196 for (EdgeVector::const_iterator it = result.begin(); it != result.end(); ++it) {
3197 std::cout <<
" edge=" << (*it)->getID() <<
" edgeAngle=" << (*it)->getAngleAtNode(
this) <<
" angleToShape=" << (*it)->getAngleAtNodeToCenter(
this) <<
"\n";
3199 std::cout <<
" allEdges before: " <<
toString(result) <<
"\n";
3204 std::cout <<
" allEdges sorted: " <<
toString(result) <<
"\n";
3206 rotate(result.begin(), std::find(result.begin(), result.end(), *
myAllEdges.begin()), result.end());
3208 std::cout <<
" allEdges rotated: " <<
toString(result) <<
"\n";
3219 assert(
id[0] ==
':');
3220 std::string::size_type sep_index =
id.rfind(
'_');
3221 if (sep_index == std::string::npos) {
3222 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3225 sep_index =
id.substr(0, sep_index).rfind(
'_');
3226 if (sep_index == std::string::npos) {
3227 WRITE_ERROR(
"Invalid lane id '" +
id +
"' (missing '_').");
3230 return id.substr(1, sep_index - 1);
3240 if (turnDest !=
nullptr) {
3261 if ((*i)->rightOnRedConflict(index, foeIndex)) {
3284 std::vector<NBEdge*>::iterator j;
3285 for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
3288 if (allEdges.size() > 1 && j != allEdges.end()) {
3293 NBEdge* firstOfAll = allEdges.front();
3294 NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
3295 NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
3301 rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
3302 if (firstOfIncoming !=
nullptr) {
3303 rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
3305 if (firstOfOutgoing !=
nullptr) {
3306 rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
3308 #ifdef DEBUG_EDGE_SORTING
3310 std::cout <<
"sortedEdges:\n";
3311 for (
NBEdge* e : allEdges) {
3312 std::cout <<
" " << e->getID()
3313 <<
" angleToCenter=" << e->getAngleAtNodeToCenter(
this)
3314 <<
" junctionAngle=" << e->getAngleAtNode(
this) <<
"\n";
3321 if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
3322 std::vector<NBEdge*>::const_iterator in, out;
3323 std::vector<NBEdge*> allTmp;
3324 for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
3325 if ((*in)->isTurningDirectionAt(*out)) {
3326 allTmp.push_back(*in);
3327 allTmp.push_back(*out);
3332 if (allTmp.size() == allEdges.size()) {
3345 if (useNodeShape &&
myAllEdges != allEdgesOriginal) {
3349 e->computeEdgeShape();
3354 std::vector<std::pair<Position, std::string> >
3357 std::vector<std::pair<Position, std::string> >result;
3359 Position pos =
this == e->getFromNode() ? e->getGeometry().front() : e->getGeometry().back();
3360 const std::string origID = e->getParameter(
this == e->getFromNode() ?
"origFrom" :
"origTo");
3362 for (
const auto& pair : result) {
3363 if (pos.
almostSame(pair.first) || (origID !=
"" && pair.second == origID)) {
3369 result.push_back(std::make_pair(pos, origID));