34#define OFFRAMP_LOOKBACK 500
35#define MIN_SPLIT_LENGTH POSITION_EPS
39#define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
58 const bool guessAndAdd = oc.
getBool(
"ramps.guess") && mayAddOrRemove;
59 const double minHighwaySpeed = oc.
getFloat(
"ramps.min-highway-speed");
60 const double maxRampSpeed = oc.
getFloat(
"ramps.max-ramp-speed");
61 const double rampLength = oc.
getFloat(
"ramps.ramp-length");
62 const double minWeaveLength = oc.
getFloat(
"ramps.min-weave-length");
63 const bool dontSplit = oc.
getBool(
"ramps.no-split");
67 std::set<NBEdge*> incremented;
69 std::set<std::string> noramps;
70 if (oc.
isSet(
"ramps.unset")) {
72 noramps.insert(edges.begin(), edges.end());
76 for (
NBEdge*
const edge : round) {
77 noramps.insert(edge->getID());
85 if (guessAndAdd || oc.
getBool(
"ramps.guess-acceleration-lanes")) {
86 for (
const auto& it : ec) {
87 it.second->markOffRamp(
false);
91 std::set<NBNode*, ComparatorIdLess> potOnRamps;
92 std::set<NBNode*, ComparatorIdLess> potOffRamps;
93 for (
const auto& i : nc) {
97 std::cout <<
"check ramps cur=" << cur->
getID() <<
"\n";
100 if (
mayNeedOnRamp(cur, minHighwaySpeed, maxRampSpeed, noramps, minWeaveLength)) {
101 potOnRamps.insert(cur);
103 if (
mayNeedOffRamp(cur, minHighwaySpeed, maxRampSpeed, noramps)) {
104 potOffRamps.insert(cur);
107 for (std::set<NBNode*, ComparatorIdLess>::const_iterator i = potOnRamps.begin(); i != potOnRamps.end(); ++i) {
108 buildOnRamp(*i, nc, ec, dc, rampLength, dontSplit || !guessAndAdd, guessAndAdd);
110 for (std::set<NBNode*, ComparatorIdLess>::const_iterator i = potOffRamps.begin(); i != potOffRamps.end(); ++i) {
111 buildOffRamp(*i, nc, ec, dc, rampLength, dontSplit || !guessAndAdd, guessAndAdd, potOnRamps);
115 if (oc.
isSet(
"ramps.set") && mayAddOrRemove) {
117 std::set<NBNode*, ComparatorIdLess> potOnRamps;
118 for (
const std::string& i : edges) {
120 if (noramps.count(i) != 0) {
121 WRITE_WARNINGF(
TL(
"Can not build ramp on edge '%' - the edge is unsuitable."), i);
125 WRITE_WARNINGF(
TL(
"Can not build on ramp on edge '%' - the edge is not known."), i);
130 buildOnRamp(from, nc, ec, dc, rampLength, dontSplit,
true);
131 potOnRamps.insert(from);
136 WRITE_WARNINGF(
TL(
"Can not build off ramp on edge '%' - the edge is not known."), i);
141 buildOffRamp(to, nc, ec, dc, rampLength, dontSplit,
true, potOnRamps);
153 NBEdge* potHighway, *potRamp, *cont;
158 std::cout <<
"check on ramp hw=" << potHighway->
getID() <<
" ramp=" << potRamp->
getID() <<
" cont=" << cont->
getID() << std::endl;
164 while (seen < minWeaveLength) {
186 NBEdge* potHighway, *potRamp, *prev;
190 std::cout <<
"check off ramp hw=" << potHighway->
getID() <<
" ramp=" << potRamp->
getID() <<
" prev=" << prev->
getID() << std::endl;
199 NBEdge* potHighway, *potRamp, *cont;
203 std::cout <<
"buildOnRamp cur=" << cur->
getID() <<
" hw=" << potHighway->
getID() <<
" ramp=" << potRamp->
getID() <<
" cont=" << cont->
getID() <<
"\n";
212 std::set<NBEdge*> incremented;
213 if (addLanes && toAdd > 0 && std::find(incremented.begin(), incremented.end(), cont) == incremented.end()) {
214 double currLength = 0;
215 while (curr !=
nullptr && currLength + curr->
getGeometry().
length() - POSITION_EPS < rampLength) {
216 if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
223 incremented.insert(curr);
241 }
else if (curr == potHighway || curr == potRamp) {
251 if (curr !=
nullptr && !dontSplit && currLength + MIN_SPLIT_LENGTH < rampLength && curr->getNumLanes() == firstLaneNumber && std::find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
253 bool wasFirst = first == curr;
254 std::string newNodeID =
getUnusedID(curr->
getID() +
"-AddedOnRampNode", nc);
258 std::string name = curr->
getID();
261 WRITE_WARNING(
"Could not build on-ramp for edge '" + curr->
getID() +
"' for unknown reason");
268 incremented.insert(curr);
279 if (curr == cont && dontSplit && addLanes) {
280 WRITE_WARNING(
"Could not build on-ramp for edge '" + curr->
getID() +
"' due to option '--ramps.no-split'");
285 for (
int i = 0; i < firstLaneNumber - potHighway->
getNumLanes(); ++i) {
308 const std::set<NBNode*, ComparatorIdLess>& potOnRamps) {
309 NBEdge* potHighway, *potRamp, *prev;
313 std::cout <<
"buildOffRamp cur=" << cur->
getID() <<
" hw=" << potHighway->
getID() <<
" ramp=" << potRamp->
getID() <<
" prev=" << prev->
getID() <<
"\n";
322 std::set<NBEdge*> incremented;
323 if (addLanes && toAdd > 0 && std::find(incremented.begin(), incremented.end(), prev) == incremented.end()) {
324 double currLength = 0;
325 while (curr !=
nullptr && currLength + curr->
getGeometry().
length() - POSITION_EPS < rampLength) {
326 if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
333 incremented.insert(curr);
351 }
else if (curr == potHighway || curr == potRamp) {
361 if (curr !=
nullptr && !dontSplit && currLength + MIN_SPLIT_LENGTH < rampLength && curr->getNumLanes() == firstLaneNumber && std::find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
363 bool wasFirst = first == curr;
365 std::string newNodeID =
getUnusedID(curr->
getID() +
"-AddedOffRampNode", nc);
366 std::string newEdgeID =
getUnusedID(curr->
getID() +
"-AddedOffRampEdge", ec);
369 std::string name = curr->
getID();
372 WRITE_WARNING(
"Could not build off-ramp for edge '" + curr->
getID() +
"' for unknown reason");
378 incremented.insert(curr);
385 if (curr == prev && dontSplit && addLanes) {
386 WRITE_WARNING(
"Could not build off-ramp for edge '" + curr->
getID() +
"' due to option '--ramps.no-split'");
400 }
else if (potOnRamps.count(from) == 1) {
431 double offset = (0.5 * addedLanes *
447 if (fabs((*potHighway)->getSpeed() - (*potRamp)->getSpeed()) < .1) {
450 if ((*potHighway)->getSpeed() < (*potRamp)->getSpeed()) {
459 if ((*potHighway)->getNumLanes() == (*potRamp)->getNumLanes()) {
462 if ((*potHighway)->getNumLanes() < (*potRamp)->getNumLanes()) {
473 assert(edges.size() == 2);
474 *potHighway = edges[0];
497 *potHighway = edges[0];
499 assert(edges.size() == 2);
511 const std::vector<NBEdge*>& edges2 = n->
getEdges();
514 std::cout <<
" edges=" <<
toString(edges) <<
" edges2=" <<
toString(edges2) <<
"\n";
517 std::vector<NBEdge*>::const_iterator i = std::find(edges2.begin(), edges2.end(), *other);
519 if ((*i) == *potRamp) {
533 NBEdge* potHighway,
NBEdge* potRamp,
NBEdge* other,
double minHighwaySpeed,
double maxRampSpeed,
534 const std::set<std::string>& noramps) {
553 if (maxSpeed < minHighwaySpeed) {
587 if (maxRampSpeed > 0 && maxRampSpeed < potRamp->getSpeed()) {
590 if (noramps.find(other->
getID()) != noramps.end()) {
604 for (
int i = 0; i < (int)edge->
getNumLanes(); ++i) {
633 if (firstIndex % 2 == 1) {
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
std::set< NBEdge * > EdgeSet
container for unique edges
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
const double SUMO_const_laneWidth
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
A container for districts.
Storage for edges, including some functionality operating on multiple edges.
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
bool hasPostProcessConnection(const std::string &from, const std::string &to="")
add post process connections
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
The representation of a single edge during network building.
double getLength() const
Returns the computed length of the edge.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
double getLaneWidth() const
Returns the default width of lanes of this edge.
NBNode * getToNode() const
Returns the destination node of the edge.
void incLaneNo(int by)
increment lane
void markOffRamp(bool isOffRamp)
marks this edge has being an offRamp or leading to one (used for connection computation)
const PositionVector & getGeometry() const
Returns the geometry of the edge.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
EdgeBuildingStep getStep() const
The building step of this edge.
@ LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
double getSpeed() const
Returns the speed allowed on this edge.
const std::string & getID() const
void resetLaneShapes()
reset lane shapes to what they would be before cutting with the junction shapes
void setAcceleration(int lane, bool accelRamp)
marks one lane as acceleration lane
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
int getNumLanes() const
Returns the number of lanes.
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
@ VALIDATED
The connection was computed and validated.
NBNode * getFromNode() const
Returns the origin node of the edge.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
bool hasDefaultGeometryEndpointAtNode(const NBNode *node) const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
static const double UNSPECIFIED_WIDTH
unspecified lane width
bool addLane2LaneConnections(int fromLane, NBEdge *dest, int toLane, int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Instance responsible for building networks.
NBParkingCont & getParkingCont()
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Container for nodes during the netbuilding process.
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Represents a single node (junction) during network building.
SumoXMLNodeType getType() const
Returns the type of this node.
bool isTrafficLight() const
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)
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
void computeRamps(NBNetBuilder &nb, OptionsCont &oc, bool mayAddOrRemove)
static void getOffRampEdges(NBNode *n, NBEdge **potHighway, NBEdge **potRamp, NBEdge **other)
static bool mayNeedOffRamp(NBNode *cur, double minHighwaySpeed, double maxRampSpeed, const std::set< std::string > &noramps)
Determines whether the given node may be an off-ramp end.
static bool mayNeedOnRamp(NBNode *cur, double minHighwaySpeed, double maxRampSpeed, const std::set< std::string > &noramps, double minWeaveLength)
Determines whether the given node may be an on-ramp begin.
static bool determinedBySpeed(NBEdge **potHighway, NBEdge **potRamp)
void moveRampRight(NBEdge *ramp, int addedLanes)
Moves the ramp to the right, as new lanes were added.
static void getOnRampEdges(NBNode *n, NBEdge **potHighway, NBEdge **potRamp, NBEdge **other)
static const std::string ADDED_ON_RAMP_EDGE
suffix for newly generated on-ramp edges
static void patchRampGeometry(NBEdge *potRamp, NBEdge *first, NBEdge *potHighway, bool onRamp)
shift ramp geometry to merge smoothly with the motorway
std::map< NBEdge *, double > myShiftedEdges
void buildOffRamp(NBNode *cur, NBNodeCont &nc, NBEdgeCont &ec, NBDistrictCont &dc, double rampLength, bool dontSplit, bool addLanes, const std::set< NBNode *, ComparatorIdLess > &potOnRamps)
Builds an off-ramp ending at the given node.
static std::string getUnusedID(const std::string &prefix, const T &objectCont)
static bool determinedByLaneNumber(NBEdge **potHighway, NBEdge **potRamp)
static bool hasWrongMode(NBEdge *edge)
whether the edge has a mode that does not indicate a ramp edge
NBRampsComputer()
Computes highway on-/off-ramps (if wished)
void buildOnRamp(NBNode *cur, NBNodeCont &nc, NBEdgeCont &ec, NBDistrictCont &dc, double rampLength, bool dontSplit, bool addLanes)
Builds an on-ramp starting at the given node.
static bool fulfillsRampConstraints(NBEdge *potHighway, NBEdge *potRamp, NBEdge *other, double minHighwaySpeed, double maxRampSpeed, const std::set< std::string > &noramps)
Checks whether an on-/off-ramp can be bult here.
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)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
A point in 2D or 3D with translation and scaling methods.
double length() const
Returns the length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects