41#define DEBUGCOND (myNode.getID() == "C")
56 myRadius(node.getRadius())
71#ifdef DEBUG_NODE_SHAPE
103 assert(l1[0].distanceTo2D(l1[1]) >=
EXT);
104 assert(l2[0].distanceTo2D(l2[1]) >=
EXT);
107 tmp.push_back(l1[1]);
109 tmp[1].set(-tmp[1].y(), tmp[1].x());
114 if (l2.
length2D() - offset > POSITION_EPS) {
117 l2.erase(l2.begin(), l2.begin() + (l2.size() - tl2.size()));
135 double smallRadius = useDefaultRadius ? oc.
getFloat(
"junctions.small-radius") :
myRadius;
136 const int cornerDetail = oc.
getInt(
"junctions.corner-detail");
137 const double sCurveStretch = oc.
getFloat(
"junctions.scurve-stretch");
138 const bool rectangularCut = oc.
getBool(
"rectangular-lane-cut");
139 const bool openDriveOutput = oc.
isSet(
"opendrive-output");
146 const double advanceStopLine = oc.
exists(
"opendrive-files") && oc.
isSet(
"opendrive-files") ? oc.
getFloat(
"opendrive.advance-stopline") : 0;
149#ifdef DEBUG_NODE_SHAPE
151 std::cout <<
"\ncomputeNodeShapeDefault node " <<
myNode.
getID() <<
" simple=" << simpleContinuation <<
" useDefaultRadius=" << useDefaultRadius <<
" radius=" <<
myRadius <<
"\n";
156 EdgeVector::const_iterator i;
158 std::map<NBEdge*, std::set<NBEdge*> > same;
171 if (newAll.size() < 2) {
180 std::map<NBEdge*, double> distances;
181 std::map<NBEdge*, bool> myExtended;
183 for (i = newAll.begin(); i != newAll.end(); ++i) {
184 EdgeVector::const_iterator cwi = i;
185 EdgeVector::const_iterator ccwi = i;
188 initNeighbors(newAll, i, geomsCW, geomsCCW, cwi, ccwi, cad, ccad);
189 assert(geomsCCW.find(*i) != geomsCCW.end());
190 assert(geomsCW.find(*ccwi) != geomsCW.end());
191 assert(geomsCW.find(*cwi) != geomsCW.end());
197 (simpleContinuation && fabs(ccad - cad) < (
double) 0.1)
200 || (!simpleContinuation && fabs(ccad - cad) <
DEG2RAD(22.5)))
204 if (myExtended.find(*ccwi) != myExtended.end()) {
205 p = geomsCCW[*ccwi][0];
206 p.
add(geomsCW[*ccwi][0]);
208#ifdef DEBUG_NODE_SHAPE
210 std::cout <<
" extended: p=" << p <<
" angle=" << (ccad - cad) <<
"\n";
214 p = geomsCCW[*ccwi][0];
215 p.
add(geomsCW[*ccwi][0]);
216 p.
add(geomsCCW[*i][0]);
217 p.
add(geomsCW[*i][0]);
219#ifdef DEBUG_NODE_SHAPE
221 std::cout <<
" unextended: p=" << p <<
" angle=" << (ccad - cad) <<
"\n";
227 geomsCCW[*i].nearest_offset_to_point2D(p),
228 geomsCW[*i].nearest_offset_to_point2D(p));
244 (*i)->setGeometry(g);
246 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
247 geomsCCW[*i].extrapolate(
EXT);
248 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
249 geomsCW[*i].extrapolate(
EXT);
252 myExtended[*i] =
true;
253#ifdef DEBUG_NODE_SHAPE
255 std::cout <<
" extending (dist=" << dist <<
")\n";
259 if (!simpleContinuation) {
263 double radius2 = fabs(ccad - cad) * (*i)->getNumLanes();
264 if (radius2 > NUMERICAL_EPS || openDriveOutput) {
265 radius2 =
MAX2(0.15, radius2);
272 radius2 =
MAX2(radius2, width / 2);
274 if (!useDefaultRadius) {
278#ifdef DEBUG_NODE_SHAPE
280 std::cout <<
" using radius=" << radius2 <<
" ccad=" << ccad <<
" cad=" << cad <<
"\n";
284 distances[*i] = dist;
290 const bool ccwCloser = ccad < cad;
293 const bool neighLargeTurn = ccwCloser ? ccwLargeTurn : cwLargeTurn;
294 const bool neigh2LargeTurn = ccwCloser ? cwLargeTurn : ccwLargeTurn;
296 const PositionVector& currGeom = ccwCloser ? geomsCCW[*i] : geomsCW[*i];
298 const PositionVector& currGeom2 = ccwCloser ? geomsCW[*i] : geomsCCW[*i];
300 const PositionVector& neighGeom = ccwCloser ? geomsCW[*ccwi] : geomsCCW[*cwi];
302 const PositionVector& neighGeom2 = ccwCloser ? geomsCCW[*cwi] : geomsCW[*ccwi];
303#ifdef DEBUG_NODE_SHAPE
305 std::cout <<
" i=" << (*i)->getID() <<
" neigh=" << (*ccwi)->getID() <<
" neigh2=" << (*cwi)->getID() <<
"\n";
306 std::cout <<
" ccwCloser=" << ccwCloser
307 <<
"\n currGeom=" << currGeom <<
" neighGeom=" << neighGeom
308 <<
"\n currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2
312 if (!simpleContinuation) {
315#ifdef DEBUG_NODE_SHAPE
317 std::cout <<
" neigh intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
"\n";
320 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
323 const double farAngleDist = ccwCloser ? cad : ccad;
324 double a1 = distances[*i];
326#ifdef DEBUG_NODE_SHAPE
328 std::cout <<
" neigh2 also intersects a1=" << a1 <<
" a2=" << a2 <<
" ccad=" <<
RAD2DEG(ccad) <<
" cad=" <<
RAD2DEG(cad) <<
" dist[cwi]=" << distances[*cwi] <<
" dist[ccwi]=" << distances[*ccwi] <<
" farAngleDist=" <<
RAD2DEG(farAngleDist) <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
335 distances[*i] =
MAX2(a1, a2);
336 }
else if (ccad >
DEG2RAD(90. + 45.) && cad >
DEG2RAD(90. + 45.)) {
338 }
else if (farAngleDist <
DEG2RAD(135) || (fabs(
RAD2DEG(farAngleDist) - 180) > 1 && fabs(a2 - a1) < 10)) {
339 distances[*i] =
MAX2(a1, a2);
341#ifdef DEBUG_NODE_SHAPE
343 std::cout <<
" a1=" << a1 <<
" a2=" << a2 <<
" dist=" << distances[*i] <<
"\n";
348 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
350#ifdef DEBUG_NODE_SHAPE
352 std::cout <<
" neigh2 intersects dist=" << distances[*i] <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
357#ifdef DEBUG_NODE_SHAPE
359 std::cout <<
" no intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
368 distances[*i] = (double)
EXT;
372 if (useDefaultRadius && sCurveStretch > 0) {
374 if (sCurveWidth > 0) {
375 const double sCurveRadius =
myRadius + sCurveWidth /
SUMO_const_laneWidth * sCurveStretch * pow((*i)->getSpeed(), 2 + sCurveStretch) / 1000;
376 const double stretch =
EXT + sCurveRadius - distances[*i];
378 distances[*i] += stretch;
380 const double shorten = distances[*i] -
EXT;
381 (*i)->shortenGeometryAtNode(&
myNode, shorten);
382 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
383 (*k)->shortenGeometryAtNode(&
myNode, shorten);
385#ifdef DEBUG_NODE_SHAPE
387 std::cout <<
" stretching junction: sCurveWidth=" << sCurveWidth <<
" sCurveRadius=" << sCurveRadius <<
" stretch=" << stretch <<
" dist=" << distances[*i] <<
"\n";
395 for (
NBEdge*
const edge : newAll) {
396 if (distances.find(edge) == distances.end()) {
398 distances[edge] =
EXT;
402 const double off =
EXT - NUMERICAL_EPS;
406 for (
NBEdge*
const edge : newAll) {
407 if (distances[edge] < off && edge->hasDefaultGeometryEndpointAtNode(&
myNode)) {
408 for (EdgeVector::const_iterator j = newAll.begin(); j != newAll.end(); ++j) {
409 if (distances[*j] > off && (*j)->hasDefaultGeometryEndpointAtNode(&
myNode) && distances[edge] + distances[*j] < minDistSum) {
411 if (angleDiff > 160 || angleDiff < 20) {
412#ifdef DEBUG_NODE_SHAPE
414 std::cout <<
" increasing dist for i=" << edge->getID() <<
" because of j=" << (*j)->getID() <<
" jDist=" << distances[*j]
415 <<
" oldI=" << distances[edge] <<
" newI=" << minDistSum - distances[*j]
416 <<
" angleDiff=" << angleDiff
417 <<
" geomI=" << edge->getGeometry() <<
" geomJ=" << (*j)->getGeometry() <<
"\n";
420 distances[edge] = minDistSum - distances[*j];
430 for (i = newAll.begin(); i != newAll.end(); ++i) {
434 double offset = distances[*i];
435 if (!(*i)->hasDefaultGeometryEndpointAtNode(&
myNode)) {
437 if (advanceStopLine > 0 && offset <
EXT) {
438#ifdef DEBUG_NODE_SHAPE
439 std::cout <<
" i=" << (*i)->getID() <<
" offset=" << offset <<
" advanceStopLine=" << advanceStopLine <<
"\n";
442 (*i)->extendGeometryAtNode(&
myNode, advanceStopLine);
443 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
444 (*k)->extendGeometryAtNode(&
myNode, advanceStopLine);
447 offset =
MAX2(
EXT - advanceStopLine, offset);
451 offset = (double) - .1;
455 if (i != newAll.begin()) {
463#ifdef DEBUG_NODE_SHAPE
465 std::cout <<
" build stopLine for i=" << (*i)->getID() <<
" offset=" << offset <<
" dist=" << distances[*i] <<
" cwLength=" << cwBound.
length2D() <<
" ccwLength=" << ccwBound.
length2D() <<
" p=" << p <<
" p2=" << p2 <<
" ccwBound=" << ccwBound <<
" cwBound=" << cwBound <<
"\n";
468 (*i)->setNodeBorder(&
myNode, p, p2, rectangularCut);
469 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
470 (*k)->setNodeBorder(&
myNode, p, p2, rectangularCut);
474 ret.
append(
getSmoothCorner(geomsCW[*(newAll.end() - 1)], geomsCCW[*newAll.begin()], ret[-1], ret[0], cornerDetail));
475#ifdef DEBUG_NODE_SHAPE
477 std::cout <<
" final shape=" << ret <<
"\n";
487 double result = intersections[0];
488 for (std::vector<double>::iterator it = intersections.begin() + 1; it != intersections.end(); ++it) {
489 if (fabs(*it - offset) < fabs(result - offset)) {
498 std::map<
NBEdge*, std::set<NBEdge*> >& same)
const {
507 for (
NBEdge* e2s : same[e2]) {
512 for (
NBEdge* e1s : same[e1]) {
513 if ((e2s->getPermissions() & e1s->getPermissions() &
SVC_LARGE_TURN) != 0
514 && (e2s->getToNode() == e1s->getFromNode() || e1s->getToNode() == e2s->getFromNode())) {
519 for (
NBEdge* e1s : same[e1]) {
533 if (cornerDetail > 0) {
536#ifdef DEBUG_SMOOTH_CORNERS
538 std::cout <<
" begLength=" << begShape2.
length2D() <<
" begSplit=" << begSplit <<
"\n";
541 if (begSplit > POSITION_EPS && begSplit < begShape2.
length2D() - POSITION_EPS) {
542 begShape2 = begShape2.
splitAt(begSplit,
true).first;
548#ifdef DEBUG_SMOOTH_CORNERS
550 std::cout <<
" endLength=" << endShape2.
length2D() <<
" endSplit=" << endSplit <<
"\n";
553 if (endSplit > POSITION_EPS && endSplit < endShape2.
length2D() - POSITION_EPS) {
554 endShape2 = endShape2.
splitAt(endSplit,
true).second;
561#ifdef DEBUG_SMOOTH_CORNERS
563 std::cout <<
"getSmoothCorner begPoint=" << begPoint <<
" endPoint=" << endPoint
564 <<
" begShape=" << begShape <<
" endShape=" << endShape
565 <<
" begShape2=" << begShape2 <<
" endShape2=" << endShape2
569 if (begShape2.size() < 2 || endShape2.size() < 2) {
573 NBNode* recordError =
nullptr;
574#ifdef DEBUG_SMOOTH_CORNERS
576 std::cout <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
587#ifdef DEBUG_SMOOTH_CORNERS
589 std::cout <<
" curve=" << curve <<
" curveLength=" << curve.
length2D() <<
" dist=" << begPoint.
distanceTo2D(endPoint) <<
" curvature=" << curvature <<
"\n";
592 if (curvature > 2 && angle >
DEG2RAD(85)) {
596 if (curve.size() > 2) {
597 curve.erase(curve.begin());
610 for (
NBEdge*
const edge : edges) {
613 geomsCCW[edge] = edge->getCCWBoundaryLine(
myNode);
615 WRITE_WARNING(
"While computing intersection geometry at junction '" +
myNode.
getID() +
"': " + std::string(e.what()));
616 geomsCCW[edge] = edge->getGeometry();
619 geomsCW[edge] = edge->getCWBoundaryLine(
myNode);
621 WRITE_WARNING(
"While computing intersection geometry at junction '" +
myNode.
getID() +
"': " + std::string(e.what()));
622 geomsCW[edge] = edge->getGeometry();
625 if (geomsCCW[edge].length2D() < NUMERICAL_EPS) {
626 geomsCCW[edge] = edge->getGeometry();
628 if (geomsCW[edge].length2D() < NUMERICAL_EPS) {
629 geomsCW[edge] = edge->getGeometry();
632 geomsCCW[edge] = geomsCCW[edge].getSubpart2D(0,
MAX2(
EXT, edge->getTotalWidth()));
633 geomsCW[edge] = geomsCW[edge].getSubpart2D(0,
MAX2(
EXT, edge->getTotalWidth()));
635 geomsCCW[edge].extrapolate2D(
EXT,
true);
636 geomsCW[edge].extrapolate2D(
EXT,
true);
638 geomsCCW[edge].extrapolate(
EXT2,
false,
true);
639 geomsCW[edge].extrapolate(
EXT2,
false,
true);
647 const double angleChangeLookahead = 35;
650 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); i++) {
651 EdgeVector::const_iterator j;
652 if (i == edges.end() - 1) {
657 const bool incoming = (*i)->getToNode() == &
myNode;
658 const bool incoming2 = (*j)->getToNode() == &
myNode;
659 const bool differentDirs = (incoming != incoming2);
660 const bool sameGeom = (*i)->getGeometry() == (differentDirs ? (*j)->getGeometry().reverse() : (*j)->getGeometry());
663 const double angle1further = (g1.size() > 2 && g1[0].distanceTo2D(g1[1]) < angleChangeLookahead ?
665 const double angle2further = (g2.size() > 2 && g2[0].distanceTo2D(g2[1]) < angleChangeLookahead ?
669 const bool ambiguousGeometry = ((angleDiff > 0 && angleDiffFurther < 0) || (angleDiff < 0 && angleDiffFurther > 0));
674#ifdef DEBUG_NODE_SHAPE
676 std::cout <<
" checkSameDirection " << (*i)->getID() <<
" " << (*j)->getID()
677 <<
" diffDirs=" << differentDirs
678 <<
" isOpposite=" << (differentDirs && foundOpposite.count(*i) == 0)
679 <<
" angleDiff=" << angleDiff
680 <<
" ambiguousGeometry=" << ambiguousGeometry
686 if (sameGeom || fabs(angleDiff) <
DEG2RAD(20)) {
687 const bool isOpposite = differentDirs && foundOpposite.count(*i) == 0;
689 foundOpposite.insert(*i);
690 foundOpposite.insert(*j);
694 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
700 for (std::set<NBEdge*>::iterator k = same[*j].begin(); k != same[*j].end(); ++k) {
708#ifdef DEBUG_NODE_SHAPE
710 std::cout <<
" joinedSameDirectionEdges " << (*i)->getID() <<
" " << (*j)->getID() <<
" isOpposite=" << isOpposite <<
" ambiguousGeometry=" << ambiguousGeometry <<
"\n";
742 double endAngleDiff = 0;
743 if (geom1.size() >= 2 && geom2.size() >= 2) {
746 geom2.
angleAt2D((
int)geom2.size() - 2))));
749 std::vector<double> distances = geom1.
distances(geom2,
true);
752 const bool curvingTowards = geom1[0].distanceTo2D(geom2[0]) > minDistanceThreshold && minDist < minDistanceThreshold;
753 const bool onTop = (maxDist - POSITION_EPS < minDistanceThreshold) && endAngleDiff < 30;
758#ifdef DEBUG_NODE_SHAPE
760 std::cout <<
" badIntersect: onTop=" << onTop <<
" curveTo=" << curvingTowards <<
" intersects=" << intersects
761 <<
" endAngleDiff=" << endAngleDiff
762 <<
" geom1=" << geom1 <<
" geom2=" << geom2
763 <<
" distances=" <<
toString(distances) <<
" minDist=" << minDist <<
" maxDist=" << maxDist <<
" thresh=" << minDistanceThreshold
764 <<
" intersectPos=" << intersect
768 return onTop || curvingTowards || !intersects;
775 std::map<
NBEdge*, std::set<NBEdge*> >& same,
782 auto e2NewAll = std::find(newAll.begin(), newAll.end(), e1);
783#ifdef DEBUG_NODE_SHAPE
784 if (
DEBUGCOND) std::cout <<
"computeUniqueDirectionList e1=" << e1->getID()
785 <<
" deleted=" << (e2NewAll == newAll.end())
788 if (e2NewAll == newAll.end()) {
791 auto e1It = std::find(all.begin(), all.end(), e1);
797 for (
NBEdge* e2 : same[e1]) {
798#ifdef DEBUG_NODE_SHAPE
800 std::cout <<
" e2=" << e2->getID() <<
"\n";
803 auto e2It = std::find(all.begin(), all.end(), e2);
804 if (e2It + 1 == bestCCW || (e2It == (all.end() - 1) && bestCCW == all.begin())) {
807#ifdef DEBUG_NODE_SHAPE
809 std::cout <<
" bestCCW=" << e2->getID() <<
"\n";
812 }
else if (bestCW + 1 == e2It || (bestCW == (all.end() - 1) && e2It == all.begin())) {
815#ifdef DEBUG_NODE_SHAPE
817 std::cout <<
" bestCW=" << e2->getID() <<
"\n";
823 if (bestCW != e1It) {
824 geomsCW[e1] = geomsCW[*bestCW];
827 if (bestCCW != e1It) {
828 geomsCCW[e1] = geomsCCW[*bestCCW];
832 for (
NBEdge* e2 : same[e1]) {
833 auto e2NewAllIt = std::find(newAll.begin(), newAll.end(), e2);
834 if (e2NewAllIt != newAll.end()) {
835 newAll.erase(e2NewAllIt);
839#ifdef DEBUG_NODE_SHAPE
841 std::cout <<
" newAll:\n";
842 for (
NBEdge* e : newAll) {
843 std::cout <<
" " << e->getID() <<
" geomCCW=" << geomsCCW[e] <<
" geomsCW=" << geomsCW[e] <<
"\n";
855 EdgeVector::const_iterator& cwi,
856 EdgeVector::const_iterator& ccwi,
859 const double twoPI = (double)(2 *
M_PI);
862 if (cwi == edges.end()) {
863 std::advance(cwi, -((
int)edges.size()));
866 if (ccwi == edges.begin()) {
867 std::advance(ccwi, edges.size() - 1);
872 const double angleCurCCW = geomsCCW[*current].angleAt2D(0);
873 const double angleCurCW = geomsCW[*current].angleAt2D(0);
874 const double angleCCW = geomsCW[*ccwi].angleAt2D(0);
875 const double angleCW = geomsCCW[*cwi].angleAt2D(0);
876 ccad = angleCCW - angleCurCCW;
880 cad = angleCurCW - angleCW;
890#ifdef DEBUG_NODE_SHAPE
892 std::cout <<
"computeNodeShapeSmall node=" <<
myNode.
getID() <<
"\n";
900 Position delta = edgebound1[1] - edgebound1[0];
901 delta.
set(-delta.
y(), delta.
x());
916 e->resetNodeBorder(&
myNode);
927 const double radius = oc.
getFloat(
"default.junctions.radius");
928 const double smallRadius = oc.
getFloat(
"junctions.small-radius");
929 double maxRightAngle = 0;
930 double extraWidthRight = 0;
931 double maxLeftAngle = 0;
932 double extraWidthLeft = 0;
934 int totalWideLanesIn = 0;
937 for (
int i = 0; i < in->getNumLanes(); i++) {
942 totalWideLanesIn += wideLanesIn;
944 if ((in->getPermissions() & out->getPermissions() &
SVC_LARGE_TURN) != 0) {
949 in->getGeometry().angleAt2D(-2),
950 out->getGeometry().angleAt2D(0));
952 if (maxRightAngle < -angle) {
953 maxRightAngle = -angle;
957 if (maxLeftAngle < angle) {
958 maxLeftAngle = angle;
963 while (*pIn != out) {
964 extraWidthLeft += (*pIn)->getTotalWidth();
967 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" extra=" << (*pIn)->getID() <<
" extraWidthLeft=" << extraWidthLeft <<
"\n";
974 int wideLanesOut = 0;
975 for (
int i = 0; i < out->getNumLanes(); i++) {
982 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" wideLanesIn=" << wideLanesIn <<
" wideLanesOut=" << wideLanesOut <<
"\n";
985 laneDelta =
MAX2(laneDelta, abs(wideLanesOut - wideLanesIn));
991 int totalWideLanesOut = 0;
993 for (
int i = 0; i < out->getNumLanes(); i++) {
999 if (totalWideLanesIn == totalWideLanesOut) {
1006 double result = radius;
1008 double maxTurnAngle = maxRightAngle;
1009 double extraWidth = extraWidthRight;
1010 if (maxRightAngle <
DEG2RAD(5)) {
1011 maxTurnAngle = maxLeftAngle;
1012 extraWidth = extraWidthLeft;
1014 const double minRadius = maxTurnAngle >=
DEG2RAD(30) ?
MIN2(smallRadius, radius) : smallRadius;
1018 result = radius * tan(0.5 *
MIN2(0.5 *
M_PI, maxTurnAngle)) - extraWidth;
1020 result =
MAX2(minRadius, result);
1023 std::cout <<
"getDefaultRadius n=" <<
myNode.
getID()
1024 <<
" r=" << radius <<
" sr=" << smallRadius
1025 <<
" mr=" << minRadius
1026 <<
" laneDelta=" << laneDelta
1027 <<
" rightA=" <<
RAD2DEG(maxRightAngle)
1028 <<
" leftA=" <<
RAD2DEG(maxLeftAngle)
1029 <<
" maxA=" <<
RAD2DEG(maxTurnAngle)
1030 <<
" extraWidth=" << extraWidth
1031 <<
" result=" << result <<
"\n";
1042 while (lane < e->getNumLanes() && e->
getPermissions(lane) == 0) {
1046 while (lane < e->getNumLanes() && (e->
getPermissions(lane) & exclude) == 0) {
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
const SVCPermissions SVCAll
all VClasses are allowed
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_DELIVERY
vehicle is a small delivery vehicle
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ TURN
The link is a 180 degree turn.
const double SUMO_const_laneWidth
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
std::string joinNamedToStringSorting(const std::set< T * > &ns, const T_BETWEEN &between)
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
The representation of a single edge during network building.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
double getLaneWidth() const
Returns the default width of lanes of this edge.
NBNode * getToNode() const
Returns the destination node of the edge.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
NBNode * getFromNode() const
Returns the origin node of the edge.
static const double UNSPECIFIED_WIDTH
unspecified lane width
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Represents a single node (junction) during network building.
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
double getDisplacementError() const
compute the displacement error during s-curve computation
bool isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
static const double UNSPECIFIED_RADIUS
unspecified lane width
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
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.
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
bool isConstantWidthTransition() const
detects whether a given junction splits or merges lanes while keeping constant road width
static const int AVOID_WIDE_LEFT_TURN
const Position & getPosition() const
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
double getRadius() const
Returns the turning radius of this node.
PositionVector getSmoothCorner(PositionVector begShape, PositionVector endShape, const Position &begPoint, const Position &endPoint, int cornerDetail)
Compute smoothed corner shape.
double closestIntersection(const PositionVector &geom1, const PositionVector &geom2, double offset)
return the intersection point closest to the given offset
const PositionVector computeNodeShapeSmall()
Computes the node geometry using normals.
double myRadius
the computed node radius
EdgeVector computeUniqueDirectionList(const EdgeVector &all, std::map< NBEdge *, std::set< NBEdge * > > &same, GeomsMap &geomsCCW, GeomsMap &geomsCW)
Joins edges.
double EXT
the maximum distance to search for a place where neighboring edges intersect and do not overlap
void computeEdgeBoundaries(const EdgeVector &edges, GeomsMap &geomsCCW, GeomsMap &geomsCW)
compute clockwise/counter-clockwise edge boundaries
std::map< NBEdge *, PositionVector > GeomsMap
NBNodeShapeComputer(const NBNode &node)
Constructor.
~NBNodeShapeComputer()
Destructor.
bool badIntersection(const NBEdge *e1, const NBEdge *e2, double distance)
const PositionVector computeNodeShapeDefault(bool simpleContinuation)
Computes the node geometry Edges with the same direction are grouped. Then the node geometry is built...
const PositionVector compute(bool forceSmall)
Computes the shape of the assigned junction.
const NBNode & myNode
The node to compute the geometry for.
void computeSameEnd(PositionVector &l1, PositionVector &l2)
void joinSameDirectionEdges(const EdgeVector &edges, std::map< NBEdge *, std::set< NBEdge * > > &same)
Joins edges and computes ccw/cw boundaries.
double getDefaultRadius(const OptionsCont &oc)
determine the default radius appropriate for the current junction
static void initNeighbors(const EdgeVector &edges, const EdgeVector::const_iterator ¤t, GeomsMap &geomsCW, GeomsMap &geomsCCW, EdgeVector::const_iterator &cwi, EdgeVector::const_iterator &ccwi, double &cad, double &ccad)
Initialize neighbors and angles.
bool needsLargeTurn(NBEdge *e1, NBEdge *e2, std::map< NBEdge *, std::set< NBEdge * > > &same) const
whether the given edges (along with those in the same direction) requires a large turning radius
static const SVCPermissions SVC_LARGE_TURN
static double getExtraWidth(const NBEdge *e, SVCPermissions exclude)
compute with of rightmost lanes that exlude the given permissions
static bool isRailwayNode(const NBNode *n)
whether the given node only has rail edges
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
A point in 2D or 3D with translation and scaling methods.
void set(double x, double y)
set positions x and y
static const Position INVALID
used to indicate that a position is valid
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
double x() const
Returns the x-position.
void add(const Position &pos)
Adds the given position to this one.
void setz(double z)
set position z
void mul(double val)
Multiplies both positions with the given value.
double z() const
Returns the z-position.
double y() const
Returns the y-position.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
double length() const
Returns the length.
Position intersectionPosition2D(const Position &p1, const Position &p2, const double withinDist=0.) const
Returns the position of the intersection.
void push_front_noDoublePos(const Position &p)
insert in front a non double position
void add(double xoff, double yoff, double zoff)
std::vector< double > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
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)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
PositionVector interpolateZ(double zStart, double zEnd) const
returned vector that varies z smoothly over its length
double angleAt2D(int pos) const
get angle in certain position of position vector
void extrapolate2D(const double val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
void push_back_noDoublePos(const Position &p)
insert in back a non double position
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
PositionVector reverse() const
reverse position vector
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
void sub(const Position &offset)
PositionVector getSubpart(double beginOffset, double endOffset) const
get subpart of a position vector
static T maxValue(const std::vector< T > &v)
static T minValue(const std::vector< T > &v)