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