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;
633 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); i++) {
634 EdgeVector::const_iterator j;
635 if (i == edges.end() - 1) {
640 const bool incoming = (*i)->getToNode() == &
myNode;
641 const bool incoming2 = (*j)->getToNode() == &
myNode;
642 const bool differentDirs = (incoming != incoming2);
643 const bool sameGeom = (*i)->getGeometry() == (differentDirs ? (*j)->getGeometry().reverse() : (*j)->getGeometry());
646 const double angle1further = (g1.size() > 2 && g1[0].distanceTo2D(g1[1]) < angleChangeLookahead ?
648 const double angle2further = (g2.size() > 2 && g2[0].distanceTo2D(g2[1]) < angleChangeLookahead ?
652 const bool ambiguousGeometry = ((angleDiff > 0 && angleDiffFurther < 0) || (angleDiff < 0 && angleDiffFurther > 0));
657#ifdef DEBUG_NODE_SHAPE
659 std::cout <<
" checkSameDirection " << (*i)->getID() <<
" " << (*j)->getID()
660 <<
" diffDirs=" << differentDirs
661 <<
" isOpposite=" << (differentDirs && foundOpposite.count(*i) == 0)
662 <<
" angleDiff=" << angleDiff
663 <<
" ambiguousGeometry=" << ambiguousGeometry
669 if (sameGeom || fabs(angleDiff) <
DEG2RAD(20)) {
670 const bool isOpposite = differentDirs && foundOpposite.count(*i) == 0;
672 foundOpposite.insert(*i);
673 foundOpposite.insert(*j);
677 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
683 for (std::set<NBEdge*>::iterator k = same[*j].begin(); k != same[*j].end(); ++k) {
691#ifdef DEBUG_NODE_SHAPE
693 std::cout <<
" joinedSameDirectionEdges " << (*i)->getID() <<
" " << (*j)->getID() <<
" isOpposite=" << isOpposite <<
" ambiguousGeometry=" << ambiguousGeometry <<
"\n";
725 double endAngleDiff = 0;
726 if (geom1.size() >= 2 && geom2.size() >= 2) {
729 geom2.
angleAt2D((
int)geom2.size() - 2))));
732 std::vector<double> distances = geom1.
distances(geom2,
true);
735 const bool curvingTowards = geom1[0].distanceTo2D(geom2[0]) > minDistanceThreshold && minDist < minDistanceThreshold;
736 const bool onTop = (maxDist - POSITION_EPS < minDistanceThreshold) && endAngleDiff < 30;
741#ifdef DEBUG_NODE_SHAPE
743 std::cout <<
" badIntersect: onTop=" << onTop <<
" curveTo=" << curvingTowards <<
" intersects=" << intersects
744 <<
" endAngleDiff=" << endAngleDiff
745 <<
" geom1=" << geom1 <<
" geom2=" << geom2
746 <<
" distances=" <<
toString(distances) <<
" minDist=" << minDist <<
" maxDist=" << maxDist <<
" thresh=" << minDistanceThreshold
747 <<
" intersectPos=" << intersect
751 return onTop || curvingTowards || !intersects;
758 std::map<
NBEdge*, std::set<NBEdge*> >& same,
765 auto e2NewAll = std::find(newAll.begin(), newAll.end(), e1);
766#ifdef DEBUG_NODE_SHAPE
767 if (
DEBUGCOND) std::cout <<
"computeUniqueDirectionList e1=" << e1->getID()
768 <<
" deleted=" << (e2NewAll == newAll.end())
771 if (e2NewAll == newAll.end()) {
774 auto e1It = std::find(all.begin(), all.end(), e1);
780 for (
NBEdge* e2 : same[e1]) {
781#ifdef DEBUG_NODE_SHAPE
783 std::cout <<
" e2=" << e2->getID() <<
"\n";
786 auto e2It = std::find(all.begin(), all.end(), e2);
787 if (e2It + 1 == bestCCW || (e2It == (all.end() - 1) && bestCCW == all.begin())) {
790#ifdef DEBUG_NODE_SHAPE
792 std::cout <<
" bestCCW=" << e2->getID() <<
"\n";
795 }
else if (bestCW + 1 == e2It || (bestCW == (all.end() - 1) && e2It == all.begin())) {
798#ifdef DEBUG_NODE_SHAPE
800 std::cout <<
" bestCW=" << e2->getID() <<
"\n";
806 if (bestCW != e1It) {
807 geomsCW[e1] = geomsCW[*bestCW];
810 if (bestCCW != e1It) {
811 geomsCCW[e1] = geomsCCW[*bestCCW];
815 for (
NBEdge* e2 : same[e1]) {
816 auto e2NewAllIt = std::find(newAll.begin(), newAll.end(), e2);
817 if (e2NewAllIt != newAll.end()) {
818 newAll.erase(e2NewAllIt);
822#ifdef DEBUG_NODE_SHAPE
824 std::cout <<
" newAll:\n";
825 for (
NBEdge* e : newAll) {
826 std::cout <<
" " << e->getID() <<
" geomCCW=" << geomsCCW[e] <<
" geomsCW=" << geomsCW[e] <<
"\n";
838 EdgeVector::const_iterator& cwi,
839 EdgeVector::const_iterator& ccwi,
842 const double twoPI = (double)(2 *
M_PI);
845 if (cwi == edges.end()) {
846 std::advance(cwi, -((
int)edges.size()));
849 if (ccwi == edges.begin()) {
850 std::advance(ccwi, edges.size() - 1);
855 const double angleCurCCW = geomsCCW[*current].angleAt2D(0);
856 const double angleCurCW = geomsCW[*current].angleAt2D(0);
857 const double angleCCW = geomsCW[*ccwi].angleAt2D(0);
858 const double angleCW = geomsCCW[*cwi].angleAt2D(0);
859 ccad = angleCCW - angleCurCCW;
863 cad = angleCurCW - angleCW;
873#ifdef DEBUG_NODE_SHAPE
875 std::cout <<
"computeNodeShapeSmall node=" <<
myNode.
getID() <<
"\n";
883 Position delta = edgebound1[1] - edgebound1[0];
884 delta.
set(-delta.
y(), delta.
x());
899 e->resetNodeBorder(&
myNode);
910 const double radius = oc.
getFloat(
"default.junctions.radius");
911 const double smallRadius = oc.
getFloat(
"junctions.small-radius");
912 double maxRightAngle = 0;
913 double extraWidthRight = 0;
914 double maxLeftAngle = 0;
915 double extraWidthLeft = 0;
917 int totalWideLanesIn = 0;
920 for (
int i = 0; i < in->getNumLanes(); i++) {
925 totalWideLanesIn += wideLanesIn;
927 if ((in->getPermissions() & out->getPermissions() &
SVC_LARGE_TURN) != 0) {
932 in->getGeometry().angleAt2D(-2),
933 out->getGeometry().angleAt2D(0));
935 if (maxRightAngle < -angle) {
936 maxRightAngle = -angle;
940 if (maxLeftAngle < angle) {
941 maxLeftAngle = angle;
946 while (*pIn != out) {
947 extraWidthLeft += (*pIn)->getTotalWidth();
950 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" extra=" << (*pIn)->getID() <<
" extraWidthLeft=" << extraWidthLeft <<
"\n";
957 int wideLanesOut = 0;
958 for (
int i = 0; i < out->getNumLanes(); i++) {
965 std::cout <<
" in=" << in->getID() <<
" out=" << out->getID() <<
" wideLanesIn=" << wideLanesIn <<
" wideLanesOut=" << wideLanesOut <<
"\n";
968 laneDelta =
MAX2(laneDelta, abs(wideLanesOut - wideLanesIn));
974 int totalWideLanesOut = 0;
976 for (
int i = 0; i < out->getNumLanes(); i++) {
982 if (totalWideLanesIn == totalWideLanesOut) {
989 double result = radius;
991 double maxTurnAngle = maxRightAngle;
992 double extraWidth = extraWidthRight;
993 if (maxRightAngle <
DEG2RAD(5)) {
994 maxTurnAngle = maxLeftAngle;
995 extraWidth = extraWidthLeft;
997 const double minRadius = maxTurnAngle >=
DEG2RAD(30) ?
MIN2(smallRadius, radius) : smallRadius;
1001 result = radius * tan(0.5 *
MIN2(0.5 *
M_PI, maxTurnAngle)) - extraWidth;
1003 result =
MAX2(minRadius, result);
1006 std::cout <<
"getDefaultRadius n=" <<
myNode.
getID()
1007 <<
" r=" << radius <<
" sr=" << smallRadius
1008 <<
" mr=" << minRadius
1009 <<
" laneDelta=" << laneDelta
1010 <<
" rightA=" <<
RAD2DEG(maxRightAngle)
1011 <<
" leftA=" <<
RAD2DEG(maxLeftAngle)
1012 <<
" maxA=" <<
RAD2DEG(maxTurnAngle)
1013 <<
" extraWidth=" << extraWidth
1014 <<
" result=" << result <<
"\n";
1025 while (lane < e->getNumLanes() && e->
getPermissions(lane) == 0) {
1029 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.
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.
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)