LCOV - code coverage report
Current view: top level - src/netimport/vissim/tempstructs - NIVissimConnectionCluster.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 51.1 % 321 164
Test Date: 2024-11-22 15:46:21 Functions: 48.5 % 33 16

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

Generated by: LCOV version 2.0-1