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 IntVector
00100 NIVissimConnectionCluster::NodeSubCluster::getConnectionIDs() const {
00101     IntVector 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 IntVector& 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 (IntVector::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 IntVector& connections, const Boundary& boundary,
00150     int nodeCluster, const IntVector& 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 (IntVector::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 (IntVector::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 (IntVector::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             MsgHandler::getMessageInstance()->progressMsg("Checked(1): " + toString(pos) + "/" + toString(myClusters.size()) + "         ");
00258             pos++;
00259         }
00260     }
00261     //
00262     pos = 0;
00263     i = myClusters.begin();
00264     while (i != myClusters.end()) {
00265         ContType::iterator j = i + 1;
00266         // check whether every combination has been processed
00267         while (j != myClusters.end()) {
00268             // check whether the current clusters overlap
00269             if ((*i)->joinable(*j, offset)) {
00270                 joinAble.push_back(*j);
00271             }
00272             j++;
00273         }
00274         for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
00275                 k != joinAble.end(); k++) {
00276             // add the overlaping cluster
00277             (*i)->add(*k);
00278             // erase the overlaping cluster
00279             delete *k;
00280             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00281         }
00282         //
00283         if (joinAble.size() > 0) {
00284             i = myClusters.begin();
00285             // clear temporary storages
00286             joinAble.clear();
00287             pos = 0;
00288         } else {
00289             i++;
00290             pos++;
00291             MsgHandler::getMessageInstance()->progressMsg("Checked(2): " + toString(pos) + "/" + toString(myClusters.size()) + "         ");
00292         }
00293     }
00294     // check for weak district connections
00295     //  (junctions made up by district connections, where prohibitions are not
00296     //   modelled properly)
00297     pos = 0;
00298     i = myClusters.begin();
00299     while (i != myClusters.end()) {
00300         ContType::iterator j = i + 1;
00301         // check whether every combination has been processed
00302         while (j != myClusters.end()) {
00303             // check whether the current clusters overlap
00304             if ((*i)->isWeakDistrictConnRealisation(*j)) {
00305                 joinAble.push_back(*j);
00306             }
00307             j++;
00308         }
00309         for (std::vector<NIVissimConnectionCluster*>::iterator k = joinAble.begin();
00310                 k != joinAble.end(); k++) {
00311             // add the overlaping cluster
00312             (*i)->add(*k);
00313             // erase the overlaping cluster
00314             delete *k;
00315             myClusters.erase(find(myClusters.begin(), myClusters.end(), *k));
00316         }
00317         //
00318         if (joinAble.size() > 0) {
00319             i = myClusters.begin();
00320             // clear temporary storages
00321             joinAble.clear();
00322             pos = 0;
00323         } else {
00324             i++;
00325             pos++;
00326             MsgHandler::getMessageInstance()->progressMsg("Checked(3): " + toString(pos) + "/" + toString(myClusters.size()) + "         ");
00327         }
00328     }
00329 }
00330 
00331 
00332 bool
00333 NIVissimConnectionCluster::joinable(NIVissimConnectionCluster* c2, SUMOReal offset) {
00334     // join clusters which have at least one connection in common
00335     if (VectorHelper<int>::subSetExists(myConnections, c2->myConnections)) {
00336         return true;
00337     }
00338 
00339     // connections shall overlap otherwise
00340     if (!overlapsWith(c2, offset)) {
00341         return false;
00342     }
00343 
00344     // at least one of the clusters shall not be assigned to a node in previous (!!!??)
00345     if (hasNodeCluster() && c2->hasNodeCluster()) {
00346         return false;
00347     }
00348 
00349     // join clusters which where connections do disturb each other
00350     if (VectorHelper<int>::subSetExists(c2->getDisturbanceParticipators(), myConnections)
00351             ||
00352             VectorHelper<int>::subSetExists(getDisturbanceParticipators(), c2->myConnections)) {
00353 
00354         return true;
00355     }
00356 
00357 
00358     // join clusters which do share the same incoming or outgoing edges (not mutually)
00359     IntVector extendedOutgoing1;
00360     IntVector extendedIncoming1;
00361     IntVector extendedOutgoing2;
00362     IntVector extendedIncoming2;
00363     if (myIncomingEdges.size() > 1 || c2->myIncomingEdges.size() > 1) {
00364         extendedOutgoing1 =
00365             extendByToTreatAsSame(myOutgoingEdges, myIncomingEdges);
00366         extendedIncoming1 =
00367             extendByToTreatAsSame(myIncomingEdges, myOutgoingEdges);
00368         extendedOutgoing2 =
00369             extendByToTreatAsSame(c2->myOutgoingEdges, c2->myIncomingEdges);
00370         extendedIncoming2 =
00371             extendByToTreatAsSame(c2->myIncomingEdges, c2->myOutgoingEdges);
00372     } else {
00373         extendedOutgoing1 = myIncomingEdges;
00374         extendedIncoming1 = myOutgoingEdges;
00375         extendedOutgoing2 = c2->myIncomingEdges;
00376         extendedIncoming2 = c2->myOutgoingEdges;
00377     }
00378 
00379     if (VectorHelper<int>::subSetExists(extendedOutgoing1, extendedOutgoing2)
00380             ||
00381             VectorHelper<int>::subSetExists(extendedIncoming1, extendedIncoming2)
00382        ) {
00383         return true;
00384     }
00385     return false;
00386 }
00387 
00388 
00389 bool
00390 NIVissimConnectionCluster::isWeakDistrictConnRealisation(NIVissimConnectionCluster* c2) {
00391     if ((myIncomingEdges.size() == 1 && myOutgoingEdges.size() == 1)) {
00392         return false;
00393     }
00394     if ((c2->myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1)) {
00395         return false;
00396     }
00397 
00398     // ok, may be the other way round
00399     if (myIncomingEdges.size() == 1 && c2->myOutgoingEdges.size() == 1) {
00400         return c2->isWeakDistrictConnRealisation(this);
00401     }
00402     // connections must cross
00403     bool crosses = false;
00404     for (IntVector::const_iterator j1 = myConnections.begin(); j1 != myConnections.end() && !crosses; j1++) {
00405         NIVissimConnection* c1 = NIVissimConnection::dictionary(*j1);
00406         const PositionVector& g1 = c1->getGeometry();
00407         for (IntVector::const_iterator j2 = c2->myConnections.begin(); j2 != c2->myConnections.end() && !crosses; j2++) {
00408             NIVissimConnection* c2 = NIVissimConnection::dictionary(*j2);
00409             const PositionVector& g2 = c2->getGeometry();
00410             if (g1.intersects(g2)) {
00411                 crosses = true;
00412             }
00413         }
00414     }
00415     if (!crosses) {
00416         return false;
00417     }
00418     // ok, check for connection
00419     if (myOutgoingEdges.size() != 1 || c2->myIncomingEdges.size() != 1) {
00420         return false;
00421     }
00422     // check whether the connection is bidirectional
00423     NIVissimEdge* oe = NIVissimEdge::dictionary(myOutgoingEdges[0]);
00424     NIVissimEdge* ie = NIVissimEdge::dictionary(c2->myIncomingEdges[0]);
00425     if (oe == 0 || ie == 0) {
00426         return false;
00427     }
00428     Line l1(oe->getGeometry().getBegin(), oe->getGeometry().getEnd());
00429     Line l2(ie->getGeometry().getEnd(), ie->getGeometry().getBegin());
00430     SUMOReal a1 = l1.atan2DegreeAngle();
00431     SUMOReal a2 = l2.atan2DegreeAngle();
00432     return fabs(a1 - a2) < 5;
00433 }
00434 
00435 
00436 bool
00437 NIVissimConnectionCluster::liesOnSameEdgesEnd(NIVissimConnectionCluster* cc2) {
00438     //
00439     for (IntVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00440         NIVissimConnection* c1 = NIVissimConnection::dictionary(*i);
00441         for (IntVector::iterator j = cc2->myConnections.begin(); j != cc2->myConnections.end(); j++) {
00442             NIVissimConnection* c2 = NIVissimConnection::dictionary(*j);
00443             if (c1->getFromEdgeID() == c2->getFromEdgeID()) {
00444                 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());
00445                 const PositionVector& g = e->getGeometry();
00446                 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D(
00447                                     g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
00448                 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D(
00449                                     g.getBegin(), g.getEnd(), c2->getBoundary().getCenter());
00450                 if (pos1 <= 5.0 && pos2 <= 5.0) {
00451                     return true;
00452                 }
00453             }
00454             if (c1->getToEdgeID() == c2->getToEdgeID()) {
00455                 NIVissimEdge* e = NIVissimEdge::dictionary(c1->getFromEdgeID());
00456                 const PositionVector& g = e->getGeometry();
00457                 SUMOReal pos1 = GeomHelper::nearest_position_on_line_to_point2D(
00458                                     g.getBegin(), g.getEnd(), c1->getBoundary().getCenter());
00459                 SUMOReal pos2 = GeomHelper::nearest_position_on_line_to_point2D(
00460                                     g.getBegin(), g.getEnd(), c2->getBoundary().getCenter());
00461                 if (pos1 >= g.length() - 5.0 && pos2 >= g.length() - 5.0) {
00462                     return true;
00463                 }
00464             }
00465         }
00466     }
00467     return false;
00468 }
00469 
00470 
00471 IntVector
00472 NIVissimConnectionCluster::extendByToTreatAsSame(const IntVector& iv1,
00473         const IntVector& iv2) const {
00474     IntVector ret(iv1);
00475     for (IntVector::const_iterator i = iv1.begin(); i != iv1.end(); i++) {
00476         NIVissimEdge* e = NIVissimEdge::dictionary(*i);
00477         const std::vector<NIVissimEdge*> treatAsSame = e->getToTreatAsSame();
00478         for (std::vector<NIVissimEdge*>::const_iterator j = treatAsSame.begin(); j != treatAsSame.end(); j++) {
00479             if (find(iv2.begin(), iv2.end(), (*j)->getID()) == iv2.end()) {
00480                 ret.push_back((*j)->getID());
00481             }
00482         }
00483     }
00484     return ret;
00485 }
00486 
00487 IntVector
00488 NIVissimConnectionCluster::getDisturbanceParticipators() {
00489     IntVector ret;
00490     for (IntVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00491         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00492         const IntVector& disturbances = c->getDisturbances();
00493         for (IntVector::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) {
00494             NIVissimDisturbance* d = NIVissimDisturbance::dictionary(*j);
00495             ret.push_back(d->getEdgeID());
00496             ret.push_back(d->getDisturbanceID());
00497         }
00498     }
00499     return ret;
00500 }
00501 
00502 
00503 void
00504 NIVissimConnectionCluster::buildNodeClusters() {
00505     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00506         IntVector disturbances;
00507         IntVector tls;
00508         IntVector nodes;
00509         int tlsid = -1;
00510         int nodeid = -1;
00511         if ((*i)->myConnections.size() > 0) {
00512             (*i)->recomputeBoundary();
00513             disturbances = NIVissimDisturbance::getWithin((*i)->myBoundary);
00514         }
00515         nodes = (*i)->myNodes;//NIVissimTL::getWithin((*i)->myBoundary, 5.0);
00516         if (nodes.size() > 1) {
00517             WRITE_WARNING("NIVissimConnectionCluster:More than a single node");
00518             //          throw 1; // !!! eigentlich sollte hier nur eine Ampelanlage sein
00519         }
00520         if (nodes.size() > 0) {
00521             nodeid = nodes[0];
00522         }
00523         //
00524         //
00525         int id = NIVissimNodeCluster::dictionary(
00526                      nodeid, tlsid, (*i)->myConnections,
00527                      disturbances, (*i)->myIncomingEdges.size() < 2);
00528         assert((*i)->myNodeCluster == id || (*i)->myNodeCluster < 0);
00529         (*i)->myNodeCluster = id;
00530     }
00531 }
00532 
00533 
00534 void
00535 NIVissimConnectionCluster::searchForConnection(int id) {
00536     int pos = 0;
00537     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00538         IntVector connections = (*i)->myConnections;
00539         if (find(connections.begin(), connections.end(), id) != connections.end()) {
00540             for (IntVector::iterator j = connections.begin(); j != connections.end(); j++) {
00541                 int checkdummy = *j;
00542             }
00543         }
00544         pos++;
00545     }
00546 }
00547 
00548 
00549 void
00550 NIVissimConnectionCluster::_debugOut(std::ostream& into) {
00551     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00552         IntVector connections = (*i)->myConnections;
00553         for (IntVector::iterator j = connections.begin(); j != connections.end(); j++) {
00554             if (j != connections.begin()) {
00555                 into << ", ";
00556             }
00557             into << *j;
00558         }
00559         into << "(" << (*i)->myBoundary << ")" << std::endl;
00560     }
00561     into << "---------------------------" << std::endl;
00562 }
00563 
00564 
00565 
00566 bool
00567 NIVissimConnectionCluster::hasNodeCluster() const {
00568     return myNodeCluster != -1;
00569 }
00570 
00571 
00572 size_t
00573 NIVissimConnectionCluster::dictSize() {
00574     return myClusters.size();
00575 }
00576 
00577 
00578 void
00579 NIVissimConnectionCluster::removeConnections(const NodeSubCluster& c) {
00580     for (NodeSubCluster::ConnectionCont::const_iterator i = c.myConnections.begin(); i != c.myConnections.end(); i++) {
00581         NIVissimConnection* conn = *i;
00582         int connid = conn->getID();
00583         IntVector::iterator j = find(myConnections.begin(), myConnections.end(), connid);
00584         if (j != myConnections.end()) {
00585             myConnections.erase(j);
00586         }
00587     }
00588     recomputeBoundary();
00589 }
00590 
00591 
00592 void
00593 NIVissimConnectionCluster::recomputeBoundary() {
00594     myBoundary = Boundary();
00595     for (IntVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00596         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00597         if (c != 0) {
00598             myBoundary.add(c->getFromGeomPosition());
00599             myBoundary.add(c->getToGeomPosition());
00600             if (c->getGeometry().size() != 0) {
00601                 myBoundary.add(c->getGeometry().getBoxBoundary());
00602             }
00603         }
00604     }
00605     assert(myBoundary.xmax() >= myBoundary.xmin());
00606 }
00607 
00608 
00609 NBNode*
00610 NIVissimConnectionCluster::getNBNode() const {
00611     return NIVissimNodeCluster::dictionary(myNodeCluster)->getNBNode();
00612 }
00613 
00614 
00615 bool
00616 NIVissimConnectionCluster::around(const Position& p, SUMOReal offset) const {
00617     assert(myBoundary.xmax() >= myBoundary.xmin());
00618     return myBoundary.around(p, offset);
00619 }
00620 
00621 
00622 
00623 void
00624 NIVissimConnectionCluster::recheckEdges() {
00625     assert(myConnections.size() != 0);
00626     // remove the cluster from all edges at first
00627     IntVector::iterator i;
00628     for (i = myEdges.begin(); i != myEdges.end(); i++) {
00629         NIVissimEdge* edge = NIVissimEdge::dictionary(*i);
00630         edge->removeFromConnectionCluster(this);
00631     }
00632     // clear edge information
00633     myEdges.clear();
00634     // recheck which edges do still participate and add edges
00635     for (i = myConnections.begin(); i != myConnections.end(); i++) {
00636         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00637         assert(myBoundary.xmax() >= myBoundary.xmin());
00638         if (myBoundary.around(c->getFromGeomPosition(), 5)) {
00639             myEdges.push_back(c->getFromEdgeID());
00640         }
00641         assert(myBoundary.xmax() >= myBoundary.xmin());
00642         if (myBoundary.around(c->getToGeomPosition(), 5)) {
00643             myEdges.push_back(c->getToEdgeID());
00644         }
00645     }
00646     // connect edges
00647     for (i = myEdges.begin(); i != myEdges.end(); i++) {
00648         NIVissimEdge* edge = NIVissimEdge::dictionary(*i);
00649         edge->addToConnectionCluster(this);
00650     }
00651 }
00652 
00653 
00654 SUMOReal
00655 NIVissimConnectionCluster::getPositionForEdge(int edgeid) const {
00656     // return the middle of the connections when there are any
00657     if (myConnections.size() != 0) {
00658         SUMOReal sum = 0;
00659         size_t part = 0;
00660         IntVector::const_iterator i;
00661         for (i = myConnections.begin(); i != myConnections.end(); i++) {
00662             NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00663             if (c->getFromEdgeID() == edgeid) {
00664                 part++;
00665                 sum += c->getFromPosition();
00666             }
00667             if (c->getToEdgeID() == edgeid) {
00668                 part++;
00669                 sum += c->getToPosition();
00670             }
00671         }
00672         if (part > 0) {
00673             return sum / (SUMOReal) part;
00674         }
00675     }
00676     // use the position of the node if possible
00677     if (myNodeCluster >= 0) {
00678         // try to find the nearest point on the edge
00679         //  !!! only the main geometry is regarded
00680         NIVissimNodeDef* node =
00681             NIVissimNodeDef::dictionary(myNodeCluster);
00682         if (node != 0) {
00683             SUMOReal pos = node->getEdgePosition(edgeid);
00684             if (pos >= 0) {
00685                 return pos;
00686             }
00687         }
00688         /*
00689                 SUMOReal try1 = GeomHelper::nearest_position_on_line_to_point(
00690                     edge->getBegin2D(), edge->getEnd2D(), node->getPos());
00691                 if(try1>=0) {
00692                     return try1;
00693                 }
00694                 // try to use simple distance
00695                 SUMOReal dist1 =
00696                     GeomHelper::distance(node->getPos(), edge->getBegin2D());
00697                 SUMOReal dist2 =
00698                     GeomHelper::distance(node->getPos(), edge->getEnd2D());
00699                 return dist1<dist2
00700                     ? 0 : edge->getLength();
00701                     */
00702     }
00703     // what else?
00704     WRITE_WARNING("NIVissimConnectionCluster: how to get an edge's position?");
00705     // !!!
00706     assert(myBoundary.xmin() <= myBoundary.xmax());
00707     NIVissimEdge* edge = NIVissimEdge::dictionary(edgeid);
00708     IntVector::const_iterator i = find(myEdges.begin(), myEdges.end(), edgeid);
00709     if (i == myEdges.end()) {
00710         // edge does not exist!?
00711         throw 1;
00712     }
00713     const PositionVector& edgeGeom = edge->getGeometry();
00714     Position p = GeomHelper::crossPoint(myBoundary, edgeGeom);
00715     return GeomHelper::nearest_position_on_line_to_point2D(
00716                edgeGeom.getBegin(), edgeGeom.getEnd(), p);
00717 }
00718 
00719 
00720 
00721 void
00722 NIVissimConnectionCluster::clearDict() {
00723     for (ContType::iterator i = myClusters.begin(); i != myClusters.end(); i++) {
00724         delete(*i);
00725     }
00726     myClusters.clear();
00727     myFirstFreeID = 100000;
00728 }
00729 
00730 
00731 PositionVector
00732 NIVissimConnectionCluster::getIncomingContinuationGeometry(NIVissimEdge* e) const {
00733     // collect connection where this edge is the incoming one
00734     std::vector<NIVissimConnection*> edgeIsIncoming;
00735     for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00736         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00737         if (c->getFromEdgeID() == e->getID()) {
00738             edgeIsIncoming.push_back(c);
00739         }
00740     }
00741     //
00742     if (edgeIsIncoming.size() == 0) {
00743         return PositionVector();
00744     }
00745     // sort connected edges in same direction
00746     sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
00747          same_direction_sorter(e->getGeometry().beginEndAngle()));
00748     NIVissimConnection* c = *(edgeIsIncoming.begin());
00749     return c->getGeometry();
00750 }
00751 
00752 
00753 
00754 NIVissimConnection*
00755 NIVissimConnectionCluster::getIncomingContinuation(NIVissimEdge* e) const {
00756     // collect connection where this edge is the incoming one
00757     std::vector<NIVissimConnection*> edgeIsIncoming;
00758     for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00759         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00760         if (c->getFromEdgeID() == e->getID()) {
00761             edgeIsIncoming.push_back(c);
00762         }
00763     }
00764     //
00765     if (edgeIsIncoming.size() == 0) {
00766         return 0;
00767     }
00768     // sort connected edges in same direction
00769     sort(edgeIsIncoming.begin(), edgeIsIncoming.end(),
00770          same_direction_sorter(e->getGeometry().beginEndAngle()));
00771     return *(edgeIsIncoming.begin());
00772 }
00773 
00774 
00775 
00776 PositionVector
00777 NIVissimConnectionCluster::getOutgoingContinuationGeometry(NIVissimEdge* e) const {
00778     // collect connection where this edge is the outgoing one
00779     std::vector<NIVissimConnection*> edgeIsOutgoing;
00780     for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00781         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00782         if (c->getToEdgeID() == e->getID()) {
00783             edgeIsOutgoing.push_back(c);
00784         }
00785     }
00786     //
00787     if (edgeIsOutgoing.size() == 0) {
00788         return PositionVector();
00789     }
00790     // sort connected edges in same direction
00791     sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
00792          same_direction_sorter(e->getGeometry().beginEndAngle()));
00793     NIVissimConnection* c = *(edgeIsOutgoing.begin());
00794     return c->getGeometry();
00795 }
00796 
00797 
00798 NIVissimConnection*
00799 NIVissimConnectionCluster::getOutgoingContinuation(NIVissimEdge* e) const {
00800     // collect connection where this edge is the outgoing one
00801     std::vector<NIVissimConnection*> edgeIsOutgoing;
00802     for (IntVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
00803         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00804         if (c->getToEdgeID() == e->getID()) {
00805             edgeIsOutgoing.push_back(c);
00806         }
00807     }
00808     //
00809     if (edgeIsOutgoing.size() == 0) {
00810         return 0;
00811     }
00812     // sort connected edges in same direction
00813     sort(edgeIsOutgoing.begin(), edgeIsOutgoing.end(),
00814          same_direction_sorter(e->getGeometry().beginEndAngle()));
00815     return *(edgeIsOutgoing.begin());
00816 }
00817 
00818 
00819 
00820 /****************************************************************************/
00821 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines