Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NGNet.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2003-2024 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/****************************************************************************/
21// The class storing the generated network
22/****************************************************************************/
23#include <config.h>
24
25#include <iostream>
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29#include <cmath>
30#include <netbuild/NBNode.h>
31#include <netbuild/NBNodeCont.h>
32#include <netbuild/NBEdge.h>
33#include <netbuild/NBEdgeCont.h>
40#include "NGNet.h"
41
42
43// ===========================================================================
44// method definitions
45// ===========================================================================
47 myLastID(0),
48 myAlphaIDs(OptionsCont::getOptions().getBool("alphanumerical-ids")),
49 myNetBuilder(nb) {
50}
51
52
54 for (NGEdgeList::iterator ni = myEdgeList.begin(); ni != myEdgeList.end(); ++ni) {
55 delete *ni;
56 }
57 for (NGNodeList::iterator ni = myNodeList.begin(); ni != myNodeList.end(); ++ni) {
58 delete *ni;
59 }
60}
61
62
63std::string
65 return toString<int>(++myLastID);
66}
67
68
69NGNode*
70NGNet::findNode(int xID, int yID) {
71 for (NGNodeList::iterator ni = myNodeList.begin(); ni != myNodeList.end(); ++ni) {
72 if ((*ni)->samePos(xID, yID)) {
73 return *ni;
74 }
75 }
76 return nullptr;
77}
78
79std::string
80NGNet::alphabeticalCode(int i, int iMax) {
81 // lazy mans 26th root to determine number of characters for x-label
82 int xn = 1;
83 for (; std::pow(26, xn) < iMax; xn++) {};
84 std::string result = "";
85 for (int j = 0; j < xn; j++) {
86 result = char('A' + (i % 26)) + result;
87 i /= 26;
88 }
89 return result;
90}
91
92void
93NGNet::createChequerBoard(int numX, int numY, double spaceX, double spaceY, double xAttachLength, double yAttachLength) {
94
95 for (int ix = 0; ix < numX; ix++) {
96 const std::string nodeIDStart = (myAlphaIDs ? alphabeticalCode(ix, numX) : toString<int>(ix) + "/");
97 for (int iy = 0; iy < numY; iy++) {
98 // create Node
99 NGNode* node = new NGNode(nodeIDStart + toString(iy), ix, iy);
100 node->setX(ix * spaceX + xAttachLength);
101 node->setY(iy * spaceY + yAttachLength);
102 myNodeList.push_back(node);
103 // create Links
104 if (ix > 0) {
105 connect(findNode(ix - 1, iy), node);
106 }
107 if (iy > 0) {
108 connect(findNode(ix, iy - 1), node);
109 }
110 }
111 }
112 if (yAttachLength > 0.0) {
113 for (int ix = 0; ix < numX; ix++) {
114 // create nodes
115 NGNode* topNode = new NGNode("top" + toString<int>(ix), ix, numY);
116 NGNode* bottomNode = new NGNode("bottom" + toString<int>(ix), ix, numY + 1);
117 topNode->setX(ix * spaceX + xAttachLength);
118 bottomNode->setX(ix * spaceX + xAttachLength);
119 topNode->setY((numY - 1) * spaceY + 2 * yAttachLength);
120 bottomNode->setY(0);
121 topNode->setFringe();
122 bottomNode->setFringe();
123 myNodeList.push_back(topNode);
124 myNodeList.push_back(bottomNode);
125 // create links
126 connect(findNode(ix, numY - 1), topNode);
127 connect(bottomNode, findNode(ix, 0));
128 }
129 }
130 if (xAttachLength > 0.0) {
131 for (int iy = 0; iy < numY; iy++) {
132 // create nodes
133 NGNode* leftNode = new NGNode("left" + toString<int>(iy), numX, iy);
134 NGNode* rightNode = new NGNode("right" + toString<int>(iy), numX + 1, iy);
135 leftNode->setX(0);
136 rightNode->setX((numX - 1) * spaceX + 2 * xAttachLength);
137 leftNode->setY(iy * spaceY + yAttachLength);
138 rightNode->setY(iy * spaceY + yAttachLength);
139 leftNode->setFringe();
140 rightNode->setFringe();
141 myNodeList.push_back(leftNode);
142 myNodeList.push_back(rightNode);
143 // create links
144 connect(leftNode, findNode(0, iy));
145 connect(findNode(numX - 1, iy), rightNode);
146 }
147 }
148}
149
150
151double
152NGNet::radialToX(double radius, double phi) {
153 return cos(phi) * radius;
154}
155
156
157double
158NGNet::radialToY(double radius, double phi) {
159 return sin(phi) * radius;
160}
161
162
163void
164NGNet::createSpiderWeb(int numRadDiv, int numCircles, double spaceRad, bool hasCenter, double attachLength) {
165 if (numRadDiv < 3) {
166 numRadDiv = 3;
167 }
168 if (numCircles < 1) {
169 numCircles = 1;
170 }
171
172 int ir, ic;
173 double angle = (double)(2 * M_PI / numRadDiv); // angle between radial divisions
174 NGNode* node;
175 int attachCircle = -1;
176 if (attachLength > 0) {
177 numCircles += 1;
178 attachCircle = numCircles;
179 }
180 for (ic = 1; ic < numCircles + 1; ic++) {
181 const std::string nodeIDStart = alphabeticalCode(ic, numCircles);
182 if (ic == attachCircle) {
183 spaceRad = attachLength;
184 }
185 for (ir = 1; ir < numRadDiv + 1; ir++) {
186 // create Node
187 const std::string nodeID = (myAlphaIDs ?
188 nodeIDStart + toString<int>(ir) :
189 toString<int>(ir) + "/" + toString<int>(ic));
190 node = new NGNode(nodeID, ir, ic);
191 node->setX(radialToX((ic) * spaceRad, (ir - 1) * angle));
192 node->setY(radialToY((ic) * spaceRad, (ir - 1) * angle));
193 myNodeList.push_back(node);
194 // create Links
195 if (ir > 1 && ic != attachCircle) {
196 connect(findNode(ir - 1, ic), node);
197 }
198 if (ic > 1) {
199 connect(findNode(ir, ic - 1), node);
200 }
201 if (ir == numRadDiv && ic != attachCircle) {
202 connect(node, findNode(1, ic));
203 }
204 }
205 }
206 if (hasCenter) {
207 // node
208 node = new NGNode(myAlphaIDs ? "A1" : "1", 0, 0, true);
209 node->setX(0);
210 node->setY(0);
211 myNodeList.push_back(node);
212 // links
213 for (ir = 1; ir < numRadDiv + 1; ir++) {
214 connect(node, findNode(ir, 1));
215 }
216 }
217}
218
219
220void
221NGNet::connect(NGNode* node1, NGNode* node2) {
222 std::string id1 = node1->getID() + (myAlphaIDs ? "" : "to") + node2->getID();
223 std::string id2 = node2->getID() + (myAlphaIDs ? "" : "to") + node1->getID();
224 NGEdge* link1 = new NGEdge(id1, node1, node2, id2);
225 myEdgeList.push_back(link1);
226}
227
229NGNet::getDistribution(const std::string& option) {
230 const std::string& val = OptionsCont::getOptions().getString(option);
231 try {
233 } catch (NumberFormatException&) {
234 return Distribution_Parameterized(val);
235 }
236}
237
238
239void
240NGNet::toNB() const {
241 Distribution_Parameterized perturbx = getDistribution("perturb-x");
242 Distribution_Parameterized perturby = getDistribution("perturb-y");
243 Distribution_Parameterized perturbz = getDistribution("perturb-z");
244 for (const NGNode* const ngNode : myNodeList) {
245 // we need to sample in separate instructions because evaluation order is compiler dependent
246 Position perturb(perturbx.sample(), 0.);
247 perturb.sety(perturby.sample());
248 perturb.setz(perturbz.sample());
249 myNetBuilder.getNodeCont().insert(ngNode->buildNBNode(myNetBuilder, perturb));
250 }
251 const std::string type = OptionsCont::getOptions().getString("default.type");
252 const double bidiProb = OptionsCont::getOptions().getFloat("bidi-probability");
253 for (const NGEdge* const ngEdge : myEdgeList) {
254 myNetBuilder.getEdgeCont().insert(ngEdge->buildNBEdge(myNetBuilder, type));
255 // now, let's append the reverse directions...
256 if (!ngEdge->getEndNode()->connected(ngEdge->getStartNode(), true) && RandHelper::rand() <= bidiProb) {
257 myNetBuilder.getEdgeCont().insert(ngEdge->buildNBEdge(myNetBuilder, type, true));
258 }
259 }
260 // add splits depending on turn-lane options
261 const int turnLanes = OptionsCont::getOptions().getInt("turn-lanes");
262 const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
263 if (turnLanes > 0) {
264 const double turnLaneLength = OptionsCont::getOptions().getFloat("turn-lanes.length");
266 EdgeVector allEdges;
267 for (auto it = ec.begin(); it != ec.end(); ++it) {
268 allEdges.push_back(it->second);
269 }
270 for (NBEdge* e : allEdges) {
271 if (e->getToNode()->geometryLike()) {
272 continue;
273 }
274 std::vector<NBEdgeCont::Split> splits;
276 for (int i = 0; i < e->getNumLanes() + turnLanes; ++i) {
277 split.lanes.push_back(i);
278 }
279 split.pos = MAX2(0.0, e->getLength() - turnLaneLength);
280 split.speed = e->getSpeed();
281 split.node = new NBNode(e->getID() + "." + toString(split.pos), e->getGeometry().positionAtOffset(split.pos));
282 split.idBefore = e->getID();
283 split.idAfter = split.node->getID();
284 split.offsetFactor = lefthand ? -1 : 1;
285 if (turnLaneLength <= e->getLength() / 2) {
286 split.offset = -0.5 * split.offsetFactor * turnLanes * e->getLaneWidth(0);
287 if (e->getFromNode()->geometryLike()) {
288 // shift the reverse direction explicitly as it will not get a turn lane
289 NBEdge* reverse = nullptr;
290 for (NBEdge* reverseCand : e->getFromNode()->getIncomingEdges()) {
291 if (reverseCand->getFromNode() == e->getToNode()) {
292 reverse = reverseCand;
293 }
294 }
295 if (reverse != nullptr) {
296 PositionVector g = reverse->getGeometry();
297 g.move2side(-split.offset);
298 reverse->setGeometry(g);
299 }
300 }
301 }
302 splits.push_back(split);
303 ec.processSplits(e, splits,
307 }
308 }
309}
310
311
312void
314 myNodeList.push_back(node);
315}
316
317
318void
320 myEdgeList.push_back(edge);
321}
322
323
324int
326 return (int)myNodeList.size();
327}
328
329
330/****************************************************************************/
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition NBCont.h:42
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
double sample(SumoRNG *which=0) const
Draw a sample of the distribution.
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition NBEdgeCont.h:171
void processSplits(NBEdge *e, std::vector< Split > splits, NBNodeCont &nc, NBDistrictCont &dc, NBTrafficLightLogicCont &tlc)
process splits
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
Definition NBEdgeCont.h:178
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
The representation of a single edge during network building.
Definition NBEdge.h:92
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition NBEdge.h:783
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition NBEdge.cpp:637
Instance responsible for building networks.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
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.
Definition NBNode.h:66
A netgen-representation of an edge.
Definition NGEdge.h:52
double radialToX(double radius, double phi)
Returns the x-position resulting from the given radius and angle.
Definition NGNet.cpp:152
int myLastID
The last ID given to node or link.
Definition NGNet.h:201
void toNB() const
Converts the stored network into its netbuilder-representation.
Definition NGNet.cpp:240
void connect(NGNode *node1, NGNode *node2)
Connects both nodes with two edges, one for each direction.
Definition NGNet.cpp:221
void createChequerBoard(int numX, int numY, double spaceX, double spaceY, double xAttachLength, double yAttachLength)
Creates a grid network.
Definition NGNet.cpp:93
void add(NGNode *node)
Adds the given node to the network.
Definition NGNet.cpp:313
NGNet(NBNetBuilder &nb)
Constructor.
Definition NGNet.cpp:46
int nodeNo() const
Returns the number of stored nodes.
Definition NGNet.cpp:325
void createSpiderWeb(int numRadDiv, int numCircles, double spaceRad, bool hasCenter, double attachLength)
Creates a spider network.
Definition NGNet.cpp:164
double radialToY(double radius, double phi)
Returns the y-position resulting from the given radius and angle.
Definition NGNet.cpp:158
NGNode * findNode(int xPos, int yPos)
Returns the node at the given position.
Definition NGNet.cpp:70
std::string alphabeticalCode(int i, int iMax)
return a letter code for the given integer index
Definition NGNet.cpp:80
std::string getNextFreeID()
Returns the next free id.
Definition NGNet.cpp:64
static Distribution_Parameterized getDistribution(const std::string &option)
get distribution from option
Definition NGNet.cpp:229
NGNodeList myNodeList
The list of nodes.
Definition NGNet.h:210
const bool myAlphaIDs
Whether to use alphanumericalIDs.
Definition NGNet.h:204
NBNetBuilder & myNetBuilder
The builder used to build NB*-structures.
Definition NGNet.h:207
NGEdgeList myEdgeList
The list of links.
Definition NGNet.h:213
~NGNet()
Destructor.
Definition NGNet.cpp:53
A netgen-representation of a node.
Definition NGNode.h:48
void setFringe()
mark node as fringe
Definition NGNode.h:125
void setY(double y)
Sets a new value for y-position.
Definition NGNode.h:120
void setX(double x)
Sets a new value for x-position.
Definition NGNode.h:111
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
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)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
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.
Definition Position.h:37
void setz(double z)
set position z
Definition Position.h:80
void sety(double y)
set position y
Definition Position.h:75
A list of positions.
void move2side(double amount, double maxExtension=100)
move position vector to side using certain amount
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
#define M_PI
Definition odrSpiral.cpp:45
A structure which describes changes of lane number or speed along the road.
Definition NBEdgeCont.h:189
std::vector< int > lanes
The lanes after this change.
Definition NBEdgeCont.h:191