Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netimport/vissim/tempstructs/NIVissimDistrictConnection.cpp
169684 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 NIVissimDistrictConnection.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @date Sept 2002
19
///
20
// -------------------
21
/****************************************************************************/
22
#include <config.h>
23
24
#include <map>
25
#include <string>
26
#include <algorithm>
27
#include <cassert>
28
#include <utils/common/VectorHelper.h>
29
#include <utils/common/ToString.h>
30
#include <utils/geom/Position.h>
31
#include <utils/geom/GeomHelper.h>
32
#include <utils/geom/PositionVector.h>
33
#include <utils/options/OptionsCont.h>
34
#include "NIVissimAbstractEdge.h"
35
#include "NIVissimEdge.h"
36
#include <netbuild/NBEdge.h>
37
#include <netbuild/NBEdgeCont.h>
38
#include <netbuild/NBNode.h>
39
#include <netbuild/NBNodeCont.h>
40
#include <netbuild/NBDistrict.h>
41
#include <netbuild/NBDistrictCont.h>
42
#include "NIVissimDistrictConnection.h"
43
#include <utils/distribution/DistributionCont.h>
44
#include <utils/common/MsgHandler.h>
45
46
47
// ===========================================================================
48
// static member definitions
49
// ===========================================================================
50
NIVissimDistrictConnection::DictType NIVissimDistrictConnection::myDict;
51
std::map<int, std::vector<int> > NIVissimDistrictConnection::myDistrictsConnections;
52
53
54
// ===========================================================================
55
// method definitions
56
// ===========================================================================
57
NIVissimDistrictConnection::NIVissimDistrictConnection(int id,
58
const std::string& name,
59
const std::vector<int>& districts, const std::vector<double>& percentages,
60
int edgeid, double position,
61
const std::vector<std::pair<int, int> >& assignedVehicles)
62
: myID(id), myName(name), myDistricts(districts),
63
myEdgeID(edgeid), myPosition(position),
64
myAssignedVehicles(assignedVehicles) {
65
std::vector<int>::iterator i = myDistricts.begin();
66
std::vector<double>::const_iterator j = percentages.begin();
67
while (i != myDistricts.end()) {
68
myPercentages[*i] = *j;
69
i++;
70
j++;
71
}
72
}
73
74
75
NIVissimDistrictConnection::~NIVissimDistrictConnection() {}
76
77
78
79
bool
80
NIVissimDistrictConnection::dictionary(int id, const std::string& name,
81
const std::vector<int>& districts, const std::vector<double>& percentages,
82
int edgeid, double position,
83
const std::vector<std::pair<int, int> >& assignedVehicles) {
84
NIVissimDistrictConnection* o =
85
new NIVissimDistrictConnection(id, name, districts, percentages,
86
edgeid, position, assignedVehicles);
87
if (!dictionary(id, o)) {
88
delete o;
89
return false;
90
}
91
return true;
92
}
93
94
95
bool
96
NIVissimDistrictConnection::dictionary(int id, NIVissimDistrictConnection* o) {
97
DictType::iterator i = myDict.find(id);
98
if (i == myDict.end()) {
99
myDict[id] = o;
100
return true;
101
}
102
return false;
103
}
104
105
106
NIVissimDistrictConnection*
107
NIVissimDistrictConnection::dictionary(int id) {
108
DictType::iterator i = myDict.find(id);
109
if (i == myDict.end()) {
110
return nullptr;
111
}
112
return (*i).second;
113
}
114
115
void
116
NIVissimDistrictConnection::dict_BuildDistrictConnections() {
117
// pre-assign connections to districts
118
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
119
NIVissimDistrictConnection* c = (*i).second;
120
const std::vector<int>& districts = c->myDistricts;
121
for (std::vector<int>::const_iterator j = districts.begin(); j != districts.end(); j++) {
122
// assign connection to district
123
myDistrictsConnections[*j].push_back((*i).first);
124
}
125
}
126
}
127
128
129
void
130
NIVissimDistrictConnection::dict_CheckEdgeEnds() {
131
for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
132
const std::vector<int>& connections = (*k).second;
133
for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) {
134
NIVissimDistrictConnection* c = dictionary(*j);
135
c->checkEdgeEnd();
136
}
137
}
138
}
139
140
141
void
142
NIVissimDistrictConnection::checkEdgeEnd() {
143
NIVissimEdge* edge = NIVissimEdge::dictionary(myEdgeID);
144
assert(edge != 0);
145
edge->checkDistrictConnectionExistanceAt(myPosition);
146
}
147
148
149
void
150
NIVissimDistrictConnection::dict_BuildDistrictNodes(NBDistrictCont& dc,
151
NBNodeCont& nc) {
152
for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
153
// get the connections
154
const std::vector<int>& connections = (*k).second;
155
// retrieve the current district
156
std::string dsid = toString<int>((*k).first);
157
NBDistrict* district = new NBDistrict(dsid);
158
dc.insert(district);
159
// compute the middle of the district
160
PositionVector pos;
161
for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) {
162
NIVissimDistrictConnection* c = dictionary(*j);
163
pos.push_back(c->geomPosition());
164
}
165
Position distCenter = pos.getPolygonCenter();
166
if (connections.size() == 1) { // !!! ok, ok, maybe not the best way just to add an offset
167
distCenter.add(10, 10);
168
}
169
district->setCenter(distCenter);
170
// build the node
171
std::string id = "District" + district->getID();
172
NBNode* districtNode =
173
new NBNode(id, district->getPosition(), district);
174
if (!nc.insert(districtNode)) {
175
throw 1;
176
}
177
}
178
}
179
180
void
181
NIVissimDistrictConnection::dict_BuildDistricts(NBDistrictCont& dc,
182
NBEdgeCont& ec,
183
NBNodeCont& nc) {
184
// add the sources and sinks
185
// their normalised probability is computed within NBDistrict
186
// to avoid double code writing and more securty within the converter
187
// go through the district table
188
for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
189
// get the connections
190
const std::vector<int>& connections = (*k).second;
191
// retrieve the current district
192
NBDistrict* district =
193
dc.retrieve(toString<int>((*k).first));
194
NBNode* districtNode = nc.retrieve("District" + district->getID());
195
assert(district != 0 && districtNode != 0);
196
197
for (std::vector<int>::const_iterator l = connections.begin(); l != connections.end(); l++) {
198
NIVissimDistrictConnection* c = dictionary(*l);
199
// get the edge to connect the parking place to
200
NBEdge* e = ec.retrieve(toString<int>(c->myEdgeID));
201
if (e == nullptr) {
202
e = ec.retrievePossiblySplit(toString<int>(c->myEdgeID), c->myPosition);
203
}
204
if (e == nullptr) {
205
WRITE_WARNINGF(TL("Could not build district '%' - edge '%' is missing."), toString<int>((*k).first), toString<int>(c->myEdgeID));
206
continue;
207
}
208
std::string id = "ParkingPlace" + toString<int>(*l);
209
NBNode* parkingPlace = nc.retrieve(id);
210
if (parkingPlace == nullptr) {
211
double pos = c->getPosition();
212
if (pos < e->getLength() - pos) {
213
parkingPlace = e->getFromNode();
214
parkingPlace->invalidateIncomingConnections();
215
} else {
216
parkingPlace = e->getToNode();
217
parkingPlace->invalidateOutgoingConnections();
218
}
219
}
220
assert(
221
e->getToNode() == parkingPlace
222
||
223
e->getFromNode() == parkingPlace);
224
225
// build the connection to the source
226
if (e->getFromNode() == parkingPlace) {
227
id = "VissimFromParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID);
228
NBEdge* source =
229
new NBEdge(id, districtNode, parkingPlace,
230
"Connection", c->getMeanSpeed(/*distc*/) / 3.6, NBEdge::UNSPECIFIED_FRICTION, 3, -1,
231
NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);
232
if (!ec.insert(source)) { // !!! in den Konstruktor
233
throw 1; // !!!
234
}
235
double percNormed =
236
c->myPercentages[(*k).first];
237
if (!district->addSource(source, percNormed)) {
238
throw 1;
239
}
240
}
241
242
// build the connection to the destination
243
if (e->getToNode() == parkingPlace) {
244
id = "VissimToParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID);
245
NBEdge* destination =
246
new NBEdge(id, parkingPlace, districtNode,
247
"Connection", 100. / 3.6, NBEdge::UNSPECIFIED_FRICTION, 2, -1,
248
NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);
249
if (!ec.insert(destination)) { // !!! (in den Konstruktor)
250
throw 1; // !!!
251
}
252
double percNormed2 =
253
c->myPercentages[(*k).first];
254
if (!district->addSink(destination, percNormed2)) {
255
throw 1; // !!!
256
}
257
}
258
259
/*
260
if(e->getToNode()==districtNode) {
261
double percNormed =
262
c->myPercentages[(*k).first];
263
district->addSink(e, percNormed);
264
}
265
if(e->getFromNode()==districtNode) {
266
double percNormed =
267
c->myPercentages[(*k).first];
268
district->addSource(e, percNormed);
269
}
270
*/
271
}
272
273
/*
274
// add them as sources and sinks to the current district
275
for(std::vector<int>::const_iterator l=connections.begin(); l!=connections.end(); l++) {
276
// get the current connections
277
NIVissimDistrictConnection *c = dictionary(*l);
278
// get the edge to connect the parking place to
279
NBEdge *e = NBEdgeCont::retrieve(toString<int>(c->myEdgeID));
280
Position edgepos = c->geomPosition();
281
NBNode *edgeend = e->tryGetNodeAtPosition(c->myPosition,
282
e->getLength()/4.0);
283
if(edgeend==0) {
284
// Edge splitting omitted on build district connections by now
285
assert(false);
286
}
287
288
// build the district-node if not yet existing
289
std::string id = "VissimParkingplace" + district->getID();
290
NBNode *districtNode = nc.retrieve(id);
291
assert(districtNode!=0);
292
293
if(e->getToNode()==edgeend) {
294
// build the connection to the source
295
id = std::string("VissimFromParkingplace")
296
+ toString<int>((*k).first) + "-"
297
+ toString<int>(c->myID);
298
NBEdge *source =
299
new NBEdge(id, id, districtNode, edgeend,
300
"Connection", 100/3.6, 2, 100, 0,
301
NBEdge::EDGEFUNCTION_SOURCE);
302
NBEdgeCont::insert(source); // !!! (in den Konstruktor)
303
double percNormed =
304
c->myPercentages[(*k).first];
305
district->addSource(source, percNormed);
306
} else {
307
// build the connection to the destination
308
id = std::string("VissimToParkingplace")
309
+ toString<int>((*k).first) + "-"
310
+ toString<int>(c->myID);
311
NBEdge *destination =
312
new NBEdge(id, id, edgeend, districtNode,
313
"Connection", 100/3.6, 2, 100, 0,
314
NBEdge::EDGEFUNCTION_SINK);
315
NBEdgeCont::insert(destination); // !!! (in den Konstruktor)
316
317
// add both the source and the sink to the district
318
double percNormed =
319
c->myPercentages[(*k).first];
320
district->addSink(destination, percNormed);
321
}
322
}
323
*/
324
}
325
}
326
327
328
329
Position
330
NIVissimDistrictConnection::geomPosition() const {
331
NIVissimAbstractEdge* e = NIVissimEdge::dictionary(myEdgeID);
332
return e->getGeomPosition(myPosition);
333
}
334
335
336
NIVissimDistrictConnection*
337
NIVissimDistrictConnection::dict_findForEdge(int edgeid) {
338
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
339
if ((*i).second->myEdgeID == edgeid) {
340
return (*i).second;
341
}
342
}
343
return nullptr;
344
}
345
346
347
void
348
NIVissimDistrictConnection::clearDict() {
349
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
350
delete (*i).second;
351
}
352
myDict.clear();
353
}
354
355
356
double
357
NIVissimDistrictConnection::getMeanSpeed() const {
358
//assert(myAssignedVehicles.size()!=0);
359
if (myAssignedVehicles.size() == 0) {
360
WRITE_WARNINGF(TL("No streams assigned at district'%'.\n Using default speed 200km/h"), toString(myID));
361
return (double) 200 / (double) 3.6;
362
}
363
double speed = 0;
364
std::vector<std::pair<int, int> >::const_iterator i;
365
for (i = myAssignedVehicles.begin(); i != myAssignedVehicles.end(); i++) {
366
speed += getRealSpeed((*i).second);
367
}
368
return speed / (double) myAssignedVehicles.size();
369
}
370
371
372
double
373
NIVissimDistrictConnection::getRealSpeed(int distNo) const {
374
std::string id = toString<int>(distNo);
375
Distribution* dist = DistributionCont::dictionary("speed", id);
376
if (dist == nullptr) {
377
WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);
378
WRITE_WARNING(TL(". Using default."));
379
return OptionsCont::getOptions().getFloat("vissim.default-speed");
380
}
381
assert(dist != 0);
382
double speed = dist->getMax();
383
if (speed < 0 || speed > 1000) {
384
WRITE_WARNING(" False speed at district '" + id);
385
WRITE_WARNING(TL(". Using default."));
386
speed = OptionsCont::getOptions().getFloat("vissim.default-speed");
387
}
388
return speed;
389
}
390
391
392
/****************************************************************************/
393
394