46 #ifdef CHECK_MEMORY_LEAKS
48 #endif // CHECK_MEMORY_LEAKS
66 bool singleDirection =
false;
68 singleDirection =
true;
72 singleDirection =
true;
75 if (singleDirection) {
88 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
90 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) {
94 maxAngle =
MAX2(ad, maxAngle);
98 if (maxAngle > 22.5) {
106 if (ret.size() < 3) {
117 tmp.rotateAtP1(
M_PI / 2);
118 tmp.extrapolateBy2D(100);
149 EdgeVector::const_iterator i;
151 std::map<NBEdge*, std::set<NBEdge*> > same;
157 std::map<NBEdge*, NBEdge*> ccwBoundary;
158 std::map<NBEdge*, NBEdge*> cwBoundary;
161 ccwBoundary[*i] = *i;
168 if (newAll.size() < 2) {
177 std::map<NBEdge*, SUMOReal> distances;
178 std::map<NBEdge*, bool> myExtended;
180 for (i = newAll.begin(); i != newAll.end(); ++i) {
181 EdgeVector::const_iterator cwi = i;
182 EdgeVector::const_iterator ccwi = i;
185 initNeighbors(newAll, i, geomsCW, geomsCCW, cwi, ccwi, cad, ccad);
186 assert(geomsCCW.find(*i) != geomsCCW.end());
187 assert(geomsCW.find(*ccwi) != geomsCW.end());
188 assert(geomsCW.find(*cwi) != geomsCW.end());
194 (simpleContinuation && fabs(ccad - cad) < (
SUMOReal) 0.1)
197 || (!simpleContinuation && fabs(ccad - cad) <
DEG2RAD(22.5)))
201 if (myExtended.find(*ccwi) != myExtended.end()) {
202 p = geomsCCW[*ccwi][0];
203 p.
add(geomsCW[*ccwi][0]);
206 p = geomsCCW[*ccwi][0];
207 p.
add(geomsCW[*ccwi][0]);
208 p.
add(geomsCCW[*i][0]);
209 p.
add(geomsCW[*i][0]);
213 SUMOReal dist = geomsCCW[*i].nearest_offset_to_point2D(p);
225 (*i)->setGeometry(g);
227 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
228 geomsCCW[*i].extrapolate(100);
229 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
230 geomsCW[*i].extrapolate(100);
233 myExtended[*i] =
true;
235 if (!simpleContinuation) {
243 distances[*i] = dist;
249 const bool ccwCloser = ccad < cad;
251 const PositionVector& currGeom = ccwCloser ? geomsCCW[*i] : geomsCW[*i];
253 const PositionVector& currGeom2 = ccwCloser ? geomsCW[*i] : geomsCCW[*i];
255 const PositionVector& neighGeom = ccwCloser ? geomsCW[*ccwi] : geomsCCW[*cwi];
257 const PositionVector& neighGeom2 = ccwCloser ? geomsCCW[*cwi] : geomsCW[*ccwi];
258 if (!simpleContinuation) {
261 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
262 const SUMOReal farAngleDist = ccwCloser ? cad : ccad;
266 SUMOReal mmin =
MIN2(distances[*cwi], distances[*ccwi]);
270 }
else if (fabs(a2 - a1) < 10 || farAngleDist <
DEG2RAD(135)) {
271 distances[*i] =
MAX2(a1, a2);
275 if (*cwi != *ccwi && currGeom2.
intersects(neighGeom2)) {
278 distances[*i] = 100 + radius;
291 for (i = newAll.begin(); i != newAll.end(); ++i) {
292 if (distances.find(*i) == distances.end()) {
300 for (i = newAll.begin(); i != newAll.end(); ++i) {
314 if (i != newAll.begin()) {
330 ret.
append(
getSmoothCorner(geomsCW[*(newAll.end() - 1)], geomsCCW[*newAll.begin()], ret[-1], ret[0], cornerDetail));
339 for (std::vector<SUMOReal>::iterator it = intersections.begin() + 1; it != intersections.end(); ++it) {
340 if (fabs(*it - offset) < fabs(result - offset)) {
352 if (cornerDetail > 0) {
354 begShape[-1] = begPoint;
355 endShape[0] = endPoint;
357 if (curve.size() > 2) {
370 EdgeVector::const_iterator i, j;
375 geomsCCW[*i] = (*i)->getCCWBoundaryLine(
myNode);
377 WRITE_WARNING(std::string(
"While computing intersection geometry: ") + std::string(e.what()));
378 geomsCCW[*i] = (*i)->getGeometry();
381 geomsCW[*i] = (*i)->getCWBoundaryLine(
myNode);
383 WRITE_WARNING(std::string(
"While computing intersection geometry: ") + std::string(e.what()));
384 geomsCW[*i] = (*i)->getGeometry();
389 ? (*i)->getCCWBoundaryLine(
myNode)
390 : (*i)->getCWBoundaryLine(
myNode);
392 Line tmp = geomsCCW[*i].lineAt(0);
394 geomsCCW[*i].replaceAt(0, tmp.
p1());
395 tmp = geomsCW[*i].lineAt(0);
397 geomsCW[*i].replaceAt(0, tmp.
p1());
400 geomsCCW[*j] = (*j)->getCCWBoundaryLine(
myNode);
401 geomsCW[*j] = (*j)->getCWBoundaryLine(
myNode);
404 ? (*j)->getCCWBoundaryLine(
myNode)
405 : (*j)->getCWBoundaryLine(
myNode);
407 tmp = geomsCCW[*j].lineAt(0);
409 geomsCCW[*j].replaceAt(0, tmp.
p1());
410 tmp = geomsCW[*j].lineAt(0);
412 geomsCW[*j].replaceAt(0, tmp.
p1());
418 const SUMOReal angleChangeLookahead = 35;
421 EdgeVector::const_iterator j = i + 1;
425 const bool incoming = (*i)->getToNode() == &
myNode;
426 const bool incoming2 = (*j)->getToNode() == &
myNode;
427 const Position positionAtNode = (*i)->getGeometry()[incoming ? -1 : 0];
428 const Position positionAtNode2 = (*j)->getGeometry()[incoming2 ? -1 : 0];
433 const SUMOReal angle1further = (g1.size() > 2 && l1.
length2D() < angleChangeLookahead ?
435 const SUMOReal angle2further = (g2.size() > 2 && l2.
length2D() < angleChangeLookahead ?
439 const bool ambiguousGeometry = ((angleDiff > 0 && angleDiffFurther < 0) || (angleDiff < 0 && angleDiffFurther > 0));
440 const bool differentDirs = (incoming != incoming2);
445 if (fabs(angleDiff) < 20) {
446 const bool isOpposite = differentDirs && foundOpposite.count(*i) == 0;
448 foundOpposite.insert(*i);
449 foundOpposite.insert(*j);
451 if (isOpposite || ambiguousGeometry ||
badIntersection(*i, *j, geomsCW[*i], geomsCCW[*j], 100)) {
453 for (std::set<NBEdge*>::iterator k = same[*i].begin(); k != same[*i].end(); ++k) {
459 for (std::set<NBEdge*>::iterator k = same[*j].begin(); k != same[*j].end(); ++k) {
491 geom1 = geom1.reverse();
498 std::vector<SUMOReal> distances = geom1.
distances(geom2,
true);
502 const bool onTop = maxDist -
POSITION_EPS < minDistanceThreshold;
503 const bool curvingTowards = geom1[0].distanceTo2D(geom2[0]) > minDistanceThreshold && minDist < minDistanceThreshold;
504 const bool intersects = e1cw.
intersects(e2ccw);
505 return onTop || curvingTowards || !intersects;
511 std::map<
NBEdge*, std::set<NBEdge*> >& same,
514 std::map<NBEdge*, NBEdge*>& ccwBoundary,
515 std::map<NBEdge*, NBEdge*>& cwBoundary) {
517 std::set<NBEdge*>::const_iterator j;
518 EdgeVector::iterator i2;
519 std::map<NBEdge*, EdgeVector >::iterator k;
523 for (i2 = newAll.begin(); !changed && i2 != newAll.end();) {
524 std::set<NBEdge*> other = same[*i2];
525 for (j = other.begin(); j != other.end(); ++j) {
526 EdgeVector::iterator k = find(newAll.begin(), newAll.end(), *j);
527 if (k != newAll.end()) {
530 geomsCW[*i2] = geomsCW[*j];
531 cwBoundary[*i2] = *j;
536 ccwBoundary[*i2] = *j;
537 geomsCCW[*i2] = geomsCCW[*j];
558 EdgeVector::const_iterator& cwi,
559 EdgeVector::const_iterator& ccwi,
565 if (cwi == edges.end()) {
566 std::advance(cwi, -((
int)edges.size()));
569 if (ccwi == edges.begin()) {
570 std::advance(ccwi, edges.size() - 1);
575 const SUMOReal angleCurCCW = geomsCCW[*current].lineAt(0).atan2PositiveAngle();
576 const SUMOReal angleCurCW = geomsCW[*current].lineAt(0).atan2PositiveAngle();
577 const SUMOReal angleCCW = geomsCW[*ccwi].lineAt(0).atan2PositiveAngle();
578 const SUMOReal angleCW = geomsCCW[*cwi].lineAt(0).atan2PositiveAngle();
579 if (angleCurCCW > angleCCW) {
580 ccad = angleCurCCW - angleCCW;
582 ccad = twoPI - (angleCCW - angleCurCCW);
585 if (angleCurCW > angleCW) {
586 cad = twoPI - (angleCurCW - angleCW);
588 cad = angleCW - angleCurCW;
610 EdgeVector::const_iterator i;
613 Line edgebound1 = (*i)->getCCWBoundaryLine(
myNode).lineAt(0);
614 Line edgebound2 = (*i)->getCWBoundaryLine(
myNode).lineAt(0);
615 Line cross(edgebound1);
SUMOReal length2D() const
SUMOReal atan2DegreeAngle() const
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
PositionVector getSubpart2D(SUMOReal beginOffset, SUMOReal endOffset) const
void replaceAt(int index, const Position &by)
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.
Position getPositionAtDistance2D(SUMOReal offset) const
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...
void rotateAtP1(SUMOReal rot)
bool intersects(const Position &p1, const Position &p2) const
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.
std::map< NBEdge *, PositionVector > GeomsMap
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
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
NBNodeShapeComputer(const NBNode &node)
Constructor.
std::vector< SUMOReal > distances(const PositionVector &s, bool perpendicular=false) const
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
Line lineAt(int pos) const
void push_front_noDoublePos(const Position &p)
const Position & getPosition() const
Returns the position of this node.
const Position & p1() const
std::set< NBEdge * > EdgeSet
bool isSimpleContinuation() const
A point in 2D or 3D with translation and scaling methods.
SUMOReal z() const
Returns the z-position.
PositionVector computeSmoothShape(const PositionVector &begShape, const PositionVector &endShape, int numPoints, bool isTurnaround, SUMOReal extrapolateBeg, SUMOReal extrapolateEnd) const
Compute a smooth curve between the given geometries.
PositionVector compute()
Computes the shape of the assigned junction.
bool intersects(const Line &l) const
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.
std::vector< NBEdge * > EdgeVector
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.
void extrapolateBy2D(SUMOReal length)
static const SUMOReal DEFAULT_RADIUS
the default turning radius at intersections in m
void move2side(SUMOReal amount)
static const SUMOReal UNSPECIFIED_RADIUS
unspecified lane width
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
void push_back_noDoublePos(const Position &p)
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 ...
Position intersectsAt(const Line &l) const
void add(SUMOReal x, SUMOReal y)
void append(const PositionVector &v, SUMOReal sameThreshold=2.0)
EdgeVector computeUniqueDirectionList(std::map< NBEdge *, std::set< NBEdge * > > &same, GeomsMap &geomsCCW, GeomsMap &geomsCW, std::map< NBEdge *, NBEdge * > &ccwBoundary, std::map< NBEdge *, NBEdge * > &cwBoundary)
Joins edges and computes ccw/cw boundaries.