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

Generated on Wed May 5 00:06:34 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6