Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netimport/vissim/tempstructs/NIVissimConnectionCluster.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 NIVissimConnectionCluster.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 <algorithm>
25
#include <iostream>
26
#include <cassert>
27
#include <iterator>
28
#include <utils/geom/Boundary.h>
29
#include <utils/geom/GeomHelper.h>
30
#include <utils/common/VectorHelper.h>
31
#include <utils/common/MsgHandler.h>
32
#include <utils/common/ToString.h>
33
#include "NIVissimConnection.h"
34
#include "NIVissimDisturbance.h"
35
#include "NIVissimNodeCluster.h"
36
#include "NIVissimNodeDef.h"
37
#include "NIVissimEdge.h"
38
#include "NIVissimTL.h"
39
#include "NIVissimConnectionCluster.h"
40
41
42
// ===========================================================================
43
// static members
44
// ===========================================================================
45
NIVissimConnectionCluster::ContType NIVissimConnectionCluster::myClusters;
46
int NIVissimConnectionCluster::myFirstFreeID = 100000;
47
int NIVissimConnectionCluster::myStaticBlaID = 0;
48
49
50
51
// ===========================================================================
52
// method definitions
53
// ===========================================================================
54
// ---------------------------------------------------------------------------
55
// NIVissimConnectionCluster::NodeSubCluster - methods
56
// ---------------------------------------------------------------------------
57
NIVissimConnectionCluster::NodeSubCluster::NodeSubCluster(NIVissimConnection* c) {
58
add(c);
59
}
60
61
62
NIVissimConnectionCluster::NodeSubCluster::~NodeSubCluster() {}
63
64
65
void
66
NIVissimConnectionCluster::NodeSubCluster::add(NIVissimConnection* c) {
67
myBoundary.add(c->getBoundingBox());
68
myConnections.push_back(c);
69
}
70
71
72
void
73
NIVissimConnectionCluster::NodeSubCluster::add(const NIVissimConnectionCluster::NodeSubCluster& c) {
74
for (ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
75
add(*i);
76
}
77
}
78
79
80
int
81
NIVissimConnectionCluster::NodeSubCluster::size() const {
82
return (int)myConnections.size();
83
}
84
85
86
std::vector<int>
87
NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const {
88
std::vector<int> ret;
89
int id = NIVissimConnectionCluster::getNextFreeNodeID();
90
for (ConnectionCont::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
91
ret.push_back((*i)->getID());
92
(*i)->setNodeCluster(id);
93
}
94
return ret;
95
}
96
97
98
bool
99
NIVissimConnectionCluster::NodeSubCluster::overlapsWith(
100
const NIVissimConnectionCluster::NodeSubCluster& c,
101
double offset) {
102
assert(myBoundary.xmax() >= myBoundary.xmin());
103
assert(c.myBoundary.xmax() >= c.myBoundary.xmin());
104
return myBoundary.overlapsWith(c.myBoundary, offset);
105
}
106
107
108
109
// ---------------------------------------------------------------------------
110
// NIVissimConnectionCluster - methods
111
// ---------------------------------------------------------------------------
112
NIVissimConnectionCluster::NIVissimConnectionCluster(
113
const std::vector<int>& connections, int nodeCluster, int edgeid)
114
: myConnections(connections), myNodeCluster(nodeCluster),
115
myBlaID(myStaticBlaID++) {
116
recomputeBoundary();
117
myClusters.push_back(this);
118
assert(edgeid > 0);
119
if (edgeid >= 0) {
120
myEdges.push_back(edgeid);
121
}
122
// add information about incoming and outgoing edges
123
for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {
124
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
125
assert(c != 0);
126
myOutgoingEdges.push_back(c->getToEdgeID());
127
myIncomingEdges.push_back(c->getFromEdgeID());
128
assert(c->getFromEdgeID() == edgeid || c->getToEdgeID() == edgeid);
129
}
130
VectorHelper<int>::removeDouble(myIncomingEdges);
131
VectorHelper<int>::removeDouble(myOutgoingEdges);
132
}
133
134
135
NIVissimConnectionCluster::NIVissimConnectionCluster(
136
const std::vector<int>& connections, const Boundary& boundary,
137
int nodeCluster, const std::vector<int>& edges)
138
: myConnections(connections), myBoundary(boundary),
139
myNodeCluster(nodeCluster), myEdges(edges) {
140
myClusters.push_back(this);
141
recomputeBoundary();
142
assert(myBoundary.xmax() >= myBoundary.xmin());
143
// add information about incoming and outgoing edges
144
for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {
145
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
146
assert(c != 0);
147
myOutgoingEdges.push_back(c->getToEdgeID());
148
myIncomingEdges.push_back(c->getFromEdgeID());
149
assert(find(edges.begin(), edges.end(), c->getFromEdgeID()) != edges.end()
150
||
151
std::find(edges.begin(), edges.end(), c->getToEdgeID()) != edges.end());
152
}
153
VectorHelper<int>::removeDouble(myIncomingEdges);
154
VectorHelper<int>::removeDouble(myOutgoingEdges);
155
}
156
157
158
NIVissimConnectionCluster::~NIVissimConnectionCluster() {}
159
160
161
162
int
163
NIVissimConnectionCluster::getNextFreeNodeID() {
164
return myFirstFreeID++;
165
}
166
167
168
bool
169
NIVissimConnectionCluster::overlapsWith(NIVissimConnectionCluster* c,
170
double offset) const {
171
assert(myBoundary.xmax() >= myBoundary.xmin());
172
assert(c->myBoundary.xmax() >= c->myBoundary.xmin());
173
return c->myBoundary.overlapsWith(myBoundary, offset);
174
}
175
176
177
void
178
NIVissimConnectionCluster::add(NIVissimConnectionCluster* c) {
179
assert(myBoundary.xmax() >= myBoundary.xmin());
180
assert(c->myBoundary.xmax() >= c->myBoundary.xmin());
181
myBoundary.add(c->myBoundary);
182
for (std::vector<int>::iterator i = c->myConnections.begin(); i != c->myConnections.end(); i++) {
183
myConnections.push_back(*i);
184
}
185
VectorHelper<int>::removeDouble(myConnections);
186
assert(myNodeCluster == -1 || c->myNodeCluster == -1);
187
if (myNodeCluster == -1) {
188
myNodeCluster = c->myNodeCluster;
189
}
190
// inform edges about merging
191
// !!! merge should be done within one method
192
for (std::vector<int>::iterator j = c->myEdges.begin(); j != c->myEdges.end(); j++) {
193
NIVissimEdge::dictionary(*j)->mergedInto(c, this);
194
}
195
copy(c->myEdges.begin(), c->myEdges.end(), back_inserter(myEdges));
196
copy(c->myIncomingEdges.begin(), c->myIncomingEdges.end(),
197
back_inserter(myIncomingEdges));
198
copy(c->myOutgoingEdges.begin(), c->myOutgoingEdges.end(),
199
back_inserter(myOutgoingEdges));
200
VectorHelper<int>::removeDouble(myEdges);
201
VectorHelper<int>::removeDouble(myIncomingEdges);
202
VectorHelper<int>::removeDouble(myOutgoingEdges);
203
}
204
205
206
207
void
208
NIVissimConnectionCluster::joinBySameEdges(double offset) {
209
// !!! ...
210
// Further, we try to omit joining of overlaping nodes. This is done by holding
211
// the lists of incoming and outgoing edges and incrementally building the nodes
212
// regarding this information
213
std::vector<NIVissimConnectionCluster*> joinAble;
214
int pos = 0;
215
ContType::iterator i = myClusters.begin();
216
// step1 - faster but no complete
217
while (i != myClusters.end()) {
218
joinAble.clear();
219
ContType::iterator j = i + 1;
220
221
// check whether every combination has been processed
222
while (j != myClusters.end()) {
223
// check whether the current clusters overlap
224
if ((*i)->joinable(*j, offset)) {
225
joinAble.push_back(*j);
226
}
227
j++;
228
}
229
for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
230
k != joinAble.end(); k++) {
231
// add the overlaping cluster
232
(*i)->add(*k);
233
// erase the overlaping cluster
234
delete *k;
235
myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
236
}
237
//
238
if (joinAble.size() > 0) {
239
i = myClusters.begin() + pos;
240
// clear temporary storages
241
joinAble.clear();
242
} else {
243
i++;
244
pos++;
245
}
246
}
247
//
248
pos = 0;
249
i = myClusters.begin();
250
while (i != myClusters.end()) {
251
ContType::iterator j = i + 1;
252
// check whether every combination has been processed
253
while (j != myClusters.end()) {
254
// check whether the current clusters overlap
255
if ((*i)->joinable(*j, offset)) {
256
joinAble.push_back(*j);
257
}
258
j++;
259
}
260
for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
261
k != joinAble.end(); k++) {
262
// add the overlaping cluster
263
(*i)->add(*k);
264
// erase the overlaping cluster
265
delete *k;
266
myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
267
}
268
//
269
if (joinAble.size() > 0) {
270
i = myClusters.begin();
271
// clear temporary storages
272
joinAble.clear();
273
pos = 0;
274
} else {
275
i++;
276
pos++;
277
}
278
}
279
// check for weak district connections
280
// (junctions made up by district connections, where prohibitions are not
281
// modelled properly)
282
pos = 0;
283
i = myClusters.begin();
284
while (i != myClusters.end()) {
285
ContType::iterator j = i + 1;
286
// check whether every combination has been processed
287
while (j != myClusters.end()) {
288
// check whether the current clusters overlap
289
if ((*i)->isWeakDistrictConnRealisation(*j)) {
290
joinAble.push_back(*j);
291
}
292
j++;
293
}
294
for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
295
k != joinAble.end(); k++) {
296
// add the overlaping cluster
297
(*i)->add(*k);
298
// erase the overlaping cluster
299
delete *k;
300
myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
301
}
302
//
303
if (joinAble.size() > 0) {
304
i = myClusters.begin();
305
// clear temporary storages
306
joinAble.clear();
307
pos = 0;
308
} else {
309
i++;
310
pos++;
311
}
312
}
313
}
314
315
316
bool
317
NIVissimConnectionCluster::joinable(NIVissimConnectionCluster* c2, double offset) {
318
// join clusters which have at least one connection in common
319
if (VectorHelper<int>::subSetExists(myConnections, c2->myConnections)) {
320
return true;
321
}
322
323
// connections shall overlap otherwise
324
if (!overlapsWith(c2, offset)) {
325
return false;
326
}
327
328
// at least one of the clusters shall not be assigned to a node in previous (!!!??)
329
if (hasNodeCluster() && c2->hasNodeCluster()) {
330
return false;
331
}
332
333
// join clusters which where connections do disturb each other
334
if (VectorHelper<int>::subSetExists(c2->getDisturbanceParticipators(), myConnections)
335
||
336
VectorHelper<int>::subSetExists(getDisturbanceParticipators(), c2->myConnections)) {
337
338
return true;
339
}
340
341
342
// join clusters which do share the same incoming or outgoing edges (not mutually)
343
std::vector<int> extendedOutgoing1;
344
std::vector<int> extendedIncoming1;
345
std::vector<int> extendedOutgoing2;
346
std::vector<int> extendedIncoming2;
347
if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) {
348
extendedOutgoing1 =
349
extendByToTreatAsSame(myOutgoingEdges, myIncomingEdges);
350
extendedIncoming1 =
351
extendByToTreatAsSame(myIncomingEdges, myOutgoingEdges);
352
extendedOutgoing2 =
353
extendByToTreatAsSame(c2->myOutgoingEdges, c2->myIncomingEdges);
354
extendedIncoming2 =
355
extendByToTreatAsSame(c2->myIncomingEdges, c2->myOutgoingEdges);
356
} else {
357
extendedOutgoing1 = myIncomingEdges;
358
extendedIncoming1 = myOutgoingEdges;
359
extendedOutgoing2 = c2->myIncomingEdges;
360
extendedIncoming2 = c2->myOutgoingEdges;
361
}
362
363
if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2)
364
||
365
VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2)
366
) {
367
return true;
368
}
369
return false;
370
}
371
372
373
bool
374
NIVissimConnectionCluster::isWeakDistrictConnRealisation(NIVissimConnectionCluster* c2) {
375
if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) {
376
return false;
377
}
378
if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) {
379
return false;
380
}
381
382
// ok, may be the other way round
383
if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) {
384
return c2->isWeakDistrictConnRealisation(this);
385
}
386
// connections must cross
387
bool crosses = false;
388
for (std::vector<int>::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) {
389
const PositionVector& g1 = NIVissimConnection::dictionary(*j1)->getGeometry();
390
for (const int j2 : c2->myConnections) {
391
const PositionVector& g2 = NIVissimConnection::dictionary(j2)->getGeometry();
392
if (g1.intersects(g2)) {
393
crosses = true;
394
break;
395
}
396
}
397
}
398
if (!crosses) {
399
return false;
400
}
401
// ok, check for connection
402
if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) {
403
return false;
404
}
405
// check whether the connection is bidirectional
406
NIVissimEdge* oe = NIVissimEdge::dictionary(myOutgoingEdges[0]);
407
NIVissimEdge* ie = NIVissimEdge::dictionary(c2->myIncomingEdges[0]);
408
if (oe == nullptr || ie == nullptr) {
409
return false;
410
}
411
return fabs(GeomHelper::angleDiff(oe->getGeometry().beginEndAngle(), ie->getGeometry().beginEndAngle())) < DEG2RAD(5);
412
}
413
414
415
bool
416
NIVissimConnectionCluster::liesOnSameEdgesEnd(NIVissimConnectionCluster* cc2) {
417
//
418
for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
419
NIVissimConnection* c1 = NIVissimConnection::dictionary(*i);
420
for (std::vector<int>::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) {
421
NIVissimConnection* c2 = NIVissimConnection::dictionary(*j);
422
if (c1->getFromEdgeID() == c2->getFromEdgeID()) {
423
NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());
424
const PositionVector& g = e->getGeometry();
425
double pos1 = GeomHelper::nearest_offset_on_line_to_point2D(
426
g.front(), g.back(), c1->getBoundary().getCenter());
427
double pos2 = GeomHelper::nearest_offset_on_line_to_point2D(
428
g.front(), g.back(), c2->getBoundary().getCenter());
429
if (pos1 <= 5.0 && pos2 <= 5.0) {
430
return true;
431
}
432
}
433
if (c1->getToEdgeID() == c2->getToEdgeID()) {
434
NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());
435
const PositionVector& g = e->getGeometry();
436
double pos1 = GeomHelper::nearest_offset_on_line_to_point2D(
437
g.front(), g.back(), c1->getBoundary().getCenter());
438
double pos2 = GeomHelper::nearest_offset_on_line_to_point2D(
439
g.front(), g.back(), c2->getBoundary().getCenter());
440
if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) {
441
return true;
442
}
443
}
444
}
445
}
446
return false;
447
}
448
449
450
std::vector<int>
451
NIVissimConnectionCluster::extendByToTreatAsSame(const std::vector<int>& iv1,
452
const std::vector<int>& iv2) const {
453
std::vector<int> ret(iv1);
454
for (std::vector<int>::const_iterator i = iv1.begin(); i != iv1.end(); i++) {
455
NIVissimEdge* e = NIVissimEdge::dictionary(*i);
456
const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame();
457
for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) {
458
if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) {
459
ret.push_back((*j)->getID());
460
}
461
}
462
}
463
return ret;
464
}
465
466
std::vector<int>
467
NIVissimConnectionCluster::getDisturbanceParticipators() {
468
std::vector<int> ret;
469
for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
470
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
471
const std::vector<int>& disturbances = c->getDisturbances();
472
for (std::vector<int>::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) {
473
NIVissimDisturbance* d = NIVissimDisturbance::dictionary(*j);
474
ret.push_back(d->getEdgeID());
475
ret.push_back(d->getDisturbanceID());
476
}
477
}
478
return ret;
479
}
480
481
482
void
483
NIVissimConnectionCluster::buildNodeClusters() {
484
for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
485
std::vector<int> disturbances;
486
std::vector<int> tls;
487
std::vector<int> nodes;
488
int tlsid = -1;
489
int nodeid = -1;
490
if ((*i)->myConnections.size() > 0) {
491
(*i)->recomputeBoundary();
492
disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary);
493
}
494
nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0);
495
if (nodes.size() > 1) {
496
WRITE_WARNING(TL("NIVissimConnectionCluster: More than a single node"));
497
// throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein
498
}
499
if (nodes.size() > 0) {
500
nodeid = nodes[0];
501
}
502
//
503
//
504
int id = NIVissimNodeCluster::dictionary(
505
nodeid, tlsid, (*i)->myConnections,
506
disturbances, (*i)->myIncomingEdges.size() < 2);
507
assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0);
508
(*i)->myNodeCluster = id;
509
}
510
}
511
512
513
void
514
NIVissimConnectionCluster::_debugOut(std::ostream& into) {
515
for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
516
std::vector<int> connections = (*i)->myConnections;
517
for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) {
518
if (j != connections.begin()) {
519
into << ", ";
520
}
521
into << *j;
522
}
523
into << "(" << (*i)->myBoundary << ")" << std::endl;
524
}
525
into << "---------------------------" << std::endl;
526
}
527
528
529
530
bool
531
NIVissimConnectionCluster::hasNodeCluster() const {
532
return myNodeCluster != -1;
533
}
534
535
536
void
537
NIVissimConnectionCluster::removeConnections(const NodeSubCluster& c) {
538
for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
539
NIVissimConnection* conn = *i;
540
int connid = conn->getID();
541
std::vector<int>::iterator j = std::find(myConnections.begin(), myConnections.end(), connid);
542
if (j != myConnections.end()) {
543
myConnections.erase(j);
544
}
545
}
546
recomputeBoundary();
547
}
548
549
550
void
551
NIVissimConnectionCluster::recomputeBoundary() {
552
myBoundary = Boundary();
553
for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
554
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
555
if (c != nullptr) {
556
myBoundary.add(c->getFromGeomPosition());
557
myBoundary.add(c->getToGeomPosition());
558
if (c->getGeometry().size() != 0) {
559
myBoundary.add(c->getGeometry().getBoxBoundary());
560
}
561
}
562
}
563
assert(myBoundary.xmax() >= myBoundary.xmin());
564
}
565
566
567
NBNode*
568
NIVissimConnectionCluster::getNBNode() const {
569
return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode();
570
}
571
572
573
bool
574
NIVissimConnectionCluster::around(const Position& p, double offset) const {
575
assert(myBoundary.xmax() >= myBoundary.xmin());
576
return myBoundary.around(p, offset);
577
}
578
579
580
581
void
582
NIVissimConnectionCluster::recheckEdges() {
583
assert(myConnections.size() != 0);
584
// remove the cluster from all edges at first
585
std::vector<int>::iterator i;
586
for (i = myEdges.begin(); i != myEdges.end(); i++) {
587
NIVissimEdge* edge = NIVissimEdge::dictionary(*i);
588
edge->removeFromConnectionCluster(this);
589
}
590
// clear edge information
591
myEdges.clear();
592
// recheck which edges do still participate and add edges
593
for (i = myConnections.begin(); i != myConnections.end(); i++) {
594
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
595
assert(myBoundary.xmax() >= myBoundary.xmin());
596
if (myBoundary.around(c->getFromGeomPosition(), 5)) {
597
myEdges.push_back(c->getFromEdgeID());
598
}
599
assert(myBoundary.xmax() >= myBoundary.xmin());
600
if (myBoundary.around(c->getToGeomPosition(), 5)) {
601
myEdges.push_back(c->getToEdgeID());
602
}
603
}
604
// connect edges
605
for (i = myEdges.begin(); i != myEdges.end(); i++) {
606
NIVissimEdge* edge = NIVissimEdge::dictionary(*i);
607
edge->addToConnectionCluster(this);
608
}
609
}
610
611
612
double
613
NIVissimConnectionCluster::getPositionForEdge(int edgeid) const {
614
// return the middle of the connections when there are any
615
if (myConnections.size() != 0) {
616
double sum = 0;
617
int part = 0;
618
std::vector<int>::const_iterator i;
619
for (i = myConnections.begin(); i != myConnections.end(); i++) {
620
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
621
if (c->getFromEdgeID() == edgeid) {
622
part++;
623
sum += c->getFromPosition();
624
}
625
if (c->getToEdgeID() == edgeid) {
626
part++;
627
sum += c->getToPosition();
628
}
629
}
630
if (part > 0) {
631
return sum / (double) part;
632
}
633
}
634
// use the position of the node if possible
635
if (myNodeCluster >= 0) {
636
// try to find the nearest point on the edge
637
// !!! only the main geometry is regarded
638
NIVissimNodeDef* node =
639
NIVissimNodeDef::dictionary(myNodeCluster);
640
if (node != nullptr) {
641
double pos = node->getEdgePosition(edgeid);
642
if (pos >= 0) {
643
return pos;
644
}
645
}
646
/*
647
double try1 = GeomHelper::nearest_offset_on_line_to_point(
648
edge->getBegin2D(), edge->getEnd2D(), node->getPos());
649
if(try1>=0) {
650
return try1;
651
}
652
// try to use simple distance
653
double dist1 =
654
GeomHelper::distance(node->getPos(), edge->getBegin2D());
655
double dist2 =
656
GeomHelper::distance(node->getPos(), edge->getEnd2D());
657
return dist1<dist2
658
? 0 : edge->getLength();
659
*/
660
}
661
// what else?
662
WRITE_WARNING(TL("NIVissimConnectionCluster: how to get an edge's position?"));
663
// !!!
664
assert(myBoundary.xmin() <= myBoundary.xmax());
665
NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid);
666
std::vector<int>::const_iterator i = std::find(myEdges.begin(), myEdges.end(), edgeid);
667
if (i == myEdges.end()) {
668
// edge does not exist!?
669
throw 1;
670
}
671
const PositionVector& edgeGeom = edge->getGeometry();
672
Position p = GeomHelper::crossPoint(myBoundary, edgeGeom);
673
return GeomHelper::nearest_offset_on_line_to_point2D(
674
edgeGeom.front(), edgeGeom.back(), p);
675
}
676
677
678
679
void
680
NIVissimConnectionCluster::clearDict() {
681
for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
682
delete (*i);
683
}
684
myClusters.clear();
685
myFirstFreeID = 100000;
686
}
687
688
689
PositionVector
690
NIVissimConnectionCluster::getIncomingContinuationGeometry(NIVissimEdge* e) const {
691
// collect connection where this edge is the incoming one
692
std::vector<NIVissimConnection*> edgeIsIncoming;
693
for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
694
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
695
if (c->getFromEdgeID() == e->getID()) {
696
edgeIsIncoming.push_back(c);
697
}
698
}
699
//
700
if (edgeIsIncoming.size() == 0) {
701
return PositionVector();
702
}
703
// sort connected edges in same direction
704
sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
705
same_direction_sorter(e->getGeometry().beginEndAngle()));
706
NIVissimConnection* c = *(edgeIsIncoming.begin());
707
return c->getGeometry();
708
}
709
710
711
712
NIVissimConnection*
713
NIVissimConnectionCluster::getIncomingContinuation(NIVissimEdge* e) const {
714
// collect connection where this edge is the incoming one
715
std::vector<NIVissimConnection*> edgeIsIncoming;
716
for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
717
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
718
if (c->getFromEdgeID() == e->getID()) {
719
edgeIsIncoming.push_back(c);
720
}
721
}
722
//
723
if (edgeIsIncoming.size() == 0) {
724
return nullptr;
725
}
726
// sort connected edges in same direction
727
sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
728
same_direction_sorter(e->getGeometry().beginEndAngle()));
729
return *(edgeIsIncoming.begin());
730
}
731
732
733
734
PositionVector
735
NIVissimConnectionCluster::getOutgoingContinuationGeometry(NIVissimEdge* e) const {
736
// collect connection where this edge is the outgoing one
737
std::vector<NIVissimConnection*> edgeIsOutgoing;
738
for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
739
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
740
if (c->getToEdgeID() == e->getID()) {
741
edgeIsOutgoing.push_back(c);
742
}
743
}
744
//
745
if (edgeIsOutgoing.size() == 0) {
746
return PositionVector();
747
}
748
// sort connected edges in same direction
749
sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
750
same_direction_sorter(e->getGeometry().beginEndAngle()));
751
NIVissimConnection* c = *(edgeIsOutgoing.begin());
752
return c->getGeometry();
753
}
754
755
756
NIVissimConnection*
757
NIVissimConnectionCluster::getOutgoingContinuation(NIVissimEdge* e) const {
758
// collect connection where this edge is the outgoing one
759
std::vector<NIVissimConnection*> edgeIsOutgoing;
760
for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
761
NIVissimConnection* c = NIVissimConnection::dictionary(*i);
762
if (c->getToEdgeID() == e->getID()) {
763
edgeIsOutgoing.push_back(c);
764
}
765
}
766
//
767
if (edgeIsOutgoing.size() == 0) {
768
return nullptr;
769
}
770
// sort connected edges in same direction
771
sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
772
same_direction_sorter(e->getGeometry().beginEndAngle()));
773
return *(edgeIsOutgoing.begin());
774
}
775
776
777
/****************************************************************************/
778
779