40 #define DEBUGCOND (myNode.getID() == "C")
56 myRadius(node.getRadius()) {
68 bool singleDirection =
false;
70 singleDirection =
true;
74 singleDirection =
true;
77 #ifdef DEBUG_NODE_SHAPE
87 if (singleDirection) {
100 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
101 double ia = (*i)->getAngleAtNode(&
myNode);
102 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) {
103 double oa = (*j)->getAngleAtNode(&
myNode);
106 maxAngle =
MAX2(ad, maxAngle);
110 if (maxAngle > 22.5) {
118 if (ret.size() < 3) {
127 assert(l1[0].distanceTo2D(l1[1]) >=
EXT);
128 assert(l2[0].distanceTo2D(l2[1]) >=
EXT);
131 tmp.push_back(l1[1]);
133 tmp[1].set(-tmp[1].y(), tmp[1].x());
138 if (l2.
length2D() - offset > POSITION_EPS) {
141 l2.erase(l2.begin(), l2.begin() + (l2.size() - tl2.size()));
159 const double smallRadius = oc.
getFloat(
"junctions.small-radius");
160 const int cornerDetail = oc.
getInt(
"junctions.corner-detail");
161 const double sCurveStretch = oc.
getFloat(
"junctions.scurve-stretch");
162 const bool rectangularCut = oc.
getBool(
"rectangular-lane-cut");
163 const bool openDriveOutput = oc.
isSet(
"opendrive-output");
170 const double advanceStopLine = oc.
exists(
"opendrive-files") && oc.
isSet(
"opendrive-files") ? oc.
getFloat(
"opendrive.advance-stopline") : 0;
173 #ifdef DEBUG_NODE_SHAPE
175 std::cout <<
"\ncomputeNodeShapeDefault node " <<
myNode.
getID() <<
" simple=" << simpleContinuation <<
" useDefaultRadius=" << useDefaultRadius <<
" radius=" <<
myRadius <<
"\n";
180 EdgeVector::const_iterator i;
182 std::map<NBEdge*, std::set<NBEdge*> > same;
195 if (newAll.size() < 2) {
204 std::map<NBEdge*, double> distances;
205 std::map<NBEdge*, bool> myExtended;
207 for (i = newAll.begin(); i != newAll.end(); ++i) {
208 EdgeVector::const_iterator cwi = i;
209 EdgeVector::const_iterator ccwi = i;
212 initNeighbors(newAll, i, geomsCW, geomsCCW, cwi, ccwi, cad, ccad);
213 assert(geomsCCW.find(*i) != geomsCCW.end());
214 assert(geomsCW.find(*ccwi) != geomsCW.end());
215 assert(geomsCW.find(*cwi) != geomsCW.end());
221 (simpleContinuation && fabs(ccad - cad) < (
double) 0.1)
224 || (!simpleContinuation && fabs(ccad - cad) <
DEG2RAD(22.5)))
228 if (myExtended.find(*ccwi) != myExtended.end()) {
229 p = geomsCCW[*ccwi][0];
230 p.
add(geomsCW[*ccwi][0]);
232 #ifdef DEBUG_NODE_SHAPE
234 std::cout <<
" extended: p=" << p <<
" angle=" << (ccad - cad) <<
"\n";
238 p = geomsCCW[*ccwi][0];
239 p.
add(geomsCW[*ccwi][0]);
240 p.
add(geomsCCW[*i][0]);
241 p.
add(geomsCW[*i][0]);
243 #ifdef DEBUG_NODE_SHAPE
245 std::cout <<
" unextended: p=" << p <<
" angle=" << (ccad - cad) <<
"\n";
251 geomsCCW[*i].nearest_offset_to_point2D(p),
252 geomsCW[*i].nearest_offset_to_point2D(p));
264 (*i)->setGeometry(g);
266 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
267 geomsCCW[*i].extrapolate(
EXT);
268 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
269 geomsCW[*i].extrapolate(
EXT);
272 myExtended[*i] =
true;
273 #ifdef DEBUG_NODE_SHAPE
275 std::cout <<
" extending (dist=" << dist <<
")\n";
279 if (!simpleContinuation) {
283 double radius2 = fabs(ccad - cad) * (*i)->getNumLanes();
284 if (radius2 > NUMERICAL_EPS || openDriveOutput) {
285 radius2 =
MAX2(0.15, radius2);
288 #ifdef DEBUG_NODE_SHAPE
290 std::cout <<
" using radius=" << fabs(ccad - cad) * (*i)->getNumLanes() <<
" ccad=" << ccad <<
" cad=" << cad <<
"\n";
294 distances[*i] = dist;
300 const bool ccwCloser = ccad < cad;
303 const bool neighLargeTurn = ccwCloser ? ccwLargeTurn : cwLargeTurn;
304 const bool neigh2LargeTurn = ccwCloser ? cwLargeTurn : ccwLargeTurn;
306 const PositionVector& currGeom = ccwCloser ? geomsCCW[*i] : geomsCW[*i];
308 const PositionVector& currGeom2 = ccwCloser ? geomsCW[*i] : geomsCCW[*i];
310 const PositionVector& neighGeom = ccwCloser ? geomsCW[*ccwi] : geomsCCW[*cwi];
312 const PositionVector& neighGeom2 = ccwCloser ? geomsCCW[*cwi] : geomsCW[*ccwi];
313 #ifdef DEBUG_NODE_SHAPE
315 std::cout <<
" i=" << (*i)->getID() <<
" neigh=" << (*ccwi)->getID() <<
" neigh2=" << (*cwi)->getID() <<
"\n";
316 std::cout <<
" ccwCloser=" << ccwCloser
317 <<
"\n currGeom=" << currGeom <<
" neighGeom=" << neighGeom
318 <<
"\n currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2
322 if (!simpleContinuation) {
325 #ifdef DEBUG_NODE_SHAPE
327 std::cout <<
" neigh intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
"\n";
330 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
333 const double farAngleDist = ccwCloser ? cad : ccad;
334 double a1 = distances[*i];
336 #ifdef DEBUG_NODE_SHAPE
338 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";
345 distances[*i] =
MAX2(a1, a2);
346 }
else if (ccad >
DEG2RAD(90. + 45.) && cad >
DEG2RAD(90. + 45.)) {
348 }
else if (farAngleDist <
DEG2RAD(135) || (fabs(
RAD2DEG(farAngleDist) - 180) > 1 && fabs(a2 - a1) < 10)) {
349 distances[*i] =
MAX2(a1, a2);
351 #ifdef DEBUG_NODE_SHAPE
353 std::cout <<
" a1=" << a1 <<
" a2=" << a2 <<
" dist=" << distances[*i] <<
"\n";
358 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
360 #ifdef DEBUG_NODE_SHAPE
362 std::cout <<
" neigh2 intersects dist=" << distances[*i] <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
367 #ifdef DEBUG_NODE_SHAPE
369 std::cout <<
" no intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
378 distances[*i] = (double)
EXT;
382 if (useDefaultRadius && sCurveStretch > 0) {
384 if (sCurveWidth > 0) {
385 const double sCurveRadius =
myRadius + sCurveWidth /
SUMO_const_laneWidth * sCurveStretch * pow((*i)->getSpeed(), 2 + sCurveStretch) / 1000;
386 const double stretch =
EXT + sCurveRadius - distances[*i];
388 distances[*i] += stretch;
390 const double shorten = distances[*i] -
EXT;
391 (*i)->shortenGeometryAtNode(&
myNode, shorten);
392 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
393 (*k)->shortenGeometryAtNode(&
myNode, shorten);
395 #ifdef DEBUG_NODE_SHAPE
397 std::cout <<
" stretching junction: sCurveWidth=" << sCurveWidth <<
" sCurveRadius=" << sCurveRadius <<
" stretch=" << stretch <<
" dist=" << distances[*i] <<
"\n";
405 for (i = newAll.begin(); i != newAll.end(); ++i) {
406 if (distances.find(*i) == distances.end()) {
414 for (i = newAll.begin(); i != newAll.end(); ++i) {
415 if (distances[*i] <
EXT && (*i)->hasDefaultGeometryEndpointAtNode(&
myNode)) {
416 for (EdgeVector::const_iterator j = newAll.begin(); j != newAll.end(); ++j) {
417 if (distances[*j] >
EXT && (*j)->hasDefaultGeometryEndpointAtNode(&
myNode) && distances[*i] + distances[*j] < minDistSum) {
419 if (angleDiff > 160 || angleDiff < 20) {
420 #ifdef DEBUG_NODE_SHAPE
422 std::cout <<
" increasing dist for i=" << (*i)->getID() <<
" because of j=" << (*j)->getID() <<
" jDist=" << distances[*j]
423 <<
" oldI=" << distances[*i] <<
" newI=" << minDistSum - distances[*j]
424 <<
" angleDiff=" << angleDiff
425 <<
" geomI=" << (*i)->getGeometry() <<
" geomJ=" << (*j)->getGeometry() <<
"\n";
428 distances[*i] = minDistSum - distances[*j];
438 for (i = newAll.begin(); i != newAll.end(); ++i) {
442 double offset = distances[*i];
443 if (!(*i)->hasDefaultGeometryEndpointAtNode(&
myNode)) {
445 if (advanceStopLine > 0 && offset <
EXT) {
446 #ifdef DEBUG_NODE_SHAPE
447 std::cout <<
" i=" << (*i)->getID() <<
" offset=" << offset <<
" advanceStopLine=" << advanceStopLine <<
"\n";
450 (*i)->extendGeometryAtNode(&
myNode, advanceStopLine);
451 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
452 (*k)->extendGeometryAtNode(&
myNode, advanceStopLine);
455 offset =
MAX2(
EXT - advanceStopLine, offset);
459 offset = (double) - .1;
463 if (i != newAll.begin()) {
471 #ifdef DEBUG_NODE_SHAPE
473 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";
476 (*i)->setNodeBorder(&
myNode, p, p2, rectangularCut);
477 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
478 (*k)->setNodeBorder(&
myNode, p, p2, rectangularCut);
482 ret.
append(
getSmoothCorner(geomsCW[*(newAll.end() - 1)], geomsCCW[*newAll.begin()], ret[-1], ret[0], cornerDetail));
483 #ifdef DEBUG_NODE_SHAPE
485 std::cout <<
" final shape=" << ret <<
"\n";
495 double result = intersections[0];
496 for (std::vector<double>::iterator it = intersections.begin() + 1; it != intersections.end(); ++it) {
497 if (fabs(*it - offset) < fabs(result - offset)) {
506 std::map<
NBEdge*, std::set<NBEdge*> >& same)
const {
515 for (
NBEdge* e2s : same[e2]) {
520 for (
NBEdge* e1s : same[e1]) {
521 if ((e2s->getPermissions() & e1s->getPermissions() &
SVC_LARGE_TURN) != 0
522 && (e2s->getToNode() == e1s->getFromNode() || e1s->getToNode() == e2s->getFromNode())) {
527 for (
NBEdge* e1s : same[e1]) {
541 if (cornerDetail > 0) {
544 #ifdef DEBUG_SMOOTH_CORNERS
546 std::cout <<
" begLength=" << begShape2.
length2D() <<
" begSplit=" << begSplit <<
"\n";
549 if (begSplit > POSITION_EPS && begSplit < begShape2.
length2D() - POSITION_EPS) {
550 begShape2 = begShape2.
splitAt(begSplit,
true).first;
556 #ifdef DEBUG_SMOOTH_CORNERS
558 std::cout <<
" endLength=" << endShape2.
length2D() <<
" endSplit=" << endSplit <<
"\n";
561 if (endSplit > POSITION_EPS && endSplit < endShape2.
length2D() - POSITION_EPS) {
562 endShape2 = endShape2.
splitAt(endSplit,
true).second;
569 #ifdef DEBUG_SMOOTH_CORNERS
571 std::cout <<
"getSmoothCorner begPoint=" << begPoint <<
" endPoint=" << endPoint
572 <<
" begShape=" << begShape <<
" endShape=" << endShape
573 <<
" begShape2=" << begShape2 <<
" endShape2=" << endShape2
577 if (begShape2.size() < 2 || endShape2.size() < 2) {
581 NBNode* recordError =
nullptr;
582 #ifdef DEBUG_SMOOTH_CORNERS
584 std::cout <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
595 #ifdef DEBUG_SMOOTH_CORNERS
597 std::cout <<
" curve=" << curve <<
" curveLength=" << curve.
length2D() <<
" dist=" << begPoint.
distanceTo2D(endPoint) <<
" curvature=" << curvature <<
"\n";
600 if (curvature > 2 && angle >
DEG2RAD(85)) {
604 if (curve.size() > 2) {
605 curve.erase(curve.begin());
618 for (
NBEdge* edge : edges) {
621 geomsCCW[edge] = edge->getCCWBoundaryLine(
myNode);
623 WRITE_WARNING(
"While computing intersection geometry at junction '" +
myNode.
getID() +
"': " + std::string(e.what()));
624 geomsCCW[edge] = edge->getGeometry();
627 geomsCW[edge] = edge->getCWBoundaryLine(
myNode);
629 WRITE_WARNING(
"While computing intersection geometry at junction '" +
myNode.
getID() +
"': " + std::string(e.what()));
630 geomsCW[edge] = edge->getGeometry();
633 if (geomsCCW[edge].length2D() < NUMERICAL_EPS) {
634 geomsCCW[edge] = edge->getGeometry();
636 if (geomsCW[edge].length2D() < NUMERICAL_EPS) {
637 geomsCW[edge] = edge->getGeometry();
640 geomsCCW[edge].extrapolate2D(
EXT,
true);
641 geomsCW[edge].extrapolate2D(
EXT,
true);
642 geomsCCW[edge].extrapolate(
EXT2,
false,
true);
643 geomsCW[edge].extrapolate(
EXT2,
false,
true);
652 const double angleChangeLookahead = 35;
654 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); i++) {
655 EdgeVector::const_iterator j;
656 if (i == edges.end() - 1) {
661 const bool incoming = (*i)->getToNode() == &
myNode;
662 const bool incoming2 = (*j)->getToNode() == &
myNode;
663 const Position positionAtNode = (*i)->getGeometry()[incoming ? -1 : 0];
664 const Position positionAtNode2 = (*j)->getGeometry()[incoming2 ? -1 : 0];
667 const double angle1further = (g1.size() > 2 && g1[0].distanceTo2D(g1[1]) < angleChangeLookahead ?
669 const double angle2further = (g2.size() > 2 && g2[0].distanceTo2D(g2[1]) < angleChangeLookahead ?
673 const bool ambiguousGeometry = ((angleDiff > 0 && angleDiffFurther < 0) || (angleDiff < 0 && angleDiffFurther > 0));
674 const bool differentDirs = (incoming != incoming2);
679 #ifdef DEBUG_NODE_SHAPE
681 std::cout <<
" checkSameDirection " << (*i)->getID() <<
" " << (*j)->getID()
682 <<
" diffDirs=" << differentDirs
683 <<
" isOpposite=" << (differentDirs && foundOpposite.count(*i) == 0)
684 <<
" angleDiff=" << angleDiff
685 <<
" ambiguousGeometry=" << ambiguousGeometry
691 if (fabs(angleDiff) <
DEG2RAD(20)) {
692 const bool isOpposite = differentDirs && foundOpposite.count(*i) == 0;
694 foundOpposite.insert(*i);
695 foundOpposite.insert(*j);
699 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
705 for (std::set<NBEdge*>::iterator k = same[*j].begin(); k != same[*j].end(); ++k) {
713 #ifdef DEBUG_NODE_SHAPE
715 std::cout <<
" joinedSameDirectionEdges " << (*i)->getID() <<
" " << (*j)->getID() <<
" isOpposite=" << isOpposite <<
" ambiguousGeometry=" << ambiguousGeometry <<
"\n";
747 double endAngleDiff = 0;
748 if (geom1.size() >= 2 && geom2.size() >= 2) {
751 geom2.
angleAt2D((
int)geom2.size() - 2))));
754 std::vector<double> distances = geom1.
distances(geom2,
true);
757 const bool curvingTowards = geom1[0].distanceTo2D(geom2[0]) > minDistanceThreshold && minDist < minDistanceThreshold;
758 const bool onTop = (maxDist - POSITION_EPS < minDistanceThreshold) && endAngleDiff < 30;
763 #ifdef DEBUG_NODE_SHAPE
765 std::cout <<
" badIntersect: onTop=" << onTop <<
" curveTo=" << curvingTowards <<
" intersects=" << intersects
766 <<
" endAngleDiff=" << endAngleDiff
767 <<
" geom1=" << geom1 <<
" geom2=" << geom2
768 <<
" distances=" <<
toString(distances) <<
" minDist=" << minDist <<
" maxDist=" << maxDist <<
" thresh=" << minDistanceThreshold
769 <<
" intersectPos=" << intersect
773 return onTop || curvingTowards || !intersects;
780 std::map<
NBEdge*, std::set<NBEdge*> >& same,
787 auto e2NewAll = std::find(newAll.begin(), newAll.end(), e1);
788 #ifdef DEBUG_NODE_SHAPE
789 if (
DEBUGCOND) std::cout <<
"computeUniqueDirectionList e1=" << e1->getID()
790 <<
" deleted=" << (e2NewAll == newAll.end())
793 if (e2NewAll == newAll.end()) {
796 auto e1It = std::find(all.begin(), all.end(), e1);
802 for (
NBEdge* e2 : same[e1]) {
803 #ifdef DEBUG_NODE_SHAPE
805 std::cout <<
" e2=" << e2->getID() <<
"\n";
808 auto e2It = std::find(all.begin(), all.end(), e2);
809 if (e2It + 1 == bestCCW || (e2It == (all.end() - 1) && bestCCW == all.begin())) {
812 #ifdef DEBUG_NODE_SHAPE
814 std::cout <<
" bestCCW=" << e2->getID() <<
"\n";
817 }
else if (bestCW + 1 == e2It || (bestCW == (all.end() - 1) && e2It == all.begin())) {
820 #ifdef DEBUG_NODE_SHAPE
822 std::cout <<
" bestCW=" << e2->getID() <<
"\n";
828 if (bestCW != e1It) {
829 geomsCW[e1] = geomsCW[*bestCW];
832 if (bestCCW != e1It) {
833 geomsCCW[e1] = geomsCCW[*bestCCW];
837 for (
NBEdge* e2 : same[e1]) {
838 auto e2NewAll = std::find(newAll.begin(), newAll.end(), e2);
839 if (e2NewAll != newAll.end()) {
840 newAll.erase(e2NewAll);
844 #ifdef DEBUG_NODE_SHAPE
846 std::cout <<
" newAll:\n";
847 for (
NBEdge* e : newAll) {
848 std::cout <<
" " << e->getID() <<
" geomCCW=" << geomsCCW[e] <<
" geomsCW=" << geomsCW[e] <<
"\n";
860 EdgeVector::const_iterator& cwi,
861 EdgeVector::const_iterator& ccwi,
864 const double twoPI = (double)(2 *
M_PI);
867 if (cwi == edges.end()) {
868 std::advance(cwi, -((
int)edges.size()));
871 if (ccwi == edges.begin()) {
872 std::advance(ccwi, edges.size() - 1);
877 const double angleCurCCW = geomsCCW[*current].angleAt2D(0);
878 const double angleCurCW = geomsCW[*current].angleAt2D(0);
879 const double angleCCW = geomsCW[*ccwi].angleAt2D(0);
880 const double angleCW = geomsCCW[*cwi].angleAt2D(0);
881 ccad = angleCCW - angleCurCCW;
885 cad = angleCurCW - angleCW;
895 #ifdef DEBUG_NODE_SHAPE
897 std::cout <<
"computeNodeShapeSmall node=" <<
myNode.
getID() <<
"\n";
905 Position delta = edgebound1[1] - edgebound1[0];
906 delta.
set(-delta.
y(), delta.
x());
921 e->resetNodeBorder(&
myNode);
932 const double radius = oc.
getFloat(
"default.junctions.radius");
933 const double smallRadius = oc.
getFloat(
"junctions.small-radius");
934 double maxRightAngle = 0;
935 double extraWidthRight = 0;
936 double maxLeftAngle = 0;
937 double extraWidthLeft = 0;
939 int totalWideLanesIn = 0;
942 for (
int i = 0; i < in->getNumLanes(); i++) {
947 totalWideLanesIn += wideLanesIn;
949 if ((in->getPermissions() & out->getPermissions() &
SVC_LARGE_TURN) != 0) {
954 in->getGeometry().angleAt2D(-2),
955 out->getGeometry().angleAt2D(0));
957 if (maxRightAngle < -angle) {
958 maxRightAngle = -angle;
962 if (maxLeftAngle < angle) {
963 maxLeftAngle = angle;
968 while (*pIn != out) {
969 extraWidthLeft += (*pIn)->getTotalWidth();
972 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" extra=" << (*pIn)->getID() <<
" extraWidthLeft=" << extraWidthLeft <<
"\n";
979 int wideLanesOut = 0;
980 for (
int i = 0; i < out->getNumLanes(); i++) {
987 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" wideLanesIn=" << wideLanesIn <<
" wideLanesOut=" << wideLanesOut <<
"\n";
990 laneDelta =
MAX2(laneDelta, abs(wideLanesOut - wideLanesIn));
996 int totalWideLanesOut = 0;
998 for (
int i = 0; i < out->getNumLanes(); i++) {
1000 totalWideLanesOut++;
1004 if (totalWideLanesIn == totalWideLanesOut) {
1011 double result = radius;
1013 double maxTurnAngle = maxRightAngle;
1014 double extraWidth = extraWidthRight;
1015 if (maxRightAngle <
DEG2RAD(5)) {
1016 maxTurnAngle = maxLeftAngle;
1017 extraWidth = extraWidthLeft;
1022 result =
MAX2(smallRadius, radius * tan(0.5 *
MIN2(0.5 *
M_PI, maxTurnAngle)) - extraWidth);
1026 std::cout <<
"getDefaultRadius n=" <<
myNode.
getID() <<
" 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_WARNING(msg)
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
void computeSameEnd(PositionVector &l1, PositionVector &l2)
const SVCPermissions SVCAll
all VClasses are allowed
@ 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 double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
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.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
NBNode * getToNode() const
Returns the destination node of the edge.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
NBNode * getFromNode() const
Returns the origin node of the edge.
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 & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end 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.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
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
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
double myRadius
the computed node radius
EdgeVector computeUniqueDirectionList(const EdgeVector &all, std::map< NBEdge *, std::set< NBEdge * > > &same, GeomsMap &geomsCCW, GeomsMap &geomsCW)
Joins edges.
PositionVector computeNodeShapeSmall()
Computes the node geometry using normals.
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 NBNode & myNode
The node to compute the geometry for.
PositionVector compute()
Computes the shape of the assigned junction.
PositionVector computeNodeShapeDefault(bool simpleContinuation)
Computes the node geometry Edges with the same direction are grouped. Then the node geometry is built...
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
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 sub(double xoff, double yoff, double zoff)
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.
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)