LCOV - code coverage report
Current view: top level - src/netimport/vissim/tempstructs - NIVissimEdge.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 65.4 % 410 268
Test Date: 2024-11-22 15:46:21 Functions: 74.4 % 43 32

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2024 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          494 : NIVissimEdge::connection_position_sorter::connection_position_sorter(int edgeid)
      61          494 :     : myEdgeID(edgeid) {}
      62              : 
      63              : 
      64              : int
      65         3364 : NIVissimEdge::connection_position_sorter::operator()(int c1id,
      66              :         int c2id) const {
      67         3364 :     NIVissimConnection* c1 = NIVissimConnection::dictionary(c1id);
      68         3364 :     NIVissimConnection* c2 = NIVissimConnection::dictionary(c2id);
      69              :     double pos1 =
      70         3364 :         c1->getFromEdgeID() == myEdgeID
      71         3364 :         ? c1->getFromPosition() : c1->getToPosition();
      72              :     double pos2 =
      73         3364 :         c2->getFromEdgeID() == myEdgeID
      74         3364 :         ? c2->getFromPosition() : c2->getToPosition();
      75         3364 :     return pos1 < pos2;
      76              : }
      77              : 
      78              : 
      79              : 
      80              : 
      81              : 
      82              : 
      83              : 
      84              : 
      85         1177 : NIVissimEdge::connection_cluster_position_sorter::connection_cluster_position_sorter(int edgeid)
      86         1177 :     : myEdgeID(edgeid) {}
      87              : 
      88              : 
      89              : int
      90         2141 : NIVissimEdge::connection_cluster_position_sorter::operator()(
      91              :     NIVissimConnectionCluster* cc1,
      92              :     NIVissimConnectionCluster* cc2) const {
      93         2141 :     double pos1 = cc1->getPositionForEdge(myEdgeID);
      94         2141 :     double pos2 = cc2->getPositionForEdge(myEdgeID);
      95         2141 :     if (pos2 < 0 || pos1 < 0) {
      96            0 :         cc1->getPositionForEdge(myEdgeID);
      97            0 :         cc2->getPositionForEdge(myEdgeID);
      98              :     }
      99              :     assert(pos1 >= 0 && pos2 >= 0);
     100         2141 :     return pos1 < pos2;
     101              : }
     102              : 
     103              : 
     104              : 
     105              : 
     106          683 : 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          683 :                            const NIVissimClosedLanesVector& clv) :
     112              :     NIVissimAbstractEdge(id, geom),
     113          683 :     myName(name), myType(type), myNoLanes((int)laneWidths.size()),
     114          683 :     myLaneWidths(laneWidths),
     115          683 :     myZuschlag1(zuschlag1), myZuschlag2(zuschlag2),
     116          683 :     myClosedLanes(clv),
     117          683 :     myLaneSpeeds(myNoLanes, -1),
     118          683 :     myAmWithinJunction(false)
     119              :     //, mySpeed(-1)
     120              : {
     121              :     assert(myNoLanes >= 0);
     122          683 :     if (myMaxID < myID) {
     123          683 :         myMaxID = myID;
     124              :     }
     125          683 : }
     126              : 
     127              : 
     128         1366 : NIVissimEdge::~NIVissimEdge() {
     129          733 :     for (NIVissimClosedLanesVector::iterator i = myClosedLanes.begin(); i != myClosedLanes.end(); i++) {
     130           50 :         delete (*i);
     131              :     }
     132              :     myClosedLanes.clear();
     133         1366 : }
     134              : 
     135              : 
     136              : bool
     137            0 : 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            0 :     NIVissimEdge* o = new NIVissimEdge(id, name, type, std::vector<double>(noLanes, NBEdge::UNSPECIFIED_WIDTH),
     143            0 :                                        zuschlag1, zuschlag2, length, geom, clv);
     144            0 :     if (!dictionary(id, o)) {
     145            0 :         delete o;
     146            0 :         return false;
     147              :     }
     148              :     return true;
     149              : }
     150              : 
     151              : 
     152              : 
     153              : bool
     154          683 : NIVissimEdge::dictionary(int id, NIVissimEdge* o) {
     155              :     DictType::iterator i = myDict.find(id);
     156          683 :     if (i == myDict.end()) {
     157          683 :         myDict[id] = o;
     158          683 :         return true;
     159              :     }
     160              :     return false;
     161              : }
     162              : 
     163              : 
     164              : 
     165              : NIVissimEdge*
     166         9102 : NIVissimEdge::dictionary(int id) {
     167              :     DictType::iterator i = myDict.find(id);
     168         9102 :     if (i == myDict.end()) {
     169              :         return nullptr;
     170              :     }
     171         8830 :     return (*i).second;
     172              : }
     173              : 
     174              : 
     175              : void
     176            9 : NIVissimEdge::buildConnectionClusters() {
     177              :     const double MAX_CLUSTER_DISTANCE = 10;
     178              :     // build clusters for all edges made up from not previously assigne
     179              :     //  connections
     180          692 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     181          683 :         int edgeid = (*i).first;
     182          683 :         NIVissimEdge* edge = (*i).second;
     183              :         // get all connectors using this edge
     184          683 :         std::vector<int> connectors = edge->myIncomingConnections;
     185              :         copy(edge->myOutgoingConnections.begin(), edge->myOutgoingConnections.end(), back_inserter(connectors));
     186          683 :         if (connectors.size() == 0) {
     187          189 :             continue;
     188              :         }
     189              :         // sort the connectors by the place on the edge
     190          988 :         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          494 :         bool outgoing = NIVissimConnection::dictionary(*j)->getFromEdgeID() == (*i).first;
     195              :         double position = outgoing
     196          494 :                           ? NIVissimConnection::dictionary(*j)->getFromPosition()
     197          435 :                           : NIVissimConnection::dictionary(*j)->getToPosition();
     198              : 
     199              :         // skip connections already in a cluster
     200              :         // !!! (?)
     201          494 :         while (j != connectors.end() && NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
     202              :             ++j;
     203              :         }
     204          494 :         if (j == connectors.end()) {
     205              :             continue;
     206              :         }
     207          494 :         currentCluster.push_back(*j);
     208              :         do {
     209         1854 :             if (j + 1 != connectors.end() && !NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
     210         1360 :                 bool n_outgoing = NIVissimConnection::dictionary(*(j + 1))->getFromEdgeID() == edgeid;
     211              :                 double n_position = n_outgoing
     212         1360 :                                     ? NIVissimConnection::dictionary(*(j + 1))->getFromPosition()
     213          492 :                                     : NIVissimConnection::dictionary(*(j + 1))->getToPosition();
     214         1360 :                 if (n_outgoing == outgoing && fabs(n_position - position) < MAX_CLUSTER_DISTANCE) {
     215              :                     // ok, in same cluster as prior
     216          715 :                     currentCluster.push_back(*(j + 1));
     217              :                 } else {
     218              :                     // start new cluster
     219          645 :                     VectorHelper<int>::removeDouble(currentCluster);
     220          645 :                     edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
     221              :                     currentCluster.clear();
     222          645 :                     currentCluster.push_back(*(j + 1));
     223              :                 }
     224              :                 outgoing = n_outgoing;
     225              :                 position = n_position;
     226              :             }
     227              :             j++;
     228         1854 :         } while (j != connectors.end());
     229              :         // add last connection
     230          494 :         if (currentCluster.size() > 0) {
     231          494 :             VectorHelper<int>::removeDouble(currentCluster);
     232          494 :             edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
     233              :         }
     234          683 :     }
     235            9 : }
     236              : 
     237              : 
     238              : void
     239            9 : NIVissimEdge::dict_buildNBEdges(NBDistrictCont& dc, NBNodeCont& nc,
     240              :                                 NBEdgeCont& ec, double offset) {
     241          692 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     242          683 :         NIVissimEdge* edge = (*i).second;
     243          683 :         edge->buildNBEdge(dc, nc, ec, offset);
     244              :     }
     245            9 : }
     246              : 
     247              : 
     248              : void
     249            9 : NIVissimEdge::dict_propagateSpeeds() {
     250              :     DictType::iterator i;
     251          692 :     for (i = myDict.begin(); i != myDict.end(); i++) {
     252          683 :         NIVissimEdge* edge = (*i).second;
     253          683 :         edge->setDistrictSpeed();
     254              :     }
     255          692 :     for (i = myDict.begin(); i != myDict.end(); i++) {
     256          683 :         NIVissimEdge* edge = (*i).second;
     257          683 :         edge->propagateSpeed(-1, std::vector<int>());
     258              :     }
     259           36 :     for (int j = 0; j < 3; j++) {
     260         2076 :         for (i = myDict.begin(); i != myDict.end(); i++) {
     261         2049 :             NIVissimEdge* edge = (*i).second;
     262         2049 :             edge->propagateOwn();
     263              :         }
     264         2076 :         for (i = myDict.begin(); i != myDict.end(); i++) {
     265         2049 :             NIVissimEdge* edge = (*i).second;
     266         2049 :             edge->checkUnconnectedLaneSpeeds();
     267              :         }
     268              :     }
     269            9 : }
     270              : 
     271              : 
     272              : void
     273         2049 : NIVissimEdge::checkUnconnectedLaneSpeeds() {
     274         4839 :     for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
     275         2790 :         if (myLaneSpeeds[i] == -1) {
     276              :             double speed = -1;
     277         2781 :             int j1 = i - 1; // !!! recheck - j1 may become negative?
     278              :             int j2 = i;
     279         6393 :             while (j2 != (int) myLaneSpeeds.size() && myLaneSpeeds[j2] == -1) {
     280         3612 :                 j2++;
     281              :             }
     282         2781 :             if (j1 < 0) {
     283         2040 :                 if (j2 < (int) myLaneSpeeds.size()) {
     284            0 :                     speed = myLaneSpeeds[j2];
     285              :                 }
     286              :             } else {
     287          741 :                 if (j2 >= (int) myLaneSpeeds.size()) {
     288          741 :                     speed = myLaneSpeeds[j1];
     289              :                 } else {
     290            0 :                     speed = (myLaneSpeeds[j1] + myLaneSpeeds[j2]) / (double) 2.0;
     291              :                 }
     292              :             }
     293          741 :             if (speed == -1) {
     294         2781 :                 continue;
     295              :             }
     296            0 :             myLaneSpeeds[i] = speed;
     297            0 :             std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
     298            0 :             for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
     299            0 :                 NIVissimConnection* c = *j;
     300            0 :                 NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
     301              :                 // propagate
     302            0 :                 e->propagateSpeed(/*dc, */speed, c->getToLanes());
     303              :             }
     304            0 :         }
     305              :     }
     306         2049 : }
     307              : 
     308              : 
     309              : void
     310         2049 : NIVissimEdge::propagateOwn() {
     311         4839 :     for (int i = 0; i < (int) myLaneSpeeds.size(); i++) {
     312         2790 :         if (myLaneSpeeds[i] == -1) {
     313         2781 :             continue;
     314              :         }
     315            9 :         std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
     316            9 :         for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
     317            0 :             NIVissimConnection* c = *j;
     318            0 :             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
     319              :             // propagate
     320            0 :             e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
     321              :         }
     322            9 :     }
     323         2049 : }
     324              : 
     325              : 
     326              : void
     327          683 : NIVissimEdge::propagateSpeed(double speed, std::vector<int> forLanes) {
     328              :     // if no lane is given, all set be set
     329          683 :     if (forLanes.size() == 0) {
     330         1613 :         for (int i = 0; i < myNoLanes; i++) {
     331          930 :             forLanes.push_back((int) i);
     332              :         }
     333              :     }
     334              :     // for the case of a first call
     335              :     // go through the lanes
     336         1613 :     for (std::vector<int>::const_iterator i = forLanes.begin(); i < forLanes.end(); i++) {
     337              :         // check whether a speed was set before
     338          930 :         if (myLaneSpeeds[*i] != -1) {
     339              :             // do not reset it from incoming
     340          927 :             continue;
     341              :         }
     342              :         // check whether the lane has a new speed to set
     343          930 :         if ((int) myPatchedSpeeds.size() > *i && myPatchedSpeeds[*i] != -1) {
     344              :             // use it
     345            3 :             speed = getRealSpeed(/*dc, */myPatchedSpeeds[*i]);
     346              :         }
     347              :         // check whether a speed is given
     348          930 :         if (speed == -1) {
     349              :             // do nothing if not
     350          927 :             continue;
     351              :         }
     352              :         // set the lane's speed to the given
     353            3 :         myLaneSpeeds[*i] = speed;
     354              :         // propagate the speed further
     355              :         // get the list of connected edges
     356            3 :         std::vector<NIVissimConnection*> connected = getOutgoingConnected(*i);
     357              :         // go through the list
     358            3 :         for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
     359            0 :             NIVissimConnection* c = *j;
     360            0 :             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
     361              :             // propagate
     362            0 :             e->propagateSpeed(/*dc, */speed, c->getToLanes());
     363              :         }
     364            3 :     }
     365          683 : }
     366              : 
     367              : 
     368              : 
     369              : void
     370          683 : NIVissimEdge::setDistrictSpeed() {
     371          683 :     if (myDistrictConnections.size() > 0) {
     372            0 :         double pos = *(myDistrictConnections.begin());
     373            0 :         if (pos < getLength() - pos) {
     374              :             NIVissimDistrictConnection* d =
     375            0 :                 NIVissimDistrictConnection::dict_findForEdge(myID);
     376            0 :             if (d != nullptr) {
     377            0 :                 double speed = d->getMeanSpeed(/*dc*/);
     378            0 :                 if (speed == -1) {
     379              :                     return;
     380              :                 }
     381            0 :                 for (int i = 0; i < myNoLanes; i++) {
     382            0 :                     myLaneSpeeds[i] = speed;
     383              :                     // propagate the speed further
     384              :                     // get the list of connected edges
     385            0 :                     std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
     386              :                     // go through the list
     387            0 :                     for (std::vector<NIVissimConnection*>::iterator j = connected.begin(); j != connected.end(); j++) {
     388            0 :                         NIVissimConnection* c = *j;
     389            0 :                         NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
     390              :                         // propagate
     391            0 :                         e->propagateSpeed(/*dc, */speed, c->getToLanes());
     392              :                     }
     393            0 :                 }
     394              :             }
     395              :         }
     396              :     }
     397              : }
     398              : 
     399              : 
     400              : std::vector<NIVissimConnection*>
     401           12 : NIVissimEdge::getOutgoingConnected(int lane) const {
     402              :     std::vector<NIVissimConnection*> ret;
     403           12 :     for (std::vector<int>::const_iterator i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
     404            0 :         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
     405            0 :         const std::vector<int>& lanes = c->getFromLanes();
     406            0 :         if (find(lanes.begin(), lanes.end(), lane) != lanes.end()) {
     407            0 :             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
     408            0 :             if (e != nullptr) {
     409            0 :                 ret.push_back(c);
     410              :             }
     411              :         }
     412              :     }
     413           12 :     return ret;
     414            0 : }
     415              : 
     416              : 
     417              : void
     418          683 : 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         1366 :     sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID));
     425          683 :     sort(myDistrictConnections.begin(), myDistrictConnections.end());
     426          683 :     ConnectionClusters tmpClusters = myConnectionClusters;
     427          683 :     if (tmpClusters.size() != 0) {
     428          494 :         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          494 :         fromInf = getFromNode(nc, tmpClusters);
     433              :         fromNode = fromInf.second;
     434              :         // get or build the to-node
     435              :         //if(tmpClusters.size()>0) {
     436          494 :         toInf = getToNode(nc, tmpClusters);
     437              :         toNode = toInf.second;
     438          494 :         if (fromInf.first != 0 && toNode != nullptr && fromInf.first->around(toNode->getPosition())) {
     439            4 :             WRITE_WARNINGF(TL("Will not build edge '%'."), toString(myID));
     440            2 :             myAmWithinJunction = true;
     441            2 :             return;
     442              :         }
     443              :         //}
     444              :         // if both nodes are the same, resolve the problem otherwise
     445          492 :         if (fromNode == toNode) {
     446            0 :             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          492 :     if (fromNode == nullptr) {
     460              :         fromInf.first = 0;
     461          189 :         Position pos = myGeom[0];
     462          378 :         fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, SumoXMLNodeType::NOJUNCTION);
     463          189 :         if (!nc.insert(fromNode)) {
     464            0 :             throw ProcessError(TLF("Could not insert node '%' to nodes container.", fromNode->getID()));
     465              :         }
     466              :     }
     467          681 :     if (toNode == nullptr) {
     468              :         toInf.first = 0;
     469          189 :         Position pos = myGeom[-1];
     470          378 :         toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, SumoXMLNodeType::NOJUNCTION);
     471          189 :         if (!nc.insert(toNode)) {
     472            0 :             throw ProcessError(TLF("Could not insert node '%' to nodes container.", toNode->getID()));
     473              :         }
     474              :     }
     475              : 
     476              :     // build the edge
     477              :     double avgSpeed = 0;
     478         1608 :     for (int i = 0; i < myNoLanes; i++) {
     479          927 :         if ((int)myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
     480         2772 :             myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
     481          924 :             avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
     482              :         } else {
     483            3 :             avgSpeed += myLaneSpeeds[i];
     484              :         }
     485              :     }
     486          681 :     avgSpeed /= (double) myLaneSpeeds.size();
     487          681 :     avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");
     488              : 
     489          681 :     if (fromNode == toNode) {
     490            0 :         WRITE_WARNINGF(TL("Could not build edge '%'; would connect same node."), toString(myID));
     491            0 :         return;
     492              :     }
     493              : 
     494         1362 :     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         2043 :                                    myGeom, LaneSpreadFunction::CENTER, myName, "", true);
     498         1608 :     for (int i = 0; i < myNoLanes; i++) {
     499          927 :         buildEdge->setLaneWidth(i, myLaneWidths[i]);
     500          927 :         if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) {
     501         1848 :             buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (double) 3.6);
     502              :         } else {
     503            3 :             buildEdge->setSpeed(i, myLaneSpeeds[i] / (double) 3.6);
     504              :         }
     505              :     }
     506          681 :     ec.insert(buildEdge);
     507              :     // check whether the edge contains any other clusters
     508          681 :     if (tmpClusters.size() > 0) {
     509              :         bool cont = true;
     510          247 :         for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) {
     511              :             // split the edge at the previously build node
     512          188 :             std::string nextID = buildEdge->getID() + "[1]";
     513          188 :             cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
     514              :             // !!! what to do if the edge could not be split?
     515          188 :             buildEdge = ec.retrieve(nextID);
     516              :         }
     517              :     }
     518          683 : }
     519              : 
     520              : 
     521              : double
     522            3 : NIVissimEdge::getRealSpeed(int distNo) {
     523            3 :     std::string id = toString<int>(distNo);
     524            3 :     Distribution* dist = DistributionCont::dictionary("speed", id);
     525            3 :     if (dist == nullptr) {
     526            0 :         WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);
     527            0 :         return -1;
     528              :     }
     529              :     assert(dist != 0);
     530            3 :     double speed = dist->getMax();
     531            3 :     if (speed < 0 || speed > 1000) {
     532            0 :         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          494 : 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          494 :     NIVissimConnectionCluster* c = *(clusters.begin());
     582              :     // check whether the edge starts within a already build node
     583          494 :     if (c->around(beg, MAX_DISTANCE)) {
     584              :         clusters.erase(clusters.begin());
     585              :         return std::pair<NIVissimConnectionCluster*, NBNode*>
     586          429 :                (c, c->getNBNode());
     587              :     }
     588              :     // check for a parking place at the begin
     589           65 :     if (myDistrictConnections.size() > 0) {
     590            0 :         double pos = *(myDistrictConnections.begin());
     591            0 :         if (pos < 10) {
     592            0 :             NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
     593            0 :             if (!nc.insert(node)) {
     594            0 :                 throw 1;
     595              :             }
     596            0 :             while (myDistrictConnections.size() > 0 && *(myDistrictConnections.begin()) < 10) {
     597            0 :                 myDistrictConnections.erase(myDistrictConnections.begin());
     598              :             }
     599            0 :             return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
     600              :         }
     601              :     }
     602              :     // build a new node for the edge's begin otherwise
     603          130 :     NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, SumoXMLNodeType::NOJUNCTION);
     604           65 :     if (!nc.insert(node)) {
     605            0 :         throw 1;
     606              :     }
     607           65 :     return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(nullptr), node);
     608              : }
     609              : 
     610              : 
     611              : std::pair<NIVissimConnectionCluster*, NBNode*>
     612          494 : NIVissimEdge::getToNode(NBNodeCont& nc, ConnectionClusters& clusters) {
     613              :     const Position& end = myGeom.back();
     614          494 :     if (clusters.size() > 0) {
     615              :         const double MAX_DISTANCE = 10.;
     616              :         assert(clusters.size() >= 1);
     617          474 :         NIVissimConnectionCluster* c = *(clusters.end() - 1);
     618              :         // check whether the edge ends within a already build node
     619          474 :         if (c->around(end, MAX_DISTANCE)) {
     620              :             clusters.erase(clusters.end() - 1);
     621          444 :             return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
     622              :         }
     623              :     }
     624              :     // check for a parking place at the end
     625           50 :     if (myDistrictConnections.size() > 0) {
     626            0 :         double pos = *(myDistrictConnections.end() - 1);
     627            0 :         if (pos > myGeom.length() - 10) {
     628            0 :             NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
     629            0 :             if (!nc.insert(node)) {
     630            0 :                 throw 1;
     631              :             }
     632            0 :             while (myDistrictConnections.size() > 0 && *(myDistrictConnections.end() - 1) < myGeom.length() - 10) {
     633            0 :                 myDistrictConnections.erase(myDistrictConnections.end() - 1);
     634              :             }
     635            0 :             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          100 :     NBNode* node = new NBNode(toString<int>(myID) + "-end", end, SumoXMLNodeType::NOJUNCTION);
     641           50 :     if (!nc.insert(node)) {
     642            0 :         throw 1;
     643              :     }
     644           50 :     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            0 : NIVissimEdge::remapOneOfNodes(NBNodeCont& nc,
     660              :                               NIVissimDistrictConnection* d,
     661              :                               NBNode* fromNode, NBNode* toNode) {
     662            0 :     std::string nid = "ParkingPlace" + toString<int>(d->getID());
     663            0 :     if (d->geomPosition().distanceTo(fromNode->getPosition())
     664              :             <
     665            0 :             d->geomPosition().distanceTo(toNode->getPosition())) {
     666              : 
     667              :         NBNode* newNode = new NBNode(nid,
     668              :                                      fromNode->getPosition(),
     669            0 :                                      SumoXMLNodeType::NOJUNCTION);
     670            0 :         nc.erase(fromNode);
     671            0 :         nc.insert(newNode);
     672            0 :         return std::pair<NBNode*, NBNode*>(newNode, toNode);
     673              :     } else {
     674              :         NBNode* newNode = new NBNode(nid,
     675              :                                      toNode->getPosition(),
     676            0 :                                      SumoXMLNodeType::NOJUNCTION);
     677            0 :         nc.erase(toNode);
     678            0 :         nc.insert(newNode);
     679            0 :         return std::pair<NBNode*, NBNode*>(fromNode, newNode);
     680              :     }
     681              : }
     682              : 
     683              : 
     684              : 
     685              : std::pair<NBNode*, NBNode*>
     686            0 : 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            0 :         NIVissimDistrictConnection::dict_findForEdge(myID);
     692            0 :     if (d != nullptr) {
     693            0 :         Position pos = d->geomPosition();
     694              :         double position = d->getPosition();
     695              :         // the district is at the begin of the edge
     696            0 :         if (myGeom.length() - position > position) {
     697            0 :             std::string nid = "ParkingPlace" + toString<int>(d->getID());
     698            0 :             NBNode* node = nc.retrieve(nid);
     699            0 :             if (node == nullptr) {
     700              :                 node = new NBNode(nid,
     701            0 :                                   pos, SumoXMLNodeType::NOJUNCTION);
     702            0 :                 if (!nc.insert(node)) {
     703            0 :                     throw 1;
     704              :                 }
     705              :             }
     706            0 :             return std::pair<NBNode*, NBNode*>(node, prevTo);
     707              :         }
     708              :         // the district is at the end of the edge
     709              :         else {
     710            0 :             std::string nid = "ParkingPlace" + toString<int>(d->getID());
     711            0 :             NBNode* node = nc.retrieve(nid);
     712            0 :             if (node == nullptr) {
     713            0 :                 node = new NBNode(nid, pos, SumoXMLNodeType::NOJUNCTION);
     714            0 :                 if (!nc.insert(node)) {
     715            0 :                     throw 1;
     716              :                 }
     717              :             }
     718              :             assert(node != 0);
     719            0 :             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            0 :     if (myConnectionClusters.size() == 1) {
     726              :         NBNode* node = prevFrom; // it is the same as getToNode()
     727              : 
     728            0 :         NIVissimConnectionCluster* c = *(myConnectionClusters.begin());
     729              :         // no end node given
     730            0 :         if (c->around(myGeom.front(), offset) && !c->around(myGeom.back(), offset)) {
     731              :             NBNode* end = new NBNode(
     732            0 :                 toString<int>(myID) + "-End",
     733              :                 myGeom.back(),
     734            0 :                 SumoXMLNodeType::NOJUNCTION);
     735            0 :             if (!nc.insert(end)) {
     736            0 :                 throw 1;
     737              :             }
     738            0 :             return std::pair<NBNode*, NBNode*>(node, end);
     739              :         }
     740              : 
     741              :         // no begin node given
     742            0 :         if (!c->around(myGeom.front(), offset) && c->around(myGeom.back(), offset)) {
     743              :             NBNode* beg = new NBNode(
     744            0 :                 toString<int>(myID) + "-Begin",
     745              :                 myGeom.front(),
     746            0 :                 SumoXMLNodeType::NOJUNCTION);
     747            0 :             if (!nc.insert(beg)) {
     748              :                 std::cout << "nope, NIVissimDisturbance" << std::endl;
     749            0 :                 throw 1;
     750              :             }
     751            0 :             return std::pair<NBNode*, NBNode*>(beg, node);
     752              :         }
     753              : 
     754              :         // self-loop edge - both points lie within the same cluster
     755            0 :         if (c->around(myGeom.front()) && c->around(myGeom.back())) {
     756            0 :             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            0 :     return std::pair<NBNode*, NBNode*>(prevFrom, prevTo);
     762              : }
     763              : 
     764              : 
     765              : 
     766              : 
     767              : void
     768            0 : NIVissimEdge::setNodeCluster(int nodeid) {
     769            0 :     myNode = nodeid;
     770            0 : }
     771              : 
     772              : 
     773              : void
     774            0 : NIVissimEdge::buildGeom() {}
     775              : 
     776              : 
     777              : void
     778          927 : NIVissimEdge::addIncomingConnection(int id) {
     779          927 :     myIncomingConnections.push_back(id);
     780          927 : }
     781              : 
     782              : 
     783              : void
     784          927 : NIVissimEdge::addOutgoingConnection(int id) {
     785          927 :     myOutgoingConnections.push_back(id);
     786          927 : }
     787              : 
     788              : 
     789              : 
     790              : void
     791          803 : NIVissimEdge::mergedInto(NIVissimConnectionCluster* old,
     792              :                          NIVissimConnectionCluster* act) {
     793              :     ConnectionClusters::iterator i =
     794          803 :         std::find(myConnectionClusters.begin(), myConnectionClusters.end(), old);
     795          803 :     if (i != myConnectionClusters.end()) {
     796          803 :         myConnectionClusters.erase(i);
     797              :     }
     798          803 :     i = std::find(myConnectionClusters.begin(), myConnectionClusters.end(), act);
     799          803 :     if (i == myConnectionClusters.end()) {
     800          734 :         myConnectionClusters.push_back(act);
     801              :     }
     802          803 : }
     803              : 
     804              : 
     805              : 
     806              : void
     807            0 : NIVissimEdge::removeFromConnectionCluster(NIVissimConnectionCluster* c) {
     808              :     ConnectionClusters::iterator i =
     809            0 :         std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
     810              :     assert(i != myConnectionClusters.end());
     811            0 :     myConnectionClusters.erase(i);
     812            0 : }
     813              : 
     814              : 
     815              : void
     816            0 : NIVissimEdge::addToConnectionCluster(NIVissimConnectionCluster* c) {
     817              :     ConnectionClusters::iterator i =
     818            0 :         std::find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
     819            0 :     if (i == myConnectionClusters.end()) {
     820            0 :         myConnectionClusters.push_back(c);
     821              :     }
     822            0 : }
     823              : 
     824              : 
     825              : Position // !!! reference?
     826            0 : NIVissimEdge::getBegin2D() const {
     827            0 :     return myGeom[0];
     828              : }
     829              : 
     830              : 
     831              : Position // !!! reference?
     832            0 : NIVissimEdge::getEnd2D() const {
     833            0 :     return myGeom[-1];
     834              : }
     835              : 
     836              : 
     837              : double
     838            0 : NIVissimEdge::getLength() const {
     839            0 :     return myGeom.length();
     840              : }
     841              : 
     842              : 
     843              : void
     844            0 : NIVissimEdge::checkDistrictConnectionExistanceAt(double pos) {
     845            0 :     if (find(myDistrictConnections.begin(), myDistrictConnections.end(), pos) == myDistrictConnections.end()) {
     846            0 :         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            0 : }
     854              : 
     855              : 
     856              : void
     857            6 : NIVissimEdge::setSpeed(int lane, int speedDist) {
     858            9 :     while ((int)myPatchedSpeeds.size() <= lane) {
     859            3 :         myPatchedSpeeds.push_back(-1);
     860              :     }
     861            6 :     myPatchedSpeeds[lane] = speedDist;
     862            6 : }
     863              : 
     864              : 
     865              : void
     866            9 : NIVissimEdge::dict_checkEdges2Join() {
     867              :     // go through the edges
     868          692 :     for (DictType::iterator i1 = myDict.begin(); i1 != myDict.end(); i1++) {
     869              :         // retrieve needed values from the first edge
     870          683 :         NIVissimEdge* e1 = (*i1).second;
     871          683 :         const PositionVector& g1 = e1->getGeometry();
     872              :         // check all other edges
     873              :         DictType::iterator i2 = i1;
     874              :         i2++;
     875        38738 :         for (; i2 != myDict.end(); i2++) {
     876              :             // retrieve needed values from the second edge
     877        38055 :             NIVissimEdge* e2 = (*i2).second;
     878        38055 :             const PositionVector& g2 = e2->getGeometry();
     879              :             // get the connection description
     880        38055 :             NIVissimConnection* c = e1->getConnectionTo(e2);
     881        38055 :             if (c == nullptr) {
     882        37312 :                 c = e2->getConnectionTo(e1);
     883              :             }
     884              :             // the edge must not be a direct contiuation of the other
     885        37312 :             if (c != nullptr) {
     886         1055 :                 if ((c->getFromEdgeID() == e1->getID() && fabs(c->getFromPosition() - e1->getGeometry().length()) < 5)
     887         1263 :                         ||
     888          951 :                         (c->getFromEdgeID() == e2->getID() && fabs(c->getFromPosition() - e2->getGeometry().length()) < 5)) {
     889              : 
     890          614 :                     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        37441 :             if (fabs(GeomHelper::angleDiff(g1.beginEndAngle(), g2.beginEndAngle())) > DEG2RAD(2.0)) {
     898              :                 // continue if the lines are not parallel
     899        36474 :                 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          967 :             if (g1.back().distanceTo(g2.back()) > 10) {
     906              :                 // continue if the lines do not end at the same length
     907          933 :                 continue;
     908              :             }
     909              :             // ok, seem to be different lanes for the same edge
     910              :             //  mark as possibly joined later
     911           34 :             e1->addToTreatAsSame(e2);
     912           34 :             e2->addToTreatAsSame(e1);
     913              :         }
     914              :     }
     915            9 : }
     916              : 
     917              : 
     918              : bool
     919           68 : NIVissimEdge::addToTreatAsSame(NIVissimEdge* e) {
     920           68 :     if (e == this) {
     921              :         return false;
     922              :     }
     923              :     // check whether this edge already knows about the other
     924           68 :     if (find(myToTreatAsSame.begin(), myToTreatAsSame.end(), e) == myToTreatAsSame.end()) {
     925           68 :         myToTreatAsSame.push_back(e);
     926           68 :         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        75367 : NIVissimEdge::getConnectionTo(NIVissimEdge* e) {
     949              :     std::vector<int>::iterator i;
     950       172404 :     for (i = myIncomingConnections.begin(); i != myIncomingConnections.end(); i++) {
     951        97468 :         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
     952        97468 :         if (c->getFromEdgeID() == e->getID()) {
     953          431 :             return c;
     954              :         }
     955              :     }
     956       171088 :     for (i = myOutgoingConnections.begin(); i != myOutgoingConnections.end(); i++) {
     957        96464 :         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
     958        96464 :         if (c->getToEdgeID() == e->getID()) {
     959          312 :             return c;
     960              :         }
     961              :     }
     962              :     return nullptr;
     963              : }
     964              : 
     965              : 
     966              : const std::vector<NIVissimEdge*>&
     967         4011 : NIVissimEdge::getToTreatAsSame() const {
     968         4011 :     return myToTreatAsSame;
     969              : }
     970              : 
     971              : 
     972              : void
     973            1 : NIVissimEdge::reportUnsetSpeeds() {
     974            1 :     if (myLanesWithMissingSpeeds.size() == 0) {
     975            0 :         return;
     976              :     }
     977            1 :     std::ostringstream str;
     978            1 :     str << "The following lanes have no explicit speed information:\n  ";
     979          115 :     for (std::vector<std::string>::iterator i = myLanesWithMissingSpeeds.begin(); i != myLanesWithMissingSpeeds.end(); ++i) {
     980          114 :         if (i != myLanesWithMissingSpeeds.begin()) {
     981          113 :             str << ", ";
     982              :         }
     983              :         str << *i;
     984              :     }
     985            1 :     WRITE_WARNING(str.str());
     986            1 : }
     987              : 
     988              : 
     989              : NIVissimEdge*
     990            2 : 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            2 :     if (myIncomingConnections.size() != 0) {
    1000            2 :         return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myIncomingConnections.front())->getFromEdgeID());
    1001              :     }
    1002              :     return nullptr;
    1003              : }
    1004              : 
    1005              : 
    1006              : NIVissimEdge*
    1007            6 : 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            6 :     if (myOutgoingConnections.size() != 0) {
    1017            6 :         return NIVissimEdge::dictionary(NIVissimConnection::dictionary(myOutgoingConnections.front())->getToEdgeID());
    1018              :     }
    1019              :     return nullptr;
    1020              : }
    1021              : 
    1022              : 
    1023              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1