Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netimport/vissim/tempstructs/NIVissimEdge.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 NIVissimEdge.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @date Sept 2002
19
///
20
// A temporary storage for edges imported from Vissim
21
/****************************************************************************/
22
#include <config.h>
23
24
#include <string>
25
#include <algorithm>
26
#include <map>
27
#include <cassert>
28
#include <iomanip>
29
#include <cmath>
30
#include <iostream>
31
#include <sstream>
32
#include <iterator>
33
#include <utils/common/ToString.h>
34
#include <utils/geom/PositionVector.h>
35
#include <utils/geom/GeomHelper.h>
36
#include <utils/distribution/DistributionCont.h>
37
#include <netbuild/NBNode.h>
38
#include <netbuild/NBNodeCont.h>
39
#include <utils/options/OptionsCont.h>
40
#include "NIVissimNodeCluster.h"
41
#include "NIVissimDistrictConnection.h"
42
#include "NIVissimClosedLanesVector.h"
43
#include "NIVissimConnection.h"
44
#include "NIVissimDisturbance.h"
45
#include "NIVissimEdge.h"
46
#include <utils/common/MsgHandler.h>
47
48
49
// ===========================================================================
50
// static members
51
// ===========================================================================
52
NIVissimEdge::DictType NIVissimEdge::myDict;
53
int NIVissimEdge::myMaxID = 0;
54
std::vector<std::string> NIVissimEdge::myLanesWithMissingSpeeds;
55
56
57
// ===========================================================================
58
// method definitions
59
// ===========================================================================
60
NIVissimEdge::connection_position_sorter::connection_position_sorter(int edgeid)
61
: myEdgeID(edgeid) {}
62
63
64
int
65
NIVissimEdge::connection_position_sorter::operator()(int c1id,
66
int c2id) const {
67
NIVissimConnection* c1 = NIVissimConnection::dictionary(c1id);
68
NIVissimConnection* c2 = NIVissimConnection::dictionary(c2id);
69
double pos1 =
70
c1->getFromEdgeID() == myEdgeID
71
? c1->getFromPosition() : c1->getToPosition();
72
double pos2 =
73
c2->getFromEdgeID() == myEdgeID
74
? c2->getFromPosition() : c2->getToPosition();
75
return pos1 < pos2;
76
}
77
78
79
80
81
82
83
84
85
NIVissimEdge::connection_cluster_position_sorter::connection_cluster_position_sorter(int edgeid)
86
: myEdgeID(edgeid) {}
87
88
89
int
90
NIVissimEdge::connection_cluster_position_sorter::operator()(
91
NIVissimConnectionCluster* cc1,
92
NIVissimConnectionCluster* cc2) const {
93
double pos1 = cc1->getPositionForEdge(myEdgeID);
94
double pos2 = cc2->getPositionForEdge(myEdgeID);
95
if (pos2 < 0 || pos1 < 0) {
96
cc1->getPositionForEdge(myEdgeID);
97
cc2->getPositionForEdge(myEdgeID);
98
}
99
assert(pos1 >= 0 && pos2 >= 0);
100
return pos1 < pos2;
101
}
102
103
104
105
106
NIVissimEdge::NIVissimEdge(int id, const std::string& name,
107
const std::string& type,
108
std::vector<double> laneWidths,
109
double zuschlag1, double zuschlag2,
110
double /*length*/, const PositionVector& geom,
111
const NIVissimClosedLanesVector& clv) :
112
NIVissimAbstractEdge(id, geom),
113
myName(name), myType(type), myNoLanes((int)laneWidths.size()),
114
myLaneWidths(laneWidths),
115
myZuschlag1(zuschlag1), myZuschlag2(zuschlag2),
116
myClosedLanes(clv),
117
myLaneSpeeds(myNoLanes, -1),
118
myAmWithinJunction(false)
119
//, mySpeed(-1)
120
{
121
assert(myNoLanes >= 0);
122
if (myMaxID < myID) {
123
myMaxID = myID;
124
}
125
}
126
127
128
NIVissimEdge::~NIVissimEdge() {
129
for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
130
delete (*i);
131
}
132
myClosedLanes.clear();
133
}
134
135
136
bool
137
NIVissimEdge::dictionary(int id, const std::string& name,
138
const std::string& type, int noLanes,
139
double zuschlag1, double zuschlag2, double length,
140
const PositionVector& geom,
141
const NIVissimClosedLanesVector& clv) {
142
NIVissimEdge* o = new NIVissimEdge(id, name, type, std::vector<double>(noLanes, NBEdge::UNSPECIFIED_WIDTH),
143
zuschlag1, zuschlag2, length, geom, clv);
144
if (!dictionary(id, o)) {
145
delete o;
146
return false;
147
}
148
return true;
149
}
150
151
152
153
bool
154
NIVissimEdge::dictionary(int id, NIVissimEdge* o) {
155
DictType::iterator i = myDict.find(id);
156
if (i == myDict.end()) {
157
myDict[id] = o;
158
return true;
159
}
160
return false;
161
}
162
163
164
165
NIVissimEdge*
166
NIVissimEdge::dictionary(int id) {
167
DictType::iterator i = myDict.find(id);
168
if (i == myDict.end()) {
169
return nullptr;
170
}
171
return (*i).second;
172
}
173
174
175
void
176
NIVissimEdge::buildConnectionClusters() {
177
const double MAX_CLUSTER_DISTANCE = 10;
178
// build clusters for all edges made up from not previously assigne
179
// connections
180
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
181
int edgeid = (*i).first;
182
NIVissimEdge* edge = (*i).second;
183
// get all connectors using this edge
184
std::vector<int> connectors = edge->myIncomingConnections;
185
copy(edge->myOutgoingConnections.begin(), edge->myOutgoingConnections.end(), back_inserter(connectors));
186
if (connectors.size() == 0) {
187
continue;
188
}
189
// sort the connectors by the place on the edge
190
sort(connectors.begin(), connectors.end(), connection_position_sorter(edgeid));
191
// try to cluster the connections participating within the current edge
192
std::vector<int> currentCluster;
193
std::vector<int>::iterator j = connectors.begin();
194
bool outgoing = NIVissimConnection::dictionary(*j)->getFromEdgeID() == (*i).first;
195
double position = outgoing
196
? NIVissimConnection::dictionary(*j)->getFromPosition()
197
: NIVissimConnection::dictionary(*j)->getToPosition();
198
199
// skip connections already in a cluster
200
// !!! (?)
201
while (j != connectors.end() && NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
202
++j;
203
}
204
if (j == connectors.end()) {
205
continue;
206
}
207
currentCluster.push_back(*j);
208
do {
209
if (j + 1 != connectors.end() && !NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
210
bool n_outgoing = NIVissimConnection::dictionary(*(j + 1))->getFromEdgeID() == edgeid;
211
double n_position = n_outgoing
212
? NIVissimConnection::dictionary(*(j + 1))->getFromPosition()
213
: NIVissimConnection::dictionary(*(j + 1))->getToPosition();
214
if (n_outgoing == outgoing && fabs(n_position - position) < MAX_CLUSTER_DISTANCE) {
215
// ok, in same cluster as prior
216
currentCluster.push_back(*(j + 1));
217
} else {
218
// start new cluster
219
VectorHelper<int>::removeDouble(currentCluster);
220
edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
221
currentCluster.clear();
222
currentCluster.push_back(*(j + 1));
223
}
224
outgoing = n_outgoing;
225
position = n_position;
226
}
227
j++;
228
} while (j != connectors.end());
229
// add last connection
230
if (currentCluster.size() > 0) {
231
VectorHelper<int>::removeDouble(currentCluster);
232
edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
233
}
234
}
235
}
236
237
238
void
239
NIVissimEdge::dict_buildNBEdges(NBDistrictCont& dc, NBNodeCont& nc,
240
NBEdgeCont& ec, double offset) {
241
for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
242
NIVissimEdge* edge = (*i).second;
243
edge->buildNBEdge(dc, nc, ec, offset);
244
}
245
}
246
247
248
void
249
NIVissimEdge::dict_propagateSpeeds() {
250
DictType::iterator i;
251
for (i = myDict.begin(); i != myDict.end(); i++) {
252
NIVissimEdge* edge = (*i).second;
253
edge->setDistrictSpeed();
254
}
255
for (i = myDict.begin(); i != myDict.end(); i++) {
256
NIVissimEdge* edge = (*i).second;
257
edge->propagateSpeed(-1, std::vector<int>());
258
}
259
for (int j = 0; j < 3; j++) {
260
for (i = myDict.begin(); i != myDict.end(); i++) {
261
NIVissimEdge* edge = (*i).second;
262
edge->propagateOwn();
263
}
264
for (i = myDict.begin(); i != myDict.end(); i++) {
265
NIVissimEdge* edge = (*i).second;
266
edge->checkUnconnectedLaneSpeeds();
267
}
268
}
269
}
270
271
272
void
273
NIVissimEdge::checkUnconnectedLaneSpeeds() {
274
for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
275
if (myLaneSpeeds[i] == -1) {
276
double speed = -1;
277
int j1 = i - 1; // !!! recheck - j1 may become negative?
278
int j2 = i;
279
while (j2 != (int) myLaneSpeeds.size() && myLaneSpeeds[j2] == -1) {
280
j2++;
281
}
282
if (j1 < 0) {
283
if (j2 < (int) myLaneSpeeds.size()) {
284
speed = myLaneSpeeds[j2];
285
}
286
} else {
287
if (j2 >= (int) myLaneSpeeds.size()) {
288
speed = myLaneSpeeds[j1];
289
} else {
290
speed = (myLaneSpeeds[j1] + myLaneSpeeds[j2]) / (double) 2.0;
291
}
292
}
293
if (speed == -1) {
294
continue;
295
}
296
myLaneSpeeds[i] = speed;
297
std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
298
for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
299
NIVissimConnection* c = *j;
300
NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
301
// propagate
302
e->propagateSpeed(/*dc, */speed, c->getToLanes());
303
}
304
}
305
}
306
}
307
308
309
void
310
NIVissimEdge::propagateOwn() {
311
for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
312
if (myLaneSpeeds[i] == -1) {
313
continue;
314
}
315
std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
316
for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
317
NIVissimConnection* c = *j;
318
NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
319
// propagate
320
e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
321
}
322
}
323
}
324
325
326
void
327
NIVissimEdge::propagateSpeed(double speed, std::vector<int> forLanes) {
328
// if no lane is given, all set be set
329
if (forLanes.size() == 0) {
330
for (int i = 0; i < myNoLanes; i++) {
331
forLanes.push_back((int) i);
332
}
333
}
334
// for the case of a first call
335
// go through the lanes
336
for (std::vector<int>::const_iterator i = forLanes.begin(); i < forLanes.end(); i++) {
337
// check whether a speed was set before
338
if (myLaneSpeeds[*i] != -1) {
339
// do not reset it from incoming
340
continue;
341
}
342
// check whether the lane has a new speed to set
343
if ((int) myPatchedSpeeds.size() > *i && myPatchedSpeeds[*i] != -1) {
344
// use it
345
speed = getRealSpeed(/*dc, */myPatchedSpeeds[*i]);
346
}
347
// check whether a speed is given
348
if (speed == -1) {
349
// do nothing if not
350
continue;
351
}
352
// set the lane's speed to the given
353
myLaneSpeeds[*i] = speed;
354
// propagate the speed further
355
// get the list of connected edges
356
std::vector<NIVissimConnection*> connected = getOutgoingConnected(*i);
357
// go through the list
358
for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
359
NIVissimConnection* c = *j;
360
NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
361
// propagate
362
e->propagateSpeed(/*dc, */speed, c->getToLanes());
363
}
364
}
365
}
366
367
368
369
void
370
NIVissimEdge::setDistrictSpeed() {
371
if (myDistrictConnections.size() > 0) {
372
double pos = *(myDistrictConnections.begin());
373
if (pos < getLength() - pos) {
374
NIVissimDistrictConnection* d =
375
NIVissimDistrictConnection::dict_findForEdge(myID);
376
if (d != nullptr) {
377
double speed = d->getMeanSpeed(/*dc*/);
378
if (speed == -1) {
379
return;
380
}
381
for (int i = 0; i < myNoLanes; i++) {
382
myLaneSpeeds[i] = speed;
383
// propagate the speed further
384
// get the list of connected edges
385
std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
386
// go through the list
387
for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
388
NIVissimConnection* c = *j;
389
NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
390
// propagate
391
e->propagateSpeed(/*dc, */speed, c->getToLanes());
392
}
393
}
394
}
395
}
396
}
397
}
398
399
400
std::vector<NIVissimConnection*>
401
NIVissimEdge::getOutgoingConnected(int lane) const {
402
std::vector<NIVissimConnection*> ret;
403
for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
404
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
405
const std::vector<int>& lanes = c->getFromLanes();
406
if (find(lanes.begin(), lanes.end(), lane) != lanes.end()) {
407
NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
408
if (e != nullptr) {
409
ret.push_back(c);
410
}
411
}
412
}
413
return ret;
414
}
415
416
417
void
418
NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec,
419
double sameNodesOffset) {
420
// build the edge
421
std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
422
NBNode* fromNode, *toNode;
423
fromNode = toNode = nullptr;
424
sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID));
425
sort(myDistrictConnections.begin(), myDistrictConnections.end());
426
ConnectionClusters tmpClusters = myConnectionClusters;
427
if (tmpClusters.size() != 0) {
428
sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID));
429
// get or build the from-node
430
// A node may have to be build when the edge starts or ends at
431
// a parking place or something like this
432
fromInf = getFromNode(nc, tmpClusters);
433
fromNode = fromInf.second;
434
// get or build the to-node
435
//if(tmpClusters.size()>0) {
436
toInf = getToNode(nc, tmpClusters);
437
toNode = toInf.second;
438
if (fromInf.first != 0 && toNode != nullptr && fromInf.first->around(toNode->getPosition())) {
439
WRITE_WARNINGF(TL("Will not build edge '%'."), toString(myID));
440
myAmWithinJunction = true;
441
return;
442
}
443
//}
444
// if both nodes are the same, resolve the problem otherwise
445
if (fromNode == toNode) {
446
std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode);
447
if (fromNode != tmp.first) {
448
fromInf.first = 0;
449
}
450
if (toNode != tmp.second) {
451
toInf.first = 0;
452
}
453
fromNode = tmp.first;
454
toNode = tmp.second;
455
}
456
}
457
458
//
459
if (fromNode == nullptr) {
460
fromInf.first = 0;
461
Position pos = myGeom[0];
462
fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, SumoXMLNodeType::NOJUNCTION);
463
if (!nc.insert(fromNode)) {
464
throw ProcessError(TLF("Could not insert node '%' to nodes container.", fromNode->getID()));
465
}
466
}
467
if (toNode == nullptr) {
468
toInf.first = 0;
469
Position pos = myGeom[-1];
470
toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, SumoXMLNodeType::NOJUNCTION);
471
if (!nc.insert(toNode)) {
472
throw ProcessError(TLF("Could not insert node '%' to nodes container.", toNode->getID()));
473
}
474
}
475
476
// build the edge
477
double avgSpeed = 0;
478
for (int i = 0; i < myNoLanes; i++) {
479
if ((int)myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
480
myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
481
avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
482
} else {
483
avgSpeed += myLaneSpeeds[i];
484
}
485
}
486
avgSpeed /= (double) myLaneSpeeds.size();
487
avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");
488
489
if (fromNode == toNode) {
490
WRITE_WARNINGF(TL("Could not build edge '%'; would connect same node."), toString(myID));
491
return;
492
}
493
494
NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType,
495
avgSpeed / 3.6, NBEdge::UNSPECIFIED_FRICTION, myNoLanes, -1,
496
NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
497
myGeom, LaneSpreadFunction::CENTER, myName, "", true);
498
for (int i = 0; i < myNoLanes; i++) {
499
buildEdge->setLaneWidth(i, myLaneWidths[i]);
500
if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
501
buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (double) 3.6);
502
} else {
503
buildEdge->setSpeed(i, myLaneSpeeds[i] / (double) 3.6);
504
}
505
}
506
ec.insert(buildEdge);
507
// check whether the edge contains any other clusters
508
if (tmpClusters.size() > 0) {
509
bool cont = true;
510
for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) {
511
// split the edge at the previously build node
512
std::string nextID = buildEdge->getID() + "[1]";
513
cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
514
// !!! what to do if the edge could not be split?
515
buildEdge = ec.retrieve(nextID);
516
}
517
}
518
}
519
520
521
double
522
NIVissimEdge::getRealSpeed(int distNo) {
523
std::string id = toString<int>(distNo);
524
Distribution* dist = DistributionCont::dictionary("speed", id);
525
if (dist == nullptr) {
526
WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);
527
return -1;
528
}
529
assert(dist != 0);
530
double speed = dist->getMax();
531
if (speed < 0 || speed > 1000) {
532
WRITE_WARNINGF(TL("What about distribution '%'"), toString<int>(distNo));
533
}
534
return speed;
535
}
536
537
/*
538
bool
539
NIVissimEdge::recheckSpeedPatches()
540
{
541
// int speed_idx = -1;
542
// check set speeds
543
if(myPatchedSpeeds.size()!=0) {
544
std::vector<double>::iterator i =
545
std::find(myPatchedSpeeds.begin(), myPatchedSpeeds.end(), -1);
546
if(myPatchedSpeeds.size()!=myNoLanes||i!=myPatchedSpeeds.end()) {
547
cot << "Warning! Not all lanes are patched! (edge:" << myID << ")." << endl;
548
}
549
//
550
if(std::vector<double>Helper::maxValue(myPatchedSpeeds)!=std::vector<double>Helper::minValue(myPatchedSpeeds)) {
551
cot << "Warning! Not all lanes have the same speed!! (edge:" << myID << ")." << endl;
552
}
553
//
554
/ // !!! ist natuerlich Quatsch - erst recht, wenn Edges zusammengefasst werden
555
speed = std::vector<double>Helper::sum(myPatchedSpeeds);
556
speed /= (double) myPatchedSpeeds.size();*/
557
/* return true;
558
}
559
if(myDistrictConnections.size()>0) {
560
double pos = *(myDistrictConnections.begin());
561
// if(pos<10) {
562
NIVissimDistrictConnection *d =
563
NIVissimDistrictConnection::dict_findForEdge(myID);
564
if(d!=0) {
565
return true;
566
// speed = d->getMeanSpeed();
567
}
568
// }
569
// return true;
570
}
571
return false;
572
}
573
*/
574
575
std::pair<NIVissimConnectionCluster*, NBNode*>
576
NIVissimEdge::getFromNode(NBNodeCont& nc, ConnectionClusters& clusters) {
577
// changed MAX_DISTANCE from 10 to 3.5, because 3.5 is the default lane width in VISSIM
578
const double MAX_DISTANCE = 3.5;
579
assert(clusters.size() >= 1);
580
const Position& beg = myGeom.front();
581
NIVissimConnectionCluster* c = *(clusters.begin());
582
// check whether the edge starts within a already build node
583
if (c->around(beg, MAX_DISTANCE)) {
584
clusters.erase(clusters.begin());
585
return std::pair<NIVissimConnectionCluster*, NBNode*>
586
(c, c->getNBNode());
587
}
588
// check for a parking place at the begin
589
if (myDistrictConnections.size() > 0) {
590
double pos = *(myDistrictConnections.begin());
591
if (pos < 10) {
592
NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
593
if (!nc.insert(node)) {
594
throw 1;
595
}
596
while (myDistrictConnections.size() > 0 && *(myDistrictConnections.begin()) < 10) {
597
myDistrictConnections.erase(myDistrictConnections.begin());
598
}
599
return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
600
}
601
}
602
// build a new node for the edge's begin otherwise
603
NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
604
if (!nc.insert(node)) {
605
throw 1;
606
}
607
return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
608
}
609
610
611
std::pair<NIVissimConnectionCluster*, NBNode*>
612
NIVissimEdge::getToNode(NBNodeCont& nc, ConnectionClusters& clusters) {
613
const Position& end = myGeom.back();
614
if (clusters.size() > 0) {
615
const double MAX_DISTANCE = 10.;
616
assert(clusters.size() >= 1);
617
NIVissimConnectionCluster* c = *(clusters.end() - 1);
618
// check whether the edge ends within a already build node
619
if (c->around(end, MAX_DISTANCE)) {
620
clusters.erase(clusters.end() - 1);
621
return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
622
}
623
}
624
// check for a parking place at the end
625
if (myDistrictConnections.size() > 0) {
626
double pos = *(myDistrictConnections.end() - 1);
627
if (pos > myGeom.length() - 10) {
628
NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
629
if (!nc.insert(node)) {
630
throw 1;
631
}
632
while (myDistrictConnections.size() > 0 && *(myDistrictConnections.end() - 1) < myGeom.length() - 10) {
633
myDistrictConnections.erase(myDistrictConnections.end() - 1);
634
}
635
return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
636
}
637
}
638
639
// build a new node for the edge's end otherwise
640
NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
641
if (!nc.insert(node)) {
642
throw 1;
643
}
644
return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
645
/*
646
if (clusters.size()>0) {
647
NIVissimConnectionCluster *c = *(clusters.end()-1);
648
clusters.erase(clusters.end()-1);
649
return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
650
} else {
651
// !!! self-loop edge?!
652
return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), (*(myConnectionClusters.begin()))->getNBNode());
653
}
654
*/
655
}
656
657
658
std::pair<NBNode*, NBNode*>
659
NIVissimEdge::remapOneOfNodes(NBNodeCont& nc,
660
NIVissimDistrictConnection* d,
661
NBNode* fromNode, NBNode* toNode) {
662
std::string nid = "ParkingPlace" + toString<int>(d->getID());
663
if (d->geomPosition().distanceTo(fromNode->getPosition())
664
<
665
d->geomPosition().distanceTo(toNode->getPosition())) {
666
667
NBNode* newNode = new NBNode(nid,
668
fromNode->getPosition(),
669
SumoXMLNodeType::NOJUNCTION);
670
nc.erase(fromNode);
671
nc.insert(newNode);
672
return std::pair<NBNode*, NBNode*>(newNode, toNode);
673
} else {
674
NBNode* newNode = new NBNode(nid,
675
toNode->getPosition(),
676
SumoXMLNodeType::NOJUNCTION);
677
nc.erase(toNode);
678
nc.insert(newNode);
679
return std::pair<NBNode*, NBNode*>(fromNode, newNode);
680
}
681
}
682
683
684
685
std::pair<NBNode*, NBNode*>
686
NIVissimEdge::resolveSameNode(NBNodeCont& nc, double offset,
687
NBNode* prevFrom, NBNode* prevTo) {
688
// check whether the edge is connected to a district
689
// use it if so
690
NIVissimDistrictConnection* d =
691
NIVissimDistrictConnection::dict_findForEdge(myID);
692
if (d != nullptr) {
693
Position pos = d->geomPosition();
694
double position = d->getPosition();
695
// the district is at the begin of the edge
696
if (myGeom.length() - position > position) {
697
std::string nid = "ParkingPlace" + toString<int>(d->getID());
698
NBNode* node = nc.retrieve(nid);
699
if (node == nullptr) {
700
node = new NBNode(nid,
701
pos, SumoXMLNodeType::NOJUNCTION);
702
if (!nc.insert(node)) {
703
throw 1;
704
}
705
}
706
return std::pair<NBNode*, NBNode*>(node, prevTo);
707
}
708
// the district is at the end of the edge
709
else {
710
std::string nid = "ParkingPlace" + toString<int>(d->getID());
711
NBNode* node = nc.retrieve(nid);
712
if (node == nullptr) {
713
node = new NBNode(nid, pos, SumoXMLNodeType::NOJUNCTION);
714
if (!nc.insert(node)) {
715
throw 1;
716
}
717
}
718
assert(node != 0);
719
return std::pair<NBNode*, NBNode*>(prevFrom, node);
720
}
721
}
722
// otherwise, check whether the edge is some kind of
723
// a dead end...
724
// check which end is nearer to the node centre
725
if (myConnectionClusters.size() == 1) {
726
NBNode* node = prevFrom; // it is the same as getToNode()
727
728
NIVissimConnectionCluster* c = *(myConnectionClusters.begin());
729
// no end node given
730
if (c->around(myGeom.front(), offset) && !c->around(myGeom.back(), offset)) {
731
NBNode* end = new NBNode(
732
toString<int>(myID) + "-End",
733
myGeom.back(),
734
SumoXMLNodeType::NOJUNCTION);
735
if (!nc.insert(end)) {
736
throw 1;
737
}
738
return std::pair<NBNode*, NBNode*>(node, end);
739
}
740
741
// no begin node given
742
if (!c->around(myGeom.front(), offset) && c->around(myGeom.back(), offset)) {
743
NBNode* beg = new NBNode(
744
toString<int>(myID) + "-Begin",
745
myGeom.front(),
746
SumoXMLNodeType::NOJUNCTION);
747
if (!nc.insert(beg)) {
748
std::cout << "nope, NIVissimDisturbance" << std::endl;
749
throw 1;
750
}
751
return std::pair<NBNode*, NBNode*>(beg, node);
752
}
753
754
// self-loop edge - both points lie within the same cluster
755
if (c->around(myGeom.front()) && c->around(myGeom.back())) {
756
return std::pair<NBNode*, NBNode*>(node, node);
757
}
758
}
759
// what to do in other cases?
760
// It simply is a self-looping edge....
761
return std::pair<NBNode*, NBNode*>(prevFrom, prevTo);
762
}
763
764
765
766
767
void
768
NIVissimEdge::setNodeCluster(int nodeid) {
769
myNode = nodeid;
770
}
771
772
773
void
774
NIVissimEdge::buildGeom() {}
775
776
777
void
778
NIVissimEdge::addIncomingConnection(int id) {
779
myIncomingConnections.push_back(id);
780
}
781
782
783
void
784
NIVissimEdge::addOutgoingConnection(int id) {
785
myOutgoingConnections.push_back(id);
786
}
787
788
789
790
void
791
NIVissimEdge::mergedInto(NIVissimConnectionCluster* old,
792
NIVissimConnectionCluster* act) {
793
ConnectionClusters::iterator i =
794
std::find(myConnectionClusters.begin(), myConnectionClusters.end(), old);
795
if (i != myConnectionClusters.end()) {
796
myConnectionClusters.erase(i);
797
}
798
i = std::find(myConnectionClusters.begin(), myConnectionClusters.end(), act);
799
if (i == myConnectionClusters.end()) {
800
myConnectionClusters.push_back(act);
801
}
802
}
803
804
805
806
void
807
NIVissimEdge::removeFromConnectionCluster(NIVissimConnectionCluster* c) {
808
ConnectionClusters::iterator i =
809
std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
810
assert(i != myConnectionClusters.end());
811
myConnectionClusters.erase(i);
812
}
813
814
815
void
816
NIVissimEdge::addToConnectionCluster(NIVissimConnectionCluster* c) {
817
ConnectionClusters::iterator i =
818
std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
819
if (i == myConnectionClusters.end()) {
820
myConnectionClusters.push_back(c);
821
}
822
}
823
824
825
Position // !!! reference?
826
NIVissimEdge::getBegin2D() const {
827
return myGeom[0];
828
}
829
830
831
Position // !!! reference?
832
NIVissimEdge::getEnd2D() const {
833
return myGeom[-1];
834
}
835
836
837
double
838
NIVissimEdge::getLength() const {
839
return myGeom.length();
840
}
841
842
843
void
844
NIVissimEdge::checkDistrictConnectionExistanceAt(double pos) {
845
if (find(myDistrictConnections.begin(), myDistrictConnections.end(), pos) == myDistrictConnections.end()) {
846
myDistrictConnections.push_back(pos);
847
/* int id = NIVissimConnection::getMaxID() + 1;
848
std::vector<int> currentCluster;
849
currentCluster.push_back(id);
850
myConnectionClusters.push_back(
851
new NIVissimConnectionCluster(currentCluster, -1, myID));*/
852
}
853
}
854
855
856
void
857
NIVissimEdge::setSpeed(int lane, int speedDist) {
858
while ((int)myPatchedSpeeds.size() <= lane) {
859
myPatchedSpeeds.push_back(-1);
860
}
861
myPatchedSpeeds[lane] = speedDist;
862
}
863
864
865
void
866
NIVissimEdge::dict_checkEdges2Join() {
867
// go through the edges
868
for (DictType::iterator i1 = myDict.begin(); i1 != myDict.end(); i1++) {
869
// retrieve needed values from the first edge
870
NIVissimEdge* e1 = (*i1).second;
871
const PositionVector& g1 = e1->getGeometry();
872
// check all other edges
873
DictType::iterator i2 = i1;
874
i2++;
875
for (; i2 != myDict.end(); i2++) {
876
// retrieve needed values from the second edge
877
NIVissimEdge* e2 = (*i2).second;
878
const PositionVector& g2 = e2->getGeometry();
879
// get the connection description
880
NIVissimConnection* c = e1->getConnectionTo(e2);
881
if (c == nullptr) {
882
c = e2->getConnectionTo(e1);
883
}
884
// the edge must not be a direct contiuation of the other
885
if (c != nullptr) {
886
if ((c->getFromEdgeID() == e1->getID() && fabs(c->getFromPosition() - e1->getGeometry().length()) < 5)
887
||
888
(c->getFromEdgeID() == e2->getID() && fabs(c->getFromPosition() - e2->getGeometry().length()) < 5)) {
889
890
continue;
891
}
892
}
893
// only parallel edges which do end at the same node
894
// should be joined
895
// check for parallelity
896
// !!! the usage of an explicit value is not very fine
897
if (fabs(GeomHelper::angleDiff(g1.beginEndAngle(), g2.beginEndAngle())) > DEG2RAD(2.0)) {
898
// continue if the lines are not parallel
899
continue;
900
}
901
902
// check whether the same node is approached
903
// (the distance between the ends should not be too large)
904
// !!! the usage of an explicit value is not very fine
905
if (g1.back().distanceTo(g2.back()) > 10) {
906
// continue if the lines do not end at the same length
907
continue;
908
}
909
// ok, seem to be different lanes for the same edge
910
// mark as possibly joined later
911
e1->addToTreatAsSame(e2);
912
e2->addToTreatAsSame(e1);
913
}
914
}
915
}
916
917
918
bool
919
NIVissimEdge::addToTreatAsSame(NIVissimEdge* e) {
920
if (e == this) {
921
return false;
922
}
923
// check whether this edge already knows about the other
924
if (find(myToTreatAsSame.begin(), myToTreatAsSame.end(), e) == myToTreatAsSame.end()) {
925
myToTreatAsSame.push_back(e);
926
return true;
927
} else {
928
return false; // !!! check this
929
}
930
/*
931
//
932
std::vector<NIVissimEdge*>::iterator i;
933
// add to all other that shall be treated as same
934
bool changed = true;
935
while (changed) {
936
changed = false;
937
for (i = myToTreatAsSame.begin(); !changed && i != myToTreatAsSame.end(); i++) {
938
changed |= (*i)->addToTreatAsSame(e);
939
}
940
for (i = myToTreatAsSame.begin(); !changed && i != myToTreatAsSame.end(); i++) {
941
changed |= e->addToTreatAsSame(*i);
942
}
943
}
944
*/
945
}
946
947
NIVissimConnection*
948
NIVissimEdge::getConnectionTo(NIVissimEdge* e) {
949
std::vector<int>::iterator i;
950
for (i = myIncomingConnections.begin(); i != myIncomingConnections.end(); i++) {
951
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
952
if (c->getFromEdgeID() == e->getID()) {
953
return c;
954
}
955
}
956
for (i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
957
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
958
if (c->getToEdgeID() == e->getID()) {
959
return c;
960
}
961
}
962
return nullptr;
963
}
964
965
966
const std::vector<NIVissimEdge*>&
967
NIVissimEdge::getToTreatAsSame() const {
968
return myToTreatAsSame;
969
}
970
971
972
void
973
NIVissimEdge::reportUnsetSpeeds() {
974
if (myLanesWithMissingSpeeds.size() == 0) {
975
return;
976
}
977
std::ostringstream str;
978
str << "The following lanes have no explicit speed information:\n ";
979
for (std::vector<std::string>::iterator i = myLanesWithMissingSpeeds.begin(); i != myLanesWithMissingSpeeds.end(); ++i) {
980
if (i != myLanesWithMissingSpeeds.begin()) {
981
str << ", ";
982
}
983
str << *i;
984
}
985
WRITE_WARNING(str.str());
986
}
987
988
989
NIVissimEdge*
990
NIVissimEdge::getBestIncoming() const {
991
// @todo seems as this would have been a hard hack!
992
/*
993
for (std::vector<int>::const_iterator i = myIncomingConnections.begin(); i != myIncomingConnections.end(); ++i) {
994
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
995
return NIVissimEdge::dictionary(c->getFromEdgeID());
996
}
997
return 0;
998
*/
999
if (myIncomingConnections.size() != 0) {
1000
return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myIncomingConnections.front())->getFromEdgeID());
1001
}
1002
return nullptr;
1003
}
1004
1005
1006
NIVissimEdge*
1007
NIVissimEdge::getBestOutgoing() const {
1008
// @todo seems as this would have been a hard hack!
1009
/*
1010
for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); ++i) {
1011
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
1012
return NIVissimEdge::dictionary(c->getToEdgeID());
1013
}
1014
return 0;
1015
*/
1016
if (myOutgoingConnections.size() != 0) {
1017
return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myOutgoingConnections.front())->getToEdgeID());
1018
}
1019
return nullptr;
1020
}
1021
1022
1023
/****************************************************************************/
1024
1025