Path: blob/main/src/netimport/vissim/tempstructs/NIVissimConnectionCluster.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file NIVissimConnectionCluster.cpp14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Michael Behrisch17/// @date Sept 200218///19// -------------------20/****************************************************************************/21#include <config.h>2223#include <algorithm>24#include <iostream>25#include <cassert>26#include <iterator>27#include <utils/geom/Boundary.h>28#include <utils/geom/GeomHelper.h>29#include <utils/common/VectorHelper.h>30#include <utils/common/MsgHandler.h>31#include <utils/common/ToString.h>32#include "NIVissimConnection.h"33#include "NIVissimDisturbance.h"34#include "NIVissimNodeCluster.h"35#include "NIVissimNodeDef.h"36#include "NIVissimEdge.h"37#include "NIVissimTL.h"38#include "NIVissimConnectionCluster.h"394041// ===========================================================================42// static members43// ===========================================================================44NIVissimConnectionCluster::ContType NIVissimConnectionCluster::myClusters;45int NIVissimConnectionCluster::myFirstFreeID = 100000;46int NIVissimConnectionCluster::myStaticBlaID = 0;47484950// ===========================================================================51// method definitions52// ===========================================================================53// ---------------------------------------------------------------------------54// NIVissimConnectionCluster::NodeSubCluster - methods55// ---------------------------------------------------------------------------56NIVissimConnectionCluster::NodeSubCluster::NodeSubCluster(NIVissimConnection* c) {57add(c);58}596061NIVissimConnectionCluster::NodeSubCluster::~NodeSubCluster() {}626364void65NIVissimConnectionCluster::NodeSubCluster::add(NIVissimConnection* c) {66myBoundary.add(c->getBoundingBox());67myConnections.push_back(c);68}697071void72NIVissimConnectionCluster::NodeSubCluster::add(const NIVissimConnectionCluster::NodeSubCluster& c) {73for (ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {74add(*i);75}76}777879int80NIVissimConnectionCluster::NodeSubCluster::size() const {81return (int)myConnections.size();82}838485std::vector<int>86NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const {87std::vector<int> ret;88int id = NIVissimConnectionCluster::getNextFreeNodeID();89for (ConnectionCont::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {90ret.push_back((*i)->getID());91(*i)->setNodeCluster(id);92}93return ret;94}959697bool98NIVissimConnectionCluster::NodeSubCluster::overlapsWith(99const NIVissimConnectionCluster::NodeSubCluster& c,100double offset) {101assert(myBoundary.xmax() >= myBoundary.xmin());102assert(c.myBoundary.xmax() >= c.myBoundary.xmin());103return myBoundary.overlapsWith(c.myBoundary, offset);104}105106107108// ---------------------------------------------------------------------------109// NIVissimConnectionCluster - methods110// ---------------------------------------------------------------------------111NIVissimConnectionCluster::NIVissimConnectionCluster(112const std::vector<int>& connections, int nodeCluster, int edgeid)113: myConnections(connections), myNodeCluster(nodeCluster),114myBlaID(myStaticBlaID++) {115recomputeBoundary();116myClusters.push_back(this);117assert(edgeid > 0);118if (edgeid >= 0) {119myEdges.push_back(edgeid);120}121// add information about incoming and outgoing edges122for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {123NIVissimConnection* c = NIVissimConnection::dictionary(*i);124assert(c != 0);125myOutgoingEdges.push_back(c->getToEdgeID());126myIncomingEdges.push_back(c->getFromEdgeID());127assert(c->getFromEdgeID() == edgeid || c->getToEdgeID() == edgeid);128}129VectorHelper<int>::removeDouble(myIncomingEdges);130VectorHelper<int>::removeDouble(myOutgoingEdges);131}132133134NIVissimConnectionCluster::NIVissimConnectionCluster(135const std::vector<int>& connections, const Boundary& boundary,136int nodeCluster, const std::vector<int>& edges)137: myConnections(connections), myBoundary(boundary),138myNodeCluster(nodeCluster), myEdges(edges) {139myClusters.push_back(this);140recomputeBoundary();141assert(myBoundary.xmax() >= myBoundary.xmin());142// add information about incoming and outgoing edges143for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {144NIVissimConnection* c = NIVissimConnection::dictionary(*i);145assert(c != 0);146myOutgoingEdges.push_back(c->getToEdgeID());147myIncomingEdges.push_back(c->getFromEdgeID());148assert(find(edges.begin(), edges.end(), c->getFromEdgeID()) != edges.end()149||150std::find(edges.begin(), edges.end(), c->getToEdgeID()) != edges.end());151}152VectorHelper<int>::removeDouble(myIncomingEdges);153VectorHelper<int>::removeDouble(myOutgoingEdges);154}155156157NIVissimConnectionCluster::~NIVissimConnectionCluster() {}158159160161int162NIVissimConnectionCluster::getNextFreeNodeID() {163return myFirstFreeID++;164}165166167bool168NIVissimConnectionCluster::overlapsWith(NIVissimConnectionCluster* c,169double offset) const {170assert(myBoundary.xmax() >= myBoundary.xmin());171assert(c->myBoundary.xmax() >= c->myBoundary.xmin());172return c->myBoundary.overlapsWith(myBoundary, offset);173}174175176void177NIVissimConnectionCluster::add(NIVissimConnectionCluster* c) {178assert(myBoundary.xmax() >= myBoundary.xmin());179assert(c->myBoundary.xmax() >= c->myBoundary.xmin());180myBoundary.add(c->myBoundary);181for (std::vector<int>::iterator i = c->myConnections.begin(); i != c->myConnections.end(); i++) {182myConnections.push_back(*i);183}184VectorHelper<int>::removeDouble(myConnections);185assert(myNodeCluster == -1 || c->myNodeCluster == -1);186if (myNodeCluster == -1) {187myNodeCluster = c->myNodeCluster;188}189// inform edges about merging190// !!! merge should be done within one method191for (std::vector<int>::iterator j = c->myEdges.begin(); j != c->myEdges.end(); j++) {192NIVissimEdge::dictionary(*j)->mergedInto(c, this);193}194copy(c->myEdges.begin(), c->myEdges.end(), back_inserter(myEdges));195copy(c->myIncomingEdges.begin(), c->myIncomingEdges.end(),196back_inserter(myIncomingEdges));197copy(c->myOutgoingEdges.begin(), c->myOutgoingEdges.end(),198back_inserter(myOutgoingEdges));199VectorHelper<int>::removeDouble(myEdges);200VectorHelper<int>::removeDouble(myIncomingEdges);201VectorHelper<int>::removeDouble(myOutgoingEdges);202}203204205206void207NIVissimConnectionCluster::joinBySameEdges(double offset) {208// !!! ...209// Further, we try to omit joining of overlaping nodes. This is done by holding210// the lists of incoming and outgoing edges and incrementally building the nodes211// regarding this information212std::vector<NIVissimConnectionCluster*> joinAble;213int pos = 0;214ContType::iterator i = myClusters.begin();215// step1 - faster but no complete216while (i != myClusters.end()) {217joinAble.clear();218ContType::iterator j = i + 1;219220// check whether every combination has been processed221while (j != myClusters.end()) {222// check whether the current clusters overlap223if ((*i)->joinable(*j, offset)) {224joinAble.push_back(*j);225}226j++;227}228for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();229k != joinAble.end(); k++) {230// add the overlaping cluster231(*i)->add(*k);232// erase the overlaping cluster233delete *k;234myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));235}236//237if (joinAble.size() > 0) {238i = myClusters.begin() + pos;239// clear temporary storages240joinAble.clear();241} else {242i++;243pos++;244}245}246//247pos = 0;248i = myClusters.begin();249while (i != myClusters.end()) {250ContType::iterator j = i + 1;251// check whether every combination has been processed252while (j != myClusters.end()) {253// check whether the current clusters overlap254if ((*i)->joinable(*j, offset)) {255joinAble.push_back(*j);256}257j++;258}259for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();260k != joinAble.end(); k++) {261// add the overlaping cluster262(*i)->add(*k);263// erase the overlaping cluster264delete *k;265myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));266}267//268if (joinAble.size() > 0) {269i = myClusters.begin();270// clear temporary storages271joinAble.clear();272pos = 0;273} else {274i++;275pos++;276}277}278// check for weak district connections279// (junctions made up by district connections, where prohibitions are not280// modelled properly)281pos = 0;282i = myClusters.begin();283while (i != myClusters.end()) {284ContType::iterator j = i + 1;285// check whether every combination has been processed286while (j != myClusters.end()) {287// check whether the current clusters overlap288if ((*i)->isWeakDistrictConnRealisation(*j)) {289joinAble.push_back(*j);290}291j++;292}293for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();294k != joinAble.end(); k++) {295// add the overlaping cluster296(*i)->add(*k);297// erase the overlaping cluster298delete *k;299myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));300}301//302if (joinAble.size() > 0) {303i = myClusters.begin();304// clear temporary storages305joinAble.clear();306pos = 0;307} else {308i++;309pos++;310}311}312}313314315bool316NIVissimConnectionCluster::joinable(NIVissimConnectionCluster* c2, double offset) {317// join clusters which have at least one connection in common318if (VectorHelper<int>::subSetExists(myConnections, c2->myConnections)) {319return true;320}321322// connections shall overlap otherwise323if (!overlapsWith(c2, offset)) {324return false;325}326327// at least one of the clusters shall not be assigned to a node in previous (!!!??)328if (hasNodeCluster() && c2->hasNodeCluster()) {329return false;330}331332// join clusters which where connections do disturb each other333if (VectorHelper<int>::subSetExists(c2->getDisturbanceParticipators(), myConnections)334||335VectorHelper<int>::subSetExists(getDisturbanceParticipators(), c2->myConnections)) {336337return true;338}339340341// join clusters which do share the same incoming or outgoing edges (not mutually)342std::vector<int> extendedOutgoing1;343std::vector<int> extendedIncoming1;344std::vector<int> extendedOutgoing2;345std::vector<int> extendedIncoming2;346if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) {347extendedOutgoing1 =348extendByToTreatAsSame(myOutgoingEdges, myIncomingEdges);349extendedIncoming1 =350extendByToTreatAsSame(myIncomingEdges, myOutgoingEdges);351extendedOutgoing2 =352extendByToTreatAsSame(c2->myOutgoingEdges, c2->myIncomingEdges);353extendedIncoming2 =354extendByToTreatAsSame(c2->myIncomingEdges, c2->myOutgoingEdges);355} else {356extendedOutgoing1 = myIncomingEdges;357extendedIncoming1 = myOutgoingEdges;358extendedOutgoing2 = c2->myIncomingEdges;359extendedIncoming2 = c2->myOutgoingEdges;360}361362if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2)363||364VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2)365) {366return true;367}368return false;369}370371372bool373NIVissimConnectionCluster::isWeakDistrictConnRealisation(NIVissimConnectionCluster* c2) {374if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) {375return false;376}377if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) {378return false;379}380381// ok, may be the other way round382if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) {383return c2->isWeakDistrictConnRealisation(this);384}385// connections must cross386bool crosses = false;387for (std::vector<int>::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) {388const PositionVector& g1 = NIVissimConnection::dictionary(*j1)->getGeometry();389for (const int j2 : c2->myConnections) {390const PositionVector& g2 = NIVissimConnection::dictionary(j2)->getGeometry();391if (g1.intersects(g2)) {392crosses = true;393break;394}395}396}397if (!crosses) {398return false;399}400// ok, check for connection401if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) {402return false;403}404// check whether the connection is bidirectional405NIVissimEdge* oe = NIVissimEdge::dictionary(myOutgoingEdges[0]);406NIVissimEdge* ie = NIVissimEdge::dictionary(c2->myIncomingEdges[0]);407if (oe == nullptr || ie == nullptr) {408return false;409}410return fabs(GeomHelper::angleDiff(oe->getGeometry().beginEndAngle(), ie->getGeometry().beginEndAngle())) < DEG2RAD(5);411}412413414bool415NIVissimConnectionCluster::liesOnSameEdgesEnd(NIVissimConnectionCluster* cc2) {416//417for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {418NIVissimConnection* c1 = NIVissimConnection::dictionary(*i);419for (std::vector<int>::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) {420NIVissimConnection* c2 = NIVissimConnection::dictionary(*j);421if (c1->getFromEdgeID() == c2->getFromEdgeID()) {422NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());423const PositionVector& g = e->getGeometry();424double pos1 = GeomHelper::nearest_offset_on_line_to_point2D(425g.front(), g.back(), c1->getBoundary().getCenter());426double pos2 = GeomHelper::nearest_offset_on_line_to_point2D(427g.front(), g.back(), c2->getBoundary().getCenter());428if (pos1 <= 5.0 && pos2 <= 5.0) {429return true;430}431}432if (c1->getToEdgeID() == c2->getToEdgeID()) {433NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());434const PositionVector& g = e->getGeometry();435double pos1 = GeomHelper::nearest_offset_on_line_to_point2D(436g.front(), g.back(), c1->getBoundary().getCenter());437double pos2 = GeomHelper::nearest_offset_on_line_to_point2D(438g.front(), g.back(), c2->getBoundary().getCenter());439if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) {440return true;441}442}443}444}445return false;446}447448449std::vector<int>450NIVissimConnectionCluster::extendByToTreatAsSame(const std::vector<int>& iv1,451const std::vector<int>& iv2) const {452std::vector<int> ret(iv1);453for (std::vector<int>::const_iterator i = iv1.begin(); i != iv1.end(); i++) {454NIVissimEdge* e = NIVissimEdge::dictionary(*i);455const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame();456for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) {457if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) {458ret.push_back((*j)->getID());459}460}461}462return ret;463}464465std::vector<int>466NIVissimConnectionCluster::getDisturbanceParticipators() {467std::vector<int> ret;468for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {469NIVissimConnection* c = NIVissimConnection::dictionary(*i);470const std::vector<int>& disturbances = c->getDisturbances();471for (std::vector<int>::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) {472NIVissimDisturbance* d = NIVissimDisturbance::dictionary(*j);473ret.push_back(d->getEdgeID());474ret.push_back(d->getDisturbanceID());475}476}477return ret;478}479480481void482NIVissimConnectionCluster::buildNodeClusters() {483for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {484std::vector<int> disturbances;485std::vector<int> tls;486std::vector<int> nodes;487int tlsid = -1;488int nodeid = -1;489if ((*i)->myConnections.size() > 0) {490(*i)->recomputeBoundary();491disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary);492}493nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0);494if (nodes.size() > 1) {495WRITE_WARNING(TL("NIVissimConnectionCluster: More than a single node"));496// throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein497}498if (nodes.size() > 0) {499nodeid = nodes[0];500}501//502//503int id = NIVissimNodeCluster::dictionary(504nodeid, tlsid, (*i)->myConnections,505disturbances, (*i)->myIncomingEdges.size() < 2);506assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0);507(*i)->myNodeCluster = id;508}509}510511512void513NIVissimConnectionCluster::_debugOut(std::ostream& into) {514for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {515std::vector<int> connections = (*i)->myConnections;516for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) {517if (j != connections.begin()) {518into << ", ";519}520into << *j;521}522into << "(" << (*i)->myBoundary << ")" << std::endl;523}524into << "---------------------------" << std::endl;525}526527528529bool530NIVissimConnectionCluster::hasNodeCluster() const {531return myNodeCluster != -1;532}533534535void536NIVissimConnectionCluster::removeConnections(const NodeSubCluster& c) {537for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {538NIVissimConnection* conn = *i;539int connid = conn->getID();540std::vector<int>::iterator j = std::find(myConnections.begin(), myConnections.end(), connid);541if (j != myConnections.end()) {542myConnections.erase(j);543}544}545recomputeBoundary();546}547548549void550NIVissimConnectionCluster::recomputeBoundary() {551myBoundary = Boundary();552for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {553NIVissimConnection* c = NIVissimConnection::dictionary(*i);554if (c != nullptr) {555myBoundary.add(c->getFromGeomPosition());556myBoundary.add(c->getToGeomPosition());557if (c->getGeometry().size() != 0) {558myBoundary.add(c->getGeometry().getBoxBoundary());559}560}561}562assert(myBoundary.xmax() >= myBoundary.xmin());563}564565566NBNode*567NIVissimConnectionCluster::getNBNode() const {568return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode();569}570571572bool573NIVissimConnectionCluster::around(const Position& p, double offset) const {574assert(myBoundary.xmax() >= myBoundary.xmin());575return myBoundary.around(p, offset);576}577578579580void581NIVissimConnectionCluster::recheckEdges() {582assert(myConnections.size() != 0);583// remove the cluster from all edges at first584std::vector<int>::iterator i;585for (i = myEdges.begin(); i != myEdges.end(); i++) {586NIVissimEdge* edge = NIVissimEdge::dictionary(*i);587edge->removeFromConnectionCluster(this);588}589// clear edge information590myEdges.clear();591// recheck which edges do still participate and add edges592for (i = myConnections.begin(); i != myConnections.end(); i++) {593NIVissimConnection* c = NIVissimConnection::dictionary(*i);594assert(myBoundary.xmax() >= myBoundary.xmin());595if (myBoundary.around(c->getFromGeomPosition(), 5)) {596myEdges.push_back(c->getFromEdgeID());597}598assert(myBoundary.xmax() >= myBoundary.xmin());599if (myBoundary.around(c->getToGeomPosition(), 5)) {600myEdges.push_back(c->getToEdgeID());601}602}603// connect edges604for (i = myEdges.begin(); i != myEdges.end(); i++) {605NIVissimEdge* edge = NIVissimEdge::dictionary(*i);606edge->addToConnectionCluster(this);607}608}609610611double612NIVissimConnectionCluster::getPositionForEdge(int edgeid) const {613// return the middle of the connections when there are any614if (myConnections.size() != 0) {615double sum = 0;616int part = 0;617std::vector<int>::const_iterator i;618for (i = myConnections.begin(); i != myConnections.end(); i++) {619NIVissimConnection* c = NIVissimConnection::dictionary(*i);620if (c->getFromEdgeID() == edgeid) {621part++;622sum += c->getFromPosition();623}624if (c->getToEdgeID() == edgeid) {625part++;626sum += c->getToPosition();627}628}629if (part > 0) {630return sum / (double) part;631}632}633// use the position of the node if possible634if (myNodeCluster >= 0) {635// try to find the nearest point on the edge636// !!! only the main geometry is regarded637NIVissimNodeDef* node =638NIVissimNodeDef::dictionary(myNodeCluster);639if (node != nullptr) {640double pos = node->getEdgePosition(edgeid);641if (pos >= 0) {642return pos;643}644}645/*646double try1 = GeomHelper::nearest_offset_on_line_to_point(647edge->getBegin2D(), edge->getEnd2D(), node->getPos());648if(try1>=0) {649return try1;650}651// try to use simple distance652double dist1 =653GeomHelper::distance(node->getPos(), edge->getBegin2D());654double dist2 =655GeomHelper::distance(node->getPos(), edge->getEnd2D());656return dist1<dist2657? 0 : edge->getLength();658*/659}660// what else?661WRITE_WARNING(TL("NIVissimConnectionCluster: how to get an edge's position?"));662// !!!663assert(myBoundary.xmin() <= myBoundary.xmax());664NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid);665std::vector<int>::const_iterator i = std::find(myEdges.begin(), myEdges.end(), edgeid);666if (i == myEdges.end()) {667// edge does not exist!?668throw 1;669}670const PositionVector& edgeGeom = edge->getGeometry();671Position p = GeomHelper::crossPoint(myBoundary, edgeGeom);672return GeomHelper::nearest_offset_on_line_to_point2D(673edgeGeom.front(), edgeGeom.back(), p);674}675676677678void679NIVissimConnectionCluster::clearDict() {680for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {681delete (*i);682}683myClusters.clear();684myFirstFreeID = 100000;685}686687688PositionVector689NIVissimConnectionCluster::getIncomingContinuationGeometry(NIVissimEdge* e) const {690// collect connection where this edge is the incoming one691std::vector<NIVissimConnection*> edgeIsIncoming;692for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {693NIVissimConnection* c = NIVissimConnection::dictionary(*i);694if (c->getFromEdgeID() == e->getID()) {695edgeIsIncoming.push_back(c);696}697}698//699if (edgeIsIncoming.size() == 0) {700return PositionVector();701}702// sort connected edges in same direction703sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),704same_direction_sorter(e->getGeometry().beginEndAngle()));705NIVissimConnection* c = *(edgeIsIncoming.begin());706return c->getGeometry();707}708709710711NIVissimConnection*712NIVissimConnectionCluster::getIncomingContinuation(NIVissimEdge* e) const {713// collect connection where this edge is the incoming one714std::vector<NIVissimConnection*> edgeIsIncoming;715for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {716NIVissimConnection* c = NIVissimConnection::dictionary(*i);717if (c->getFromEdgeID() == e->getID()) {718edgeIsIncoming.push_back(c);719}720}721//722if (edgeIsIncoming.size() == 0) {723return nullptr;724}725// sort connected edges in same direction726sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),727same_direction_sorter(e->getGeometry().beginEndAngle()));728return *(edgeIsIncoming.begin());729}730731732733PositionVector734NIVissimConnectionCluster::getOutgoingContinuationGeometry(NIVissimEdge* e) const {735// collect connection where this edge is the outgoing one736std::vector<NIVissimConnection*> edgeIsOutgoing;737for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {738NIVissimConnection* c = NIVissimConnection::dictionary(*i);739if (c->getToEdgeID() == e->getID()) {740edgeIsOutgoing.push_back(c);741}742}743//744if (edgeIsOutgoing.size() == 0) {745return PositionVector();746}747// sort connected edges in same direction748sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),749same_direction_sorter(e->getGeometry().beginEndAngle()));750NIVissimConnection* c = *(edgeIsOutgoing.begin());751return c->getGeometry();752}753754755NIVissimConnection*756NIVissimConnectionCluster::getOutgoingContinuation(NIVissimEdge* e) const {757// collect connection where this edge is the outgoing one758std::vector<NIVissimConnection*> edgeIsOutgoing;759for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {760NIVissimConnection* c = NIVissimConnection::dictionary(*i);761if (c->getToEdgeID() == e->getID()) {762edgeIsOutgoing.push_back(c);763}764}765//766if (edgeIsOutgoing.size() == 0) {767return nullptr;768}769// sort connected edges in same direction770sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),771same_direction_sorter(e->getGeometry().beginEndAngle()));772return *(edgeIsOutgoing.begin());773}774775776/****************************************************************************/777778779