SUMO - Simulation of Urban MObility

NIVissimConnectionCluster.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // -------------------
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 
00020 
00021 // ===========================================================================
00022 // included modules
00023 // ===========================================================================
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029 
00030 #include <algorithm>
00031 #include <iostream>
00032 #include <cassert>
00033 #include <iterator>
00034 #include <utils/geom/Boundary.h>
00035 #include <utils/geom/GeomHelper.h>
00036 #include <utils/common/VectorHelper.h>
00037 #include <utils/common/MsgHandler.h>
00038 #include <utils/common/ToString.h>
00039 #include "NIVissimConnection.h"
00040 #include "NIVissimDisturbance.h"
00041 #include "NIVissimNodeCluster.h"
00042 #include "NIVissimNodeDef.h"
00043 #include "NIVissimEdge.h"
00044 #include "NIVissimTL.h"
00045 #include "NIVissimConnectionCluster.h"
00046 
00047 #ifdef CHECK_MEMORY_LEAKS
00048 #include <foreign/nvwa/debug_new.h>
00049 #endif // CHECK_MEMORY_LEAKS
00050 
00051 
00052 // ===========================================================================
00053 // static members
00054 // ===========================================================================
00055 NIVissimConnectionCluster::ContType NIVissimConnectionCluster::myClusters;
00056 int NIVissimConnectionCluster::myFirstFreeID = 100000;
00057 int NIVissimConnectionCluster::myStaticBlaID = 0;
00058 
00059 
00060 
00061 // ===========================================================================
00062 // method definitions
00063 // ===========================================================================
00064 // ---------------------------------------------------------------------------
00065 // NIVissimConnectionCluster::NodeSubCluster - methods
00066 // ---------------------------------------------------------------------------
00067 NIVissimConnectionCluster::NodeSubCluster::NodeSubCluster(NIVissimConnection* c) {
00068     add(c);
00069 }
00070 
00071 
00072 NIVissimConnectionCluster::NodeSubCluster::~NodeSubCluster() {}
00073 
00074 
00075 void
00076 NIVissimConnectionCluster::NodeSubCluster::add(NIVissimConnection* c) {
00077     myBoundary.add(c->getBoundingBox());
00078     myConnections.push_back(c);
00079 }
00080 
00081 
00082 void
00083 NIVissimConnectionCluster::NodeSubCluster::add(const NIVissimConnectionCluster::NodeSubCluster& c) {
00084     for (ConnectionCont::const_iterator i=c.myConnections.begin(); i!=c.myConnections.end(); i++) {
00085         add(*i);
00086     }
00087 }
00088 
00089 
00090 size_t
00091 NIVissimConnectionCluster::NodeSubCluster::size() const {
00092     return myConnections.size();
00093 }
00094 
00095 
00096 IntVector
00097 NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const {
00098     IntVector ret;
00099     int id = NIVissimConnectionCluster::getNextFreeNodeID();
00100     for (ConnectionCont::const_iterator i=myConnections.begin(); i!=myConnections.end(); i++) {
00101         ret.push_back((*i)->getID());
00102         (*i)->setNodeCluster(id);
00103     }
00104     return ret;
00105 }
00106 
00107 
00108 bool
00109 NIVissimConnectionCluster::NodeSubCluster::overlapsWith(
00110     const NIVissimConnectionCluster::NodeSubCluster& c,
00111     SUMOReal offset) {
00112     assert(myBoundary.xmax()>=myBoundary.xmin());
00113     assert(c.myBoundary.xmax()>=c.myBoundary.xmin());
00114     return myBoundary.overlapsWith(c.myBoundary, offset);
00115 }
00116 
00117 
00118 
00119 // ---------------------------------------------------------------------------
00120 // NIVissimConnectionCluster - methods
00121 // ---------------------------------------------------------------------------
00122 NIVissimConnectionCluster::NIVissimConnectionCluster(
00123     const IntVector& connections, int nodeCluster, int edgeid)
00124     : myConnections(connections), myNodeCluster(nodeCluster),
00125       myBlaID(myStaticBlaID++) {
00126     recomputeBoundary();
00127     myClusters.push_back(this);
00128     assert(edgeid>0);
00129     if (edgeid>=0) {
00130         myEdges.push_back(edgeid);
00131     }
00132     // add information about incoming and outgoing edges
00133     for (IntVector::const_iterator i=connections.begin(); i!=connections.end(); i++) {
00134         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00135         assert(c!=0);
00136         myOutgoingEdges.push_back(c->getToEdgeID());
00137         myIncomingEdges.push_back(c->getFromEdgeID());
00138         assert(c->getFromEdgeID()==edgeid||c->getToEdgeID()==edgeid);
00139     }
00140     VectorHelper<int>::removeDouble(myIncomingEdges);
00141     VectorHelper<int>::removeDouble(myOutgoingEdges);
00142 }
00143 
00144 
00145 NIVissimConnectionCluster::NIVissimConnectionCluster(
00146     const IntVector& connections, const Boundary& boundary,
00147     int nodeCluster, const IntVector& edges)
00148     : myConnections(connections), myBoundary(boundary),
00149       myNodeCluster(nodeCluster), myEdges(edges) {
00150     myClusters.push_back(this);
00151     recomputeBoundary();
00152     assert(myBoundary.xmax()>=myBoundary.xmin());
00153     // add information about incoming and outgoing edges
00154     for (IntVector::const_iterator i=connections.begin(); i!=connections.end(); i++) {
00155         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00156         assert(c!=0);
00157         myOutgoingEdges.push_back(c->getToEdgeID());
00158         myIncomingEdges.push_back(c->getFromEdgeID());
00159         assert(find(edges.begin(), edges.end(), c->getFromEdgeID())!=edges.end()
00160                ||
00161                find(edges.begin(), edges.end(), c->getToEdgeID())!=edges.end());
00162     }
00163     VectorHelper<int>::removeDouble(myIncomingEdges);
00164     VectorHelper<int>::removeDouble(myOutgoingEdges);
00165 }
00166 
00167 
00168 NIVissimConnectionCluster::~NIVissimConnectionCluster() {}
00169 
00170 
00171 
00172 int
00173 NIVissimConnectionCluster::getNextFreeNodeID() {
00174     return myFirstFreeID++;
00175 }
00176 
00177 
00178 bool
00179 NIVissimConnectionCluster::overlapsWith(NIVissimConnectionCluster* c,
00180                                         SUMOReal offset) const {
00181     assert(myBoundary.xmax()>=myBoundary.xmin());
00182     assert(c->myBoundary.xmax()>=c->myBoundary.xmin());
00183     return c->myBoundary.overlapsWith(myBoundary, offset);
00184 }
00185 
00186 
00187 void
00188 NIVissimConnectionCluster::add(NIVissimConnectionCluster* c) {
00189     assert(myBoundary.xmax()>=myBoundary.xmin());
00190     assert(c->myBoundary.xmax()>=c->myBoundary.xmin());
00191     myBoundary.add(c->myBoundary);
00192     for (IntVector::iterator i=c->myConnections.begin(); i!=c->myConnections.end(); i++) {
00193         myConnections.push_back(*i);
00194     }
00195     VectorHelper<int>::removeDouble(myConnections);
00196     assert(myNodeCluster==-1||c->myNodeCluster==-1);
00197     if (myNodeCluster==-1) {
00198         myNodeCluster = c->myNodeCluster;
00199     }
00200     // inform edges about merging
00201     //  !!! merge should be done within one method
00202     for (IntVector::iterator j=c->myEdges.begin(); j!=c->myEdges.end(); j++) {
00203         NIVissimEdge::dictionary(*j)->mergedInto(c, this);
00204     }
00205     copy(c->myEdges.begin(), c->myEdges.end(), back_inserter(myEdges));
00206     copy(c->myIncomingEdges.begin(), c->myIncomingEdges.end(),
00207          back_inserter(myIncomingEdges));
00208     copy(c->myOutgoingEdges.begin(), c->myOutgoingEdges.end(),
00209          back_inserter(myOutgoingEdges));
00210     VectorHelper<int>::removeDouble(myEdges);
00211     VectorHelper<int>::removeDouble(myIncomingEdges);
00212     VectorHelper<int>::removeDouble(myOutgoingEdges);
00213 }
00214 
00215 
00216 
00217 void
00218 NIVissimConnectionCluster::joinBySameEdges(SUMOReal offset) {
00219     // !!! ...
00220     // Further, we try to omit joining of overlaping nodes. This is done by holding
00221     //  the lists of incoming and outgoing edges and incrementally building the nodes
00222     //  regarding this information
00223     std::vector<NIVissimConnectionCluster*> joinAble;
00224     size_t pos = 0;
00225     ContType::iterator i = myClusters.begin();
00226     // step1 - faster but no complete
00227     while (i!=myClusters.end()) {
00228         joinAble.clear();
00229         ContType::iterator j = i + 1;
00230 
00231         // check whether every combination has been processed
00232         while (j!=myClusters.end()) {
00233             // check whether the current clusters overlap
00234             if ((*i)->joinable(*j, offset)) {
00235                 joinAble.push_back(*j);
00236             }
00237             j++;
00238         }
00239         for (std::vector<NIVissimConnectionCluster*>::iterator k=joinAble.begin();
00240                 k!=joinAble.end(); k++) {
00241             // add the overlaping cluster
00242             (*i)->add(*k);
00243             // erase the overlaping cluster
00244             delete *k;
00245             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00246         }
00247         //
00248         if (joinAble.size()>0) {
00249             i = myClusters.begin() + pos;
00250             // clear temporary storages
00251             joinAble.clear();
00252         } else {
00253             i++;
00254             MsgHandler::getMessageInstance()->progressMsg("Checked(1): " + toString(pos) + "/" + toString(myClusters.size()) + "         ");
00255             pos++;
00256         }
00257     }
00258     //
00259     pos = 0;
00260     i = myClusters.begin();
00261     while (i!=myClusters.end()) {
00262         ContType::iterator j = i + 1;
00263         // check whether every combination has been processed
00264         while (j!=myClusters.end()) {
00265             // check whether the current clusters overlap
00266             if ((*i)->joinable(*j, offset)) {
00267                 joinAble.push_back(*j);
00268             }
00269             j++;
00270         }
00271         for (std::vector<NIVissimConnectionCluster*>::iterator k=joinAble.begin();
00272                 k!=joinAble.end(); k++) {
00273             // add the overlaping cluster
00274             (*i)->add(*k);
00275             // erase the overlaping cluster
00276             delete *k;
00277             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00278         }
00279         //
00280         if (joinAble.size()>0) {
00281             i = myClusters.begin();
00282             // clear temporary storages
00283             joinAble.clear();
00284             pos = 0;
00285         } else {
00286             i++;
00287             pos++;
00288             MsgHandler::getMessageInstance()->progressMsg("Checked(2): " + toString(pos) + "/" + toString(myClusters.size()) + "         ");
00289         }
00290     }
00291     // check for weak district connections
00292     //  (junctions made up by district connections, where prohibitions are not
00293     //   modelled properly)
00294     pos = 0;
00295     i = myClusters.begin();
00296     while (i!=myClusters.end()) {
00297         ContType::iterator j = i + 1;
00298         // check whether every combination has been processed
00299         while (j!=myClusters.end()) {
00300             // check whether the current clusters overlap
00301             if ((*i)->isWeakDistrictConnRealisation(*j)) {
00302                 joinAble.push_back(*j);
00303             }
00304             j++;
00305         }
00306         for (std::vector<NIVissimConnectionCluster*>::iterator k=joinAble.begin();
00307                 k!=joinAble.end(); k++) {
00308             // add the overlaping cluster
00309             (*i)->add(*k);
00310             // erase the overlaping cluster
00311             delete *k;
00312             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00313         }
00314         //
00315         if (joinAble.size()>0) {
00316             i = myClusters.begin();
00317             // clear temporary storages
00318             joinAble.clear();
00319             pos = 0;
00320         } else {
00321             i++;
00322             pos++;
00323             MsgHandler::getMessageInstance()->progressMsg("Checked(3): " + toString(pos) + "/" + toString(myClusters.size()) + "         ");
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     IntVector extendedOutgoing1;
00357     IntVector extendedIncoming1;
00358     IntVector extendedOutgoing2;
00359     IntVector 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 (IntVector::const_iterator j1=myConnections.begin(); j1!=myConnections.end()&&!crosses; j1++) {
00402         NIVissimConnection* c1 = NIVissimConnection::dictionary(*j1);
00403         const PositionVector& g1 = c1->getGeometry();
00404         for (IntVector::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 (IntVector::iterator i=myConnections.begin(); i!=myConnections.end(); i++) {
00437         NIVissimConnection* c1 = NIVissimConnection::dictionary(*i);
00438         for (IntVector::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_point(
00444                                     g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
00445                 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point(
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_point(
00455                                     g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
00456                 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point(
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 IntVector
00469 NIVissimConnectionCluster::extendByToTreatAsSame(const IntVector& iv1,
00470         const IntVector& iv2) const {
00471     IntVector ret(iv1);
00472     for (IntVector::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 IntVector
00485 NIVissimConnectionCluster::getDisturbanceParticipators() {
00486     IntVector ret;
00487     for (IntVector::iterator i=myConnections.begin(); i!=myConnections.end(); i++) {
00488         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00489         const IntVector& disturbances = c->getDisturbances();
00490         for (IntVector::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         IntVector disturbances;
00504         IntVector tls;
00505         IntVector 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         IntVector connections = (*i)->myConnections;
00536         if (find(connections.begin(), connections.end(), id)!=connections.end()) {
00537             for (IntVector::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         IntVector connections = (*i)->myConnections;
00550         for (IntVector::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         IntVector::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 (IntVector::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     IntVector::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         IntVector::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     IntVector::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_point(
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 (IntVector::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 (IntVector::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 (IntVector::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 (IntVector::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