SUMO - Simulation of Urban MObility
NIVissimConnectionCluster.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00009 // -------------------
00010 /****************************************************************************/
00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00013 /****************************************************************************/
00014 //
00015 //   This file is part of SUMO.
00016 //   SUMO is free software: you can redistribute it and/or modify
00017 //   it under the terms of the GNU General Public License as published by
00018 //   the Free Software Foundation, either version 3 of the License, or
00019 //   (at your option) any later version.
00020 //
00021 /****************************************************************************/
00022 
00023 
00024 // ===========================================================================
00025 // included modules
00026 // ===========================================================================
00027 #ifdef _MSC_VER
00028 #include <windows_config.h>
00029 #else
00030 #include <config.h>
00031 #endif
00032 
00033 #include <algorithm>
00034 #include <iostream>
00035 #include <cassert>
00036 #include <iterator>
00037 #include <utils/geom/Boundary.h>
00038 #include <utils/geom/GeomHelper.h>
00039 #include <utils/common/VectorHelper.h>
00040 #include <utils/common/MsgHandler.h>
00041 #include <utils/common/ToString.h>
00042 #include "NIVissimConnection.h"
00043 #include "NIVissimDisturbance.h"
00044 #include "NIVissimNodeCluster.h"
00045 #include "NIVissimNodeDef.h"
00046 #include "NIVissimEdge.h"
00047 #include "NIVissimTL.h"
00048 #include "NIVissimConnectionCluster.h"
00049 
00050 #ifdef CHECK_MEMORY_LEAKS
00051 #include <foreign/nvwa/debug_new.h>
00052 #endif // CHECK_MEMORY_LEAKS
00053 
00054 
00055 // ===========================================================================
00056 // static members
00057 // ===========================================================================
00058 NIVissimConnectionCluster::ContType NIVissimConnectionCluster::myClusters;
00059 int NIVissimConnectionCluster::myFirstFreeID = 100000;
00060 int NIVissimConnectionCluster::myStaticBlaID = 0;
00061 
00062 
00063 
00064 // ===========================================================================
00065 // method definitions
00066 // ===========================================================================
00067 // ---------------------------------------------------------------------------
00068 // NIVissimConnectionCluster::NodeSubCluster - methods
00069 // ---------------------------------------------------------------------------
00070 NIVissimConnectionCluster::NodeSubCluster::NodeSubCluster(NIVissimConnection* c) {
00071     add(c);
00072 }
00073 
00074 
00075 NIVissimConnectionCluster::NodeSubCluster::~NodeSubCluster() {}
00076 
00077 
00078 void
00079 NIVissimConnectionCluster::NodeSubCluster::add(NIVissimConnection* c) {
00080     myBoundary.add(c->getBoundingBox());
00081     myConnections.push_back(c);
00082 }
00083 
00084 
00085 void
00086 NIVissimConnectionCluster::NodeSubCluster::add(const NIVissimConnectionCluster::NodeSubCluster& c) {
00087     for (ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
00088         add(*i);
00089     }
00090 }
00091 
00092 
00093 size_t
00094 NIVissimConnectionCluster::NodeSubCluster::size() const {
00095     return myConnections.size();
00096 }
00097 
00098 
00099 std::vector<int>
00100 NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const {
00101     std::vector<int> ret;
00102     int id = NIVissimConnectionCluster::getNextFreeNodeID();
00103     for (ConnectionCont::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00104         ret.push_back((*i)->getID());
00105         (*i)->setNodeCluster(id);
00106     }
00107     return ret;
00108 }
00109 
00110 
00111 bool
00112 NIVissimConnectionCluster::NodeSubCluster::overlapsWith(
00113     const NIVissimConnectionCluster::NodeSubCluster& c,
00114     SUMOReal offset) {
00115     assert(myBoundary.xmax() >= myBoundary.xmin());
00116     assert(c.myBoundary.xmax() >= c.myBoundary.xmin());
00117     return myBoundary.overlapsWith(c.myBoundary, offset);
00118 }
00119 
00120 
00121 
00122 // ---------------------------------------------------------------------------
00123 // NIVissimConnectionCluster - methods
00124 // ---------------------------------------------------------------------------
00125 NIVissimConnectionCluster::NIVissimConnectionCluster(
00126     const std::vector<int>& connections, int nodeCluster, int edgeid)
00127     : myConnections(connections), myNodeCluster(nodeCluster),
00128       myBlaID(myStaticBlaID++) {
00129     recomputeBoundary();
00130     myClusters.push_back(this);
00131     assert(edgeid > 0);
00132     if (edgeid >= 0) {
00133         myEdges.push_back(edgeid);
00134     }
00135     // add information about incoming and outgoing edges
00136     for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {
00137         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00138         assert(c != 0);
00139         myOutgoingEdges.push_back(c->getToEdgeID());
00140         myIncomingEdges.push_back(c->getFromEdgeID());
00141         assert(c->getFromEdgeID() == edgeid || c->getToEdgeID() == edgeid);
00142     }
00143     VectorHelper<int>::removeDouble(myIncomingEdges);
00144     VectorHelper<int>::removeDouble(myOutgoingEdges);
00145 }
00146 
00147 
00148 NIVissimConnectionCluster::NIVissimConnectionCluster(
00149     const std::vector<int>& connections, const Boundary& boundary,
00150     int nodeCluster, const std::vector<int>& edges)
00151     : myConnections(connections), myBoundary(boundary),
00152       myNodeCluster(nodeCluster), myEdges(edges) {
00153     myClusters.push_back(this);
00154     recomputeBoundary();
00155     assert(myBoundary.xmax() >= myBoundary.xmin());
00156     // add information about incoming and outgoing edges
00157     for (std::vector<int>::const_iterator i = connections.begin(); i != connections.end(); i++) {
00158         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00159         assert(c != 0);
00160         myOutgoingEdges.push_back(c->getToEdgeID());
00161         myIncomingEdges.push_back(c->getFromEdgeID());
00162         assert(find(edges.begin(), edges.end(), c->getFromEdgeID()) != edges.end()
00163                ||
00164                find(edges.begin(), edges.end(), c->getToEdgeID()) != edges.end());
00165     }
00166     VectorHelper<int>::removeDouble(myIncomingEdges);
00167     VectorHelper<int>::removeDouble(myOutgoingEdges);
00168 }
00169 
00170 
00171 NIVissimConnectionCluster::~NIVissimConnectionCluster() {}
00172 
00173 
00174 
00175 int
00176 NIVissimConnectionCluster::getNextFreeNodeID() {
00177     return myFirstFreeID++;
00178 }
00179 
00180 
00181 bool
00182 NIVissimConnectionCluster::overlapsWith(NIVissimConnectionCluster* c,
00183                                         SUMOReal offset) const {
00184     assert(myBoundary.xmax() >= myBoundary.xmin());
00185     assert(c->myBoundary.xmax() >= c->myBoundary.xmin());
00186     return c->myBoundary.overlapsWith(myBoundary, offset);
00187 }
00188 
00189 
00190 void
00191 NIVissimConnectionCluster::add(NIVissimConnectionCluster* c) {
00192     assert(myBoundary.xmax() >= myBoundary.xmin());
00193     assert(c->myBoundary.xmax() >= c->myBoundary.xmin());
00194     myBoundary.add(c->myBoundary);
00195     for (std::vector<int>::iterator i = c->myConnections.begin(); i != c->myConnections.end(); i++) {
00196         myConnections.push_back(*i);
00197     }
00198     VectorHelper<int>::removeDouble(myConnections);
00199     assert(myNodeCluster == -1 || c->myNodeCluster == -1);
00200     if (myNodeCluster == -1) {
00201         myNodeCluster = c->myNodeCluster;
00202     }
00203     // inform edges about merging
00204     //  !!! merge should be done within one method
00205     for (std::vector<int>::iterator j = c->myEdges.begin(); j != c->myEdges.end(); j++) {
00206         NIVissimEdge::dictionary(*j)->mergedInto(c, this);
00207     }
00208     copy(c->myEdges.begin(), c->myEdges.end(), back_inserter(myEdges));
00209     copy(c->myIncomingEdges.begin(), c->myIncomingEdges.end(),
00210          back_inserter(myIncomingEdges));
00211     copy(c->myOutgoingEdges.begin(), c->myOutgoingEdges.end(),
00212          back_inserter(myOutgoingEdges));
00213     VectorHelper<int>::removeDouble(myEdges);
00214     VectorHelper<int>::removeDouble(myIncomingEdges);
00215     VectorHelper<int>::removeDouble(myOutgoingEdges);
00216 }
00217 
00218 
00219 
00220 void
00221 NIVissimConnectionCluster::joinBySameEdges(SUMOReal offset) {
00222     // !!! ...
00223     // Further, we try to omit joining of overlaping nodes. This is done by holding
00224     //  the lists of incoming and outgoing edges and incrementally building the nodes
00225     //  regarding this information
00226     std::vector<NIVissimConnectionCluster*> joinAble;
00227     size_t pos = 0;
00228     ContType::iterator i = myClusters.begin();
00229     // step1 - faster but no complete
00230     while (i != myClusters.end()) {
00231         joinAble.clear();
00232         ContType::iterator j = i + 1;
00233 
00234         // check whether every combination has been processed
00235         while (j != myClusters.end()) {
00236             // check whether the current clusters overlap
00237             if ((*i)->joinable(*j, offset)) {
00238                 joinAble.push_back(*j);
00239             }
00240             j++;
00241         }
00242         for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
00243                 k != joinAble.end(); k++) {
00244             // add the overlaping cluster
00245             (*i)->add(*k);
00246             // erase the overlaping cluster
00247             delete *k;
00248             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00249         }
00250         //
00251         if (joinAble.size() > 0) {
00252             i = myClusters.begin() + pos;
00253             // clear temporary storages
00254             joinAble.clear();
00255         } else {
00256             i++;
00257             pos++;
00258         }
00259     }
00260     //
00261     pos = 0;
00262     i = myClusters.begin();
00263     while (i != myClusters.end()) {
00264         ContType::iterator j = i + 1;
00265         // check whether every combination has been processed
00266         while (j != myClusters.end()) {
00267             // check whether the current clusters overlap
00268             if ((*i)->joinable(*j, offset)) {
00269                 joinAble.push_back(*j);
00270             }
00271             j++;
00272         }
00273         for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
00274                 k != joinAble.end(); k++) {
00275             // add the overlaping cluster
00276             (*i)->add(*k);
00277             // erase the overlaping cluster
00278             delete *k;
00279             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00280         }
00281         //
00282         if (joinAble.size() > 0) {
00283             i = myClusters.begin();
00284             // clear temporary storages
00285             joinAble.clear();
00286             pos = 0;
00287         } else {
00288             i++;
00289             pos++;
00290         }
00291     }
00292     // check for weak district connections
00293     //  (junctions made up by district connections, where prohibitions are not
00294     //   modelled properly)
00295     pos = 0;
00296     i = myClusters.begin();
00297     while (i != myClusters.end()) {
00298         ContType::iterator j = i + 1;
00299         // check whether every combination has been processed
00300         while (j != myClusters.end()) {
00301             // check whether the current clusters overlap
00302             if ((*i)->isWeakDistrictConnRealisation(*j)) {
00303                 joinAble.push_back(*j);
00304             }
00305             j++;
00306         }
00307         for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
00308                 k != joinAble.end(); k++) {
00309             // add the overlaping cluster
00310             (*i)->add(*k);
00311             // erase the overlaping cluster
00312             delete *k;
00313             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00314         }
00315         //
00316         if (joinAble.size() > 0) {
00317             i = myClusters.begin();
00318             // clear temporary storages
00319             joinAble.clear();
00320             pos = 0;
00321         } else {
00322             i++;
00323             pos++;
00324         }
00325     }
00326 }
00327 
00328 
00329 bool
00330 NIVissimConnectionCluster::joinable(NIVissimConnectionCluster* c2, SUMOReal offset) {
00331     // join clusters which have at least one connection in common
00332     if (VectorHelper<int>::subSetExists(myConnections, c2->myConnections)) {
00333         return true;
00334     }
00335 
00336     // connections shall overlap otherwise
00337     if (!overlapsWith(c2, offset)) {
00338         return false;
00339     }
00340 
00341     // at least one of the clusters shall not be assigned to a node in previous (!!!??)
00342     if (hasNodeCluster() && c2->hasNodeCluster()) {
00343         return false;
00344     }
00345 
00346     // join clusters which where connections do disturb each other
00347     if (VectorHelper<int>::subSetExists(c2->getDisturbanceParticipators(), myConnections)
00348             ||
00349             VectorHelper<int>::subSetExists(getDisturbanceParticipators(), c2->myConnections)) {
00350 
00351         return true;
00352     }
00353 
00354 
00355     // join clusters which do share the same incoming or outgoing edges (not mutually)
00356     std::vector<int> extendedOutgoing1;
00357     std::vector<int> extendedIncoming1;
00358     std::vector<int> extendedOutgoing2;
00359     std::vector<int> extendedIncoming2;
00360     if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) {
00361         extendedOutgoing1 =
00362             extendByToTreatAsSame(myOutgoingEdges, myIncomingEdges);
00363         extendedIncoming1 =
00364             extendByToTreatAsSame(myIncomingEdges, myOutgoingEdges);
00365         extendedOutgoing2 =
00366             extendByToTreatAsSame(c2->myOutgoingEdges, c2->myIncomingEdges);
00367         extendedIncoming2 =
00368             extendByToTreatAsSame(c2->myIncomingEdges, c2->myOutgoingEdges);
00369     } else {
00370         extendedOutgoing1 = myIncomingEdges;
00371         extendedIncoming1 = myOutgoingEdges;
00372         extendedOutgoing2 = c2->myIncomingEdges;
00373         extendedIncoming2 = c2->myOutgoingEdges;
00374     }
00375 
00376     if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2)
00377             ||
00378             VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2)
00379        ) {
00380         return true;
00381     }
00382     return false;
00383 }
00384 
00385 
00386 bool
00387 NIVissimConnectionCluster::isWeakDistrictConnRealisation(NIVissimConnectionCluster* c2) {
00388     if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) {
00389         return false;
00390     }
00391     if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) {
00392         return false;
00393     }
00394 
00395     // ok, may be the other way round
00396     if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) {
00397         return c2->isWeakDistrictConnRealisation(this);
00398     }
00399     // connections must cross
00400     bool crosses = false;
00401     for (std::vector<int>::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) {
00402         NIVissimConnection* c1 = NIVissimConnection::dictionary(*j1);
00403         const PositionVector& g1 = c1->getGeometry();
00404         for (std::vector<int>::const_iterator j2 = c2->myConnections.begin(); j2 != c2->myConnections.end() && !crosses; j2++) {
00405             NIVissimConnection* c2 = NIVissimConnection::dictionary(*j2);
00406             const PositionVector& g2 = c2->getGeometry();
00407             if (g1.intersects(g2)) {
00408                 crosses = true;
00409             }
00410         }
00411     }
00412     if (!crosses) {
00413         return false;
00414     }
00415     // ok, check for connection
00416     if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) {
00417         return false;
00418     }
00419     // check whether the connection is bidirectional
00420     NIVissimEdge* oe = NIVissimEdge::dictionary(myOutgoingEdges[0]);
00421     NIVissimEdge* ie = NIVissimEdge::dictionary(c2->myIncomingEdges[0]);
00422     if (oe == 0 || ie == 0) {
00423         return false;
00424     }
00425     Line l1(oe->getGeometry().getBegin(), oe->getGeometry().getEnd());
00426     Line l2(ie->getGeometry().getEnd(), ie->getGeometry().getBegin());
00427     SUMOReal a1 = l1.atan2DegreeAngle();
00428     SUMOReal a2 = l2.atan2DegreeAngle();
00429     return fabs(a1 - a2) < 5;
00430 }
00431 
00432 
00433 bool
00434 NIVissimConnectionCluster::liesOnSameEdgesEnd(NIVissimConnectionCluster* cc2) {
00435     //
00436     for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00437         NIVissimConnection* c1 = NIVissimConnection::dictionary(*i);
00438         for (std::vector<int>::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) {
00439             NIVissimConnection* c2 = NIVissimConnection::dictionary(*j);
00440             if (c1->getFromEdgeID() == c2->getFromEdgeID()) {
00441                 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());
00442                 const PositionVector& g = e->getGeometry();
00443                 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D(
00444                                     g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
00445                 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D(
00446                                     g.getBegin(), g.getEnd(), c2->getBoundary().getCenter());
00447                 if (pos1 <= 5.0 && pos2 <= 5.0) {
00448                     return true;
00449                 }
00450             }
00451             if (c1->getToEdgeID() == c2->getToEdgeID()) {
00452                 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());
00453                 const PositionVector& g = e->getGeometry();
00454                 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D(
00455                                     g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
00456                 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D(
00457                                     g.getBegin(), g.getEnd(), c2->getBoundary().getCenter());
00458                 if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) {
00459                     return true;
00460                 }
00461             }
00462         }
00463     }
00464     return false;
00465 }
00466 
00467 
00468 std::vector<int>
00469 NIVissimConnectionCluster::extendByToTreatAsSame(const std::vector<int>& iv1,
00470         const std::vector<int>& iv2) const {
00471     std::vector<int> ret(iv1);
00472     for (std::vector<int>::const_iterator i = iv1.begin(); i != iv1.end(); i++) {
00473         NIVissimEdge* e = NIVissimEdge::dictionary(*i);
00474         const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame();
00475         for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) {
00476             if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) {
00477                 ret.push_back((*j)->getID());
00478             }
00479         }
00480     }
00481     return ret;
00482 }
00483 
00484 std::vector<int>
00485 NIVissimConnectionCluster::getDisturbanceParticipators() {
00486     std::vector<int> ret;
00487     for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00488         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00489         const std::vector<int>& disturbances = c->getDisturbances();
00490         for (std::vector<int>::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) {
00491             NIVissimDisturbance* d = NIVissimDisturbance::dictionary(*j);
00492             ret.push_back(d->getEdgeID());
00493             ret.push_back(d->getDisturbanceID());
00494         }
00495     }
00496     return ret;
00497 }
00498 
00499 
00500 void
00501 NIVissimConnectionCluster::buildNodeClusters() {
00502     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00503         std::vector<int> disturbances;
00504         std::vector<int> tls;
00505         std::vector<int> nodes;
00506         int tlsid = -1;
00507         int nodeid = -1;
00508         if ((*i)->myConnections.size() > 0) {
00509             (*i)->recomputeBoundary();
00510             disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary);
00511         }
00512         nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0);
00513         if (nodes.size() > 1) {
00514             WRITE_WARNING("NIVissimConnectionCluster:More than a single node");
00515             //          throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein
00516         }
00517         if (nodes.size() > 0) {
00518             nodeid = nodes[0];
00519         }
00520         //
00521         //
00522         int id = NIVissimNodeCluster::dictionary(
00523                      nodeid, tlsid, (*i)->myConnections,
00524                      disturbances, (*i)->myIncomingEdges.size() < 2);
00525         assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0);
00526         (*i)->myNodeCluster = id;
00527     }
00528 }
00529 
00530 
00531 void
00532 NIVissimConnectionCluster::searchForConnection(int id) {
00533     int pos = 0;
00534     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00535         std::vector<int> connections = (*i)->myConnections;
00536         if (find(connections.begin(), connections.end(), id) != connections.end()) {
00537             for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) {
00538                 int checkdummy = *j;
00539             }
00540         }
00541         pos++;
00542     }
00543 }
00544 
00545 
00546 void
00547 NIVissimConnectionCluster::_debugOut(std::ostream& into) {
00548     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00549         std::vector<int> connections = (*i)->myConnections;
00550         for (std::vector<int>::iterator j = connections.begin(); j != connections.end(); j++) {
00551             if (j != connections.begin()) {
00552                 into << ", ";
00553             }
00554             into << *j;
00555         }
00556         into << "(" << (*i)->myBoundary << ")" << std::endl;
00557     }
00558     into << "---------------------------" << std::endl;
00559 }
00560 
00561 
00562 
00563 bool
00564 NIVissimConnectionCluster::hasNodeCluster() const {
00565     return myNodeCluster != -1;
00566 }
00567 
00568 
00569 size_t
00570 NIVissimConnectionCluster::dictSize() {
00571     return myClusters.size();
00572 }
00573 
00574 
00575 void
00576 NIVissimConnectionCluster::removeConnections(const NodeSubCluster& c) {
00577     for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
00578         NIVissimConnection* conn = *i;
00579         int connid = conn->getID();
00580         std::vector<int>::iterator j = find(myConnections.begin(), myConnections.end(), connid);
00581         if (j != myConnections.end()) {
00582             myConnections.erase(j);
00583         }
00584     }
00585     recomputeBoundary();
00586 }
00587 
00588 
00589 void
00590 NIVissimConnectionCluster::recomputeBoundary() {
00591     myBoundary = Boundary();
00592     for (std::vector<int>::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00593         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00594         if (c != 0) {
00595             myBoundary.add(c->getFromGeomPosition());
00596             myBoundary.add(c->getToGeomPosition());
00597             if (c->getGeometry().size() != 0) {
00598                 myBoundary.add(c->getGeometry().getBoxBoundary());
00599             }
00600         }
00601     }
00602     assert(myBoundary.xmax() >= myBoundary.xmin());
00603 }
00604 
00605 
00606 NBNode*
00607 NIVissimConnectionCluster::getNBNode() const {
00608     return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode();
00609 }
00610 
00611 
00612 bool
00613 NIVissimConnectionCluster::around(const Position& p, SUMOReal offset) const {
00614     assert(myBoundary.xmax() >= myBoundary.xmin());
00615     return myBoundary.around(p, offset);
00616 }
00617 
00618 
00619 
00620 void
00621 NIVissimConnectionCluster::recheckEdges() {
00622     assert(myConnections.size() != 0);
00623     // remove the cluster from all edges at first
00624     std::vector<int>::iterator i;
00625     for (i = myEdges.begin(); i != myEdges.end(); i++) {
00626         NIVissimEdge* edge = NIVissimEdge::dictionary(*i);
00627         edge->removeFromConnectionCluster(this);
00628     }
00629     // clear edge information
00630     myEdges.clear();
00631     // recheck which edges do still participate and add edges
00632     for (i = myConnections.begin(); i != myConnections.end(); i++) {
00633         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00634         assert(myBoundary.xmax() >= myBoundary.xmin());
00635         if (myBoundary.around(c->getFromGeomPosition(), 5)) {
00636             myEdges.push_back(c->getFromEdgeID());
00637         }
00638         assert(myBoundary.xmax() >= myBoundary.xmin());
00639         if (myBoundary.around(c->getToGeomPosition(), 5)) {
00640             myEdges.push_back(c->getToEdgeID());
00641         }
00642     }
00643     // connect edges
00644     for (i = myEdges.begin(); i != myEdges.end(); i++) {
00645         NIVissimEdge* edge = NIVissimEdge::dictionary(*i);
00646         edge->addToConnectionCluster(this);
00647     }
00648 }
00649 
00650 
00651 SUMOReal
00652 NIVissimConnectionCluster::getPositionForEdge(int edgeid) const {
00653     // return the middle of the connections when there are any
00654     if (myConnections.size() != 0) {
00655         SUMOReal sum = 0;
00656         size_t part = 0;
00657         std::vector<int>::const_iterator i;
00658         for (i = myConnections.begin(); i != myConnections.end(); i++) {
00659             NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00660             if (c->getFromEdgeID() == edgeid) {
00661                 part++;
00662                 sum += c->getFromPosition();
00663             }
00664             if (c->getToEdgeID() == edgeid) {
00665                 part++;
00666                 sum += c->getToPosition();
00667             }
00668         }
00669         if (part > 0) {
00670             return sum / (SUMOReal) part;
00671         }
00672     }
00673     // use the position of the node if possible
00674     if (myNodeCluster >= 0) {
00675         // try to find the nearest point on the edge
00676         //  !!! only the main geometry is regarded
00677         NIVissimNodeDef* node =
00678             NIVissimNodeDef::dictionary(myNodeCluster);
00679         if (node != 0) {
00680             SUMOReal pos = node->getEdgePosition(edgeid);
00681             if (pos >= 0) {
00682                 return pos;
00683             }
00684         }
00685         /*
00686                 SUMOReal try1 = GeomHelper::nearest_position_on_line_to_point(
00687                     edge->getBegin2D(), edge->getEnd2D(), node->getPos());
00688                 if(try1>=0) {
00689                     return try1;
00690                 }
00691                 // try to use simple distance
00692                 SUMOReal dist1 =
00693                     GeomHelper::distance(node->getPos(), edge->getBegin2D());
00694                 SUMOReal dist2 =
00695                     GeomHelper::distance(node->getPos(), edge->getEnd2D());
00696                 return dist1<dist2
00697                     ? 0 : edge->getLength();
00698                     */
00699     }
00700     // what else?
00701     WRITE_WARNING("NIVissimConnectionCluster: how to get an edge's position?");
00702     // !!!
00703     assert(myBoundary.xmin() <= myBoundary.xmax());
00704     NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid);
00705     std::vector<int>::const_iterator i = find(myEdges.begin(), myEdges.end(), edgeid);
00706     if (i == myEdges.end()) {
00707         // edge does not exist!?
00708         throw 1;
00709     }
00710     const PositionVector& edgeGeom = edge->getGeometry();
00711     Position p = GeomHelper::crossPoint(myBoundary, edgeGeom);
00712     return GeomHelper::nearest_position_on_line_to_point2D(
00713                edgeGeom.getBegin(), edgeGeom.getEnd(), p);
00714 }
00715 
00716 
00717 
00718 void
00719 NIVissimConnectionCluster::clearDict() {
00720     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00721         delete(*i);
00722     }
00723     myClusters.clear();
00724     myFirstFreeID = 100000;
00725 }
00726 
00727 
00728 PositionVector
00729 NIVissimConnectionCluster::getIncomingContinuationGeometry(NIVissimEdge* e) const {
00730     // collect connection where this edge is the incoming one
00731     std::vector<NIVissimConnection*> edgeIsIncoming;
00732     for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00733         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00734         if (c->getFromEdgeID() == e->getID()) {
00735             edgeIsIncoming.push_back(c);
00736         }
00737     }
00738     //
00739     if (edgeIsIncoming.size() == 0) {
00740         return PositionVector();
00741     }
00742     // sort connected edges in same direction
00743     sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
00744          same_direction_sorter(e->getGeometry().beginEndAngle()));
00745     NIVissimConnection* c = *(edgeIsIncoming.begin());
00746     return c->getGeometry();
00747 }
00748 
00749 
00750 
00751 NIVissimConnection*
00752 NIVissimConnectionCluster::getIncomingContinuation(NIVissimEdge* e) const {
00753     // collect connection where this edge is the incoming one
00754     std::vector<NIVissimConnection*> edgeIsIncoming;
00755     for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00756         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00757         if (c->getFromEdgeID() == e->getID()) {
00758             edgeIsIncoming.push_back(c);
00759         }
00760     }
00761     //
00762     if (edgeIsIncoming.size() == 0) {
00763         return 0;
00764     }
00765     // sort connected edges in same direction
00766     sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
00767          same_direction_sorter(e->getGeometry().beginEndAngle()));
00768     return *(edgeIsIncoming.begin());
00769 }
00770 
00771 
00772 
00773 PositionVector
00774 NIVissimConnectionCluster::getOutgoingContinuationGeometry(NIVissimEdge* e) const {
00775     // collect connection where this edge is the outgoing one
00776     std::vector<NIVissimConnection*> edgeIsOutgoing;
00777     for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00778         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00779         if (c->getToEdgeID() == e->getID()) {
00780             edgeIsOutgoing.push_back(c);
00781         }
00782     }
00783     //
00784     if (edgeIsOutgoing.size() == 0) {
00785         return PositionVector();
00786     }
00787     // sort connected edges in same direction
00788     sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
00789          same_direction_sorter(e->getGeometry().beginEndAngle()));
00790     NIVissimConnection* c = *(edgeIsOutgoing.begin());
00791     return c->getGeometry();
00792 }
00793 
00794 
00795 NIVissimConnection*
00796 NIVissimConnectionCluster::getOutgoingContinuation(NIVissimEdge* e) const {
00797     // collect connection where this edge is the outgoing one
00798     std::vector<NIVissimConnection*> edgeIsOutgoing;
00799     for (std::vector<int>::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00800         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00801         if (c->getToEdgeID() == e->getID()) {
00802             edgeIsOutgoing.push_back(c);
00803         }
00804     }
00805     //
00806     if (edgeIsOutgoing.size() == 0) {
00807         return 0;
00808     }
00809     // sort connected edges in same direction
00810     sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
00811          same_direction_sorter(e->getGeometry().beginEndAngle()));
00812     return *(edgeIsOutgoing.begin());
00813 }
00814 
00815 
00816 
00817 /****************************************************************************/
00818 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines