40 #define DEBUGCOND (myNode.getID() == "C")
56 myRadius(node.getRadius()) {
65 #ifdef DEBUG_NODE_SHAPE
97 assert(l1[0].distanceTo2D(l1[1]) >=
EXT);
98 assert(l2[0].distanceTo2D(l2[1]) >=
EXT);
101 tmp.push_back(l1[1]);
103 tmp[1].set(-tmp[1].y(), tmp[1].x());
108 if (l2.
length2D() - offset > POSITION_EPS) {
111 l2.erase(l2.begin(), l2.begin() + (l2.size() - tl2.size()));
129 const double smallRadius = oc.
getFloat(
"junctions.small-radius");
130 const int cornerDetail = oc.
getInt(
"junctions.corner-detail");
131 const double sCurveStretch = oc.
getFloat(
"junctions.scurve-stretch");
132 const bool rectangularCut = oc.
getBool(
"rectangular-lane-cut");
133 const bool openDriveOutput = oc.
isSet(
"opendrive-output");
140 const double advanceStopLine = oc.
exists(
"opendrive-files") && oc.
isSet(
"opendrive-files") ? oc.
getFloat(
"opendrive.advance-stopline") : 0;
143 #ifdef DEBUG_NODE_SHAPE
145 std::cout <<
"\ncomputeNodeShapeDefault node " <<
myNode.
getID() <<
" simple=" << simpleContinuation <<
" useDefaultRadius=" << useDefaultRadius <<
" radius=" <<
myRadius <<
"\n";
150 EdgeVector::const_iterator i;
152 std::map<NBEdge*, std::set<NBEdge*> > same;
165 if (newAll.size() < 2) {
174 std::map<NBEdge*, double> distances;
175 std::map<NBEdge*, bool> myExtended;
177 for (i = newAll.begin(); i != newAll.end(); ++i) {
178 EdgeVector::const_iterator cwi = i;
179 EdgeVector::const_iterator ccwi = i;
182 initNeighbors(newAll, i, geomsCW, geomsCCW, cwi, ccwi, cad, ccad);
183 assert(geomsCCW.find(*i) != geomsCCW.end());
184 assert(geomsCW.find(*ccwi) != geomsCW.end());
185 assert(geomsCW.find(*cwi) != geomsCW.end());
191 (simpleContinuation && fabs(ccad - cad) < (
double) 0.1)
194 || (!simpleContinuation && fabs(ccad - cad) <
DEG2RAD(22.5)))
198 if (myExtended.find(*ccwi) != myExtended.end()) {
199 p = geomsCCW[*ccwi][0];
200 p.
add(geomsCW[*ccwi][0]);
202 #ifdef DEBUG_NODE_SHAPE
204 std::cout <<
" extended: p=" << p <<
" angle=" << (ccad - cad) <<
"\n";
208 p = geomsCCW[*ccwi][0];
209 p.
add(geomsCW[*ccwi][0]);
210 p.
add(geomsCCW[*i][0]);
211 p.
add(geomsCW[*i][0]);
213 #ifdef DEBUG_NODE_SHAPE
215 std::cout <<
" unextended: p=" << p <<
" angle=" << (ccad - cad) <<
"\n";
221 geomsCCW[*i].nearest_offset_to_point2D(p),
222 geomsCW[*i].nearest_offset_to_point2D(p));
234 (*i)->setGeometry(g);
236 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
237 geomsCCW[*i].extrapolate(
EXT);
238 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
239 geomsCW[*i].extrapolate(
EXT);
242 myExtended[*i] =
true;
243 #ifdef DEBUG_NODE_SHAPE
245 std::cout <<
" extending (dist=" << dist <<
")\n";
249 if (!simpleContinuation) {
253 double radius2 = fabs(ccad - cad) * (*i)->getNumLanes();
254 if (radius2 > NUMERICAL_EPS || openDriveOutput) {
255 radius2 =
MAX2(0.15, radius2);
262 radius2 =
MAX2(radius2, width / 2);
265 #ifdef DEBUG_NODE_SHAPE
267 std::cout <<
" using radius=" << radius2 <<
" ccad=" << ccad <<
" cad=" << cad <<
"\n";
271 distances[*i] = dist;
277 const bool ccwCloser = ccad < cad;
280 const bool neighLargeTurn = ccwCloser ? ccwLargeTurn : cwLargeTurn;
281 const bool neigh2LargeTurn = ccwCloser ? cwLargeTurn : ccwLargeTurn;
283 const PositionVector& currGeom = ccwCloser ? geomsCCW[*i] : geomsCW[*i];
285 const PositionVector& currGeom2 = ccwCloser ? geomsCW[*i] : geomsCCW[*i];
287 const PositionVector& neighGeom = ccwCloser ? geomsCW[*ccwi] : geomsCCW[*cwi];
289 const PositionVector& neighGeom2 = ccwCloser ? geomsCCW[*cwi] : geomsCW[*ccwi];
290 #ifdef DEBUG_NODE_SHAPE
292 std::cout <<
" i=" << (*i)->getID() <<
" neigh=" << (*ccwi)->getID() <<
" neigh2=" << (*cwi)->getID() <<
"\n";
293 std::cout <<
" ccwCloser=" << ccwCloser
294 <<
"\n currGeom=" << currGeom <<
" neighGeom=" << neighGeom
295 <<
"\n currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2
299 if (!simpleContinuation) {
302 #ifdef DEBUG_NODE_SHAPE
304 std::cout <<
" neigh intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
"\n";
307 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
310 const double farAngleDist = ccwCloser ? cad : ccad;
311 double a1 = distances[*i];
313 #ifdef DEBUG_NODE_SHAPE
315 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";
322 distances[*i] =
MAX2(a1, a2);
323 }
else if (ccad >
DEG2RAD(90. + 45.) && cad >
DEG2RAD(90. + 45.)) {
325 }
else if (farAngleDist <
DEG2RAD(135) || (fabs(
RAD2DEG(farAngleDist) - 180) > 1 && fabs(a2 - a1) < 10)) {
326 distances[*i] =
MAX2(a1, a2);
328 #ifdef DEBUG_NODE_SHAPE
330 std::cout <<
" a1=" << a1 <<
" a2=" << a2 <<
" dist=" << distances[*i] <<
"\n";
335 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
337 #ifdef DEBUG_NODE_SHAPE
339 std::cout <<
" neigh2 intersects dist=" << distances[*i] <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
344 #ifdef DEBUG_NODE_SHAPE
346 std::cout <<
" no intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
355 distances[*i] = (double)
EXT;
359 if (useDefaultRadius && sCurveStretch > 0) {
361 if (sCurveWidth > 0) {
362 const double sCurveRadius =
myRadius + sCurveWidth /
SUMO_const_laneWidth * sCurveStretch * pow((*i)->getSpeed(), 2 + sCurveStretch) / 1000;
363 const double stretch =
EXT + sCurveRadius - distances[*i];
365 distances[*i] += stretch;
367 const double shorten = distances[*i] -
EXT;
368 (*i)->shortenGeometryAtNode(&
myNode, shorten);
369 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
370 (*k)->shortenGeometryAtNode(&
myNode, shorten);
372 #ifdef DEBUG_NODE_SHAPE
374 std::cout <<
" stretching junction: sCurveWidth=" << sCurveWidth <<
" sCurveRadius=" << sCurveRadius <<
" stretch=" << stretch <<
" dist=" << distances[*i] <<
"\n";
382 for (
NBEdge*
const edge : newAll) {
383 if (distances.find(edge) == distances.end()) {
385 distances[edge] =
EXT;
389 const double off =
EXT - NUMERICAL_EPS;
393 for (
NBEdge*
const edge : newAll) {
394 if (distances[edge] < off && edge->hasDefaultGeometryEndpointAtNode(&
myNode)) {
395 for (EdgeVector::const_iterator j = newAll.begin(); j != newAll.end(); ++j) {
396 if (distances[*j] > off && (*j)->hasDefaultGeometryEndpointAtNode(&
myNode) && distances[edge] + distances[*j] < minDistSum) {
398 if (angleDiff > 160 || angleDiff < 20) {
399 #ifdef DEBUG_NODE_SHAPE
401 std::cout <<
" increasing dist for i=" << edge->getID() <<
" because of j=" << (*j)->getID() <<
" jDist=" << distances[*j]
402 <<
" oldI=" << distances[edge] <<
" newI=" << minDistSum - distances[*j]
403 <<
" angleDiff=" << angleDiff
404 <<
" geomI=" << edge->getGeometry() <<
" geomJ=" << (*j)->getGeometry() <<
"\n";
407 distances[edge] = minDistSum - distances[*j];
417 for (i = newAll.begin(); i != newAll.end(); ++i) {
421 double offset = distances[*i];
422 if (!(*i)->hasDefaultGeometryEndpointAtNode(&
myNode)) {
424 if (advanceStopLine > 0 && offset <
EXT) {
425 #ifdef DEBUG_NODE_SHAPE
426 std::cout <<
" i=" << (*i)->getID() <<
" offset=" << offset <<
" advanceStopLine=" << advanceStopLine <<
"\n";
429 (*i)->extendGeometryAtNode(&
myNode, advanceStopLine);
430 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
431 (*k)->extendGeometryAtNode(&
myNode, advanceStopLine);
434 offset =
MAX2(
EXT - advanceStopLine, offset);
438 offset = (double) - .1;
442 if (i != newAll.begin()) {
450 #ifdef DEBUG_NODE_SHAPE
452 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";
455 (*i)->setNodeBorder(&
myNode, p, p2, rectangularCut);
456 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
457 (*k)->setNodeBorder(&
myNode, p, p2, rectangularCut);
461 ret.
append(
getSmoothCorner(geomsCW[*(newAll.end() - 1)], geomsCCW[*newAll.begin()], ret[-1], ret[0], cornerDetail));
462 #ifdef DEBUG_NODE_SHAPE
464 std::cout <<
" final shape=" << ret <<
"\n";
474 double result = intersections[0];
475 for (std::vector<double>::iterator it = intersections.begin() + 1; it != intersections.end(); ++it) {
476 if (fabs(*it - offset) < fabs(result - offset)) {
485 std::map<
NBEdge*, std::set<NBEdge*> >& same)
const {
494 for (
NBEdge* e2s : same[e2]) {
499 for (
NBEdge* e1s : same[e1]) {
500 if ((e2s->getPermissions() & e1s->getPermissions() &
SVC_LARGE_TURN) != 0
501 && (e2s->getToNode() == e1s->getFromNode() || e1s->getToNode() == e2s->getFromNode())) {
506 for (
NBEdge* e1s : same[e1]) {
520 if (cornerDetail > 0) {
523 #ifdef DEBUG_SMOOTH_CORNERS
525 std::cout <<
" begLength=" << begShape2.
length2D() <<
" begSplit=" << begSplit <<
"\n";
528 if (begSplit > POSITION_EPS && begSplit < begShape2.
length2D() - POSITION_EPS) {
529 begShape2 = begShape2.
splitAt(begSplit,
true).first;
535 #ifdef DEBUG_SMOOTH_CORNERS
537 std::cout <<
" endLength=" << endShape2.
length2D() <<
" endSplit=" << endSplit <<
"\n";
540 if (endSplit > POSITION_EPS && endSplit < endShape2.
length2D() - POSITION_EPS) {
541 endShape2 = endShape2.
splitAt(endSplit,
true).second;
548 #ifdef DEBUG_SMOOTH_CORNERS
550 std::cout <<
"getSmoothCorner begPoint=" << begPoint <<
" endPoint=" << endPoint
551 <<
" begShape=" << begShape <<
" endShape=" << endShape
552 <<
" begShape2=" << begShape2 <<
" endShape2=" << endShape2
556 if (begShape2.size() < 2 || endShape2.size() < 2) {
560 NBNode* recordError =
nullptr;
561 #ifdef DEBUG_SMOOTH_CORNERS
563 std::cout <<
" angle=" <<
RAD2DEG(angle) <<
"\n";
574 #ifdef DEBUG_SMOOTH_CORNERS
576 std::cout <<
" curve=" << curve <<
" curveLength=" << curve.
length2D() <<
" dist=" << begPoint.
distanceTo2D(endPoint) <<
" curvature=" << curvature <<
"\n";
579 if (curvature > 2 && angle >
DEG2RAD(85)) {
583 if (curve.size() > 2) {
584 curve.erase(curve.begin());
597 for (
NBEdge*
const edge : edges) {
600 geomsCCW[edge] = edge->getCCWBoundaryLine(
myNode);
602 WRITE_WARNING(
"While computing intersection geometry at junction '" +
myNode.
getID() +
"': " + std::string(e.what()));
603 geomsCCW[edge] = edge->getGeometry();
606 geomsCW[edge] = edge->getCWBoundaryLine(
myNode);
608 WRITE_WARNING(
"While computing intersection geometry at junction '" +
myNode.
getID() +
"': " + std::string(e.what()));
609 geomsCW[edge] = edge->getGeometry();
612 if (geomsCCW[edge].length2D() < NUMERICAL_EPS) {
613 geomsCCW[edge] = edge->getGeometry();
615 if (geomsCW[edge].length2D() < NUMERICAL_EPS) {
616 geomsCW[edge] = edge->getGeometry();
619 geomsCCW[edge].extrapolate2D(
EXT,
true);
620 geomsCW[edge].extrapolate2D(
EXT,
true);
621 geomsCCW[edge].extrapolate(
EXT2,
false,
true);
622 geomsCW[edge].extrapolate(
EXT2,
false,
true);
630 const double angleChangeLookahead = 35;
632 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); i++) {
633 EdgeVector::const_iterator j;
634 if (i == edges.end() - 1) {
639 const bool incoming = (*i)->getToNode() == &
myNode;
640 const bool incoming2 = (*j)->getToNode() == &
myNode;
641 const bool differentDirs = (incoming != incoming2);
642 const bool sameGeom = (*i)->getGeometry() == (differentDirs ? (*j)->getGeometry().reverse() : (*j)->getGeometry());
645 const double angle1further = (g1.size() > 2 && g1[0].distanceTo2D(g1[1]) < angleChangeLookahead ?
647 const double angle2further = (g2.size() > 2 && g2[0].distanceTo2D(g2[1]) < angleChangeLookahead ?
651 const bool ambiguousGeometry = ((angleDiff > 0 && angleDiffFurther < 0) || (angleDiff < 0 && angleDiffFurther > 0));
656 #ifdef DEBUG_NODE_SHAPE
658 std::cout <<
" checkSameDirection " << (*i)->getID() <<
" " << (*j)->getID()
659 <<
" diffDirs=" << differentDirs
660 <<
" isOpposite=" << (differentDirs && foundOpposite.count(*i) == 0)
661 <<
" angleDiff=" << angleDiff
662 <<
" ambiguousGeometry=" << ambiguousGeometry
668 if (sameGeom || fabs(angleDiff) <
DEG2RAD(20)) {
669 const bool isOpposite = differentDirs && foundOpposite.count(*i) == 0;
671 foundOpposite.insert(*i);
672 foundOpposite.insert(*j);
676 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
682 for (std::set<NBEdge*>::iterator k = same[*j].begin(); k != same[*j].end(); ++k) {
690 #ifdef DEBUG_NODE_SHAPE
692 std::cout <<
" joinedSameDirectionEdges " << (*i)->getID() <<
" " << (*j)->getID() <<
" isOpposite=" << isOpposite <<
" ambiguousGeometry=" << ambiguousGeometry <<
"\n";
724 double endAngleDiff = 0;
725 if (geom1.size() >= 2 && geom2.size() >= 2) {
728 geom2.
angleAt2D((
int)geom2.size() - 2))));
731 std::vector<double> distances = geom1.
distances(geom2,
true);
734 const bool curvingTowards = geom1[0].distanceTo2D(geom2[0]) > minDistanceThreshold && minDist < minDistanceThreshold;
735 const bool onTop = (maxDist - POSITION_EPS < minDistanceThreshold) && endAngleDiff < 30;
740 #ifdef DEBUG_NODE_SHAPE
742 std::cout <<
" badIntersect: onTop=" << onTop <<
" curveTo=" << curvingTowards <<
" intersects=" << intersects
743 <<
" endAngleDiff=" << endAngleDiff
744 <<
" geom1=" << geom1 <<
" geom2=" << geom2
745 <<
" distances=" <<
toString(distances) <<
" minDist=" << minDist <<
" maxDist=" << maxDist <<
" thresh=" << minDistanceThreshold
746 <<
" intersectPos=" << intersect
750 return onTop || curvingTowards || !intersects;
757 std::map<
NBEdge*, std::set<NBEdge*> >& same,
764 auto e2NewAll = std::find(newAll.begin(), newAll.end(), e1);
765 #ifdef DEBUG_NODE_SHAPE
766 if (
DEBUGCOND) std::cout <<
"computeUniqueDirectionList e1=" << e1->getID()
767 <<
" deleted=" << (e2NewAll == newAll.end())
770 if (e2NewAll == newAll.end()) {
773 auto e1It = std::find(all.begin(), all.end(), e1);
779 for (
NBEdge* e2 : same[e1]) {
780 #ifdef DEBUG_NODE_SHAPE
782 std::cout <<
" e2=" << e2->getID() <<
"\n";
785 auto e2It = std::find(all.begin(), all.end(), e2);
786 if (e2It + 1 == bestCCW || (e2It == (all.end() - 1) && bestCCW == all.begin())) {
789 #ifdef DEBUG_NODE_SHAPE
791 std::cout <<
" bestCCW=" << e2->getID() <<
"\n";
794 }
else if (bestCW + 1 == e2It || (bestCW == (all.end() - 1) && e2It == all.begin())) {
797 #ifdef DEBUG_NODE_SHAPE
799 std::cout <<
" bestCW=" << e2->getID() <<
"\n";
805 if (bestCW != e1It) {
806 geomsCW[e1] = geomsCW[*bestCW];
809 if (bestCCW != e1It) {
810 geomsCCW[e1] = geomsCCW[*bestCCW];
814 for (
NBEdge* e2 : same[e1]) {
815 auto e2NewAllIt = std::find(newAll.begin(), newAll.end(), e2);
816 if (e2NewAllIt != newAll.end()) {
817 newAll.erase(e2NewAllIt);
821 #ifdef DEBUG_NODE_SHAPE
823 std::cout <<
" newAll:\n";
824 for (
NBEdge* e : newAll) {
825 std::cout <<
" " << e->getID() <<
" geomCCW=" << geomsCCW[e] <<
" geomsCW=" << geomsCW[e] <<
"\n";
837 EdgeVector::const_iterator& cwi,
838 EdgeVector::const_iterator& ccwi,
841 const double twoPI = (double)(2 *
M_PI);
844 if (cwi == edges.end()) {
845 std::advance(cwi, -((
int)edges.size()));
848 if (ccwi == edges.begin()) {
849 std::advance(ccwi, edges.size() - 1);
854 const double angleCurCCW = geomsCCW[*current].angleAt2D(0);
855 const double angleCurCW = geomsCW[*current].angleAt2D(0);
856 const double angleCCW = geomsCW[*ccwi].angleAt2D(0);
857 const double angleCW = geomsCCW[*cwi].angleAt2D(0);
858 ccad = angleCCW - angleCurCCW;
862 cad = angleCurCW - angleCW;
872 #ifdef DEBUG_NODE_SHAPE
874 std::cout <<
"computeNodeShapeSmall node=" <<
myNode.
getID() <<
"\n";
882 Position delta = edgebound1[1] - edgebound1[0];
883 delta.
set(-delta.
y(), delta.
x());
898 e->resetNodeBorder(&
myNode);
909 const double radius = oc.
getFloat(
"default.junctions.radius");
910 const double smallRadius = oc.
getFloat(
"junctions.small-radius");
911 double maxRightAngle = 0;
912 double extraWidthRight = 0;
913 double maxLeftAngle = 0;
914 double extraWidthLeft = 0;
916 int totalWideLanesIn = 0;
919 for (
int i = 0; i < in->getNumLanes(); i++) {
924 totalWideLanesIn += wideLanesIn;
926 if ((in->getPermissions() & out->getPermissions() &
SVC_LARGE_TURN) != 0) {
931 in->getGeometry().angleAt2D(-2),
932 out->getGeometry().angleAt2D(0));
934 if (maxRightAngle < -angle) {
935 maxRightAngle = -angle;
939 if (maxLeftAngle < angle) {
940 maxLeftAngle = angle;
945 while (*pIn != out) {
946 extraWidthLeft += (*pIn)->getTotalWidth();
949 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" extra=" << (*pIn)->getID() <<
" extraWidthLeft=" << extraWidthLeft <<
"\n";
956 int wideLanesOut = 0;
957 for (
int i = 0; i < out->getNumLanes(); i++) {
964 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" wideLanesIn=" << wideLanesIn <<
" wideLanesOut=" << wideLanesOut <<
"\n";
967 laneDelta =
MAX2(laneDelta, abs(wideLanesOut - wideLanesIn));
973 int totalWideLanesOut = 0;
975 for (
int i = 0; i < out->getNumLanes(); i++) {
981 if (totalWideLanesIn == totalWideLanesOut) {
988 double result = radius;
990 double maxTurnAngle = maxRightAngle;
991 double extraWidth = extraWidthRight;
992 if (maxRightAngle <
DEG2RAD(5)) {
993 maxTurnAngle = maxLeftAngle;
994 extraWidth = extraWidthLeft;
996 const double minRadius = maxTurnAngle >=
DEG2RAD(30) ?
MIN2(smallRadius, radius) : smallRadius;
1000 result = radius * tan(0.5 *
MIN2(0.5 *
M_PI, maxTurnAngle)) - extraWidth;
1002 result =
MAX2(minRadius, result);
1005 std::cout <<
"getDefaultRadius n=" <<
myNode.
getID()
1006 <<
" r=" << radius <<
" sr=" << smallRadius
1007 <<
" mr=" << minRadius
1008 <<
" laneDelta=" << laneDelta
1009 <<
" rightA=" <<
RAD2DEG(maxRightAngle)
1010 <<
" leftA=" <<
RAD2DEG(maxLeftAngle)
1011 <<
" maxA=" <<
RAD2DEG(maxTurnAngle)
1012 <<
" extraWidth=" << extraWidth
1013 <<
" result=" << result <<
"\n";
1024 while (lane < e->getNumLanes() && e->
getPermissions(lane) == 0) {
1028 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 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.
static const double UNSPECIFIED_WIDTH
unspecified lane width
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)
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
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.
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.
const PositionVector compute()
Computes the shape of the assigned junction.
~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 NBNode & myNode
The node to compute the geometry for.
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 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)