Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netimport/vissim/tempstructs/NIVissimDisturbance.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 NIVissimDisturbance.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Michael Behrisch
17
/// @date Sept 2002
18
///
19
// -------------------
20
/****************************************************************************/
21
#include <config.h>
22
23
24
#include <map>
25
#include <string>
26
#include <iostream>
27
#include <cassert>
28
#include <utils/common/ToString.h>
29
#include <utils/common/MsgHandler.h>
30
#include <utils/geom/GeomHelper.h>
31
#include <utils/geom/Boundary.h>
32
#include <netbuild/NBEdge.h>
33
#include <netbuild/NBNode.h>
34
#include <netbuild/NBEdgeCont.h>
35
#include <netbuild/NBNodeCont.h>
36
#include "NIVissimEdge.h"
37
#include "NIVissimConnection.h"
38
#include "NIVissimNodeDef.h"
39
#include "NIVissimDisturbance.h"
40
#include "NIVissimNodeParticipatingEdgeVector.h"
41
42
43
// ===========================================================================
44
// static member variables
45
// ===========================================================================
46
NIVissimDisturbance::DictType NIVissimDisturbance::myDict;
47
int NIVissimDisturbance::myRunningID = 100000000;
48
49
int NIVissimDisturbance::refusedProhibits = 0;
50
51
52
// ===========================================================================
53
// method definitions
54
// ===========================================================================
55
NIVissimDisturbance::NIVissimDisturbance(int id,
56
const std::string& name,
57
const NIVissimExtendedEdgePoint& edge,
58
const NIVissimExtendedEdgePoint& by)
59
: myID(id), myNode(-1), myName(name), myEdge(edge), myDisturbance(by) {}
60
61
62
NIVissimDisturbance::~NIVissimDisturbance() {}
63
64
65
66
bool
67
NIVissimDisturbance::dictionary(const std::string& name,
68
const NIVissimExtendedEdgePoint& edge,
69
const NIVissimExtendedEdgePoint& by) {
70
int nid = myRunningID++;
71
NIVissimDisturbance* o =
72
new NIVissimDisturbance(nid, name, edge, by);
73
if (!dictionary(nid, o)) {
74
delete o;
75
}
76
return true;
77
}
78
79
80
bool
81
NIVissimDisturbance::dictionary(int id, NIVissimDisturbance* o) {
82
DictType::iterator i = myDict.find(id);
83
if (i == myDict.end()) {
84
myDict[id] = o;
85
return true;
86
}
87
return false;
88
}
89
90
91
NIVissimDisturbance*
92
NIVissimDisturbance::dictionary(int id) {
93
DictType::iterator i = myDict.find(id);
94
if (i == myDict.end()) {
95
return nullptr;
96
}
97
return (*i).second;
98
}
99
100
std::vector<int>
101
NIVissimDisturbance::getWithin(const AbstractPoly& poly) {
102
std::vector<int> ret;
103
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
104
if ((*i).second->crosses(poly)) {
105
ret.push_back((*i).second->myID);
106
}
107
}
108
return ret;
109
}
110
111
112
void
113
NIVissimDisturbance::computeBounding() {
114
assert(myBoundary == 0);
115
Boundary* bound = new Boundary();
116
if (NIVissimAbstractEdge::dictionary(myEdge.getEdgeID()) != nullptr) {
117
bound->add(myEdge.getGeomPosition());
118
}
119
if (NIVissimAbstractEdge::dictionary(myDisturbance.getEdgeID()) != nullptr) {
120
bound->add(myDisturbance.getGeomPosition());
121
}
122
myBoundary = bound;
123
assert(myBoundary != 0 && myBoundary->xmax() >= myBoundary->xmin());
124
}
125
126
127
128
bool
129
NIVissimDisturbance::addToNode(NBNode* node, NBDistrictCont& dc,
130
NBNodeCont& nc, NBEdgeCont& ec) {
131
myNode = 0;
132
NIVissimConnection* pc =
133
NIVissimConnection::dictionary(myEdge.getEdgeID());
134
NIVissimConnection* bc =
135
NIVissimConnection::dictionary(myDisturbance.getEdgeID());
136
if (pc == nullptr && bc == nullptr) {
137
// This has not been tested completely, yet
138
// Both competing abstract edges are normal edges
139
// We have to find a crossing point, build a node here,
140
// split both edges and add the connections
141
NIVissimEdge* e1 = NIVissimEdge::dictionary(myEdge.getEdgeID());
142
NIVissimEdge* e2 = NIVissimEdge::dictionary(myDisturbance.getEdgeID());
143
WRITE_WARNINGF(TL("Ugly split to prohibit '%' by '%'."), toString<int>(e1->getID()), toString<int>(e2->getID()));
144
//Position pos = e1->crossesEdgeAtPoint(e2);
145
std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID());
146
std::string id2 = toString<int>(e2->getID()) + "x" + toString<int>(e1->getID());
147
NBNode* node1 = nc.retrieve(id1);
148
NBNode* node2 = nc.retrieve(id2);
149
NBNode* splitNode = node1 == nullptr ? node2 : node1;
150
assert(node1 == nullptr || node2 == nullptr);
151
if (splitNode == nullptr) {
152
refusedProhibits++;
153
return false;
154
/* node = new NBNode(id1, pos.x(), pos.y(), "priority");
155
if(!myNodeCont.insert(node)) {
156
"nope, NIVissimDisturbance" << endl;
157
throw 1;
158
}*/
159
}
160
ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e1->getID()), myEdge.getPosition()), splitNode);
161
ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e2->getID()), myDisturbance.getPosition()), splitNode);
162
// !!! in some cases, one of the edges is not being build because it's too short
163
// !!! what to do in these cases?
164
NBEdge* mayDriveFrom = ec.retrieve(toString<int>(e1->getID()) + "[0]");
165
NBEdge* mayDriveTo = ec.retrieve(toString<int>(e1->getID()) + "[1]");
166
NBEdge* mustStopFrom = ec.retrieve(toString<int>(e2->getID()) + "[0]");
167
NBEdge* mustStopTo = ec.retrieve(toString<int>(e2->getID()) + "[1]");
168
if (mayDriveFrom != nullptr && mayDriveTo != nullptr && mustStopFrom != nullptr && mustStopTo != nullptr) {
169
node->addSortedLinkFoes(
170
NBConnection(mayDriveFrom, mayDriveTo),
171
NBConnection(mayDriveFrom, mayDriveTo));
172
} else {
173
refusedProhibits++;
174
return false;
175
// !!! warning
176
}
177
// }
178
} else if (pc != nullptr && bc == nullptr) {
179
// The prohibited abstract edge is a connection, the other
180
// is not;
181
// The connection will be prohibitesd by all connections
182
// outgoing from the "real" edge
183
184
NBEdge* e = ec.retrievePossiblySplit(toString<int>(myDisturbance.getEdgeID()), myDisturbance.getPosition());
185
if (e == nullptr) {
186
WRITE_WARNINGF(TL("Could not prohibit '%' by '%'. Have not found disturbance."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));
187
refusedProhibits++;
188
return false;
189
}
190
if (e->getFromNode() == e->getToNode()) {
191
WRITE_WARNINGF(TL("Could not prohibit '%' by '%'. Disturbance connects same node."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));
192
refusedProhibits++;
193
// What to do with self-looping edges?
194
return false;
195
}
196
// get the begin of the prohibited connection
197
std::string id_pcoe = toString<int>(pc->getFromEdgeID());
198
std::string id_pcie = toString<int>(pc->getToEdgeID());
199
NBEdge* const pcoe = ec.retrievePossiblySplit(id_pcoe, id_pcie, true);
200
NBEdge* const pcie = ec.retrievePossiblySplit(id_pcie, id_pcoe, false);
201
// check whether its ending node is the node the prohibited
202
// edge end at
203
if (pcoe != nullptr && pcie != nullptr && pcoe->getToNode() == e->getToNode()) {
204
// if so, simply prohibit the connections
205
NBNode* const toNode = e->getToNode();
206
for (NBEdge* const edge : e->getConnectedEdges()) {
207
toNode->addSortedLinkFoes(NBConnection(e, edge), NBConnection(pcoe, pcie));
208
}
209
} else {
210
WRITE_WARNINGF(TL("Would have to split edge '%' to build a prohibition"), e->getID());
211
refusedProhibits++;
212
// quite ugly - why was it not build?
213
return false;
214
/*
215
std::string nid1 = e->getID() + "[0]";
216
std::string nid2 = e->getID() + "[1]";
217
218
if(ec.splitAt(e, node)) {
219
node->addSortedLinkFoes(
220
NBConnection(
221
ec.retrieve(nid1),
222
ec.retrieve(nid2)
223
),
224
getConnection(node, myEdge.getEdgeID())
225
);
226
}
227
*/
228
}
229
} else if (bc != nullptr && pc == nullptr) {
230
// The prohibiting abstract edge is a connection, the other
231
// is not;
232
// We have to split the other one and add the prohibition
233
// description
234
235
NBEdge* e = ec.retrievePossiblySplit(toString<int>(myEdge.getEdgeID()), myEdge.getPosition());
236
if (e == nullptr) {
237
WRITE_WARNINGF(TL("Could not prohibit '%' - it was not built."), toString<int>(myEdge.getEdgeID()));
238
return false;
239
}
240
std::string nid1 = e->getID() + "[0]";
241
std::string nid2 = e->getID() + "[1]";
242
if (e->getFromNode() == e->getToNode()) {
243
WRITE_WARNINGF(TL("Could not prohibit '%' by '%'."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));
244
refusedProhibits++;
245
// What to do with self-looping edges?
246
return false;
247
}
248
// get the begin of the prohibiting connection
249
std::string id_bcoe = toString<int>(bc->getFromEdgeID());
250
std::string id_bcie = toString<int>(bc->getToEdgeID());
251
NBEdge* const bcoe = ec.retrievePossiblySplit(id_bcoe, id_bcie, true);
252
NBEdge* const bcie = ec.retrievePossiblySplit(id_bcie, id_bcoe, false);
253
// check whether its ending node is the node the prohibited
254
// edge end at
255
if (bcoe != nullptr && bcie != nullptr && bcoe->getToNode() == e->getToNode()) {
256
// if so, simply prohibit the connections
257
NBNode* const toNode = e->getToNode();
258
for (NBEdge* const edge : e->getConnectedEdges()) {
259
toNode->addSortedLinkFoes(NBConnection(bcoe, bcie), NBConnection(e, edge));
260
}
261
} else {
262
WRITE_WARNINGF(TL("Would have to split edge '%' to build a prohibition"), e->getID());
263
refusedProhibits++;
264
return false;
265
/*
266
// quite ugly - why was it not build?
267
if(ec.splitAt(e, node)) {
268
node->addSortedLinkFoes(
269
getConnection(node, myDisturbance.getEdgeID()),
270
NBConnection(
271
ec.retrieve(nid1),
272
ec.retrieve(nid2)
273
)
274
);
275
}
276
*/
277
}
278
} else {
279
// both the prohibiting and the prohibited abstract edges
280
// are connections
281
// We can retrieve the conected edges and add the desription
282
NBConnection conn1 = getConnection(node, myDisturbance.getEdgeID());
283
NBConnection conn2 = getConnection(node, myEdge.getEdgeID());
284
if (!conn1.check(ec) || !conn2.check(ec)) {
285
refusedProhibits++;
286
return false;
287
}
288
node->addSortedLinkFoes(conn1, conn2);
289
}
290
return true;
291
}
292
293
294
NBConnection
295
NIVissimDisturbance::getConnection(NBNode* node, int aedgeid) {
296
if (NIVissimEdge::dictionary(myEdge.getEdgeID()) == nullptr) {
297
NIVissimConnection* c = NIVissimConnection::dictionary(aedgeid);
298
NBEdge* from =
299
node->getPossiblySplittedIncoming(toString<int>(c->getFromEdgeID()));
300
NBEdge* to =
301
node->getPossiblySplittedOutgoing(toString<int>(c->getToEdgeID()));
302
303
// source is a connection
304
return NBConnection(toString<int>(c->getFromEdgeID()), from,
305
toString<int>(c->getToEdgeID()), to);
306
} else {
307
WRITE_WARNING(TL("NIVissimDisturbance: no connection"));
308
return NBConnection::InvalidConnection;
309
// throw 1; // !!! what to do?
310
}
311
312
}
313
314
void
315
NIVissimDisturbance::clearDict() {
316
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
317
delete (*i).second;
318
}
319
myDict.clear();
320
}
321
322
323
void
324
NIVissimDisturbance::dict_SetDisturbances() {
325
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
326
NIVissimDisturbance* d = (*i).second;
327
NIVissimAbstractEdge::dictionary(d->myEdge.getEdgeID())->addDisturbance((*i).first);
328
NIVissimAbstractEdge::dictionary(d->myDisturbance.getEdgeID())->addDisturbance((*i).first);
329
}
330
/* for(DictType::iterator i=myDict.begin(); i!=myDict.end(); i++) {
331
delete (*i).second;
332
}
333
*/
334
}
335
336
337
void
338
NIVissimDisturbance::reportRefused() {
339
if (refusedProhibits > 0) {
340
WRITE_WARNINGF(TL("Could not build % of % disturbances."), toString<int>(refusedProhibits), toString<int>((int)myDict.size()));
341
}
342
}
343
344
345
/****************************************************************************/
346
347