Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netbuild/NBContHelper.h
169666 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file NBContHelper.h
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @date Mon, 17 Dec 2001
19
///
20
// Some methods for traversing lists of edges
21
/****************************************************************************/
22
#pragma once
23
#include <config.h>
24
25
#include <vector>
26
#include <iostream>
27
#include <cmath>
28
#include <algorithm>
29
#include <cassert>
30
#include "NBHelpers.h"
31
#include "NBCont.h"
32
#include "NBEdge.h"
33
#include "NBNode.h"
34
#include <utils/common/StdDefs.h>
35
#include <utils/geom/GeomHelper.h>
36
37
38
// ===========================================================================
39
// class definitions
40
// ===========================================================================
41
/**
42
* NBContHelper
43
* Some static helper methods that traverse a sorted list of edges in both
44
* directions
45
*/
46
class NBContHelper {
47
public:
48
/** Moves the given iterator clockwise within the given container
49
of edges sorted clockwise */
50
static void nextCW(const EdgeVector& edges,
51
EdgeVector::const_iterator& from);
52
53
/** Moves the given iterator counter clockwise within the given container
54
of edges sorted clockwise */
55
static void nextCCW(const EdgeVector& edges,
56
EdgeVector::const_iterator& from);
57
58
static double getMaxSpeed(const EdgeVector& edges);
59
60
static double getMinSpeed(const EdgeVector& edges);
61
62
/** writes the vector of bools to the given stream */
63
static std::ostream& out(std::ostream& os, const std::vector<bool>& v);
64
65
66
/**
67
* relative_outgoing_edge_sorter
68
* Class to sort edges by their angle in relation to the node the
69
* edge using this class is incoming into. This is normally done to
70
* sort edges outgoing from the node the using edge is incoming in
71
* by their angle in relation to the using edge's angle (this angle
72
* is the reference angle).
73
*/
74
class relative_outgoing_edge_sorter {
75
public:
76
/// constructor
77
explicit relative_outgoing_edge_sorter(NBEdge* e) : myAngle(e->getEndAngle()) {}
78
/// constructor
79
explicit relative_outgoing_edge_sorter(double angle) : myAngle(angle) {}
80
81
public:
82
/// comparing operation
83
bool operator()(const NBEdge* e1, const NBEdge* e2) const;
84
85
private:
86
/// @brief the reference angle to compare edges agains
87
double myAngle;
88
};
89
90
91
/**
92
* relative_incoming_edge_sorter
93
* Class to sort edges by their angle in relation to an outgoing edge.
94
* This is normally done to sort edges incoming at the starting node of this edge
95
* by their angle in relation to the using edge's angle (this angle
96
* is the reference angle).
97
*/
98
class relative_incoming_edge_sorter {
99
public:
100
/// constructor
101
explicit relative_incoming_edge_sorter(NBEdge* e) : myAngle(e->getStartAngle()) {}
102
/// constructor
103
explicit relative_incoming_edge_sorter(double angle) : myAngle(angle) {}
104
105
public:
106
/// comparing operation
107
bool operator()(const NBEdge* e1, const NBEdge* e2) const;
108
109
private:
110
/// @brief the reference angle to compare edges agains
111
double myAngle;
112
};
113
114
115
/**
116
* edge_by_priority_sorter
117
* Class to sort edges by their priority
118
*/
119
class edge_by_priority_sorter {
120
public:
121
edge_by_priority_sorter(SVCPermissions permissions) : myPermissions(permissions) {}
122
/// comparing operator
123
int operator()(NBEdge* e1, NBEdge* e2) const {
124
if (e1->getPriority() != e2->getPriority()) {
125
return e1->getPriority() > e2->getPriority();
126
}
127
if (e1->getSpeed() != e2->getSpeed()) {
128
return e1->getSpeed() > e2->getSpeed();
129
}
130
return e1->getNumLanesThatAllow(myPermissions, false) > e2->getNumLanesThatAllow(myPermissions, false);
131
}
132
133
private:
134
SVCPermissions myPermissions;
135
};
136
137
// ---------------------------
138
139
/**
140
* @class edge_opposite_direction_sorter
141
* @brief Class to sort edges by their angle in relation to the given edge
142
*
143
* The resulting sorted list has the edge in the most opposite direction
144
* to the given edge as her first entry.
145
*/
146
class edge_opposite_direction_sorter {
147
public:
148
/** @brief Constructor
149
* @param[in] e The edge to which the sorting relates
150
* @param[in] n The node to consider
151
*/
152
explicit edge_opposite_direction_sorter(const NBEdge* const e, const NBNode* const n, bool regardPriority) :
153
myNode(n),
154
myEdge(e),
155
myRegardPriority(regardPriority) {
156
myAngle = getEdgeAngleAt(e, n);
157
}
158
159
/** @brief Comparing operation
160
* @param[in] e1 The first edge to compare
161
* @param[in] e2 The second edge to compare
162
* @return Which edge is more opposite to the related one
163
*/
164
int operator()(NBEdge* e1, NBEdge* e2) const {
165
if (!myRegardPriority || e1->getPriority() == e2->getPriority() || e1 == myEdge || e2 == myEdge) {
166
return getDiff(e1) > getDiff(e2);
167
} else {
168
return e1->getPriority() > e2->getPriority();
169
}
170
}
171
172
protected:
173
/** @brief Computes the angle difference between the related and the given edge
174
* @param[in] e The edge to compare the angle difference of
175
* @return The angle difference
176
*/
177
double getDiff(const NBEdge* const e) const {
178
return fabs(GeomHelper::angleDiff(getEdgeAngleAt(e, myNode), myAngle));
179
}
180
181
/** @brief Returns the given edge's angle at the given node
182
*
183
* Please note that we always consider the "outgoing direction".
184
* @param[in] e The edge to which the sorting relates
185
* @param[in] n The node to consider
186
*/
187
double getEdgeAngleAt(const NBEdge* const e, const NBNode* const n) const {
188
if (e->getFromNode() == n) {
189
return e->getGeometry().angleAt2D(0);
190
} else {
191
return e->getGeometry()[-1].angleTo2D(e->getGeometry()[-2]);
192
}
193
}
194
195
private:
196
197
/// @brief The related node
198
const NBNode* const myNode;
199
200
/// @brief the reference edge
201
const NBEdge* const myEdge;
202
203
/// @brief The angle of the related edge at the given node
204
double myAngle;
205
206
/// @brief Whether edge priority may override closer angles
207
bool myRegardPriority;
208
209
};
210
211
// ---------------------------
212
213
/**
214
* edge_similar_direction_sorter
215
* Class to sort edges by their angle in relation to the given edge
216
* The resulting list should have the edge in the most similar direction
217
* to the given edge as its first entry
218
*/
219
class edge_similar_direction_sorter {
220
public:
221
/// constructor
222
explicit edge_similar_direction_sorter(const NBEdge* const e, bool outgoing = true) :
223
myCompareOutgoing(outgoing),
224
myAngle(outgoing ? e->getShapeEndAngle() : e->getShapeStartAngle())
225
{}
226
227
/// comparing operation
228
int operator()(const NBEdge* e1, const NBEdge* e2) const {
229
const double d1 = angleDiff(myCompareOutgoing ? e1->getShapeStartAngle() : e1->getShapeEndAngle(), myAngle);
230
const double d2 = angleDiff(myCompareOutgoing ? e2->getShapeStartAngle() : e2->getShapeEndAngle(), myAngle);
231
if (fabs(fabs(d1) - fabs(d2)) < NUMERICAL_EPS) {
232
if (fabs(d1 - d2) > NUMERICAL_EPS) {
233
return d1 < d2;
234
} else {
235
return e1->getNumericalID() < e2->getNumericalID();
236
}
237
}
238
return fabs(d1) < fabs(d2);
239
}
240
241
private:
242
double angleDiff(const double angle1, const double angle2) const {
243
double d = angle2 - angle1;
244
while (d >= 180.) {
245
d -= 360.;
246
}
247
while (d < -180.) {
248
d += 360.;
249
}
250
return d;
251
}
252
253
254
private:
255
/// the angle to find the edge with the opposite direction
256
bool myCompareOutgoing;
257
double myAngle;
258
};
259
260
261
/**
262
* @class node_with_incoming_finder
263
*/
264
class node_with_incoming_finder {
265
public:
266
/// constructor
267
node_with_incoming_finder(const NBEdge* const e);
268
269
bool operator()(const NBNode* const n) const;
270
271
private:
272
const NBEdge* const myEdge;
273
274
};
275
276
277
/**
278
* @class node_with_outgoing_finder
279
*/
280
class node_with_outgoing_finder {
281
public:
282
/// constructor
283
node_with_outgoing_finder(const NBEdge* const e);
284
285
bool operator()(const NBNode* const n) const;
286
287
private:
288
const NBEdge* const myEdge;
289
290
};
291
292
293
294
295
class edge_with_destination_finder {
296
public:
297
/// constructor
298
edge_with_destination_finder(NBNode* dest);
299
300
bool operator()(NBEdge* e) const;
301
302
private:
303
NBNode* myDestinationNode;
304
305
private:
306
/// @brief invalidated assignment operator
307
edge_with_destination_finder& operator=(const edge_with_destination_finder& s);
308
309
};
310
311
312
/** Tries to return the first edge within the given container which
313
connects both given nodes */
314
static NBEdge* findConnectingEdge(const EdgeVector& edges,
315
NBNode* from, NBNode* to);
316
317
318
/** returns the maximum speed allowed on the edges */
319
static double maxSpeed(const EdgeVector& ev);
320
321
/**
322
* same_connection_edge_sorter
323
* This class is used to sort edges which connect the same nodes.
324
* The edges are sorted in dependence to edges connecting them. The
325
* rightmost will be the first in the list; the leftmost the last one.
326
*/
327
class same_connection_edge_sorter {
328
public:
329
/// constructor
330
explicit same_connection_edge_sorter() { }
331
332
/// comparing operation
333
int operator()(NBEdge* e1, NBEdge* e2) const {
334
std::pair<double, double> mm1 = getMinMaxRelAngles(e1);
335
std::pair<double, double> mm2 = getMinMaxRelAngles(e2);
336
if (mm1.first == mm2.first && mm1.second == mm2.second) {
337
// ok, let's simply sort them arbitrarily
338
return e1->getID() < e2->getID();
339
}
340
341
assert(
342
(mm1.first <= mm2.first && mm1.second <= mm2.second)
343
||
344
(mm1.first >= mm2.first && mm1.second >= mm2.second));
345
return (mm1.first >= mm2.first && mm1.second >= mm2.second);
346
}
347
348
/**
349
*
350
*/
351
std::pair<double, double> getMinMaxRelAngles(NBEdge* e) const {
352
double min = 360;
353
double max = 360;
354
const EdgeVector& ev = e->getConnectedEdges();
355
for (EdgeVector::const_iterator i = ev.begin(); i != ev.end(); ++i) {
356
double angle = NBHelpers::normRelAngle(
357
e->getTotalAngle(), (*i)->getTotalAngle());
358
if (min == 360 || min > angle) {
359
min = angle;
360
}
361
if (max == 360 || max < angle) {
362
max = angle;
363
}
364
}
365
return std::pair<double, double>(min, max);
366
}
367
};
368
369
370
friend std::ostream& operator<<(std::ostream& os, const EdgeVector& ev);
371
372
class opposite_finder {
373
public:
374
/// constructor
375
opposite_finder(NBEdge* edge)
376
: myReferenceEdge(edge) { }
377
378
bool operator()(NBEdge* e) const {
379
return e->isTurningDirectionAt(myReferenceEdge) ||
380
myReferenceEdge->isTurningDirectionAt(e);
381
}
382
383
private:
384
NBEdge* myReferenceEdge;
385
386
};
387
388
/**
389
* edge_by_angle_to_nodeShapeCentroid_sorter
390
* Class to sort edges by their angle in relation to the node shape
391
* */
392
class edge_by_angle_to_nodeShapeCentroid_sorter {
393
public:
394
/// constructor
395
explicit edge_by_angle_to_nodeShapeCentroid_sorter(const NBNode* n) : myNode(n) {}
396
397
public:
398
/// comparing operation
399
bool operator()(const NBEdge* e1, const NBEdge* e2) const;
400
401
private:
402
/// the edge to compute the relative angle of
403
const NBNode* myNode;
404
};
405
406
};
407
408