46 #ifdef CHECK_MEMORY_LEAKS
48 #endif // CHECK_MEMORY_LEAKS
51 #define DEBUGCOND (myNode.getID() == "disabled")
68 bool singleDirection =
false;
70 singleDirection =
true;
74 singleDirection =
true;
77 if (singleDirection) {
90 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
92 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) {
96 maxAngle =
MAX2(ad, maxAngle);
100 if (maxAngle > 22.5) {
108 if (ret.size() < 3) {
117 assert(l1[0].distanceTo2D(l1[1]) >= 100.);
118 assert(l2[0].distanceTo2D(l2[1]) >= 100.);
121 tmp.push_back(l1[1]);
123 tmp[1].set(-tmp[1].y(), tmp[1].x());
131 l2.erase(l2.begin(), l2.begin() + (l2.size() - tl2.size()));
152 #ifdef DEBUG_NODE_SHAPE
154 std::cout <<
"\ncomputeNodeShapeDefault node " <<
myNode.
getID() <<
" simple=" << simpleContinuation <<
" radius=" << radius <<
"\n";
159 EdgeVector::const_iterator i;
161 std::map<NBEdge*, std::set<NBEdge*> > same;
171 if (newAll.size() < 2) {
180 std::map<NBEdge*, SUMOReal> 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) < (
SUMOReal) 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));
240 (*i)->setGeometry(g);
242 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
243 geomsCCW[*i].extrapolate(100);
244 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
245 geomsCW[*i].extrapolate(100);
248 myExtended[*i] =
true;
249 #ifdef DEBUG_NODE_SHAPE
251 std::cout <<
" extending (dist=" << dist <<
")\n";
255 if (!simpleContinuation) {
259 SUMOReal radius2 = fabs(ccad - cad) * (*i)->getNumLanes();
264 #ifdef DEBUG_NODE_SHAPE
266 std::cout <<
" using radius=" << fabs(ccad - cad) * (*i)->getNumLanes() <<
" ccad=" << ccad <<
" cad=" << cad <<
"\n";
270 distances[*i] = dist;
276 const bool ccwCloser = ccad < cad;
278 const PositionVector& currGeom = ccwCloser ? geomsCCW[*i] : geomsCW[*i];
280 const PositionVector& currGeom2 = ccwCloser ? geomsCW[*i] : geomsCCW[*i];
282 const PositionVector& neighGeom = ccwCloser ? geomsCW[*ccwi] : geomsCCW[*cwi];
284 const PositionVector& neighGeom2 = ccwCloser ? geomsCCW[*cwi] : geomsCW[*ccwi];
285 #ifdef DEBUG_NODE_SHAPE
287 std::cout <<
" i=" << (*i)->getID() <<
" neigh=" << (*ccwi)->getID() <<
" neigh2=" << (*cwi)->getID() <<
"\n";
290 if (!simpleContinuation) {
293 #ifdef DEBUG_NODE_SHAPE
295 std::cout <<
" neigh intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
"\n";
298 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
299 const SUMOReal farAngleDist = ccwCloser ? cad : ccad;
302 #ifdef DEBUG_NODE_SHAPE
304 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";
308 SUMOReal mmin =
MIN2(distances[*cwi], distances[*ccwi]);
309 if (mmin > 100 && mmin < 205) {
312 }
else if (fabs(a2 - a1) < 10 || farAngleDist <
DEG2RAD(135)) {
313 distances[*i] =
MAX2(a1, a2);
315 #ifdef DEBUG_NODE_SHAPE
317 std::cout <<
" a1=" << a1 <<
" a2=" << a2 <<
" dist=" << distances[*i] <<
"\n";
322 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
324 #ifdef DEBUG_NODE_SHAPE
326 std::cout <<
" neigh2 intersects dist=" << distances[*i] <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
330 distances[*i] = 100 + radius;
331 #ifdef DEBUG_NODE_SHAPE
333 std::cout <<
" no intersects dist=" << distances[*i] <<
" currGeom=" << currGeom <<
" neighGeom=" << neighGeom <<
" currGeom2=" << currGeom2 <<
" neighGeom2=" << neighGeom2 <<
"\n";
346 if (defaultRadius && sCurveStretch > 0) {
348 if (sCurveWidth > 0) {
349 const SUMOReal sCurveRadius = radius + sCurveWidth /
SUMO_const_laneWidth * sCurveStretch * pow((*i)->getSpeed(), 2 + sCurveStretch) / 1000;
350 distances[*i] =
MAX2(distances[*i], 100 + sCurveRadius);
353 #ifdef DEBUG_NODE_SHAPE
355 std::cout <<
" stretching junction: sCurveWidth=" << sCurveWidth <<
" sCurveRadius=" << sCurveRadius <<
" dist=" << distances[*i] <<
"\n";
362 for (i = newAll.begin(); i != newAll.end(); ++i) {
363 if (distances.find(*i) == distances.end()) {
371 for (i = newAll.begin(); i != newAll.end(); ++i) {
381 if (i != newAll.begin()) {
390 #ifdef DEBUG_NODE_SHAPE
392 std::cout <<
" build stopLine for i=" << (*i)->getID() <<
" offset=" << offset <<
" ccwBound=" << ccwBound <<
" cwBound=" << cwBound <<
"\n";
395 if (rectangularCut) {
396 (*i)->setNodeBorder(&
myNode, p);
397 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
398 (*k)->setNodeBorder(&
myNode, p);
403 ret.
append(
getSmoothCorner(geomsCW[*(newAll.end() - 1)], geomsCCW[*newAll.begin()], ret[-1], ret[0], cornerDetail));
412 for (std::vector<SUMOReal>::iterator it = intersections.begin() + 1; it != intersections.end(); ++it) {
413 if (fabs(*it - offset) < fabs(result - offset)) {
425 if (cornerDetail > 0) {
427 begShape[-1] = begPoint;
428 endShape[0] = endPoint;
430 if (curve.size() > 2) {
431 curve.erase(curve.begin());
443 EdgeVector::const_iterator i, j;
448 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
450 WRITE_WARNING(std::string(
"While computing intersection geometry: ") + std::string(e.what()));
451 geomsCCW[*i] = (*i)->getGeometry();
454 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
456 WRITE_WARNING(std::string(
"While computing intersection geometry: ") + std::string(e.what()));
457 geomsCW[*i] = (*i)->getGeometry();
462 ? (*i)->getCCWBoundaryLine(
myNode)
463 : (*i)->getCWBoundaryLine(
myNode);
464 geomsCCW[*i].extrapolate2D(100,
true);
465 geomsCW[*i].extrapolate2D(100,
true);
468 geomsCCW[*j] = (*j)->getCCWBoundaryLine(
myNode);
469 geomsCW[*j] = (*j)->getCWBoundaryLine(
myNode);
472 ? (*j)->getCCWBoundaryLine(
myNode)
473 : (*j)->getCWBoundaryLine(
myNode);
474 geomsCCW[*j].extrapolate2D(100,
true);
475 geomsCW[*j].extrapolate2D(100,
true);
481 const SUMOReal angleChangeLookahead = 35;
484 EdgeVector::const_iterator j;
490 const bool incoming = (*i)->getToNode() == &
myNode;
491 const bool incoming2 = (*j)->getToNode() == &
myNode;
492 const Position positionAtNode = (*i)->getGeometry()[incoming ? -1 : 0];
493 const Position positionAtNode2 = (*j)->getGeometry()[incoming2 ? -1 : 0];
496 const SUMOReal angle1further = (g1.size() > 2 && g1[0].distanceTo2D(g1[1]) < angleChangeLookahead ?
498 const SUMOReal angle2further = (g2.size() > 2 && g2[0].distanceTo2D(g2[1]) < angleChangeLookahead ?
502 const bool ambiguousGeometry = ((angleDiff > 0 && angleDiffFurther < 0) || (angleDiff < 0 && angleDiffFurther > 0));
503 const bool differentDirs = (incoming != incoming2);
508 if (fabs(angleDiff) <
DEG2RAD(20)) {
509 const bool isOpposite = differentDirs && foundOpposite.count(*i) == 0;
511 foundOpposite.insert(*i);
512 foundOpposite.insert(*j);
514 if (isOpposite || ambiguousGeometry ||
badIntersection(*i, *j, geomsCW[*i], geomsCCW[*j], 100)) {
516 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
522 for (std::set<NBEdge*>::iterator k = same[*j].begin(); k != same[*j].end(); ++k) {
530 #ifdef DEBUG_NODE_SHAPE
532 std::cout <<
" joinedSameDirectionEdges " << (*i)->getID() <<
" " << (*j)->getID() <<
" isOpposite=" << isOpposite <<
" ambiguousGeometry=" << ambiguousGeometry <<
"\n";
559 geom1 = geom1.reverse();
566 std::vector<SUMOReal> distances = geom1.
distances(geom2,
true);
570 const bool onTop = maxDist -
POSITION_EPS < minDistanceThreshold;
571 const bool curvingTowards = geom1[0].distanceTo2D(geom2[0]) > minDistanceThreshold && minDist < minDistanceThreshold;
572 const bool intersects = e1cw.
intersects(e2ccw);
573 return onTop || curvingTowards || !intersects;
579 std::map<
NBEdge*, std::set<NBEdge*> >& same,
587 for (EdgeVector::iterator i2 = newAll.begin(); i2 != newAll.end(); ++i2) {
588 std::set<NBEdge*> other = same[*i2];
589 for (std::set<NBEdge*>::const_iterator j = other.begin(); j != other.end(); ++j) {
590 EdgeVector::iterator k = find(newAll.begin(), newAll.end(), *j);
591 if (k != newAll.end()) {
594 geomsCW[*i2] = geomsCW[*j];
599 geomsCCW[*i2] = geomsCCW[*j];
620 EdgeVector::const_iterator& cwi,
621 EdgeVector::const_iterator& ccwi,
627 if (cwi == edges.end()) {
628 std::advance(cwi, -((
int)edges.size()));
631 if (ccwi == edges.begin()) {
632 std::advance(ccwi, edges.size() - 1);
637 const SUMOReal angleCurCCW = geomsCCW[*current].angleAt2D(0);
638 const SUMOReal angleCurCW = geomsCW[*current].angleAt2D(0);
639 const SUMOReal angleCCW = geomsCW[*ccwi].angleAt2D(0);
640 const SUMOReal angleCW = geomsCCW[*cwi].angleAt2D(0);
641 ccad = angleCCW - angleCurCCW;
645 cad = angleCurCW - angleCW;
655 #ifdef DEBUG_NODE_SHAPE
657 std::cout <<
"computeNodeShapeSmall node=" <<
myNode.
getID() <<
"\n";
661 EdgeVector::const_iterator i;
666 Position delta = edgebound1[1] - edgebound1[0];
667 delta.
set(-delta.
y(), delta.
x());
670 edgebound1.extrapolate2D(500);
672 if (cross.intersects(edgebound1)) {
673 Position np = cross.intersectionPosition2D(edgebound1);
677 if (cross.intersects(edgebound2)) {
678 Position np = cross.intersectionPosition2D(edgebound2);
SUMOReal getDisplacementError() const
compute the displacement error during s-curve computation
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
const SUMOReal SUMO_const_laneWidth
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
SUMOReal getRadius() const
Returns the turning radius of this node.
void add(const Position &pos)
Adds the given position to this one.
PositionVector getSmoothCorner(PositionVector begShape, PositionVector endShape, const Position &begPoint, const Position &endPoint, int cornerDetail)
Compute smoothed corner shape.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
PositionVector computeNodeShapeDefault(bool simpleContinuation)
Computes the node geometry Edges with the same direction are grouped. Then the node geometry is built...
bool intersects(const Position &p1, const Position &p2) const
Returns the information whether this list of points interesects the given line.
SUMOReal getTotalWidth() const
Returns the combined width of all lanes of this edge.
static T minValue(const std::vector< T > &v)
const NBNode & myNode
The node to compute the geometry for.
PositionVector getSubpartByIndex(int beginIndex, int count) const
get subpart of a position vector using index and a cout
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
std::map< NBEdge *, PositionVector > GeomsMap
static SUMOReal angleDiff(const SUMOReal angle1, const SUMOReal angle2)
Returns the difference of the second angle to the first angle in radiants.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
SUMOReal x() const
Returns the x-position.
Position positionAtOffset2D(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
#define WRITE_WARNING(msg)
static OptionsCont & getOptions()
Retrieves the options.
SUMOReal closestIntersection(const PositionVector &geom1, const PositionVector &geom2, SUMOReal offset)
return the intersection point closest to the given offset
PositionVector reverse() const
reverse position vector
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
void extrapolate2D(const SUMOReal val, const bool onlyFirst=false)
extrapolate position vector in two dimensions (Z is ignored)
NBNodeShapeComputer(const NBNode &node)
Constructor.
const std::string & getID() const
Returns the id.
SUMOReal length2D() const
Returns the length.
std::vector< SUMOReal > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
void push_front_noDoublePos(const Position &p)
insert in front a non double position
const Position & getPosition() const
Returns the position of this node.
std::set< NBEdge * > EdgeSet
A point in 2D or 3D with translation and scaling methods.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
SUMOReal z() const
Returns the z-position.
PositionVector compute()
Computes the shape of the assigned junction.
SUMOReal length() const
Returns the length.
NBNode * getToNode() const
Returns the destination node of the edge.
~NBNodeShapeComputer()
Destructor.
PositionVector computeNodeShapeSmall()
Computes the node geometry using normals.
SUMOReal angleAt2D(int pos) const
get angle in certain position of position vector
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, SUMOReal extrapolateBeg, SUMOReal extrapolateEnd, NBNode *recordError=0) const
Compute a smooth curve between the given geometries.
std::vector< NBEdge * > EdgeVector
EdgeVector computeUniqueDirectionList(std::map< NBEdge *, std::set< NBEdge * > > &same, GeomsMap &geomsCCW, GeomsMap &geomsCW)
Joins edges and computes ccw/cw boundaries.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
SUMOReal y() const
Returns the y-position.
static SUMOReal getMinAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
void set(SUMOReal x, SUMOReal y)
static void initNeighbors(const EdgeVector &edges, const EdgeVector::const_iterator ¤t, GeomsMap &geomsCW, GeomsMap &geomsCCW, EdgeVector::const_iterator &cwi, EdgeVector::const_iterator &ccwi, SUMOReal &cad, SUMOReal &ccad)
Initialize neighbors and angles.
void mul(SUMOReal val)
Multiplies both positions with the given value.
bool badIntersection(const NBEdge *e1, const NBEdge *e2, const PositionVector &e1cw, const PositionVector &e2ccw, SUMOReal distance)
void joinSameDirectionEdges(std::map< NBEdge *, std::set< NBEdge * > > &same, GeomsMap &geomsCCW, GeomsMap &geomsCW)
Joins edges and computes ccw/cw boundaries.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Represents a single node (junction) during network building.
bool isSimpleContinuation(bool checkLaneNumbers=true) const
void move2side(SUMOReal amount)
move position vector to side using certain ammount
static const SUMOReal UNSPECIFIED_RADIUS
unspecified lane width
void push_back_noDoublePos(const Position &p)
insert in back a non double position
void computeSameEnd(PositionVector &l1, PositionVector &l2)
static T maxValue(const std::vector< T > &v)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::vector< SUMOReal > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
void append(const PositionVector &v, SUMOReal sameThreshold=2.0)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.