SUMO - Simulation of Urban MObility

NIVissimEdge.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // A temporary storage for edges imported from Vissim
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 <string>
00031 #include <algorithm>
00032 #include <map>
00033 #include <cassert>
00034 #include <iomanip>
00035 #include <cmath>
00036 #include <iostream>
00037 #include <sstream>
00038 #include <iterator>
00039 #include <utils/common/ToString.h>
00040 #include <utils/geom/PositionVector.h>
00041 #include <utils/geom/GeomHelper.h>
00042 #include <utils/distribution/Distribution.h>
00043 #include <netbuild/NBDistribution.h>
00044 #include <netbuild/NBNode.h>
00045 #include <netbuild/NBNodeCont.h>
00046 #include <utils/options/OptionsCont.h>
00047 #include "NIVissimNodeCluster.h"
00048 #include "NIVissimDistrictConnection.h"
00049 #include "NIVissimClosedLanesVector.h"
00050 #include "NIVissimConnection.h"
00051 #include "NIVissimDisturbance.h"
00052 #include "NIVissimEdge.h"
00053 #include <utils/common/MsgHandler.h>
00054 
00055 #ifdef CHECK_MEMORY_LEAKS
00056 #include <foreign/nvwa/debug_new.h>
00057 #endif // CHECK_MEMORY_LEAKS
00058 
00059 
00060 // ===========================================================================
00061 // static members
00062 // ===========================================================================
00063 NIVissimEdge::DictType NIVissimEdge::myDict;
00064 int NIVissimEdge::myMaxID = 0;
00065 std::vector<std::string> NIVissimEdge::myLanesWithMissingSpeeds;
00066 
00067 
00068 // ===========================================================================
00069 // method definitions
00070 // ===========================================================================
00071 NIVissimEdge::connection_position_sorter::connection_position_sorter(int edgeid)
00072     : myEdgeID(edgeid) {}
00073 
00074 
00075 int
00076 NIVissimEdge::connection_position_sorter::operator()(int c1id,
00077         int c2id) const {
00078     NIVissimConnection* c1 = NIVissimConnection::dictionary(c1id);
00079     NIVissimConnection* c2 = NIVissimConnection::dictionary(c2id);
00080     SUMOReal pos1 =
00081         c1->getFromEdgeID()==myEdgeID
00082         ? c1->getFromPosition() : c1->getToPosition();
00083     SUMOReal pos2 =
00084         c2->getFromEdgeID()==myEdgeID
00085         ? c2->getFromPosition() : c2->getToPosition();
00086     return pos1<pos2;
00087 }
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 NIVissimEdge::connection_cluster_position_sorter::connection_cluster_position_sorter(int edgeid)
00097     : myEdgeID(edgeid) {}
00098 
00099 
00100 int
00101 NIVissimEdge::connection_cluster_position_sorter::operator()(
00102     NIVissimConnectionCluster* cc1,
00103     NIVissimConnectionCluster* cc2) const {
00104     SUMOReal pos1 = cc1->getPositionForEdge(myEdgeID);
00105     SUMOReal pos2 = cc2->getPositionForEdge(myEdgeID);
00106     if (pos2<0||pos1<0) {
00107         cc1->getPositionForEdge(myEdgeID);
00108         cc2->getPositionForEdge(myEdgeID);
00109     }
00110     assert(pos1>=0&&pos2>=0);
00111     return pos1<pos2;
00112 }
00113 
00114 
00115 
00116 
00117 NIVissimEdge::NIVissimEdge(int id, const std::string& name,
00118                            const std::string& type, int noLanes,
00119                            SUMOReal zuschlag1, SUMOReal zuschlag2,
00120                            SUMOReal /*length*/, const PositionVector& geom,
00121                            const NIVissimClosedLanesVector& clv)
00122     : NIVissimAbstractEdge(id, geom),
00123       myName(name), myType(type), myNoLanes(noLanes),
00124       myZuschlag1(zuschlag1), myZuschlag2(zuschlag2),
00125       myClosedLanes(clv), myAmWithinJunction(false) { //, mySpeed(-1)
00126     assert(noLanes>=0);
00127     if (myMaxID<myID) {
00128         myMaxID = myID;
00129     }
00130     for (int i=0; i<noLanes; i++) {
00131         myLaneSpeeds.push_back(-1);
00132     }
00133 }
00134 
00135 
00136 NIVissimEdge::~NIVissimEdge() {
00137     for (NIVissimClosedLanesVector::iterator i=myClosedLanes.begin(); i!=myClosedLanes.end(); i++) {
00138         delete(*i);
00139     }
00140     myClosedLanes.clear();
00141 }
00142 
00143 
00144 bool
00145 NIVissimEdge::dictionary(int id, const std::string& name,
00146                          const std::string& type, int noLanes,
00147                          SUMOReal zuschlag1, SUMOReal zuschlag2, SUMOReal length,
00148                          const PositionVector& geom,
00149                          const NIVissimClosedLanesVector& clv) {
00150     NIVissimEdge* o = new NIVissimEdge(id, name, type, noLanes, zuschlag1,
00151                                        zuschlag2, length, geom, clv);
00152     if (!dictionary(id, o)) {
00153         delete o;
00154         return false;
00155     }
00156     return true;
00157 }
00158 
00159 
00160 
00161 bool
00162 NIVissimEdge::dictionary(int id, NIVissimEdge* o) {
00163     DictType::iterator i=myDict.find(id);
00164     if (i==myDict.end()) {
00165         myDict[id] = o;
00166         return true;
00167     }
00168     return false;
00169 }
00170 
00171 
00172 
00173 NIVissimEdge*
00174 NIVissimEdge::dictionary(int id) {
00175     DictType::iterator i=myDict.find(id);
00176     if (i==myDict.end()) {
00177         return 0;
00178     }
00179     return (*i).second;
00180 }
00181 
00182 
00183 void
00184 NIVissimEdge::buildConnectionClusters() throw() {
00185     const SUMOReal MAX_CLUSTER_DISTANCE = 10;
00186     // build clusters for all edges made up from not previously assigne
00187     //  connections
00188     for (DictType::iterator i=myDict.begin(); i!=myDict.end(); i++) {
00189         int edgeid = (*i).first;
00190         NIVissimEdge* edge = (*i).second;
00191         // get all connectors using this edge
00192         IntVector connectors = edge->myIncomingConnections;
00193         copy(edge->myOutgoingConnections.begin(), edge->myOutgoingConnections.end(), back_inserter(connectors));
00194         if (connectors.size()==0) {
00195             continue;
00196         }
00197         // sort the connectors by the place on the edge
00198         sort(connectors.begin(), connectors.end(), connection_position_sorter(edgeid));
00199         // try to cluster the connections participating within the current edge
00200         IntVector currentCluster;
00201         IntVector::iterator j=connectors.begin();
00202         bool outgoing = NIVissimConnection::dictionary(*j)->getFromEdgeID()==(*i).first;
00203         SUMOReal position = outgoing
00204                             ? NIVissimConnection::dictionary(*j)->getFromPosition()
00205                             : NIVissimConnection::dictionary(*j)->getToPosition();
00206 
00207         // skip connections already in a cluster
00208         // !!! (?)
00209         while (j!=connectors.end()&&NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
00210             ++j;
00211         }
00212         if (j==connectors.end()) {
00213             continue;
00214         }
00215         currentCluster.push_back(*j);
00216         do {
00217             if (j+1!=connectors.end()&&!NIVissimConnection::dictionary(*j)->hasNodeCluster()) {
00218                 bool n_outgoing = NIVissimConnection::dictionary(*(j+1))->getFromEdgeID()==edgeid;
00219                 SUMOReal n_position = n_outgoing
00220                                       ? NIVissimConnection::dictionary(*(j+1))->getFromPosition()
00221                                       : NIVissimConnection::dictionary(*(j+1))->getToPosition();
00222                 if (n_outgoing==outgoing && fabs(n_position-position)<MAX_CLUSTER_DISTANCE) {
00223                     // ok, in same cluster as prior
00224                     currentCluster.push_back(*(j+1));
00225                 } else {
00226                     // start new cluster
00227                     VectorHelper<int>::removeDouble(currentCluster);
00228                     edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
00229                     currentCluster.clear();
00230                     currentCluster.push_back(*(j+1));
00231                 }
00232                 outgoing = n_outgoing;
00233                 position = n_position;
00234             }
00235             j++;
00236         } while (j!=connectors.end());
00237         // add last connection
00238         if (currentCluster.size()>0) {
00239             VectorHelper<int>::removeDouble(currentCluster);
00240             edge->myConnectionClusters.push_back(new NIVissimConnectionCluster(currentCluster, -1, edgeid));
00241         }
00242     }
00243 }
00244 
00245 
00246 void
00247 NIVissimEdge::dict_buildNBEdges(NBDistrictCont& dc, NBNodeCont& nc,
00248                                 NBEdgeCont& ec, SUMOReal offset) {
00249     for (DictType::iterator i=myDict.begin(); i!=myDict.end(); i++) {
00250         NIVissimEdge* edge = (*i).second;
00251         edge->buildNBEdge(dc, nc, ec, offset);
00252     }
00253 }
00254 
00255 
00256 void
00257 NIVissimEdge::dict_propagateSpeeds(/* NBDistribution &dc */) {
00258     DictType::iterator i;
00259     for (i=myDict.begin(); i!=myDict.end(); i++) {
00260         NIVissimEdge* edge = (*i).second;
00261         edge->setDistrictSpeed(/* dc */);
00262     }
00263     for (i=myDict.begin(); i!=myDict.end(); i++) {
00264         NIVissimEdge* edge = (*i).second;
00265         edge->propagateSpeed(/* dc */ -1, IntVector());
00266     }
00267     for (int j=0; j<3; j++) {
00268         for (i=myDict.begin(); i!=myDict.end(); i++) {
00269             NIVissimEdge* edge = (*i).second;
00270             edge->propagateOwn(/* dc */);
00271         }
00272         for (i=myDict.begin(); i!=myDict.end(); i++) {
00273             NIVissimEdge* edge = (*i).second;
00274             edge->checkUnconnectedLaneSpeeds(/* dc */);
00275         }
00276     }
00277 }
00278 
00279 
00280 void
00281 NIVissimEdge::checkUnconnectedLaneSpeeds(/* NBDistribution &dc */) {
00282     for (int i=0; i<(int) myLaneSpeeds.size(); i++) {
00283         if (myLaneSpeeds[i]==-1) {
00284             SUMOReal speed = -1;
00285             int j1 = i - 1; // !!! recheck - j1 may become negative?
00286             int j2 = i;
00287             while (j2!=(int) myLaneSpeeds.size()&&myLaneSpeeds[j2]==-1) {
00288                 j2++;
00289             }
00290             if (j1<0) {
00291                 if (j2<(int) myLaneSpeeds.size()) {
00292                     speed = myLaneSpeeds[j2];
00293                 }
00294             } else {
00295                 if (j2>=(int) myLaneSpeeds.size()) {
00296                     speed = myLaneSpeeds[j1];
00297                 } else {
00298                     speed = (myLaneSpeeds[j1] + myLaneSpeeds[j2]) / (SUMOReal) 2.0;
00299                 }
00300             }
00301             if (speed==-1) {
00302                 continue;
00303             }
00304             myLaneSpeeds[i] = speed;
00305             std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
00306             for (std::vector<NIVissimConnection*>::iterator j=connected.begin(); j!=connected.end(); j++) {
00307                 NIVissimConnection* c = *j;
00308                 NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
00309                 // propagate
00310                 e->propagateSpeed(/*dc, */speed, c->getToLanes());
00311             }
00312         }
00313     }
00314 }
00315 
00316 
00317 void
00318 NIVissimEdge::propagateOwn(/* NBDistribution &dc */) {
00319     for (int i=0; i<(int) myLaneSpeeds.size(); i++) {
00320         if (myLaneSpeeds[i]==-1) {
00321             continue;
00322         }
00323         std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
00324         for (std::vector<NIVissimConnection*>::iterator j=connected.begin(); j!=connected.end(); j++) {
00325             NIVissimConnection* c = *j;
00326             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
00327             // propagate
00328             e->propagateSpeed(/*dc, */myLaneSpeeds[i], c->getToLanes());
00329         }
00330     }
00331 }
00332 
00333 
00334 void
00335 NIVissimEdge::propagateSpeed(/* NBDistribution &dc */ SUMOReal speed, IntVector forLanes) {
00336     // if no lane is given, all set be set
00337     if (forLanes.size()==0) {
00338         for (size_t i=0; i<myNoLanes; i++) {
00339             forLanes.push_back((int) i);
00340         }
00341     }
00342     // for the case of a first call
00343     // go through the lanes
00344     for (IntVector::const_iterator i=forLanes.begin(); i<forLanes.end(); i++) {
00345         // check whether a speed was set before
00346         if (myLaneSpeeds[*i]!=-1) {
00347             // do not reset it from incoming
00348             continue;
00349         }
00350         // check whether the lane has a new speed to set
00351         if ((int) myPatchedSpeeds.size()>*i&&myPatchedSpeeds[*i]!=-1) {
00352             // use it
00353             speed = getRealSpeed(/*dc, */myPatchedSpeeds[*i]);
00354         }
00355         // check whether a speed is given
00356         if (speed==-1) {
00357             // do nothing if not
00358             continue;
00359         }
00360         // set the lane's speed to the given
00361         myLaneSpeeds[*i] = speed;
00362         // propagate the speed further
00363         // get the list of connected edges
00364         std::vector<NIVissimConnection*> connected = getOutgoingConnected(*i);
00365         // go throught the list
00366         for (std::vector<NIVissimConnection*>::iterator j=connected.begin(); j!=connected.end(); j++) {
00367             NIVissimConnection* c = *j;
00368             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
00369             // propagate
00370             e->propagateSpeed(/*dc, */speed, c->getToLanes());
00371         }
00372     }
00373 }
00374 
00375 
00376 
00377 void
00378 NIVissimEdge::setDistrictSpeed(/* NBDistribution &dc */) {
00379     if (myDistrictConnections.size()>0) {
00380         SUMOReal pos = *(myDistrictConnections.begin());
00381         if (pos<getLength()-pos) {
00382             NIVissimDistrictConnection* d =
00383                 NIVissimDistrictConnection::dict_findForEdge(myID);
00384             if (d!=0) {
00385                 SUMOReal speed = d->getMeanSpeed(/*dc*/);
00386                 if (speed==-1) {
00387                     return;
00388                 }
00389                 for (unsigned int i=0; i<myNoLanes; i++) {
00390                     myLaneSpeeds[i] = speed;
00391                     // propagate the speed further
00392                     // get the list of connected edges
00393                     std::vector<NIVissimConnection*> connected = getOutgoingConnected(i);
00394                     // go throught the list
00395                     for (std::vector<NIVissimConnection*>::iterator j=connected.begin(); j!=connected.end(); j++) {
00396                         NIVissimConnection* c = *j;
00397                         NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
00398                         // propagate
00399                         e->propagateSpeed(/*dc, */speed, c->getToLanes());
00400                     }
00401                 }
00402             }
00403         }
00404     }
00405 }
00406 
00407 
00408 std::vector<NIVissimConnection*>
00409 NIVissimEdge::getOutgoingConnected(int lane) const {
00410     std::vector<NIVissimConnection*> ret;
00411     for (IntVector::const_iterator i=myOutgoingConnections.begin(); i!=myOutgoingConnections.end(); i++) {
00412         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00413         const IntVector& lanes = c->getFromLanes();
00414         if (find(lanes.begin(), lanes.end(), lane)!=lanes.end()) {
00415             NIVissimEdge* e = NIVissimEdge::dictionary(c->getToEdgeID());
00416             if (e!=0) {
00417                 ret.push_back(c);
00418             }
00419         }
00420     }
00421     return ret;
00422 }
00423 
00424 
00425 void
00426 NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec,
00427                           SUMOReal sameNodesOffset) throw(ProcessError) {
00428     // build the edge
00429     std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf;
00430     NBNode* fromNode, *toNode;
00431     fromNode = toNode = 0;
00432     sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID));
00433     sort(myDistrictConnections.begin(), myDistrictConnections.end());
00434     ConnectionClusters tmpClusters = myConnectionClusters;
00435     if (tmpClusters.size()!=0) {
00436         sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID));
00437         // get or build the from-node
00438         //  A node may have to be build when the edge starts or ends at
00439         //  a parking place or something like this
00440         fromInf = getFromNode(nc, tmpClusters);
00441         fromNode = fromInf.second;
00442         // get or build the to-node
00443         //if(tmpClusters.size()>0) {
00444         toInf = getToNode(nc, tmpClusters);
00445         toNode = toInf.second;
00446         if (fromInf.first!=0&&toNode!=0&&fromInf.first->around(toNode->getPosition())) {
00447             WRITE_WARNING("Will not build edge '" + toString(myID) + "'.");
00448             myAmWithinJunction = true;
00449             return;
00450         }
00451         //}
00452         // if both nodes are the same, resolve the problem otherwise
00453         if (fromNode==toNode) {
00454             std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode);
00455             if (fromNode!=tmp.first) {
00456                 fromInf.first = 0;
00457             }
00458             if (toNode!=tmp.second) {
00459                 toInf.first = 0;
00460             }
00461             fromNode = tmp.first;
00462             toNode = tmp.second;
00463         }
00464     }
00465 
00466     //
00467     if (fromNode==0) {
00468         fromInf.first = 0;
00469         Position pos = myGeom[0];
00470         fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, NODETYPE_NOJUNCTION);
00471         if (!nc.insert(fromNode)) {
00472             throw ProcessError("Could not insert node '" + fromNode->getID() + "' to nodes container.");
00473         }
00474     }
00475     if (toNode==0) {
00476         toInf.first = 0;
00477         Position pos = myGeom[-1];
00478         toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, NODETYPE_NOJUNCTION);
00479         if (!nc.insert(toNode)) {
00480             throw ProcessError("Could not insert node '" + toNode->getID() + "' to nodes container.");
00481         }
00482     }
00483 
00484     // build the edge
00485     SUMOReal avgSpeed = 0;
00486     int i;
00487     for (i=0; i<(int) myNoLanes; i++) {
00488         if (myLaneSpeeds.size()<=(size_t) i||myLaneSpeeds[i]==-1) {
00489             myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i));
00490             avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed");
00491         } else {
00492             avgSpeed += myLaneSpeeds[i];
00493         }
00494     }
00495     avgSpeed /= (SUMOReal) myLaneSpeeds.size();
00496     avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm");
00497 
00498     if (fromNode==toNode) {
00499         WRITE_WARNING("Could not build edge '" + toString(myID) + "'; would connect same node.");
00500         return;
00501     }
00502 
00503     NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType,
00504                                    avgSpeed/(SUMOReal) 3.6, myNoLanes, -1, -1, -1, myGeom, myName, LANESPREAD_CENTER, true);
00505     for (i=0; i<(int) myNoLanes; i++) {
00506         if ((int) myLaneSpeeds.size()<=i||myLaneSpeeds[i]==-1) {
00507             buildEdge->setLaneSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed")/(SUMOReal) 3.6);
00508         } else {
00509             buildEdge->setLaneSpeed(i, myLaneSpeeds[i]/(SUMOReal) 3.6);
00510         }
00511     }
00512     ec.insert(buildEdge);
00513     // check whether the edge contains any other clusters
00514     if (tmpClusters.size()>0) {
00515         bool cont = true;
00516         for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j!=tmpClusters.end(); ++j) {
00517             // split the edge at the previously build node
00518             std::string nextID = buildEdge->getID() + "[1]";
00519             cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode());
00520             // !!! what to do if the edge could not be split?
00521             buildEdge = ec.retrieve(nextID);
00522         }
00523     }
00524 }
00525 
00526 
00527 SUMOReal
00528 NIVissimEdge::getRealSpeed(/* NBDistribution &dc */ int distNo) {
00529     std::string id = toString<int>(distNo);
00530     Distribution* dist = NBDistribution::dictionary("speed", id);
00531     if (dist==0) {
00532         WRITE_WARNING("The referenced speed distribution '" + id + "' is not known.");
00533         return -1;
00534     }
00535     assert(dist!=0);
00536     SUMOReal speed = dist->getMax();
00537     if (speed<0||speed>1000) {
00538         WRITE_WARNING("What about distribution '" + toString<int>(distNo) + "' ");
00539     }
00540     return speed;
00541 }
00542 
00543 /*
00544 bool
00545 NIVissimEdge::recheckSpeedPatches()
00546 {
00547 //    size_t speed_idx = -1;
00548     // check set speeds
00549     if(myPatchedSpeeds.size()!=0) {
00550         DoubleVector::iterator i =
00551             find(myPatchedSpeeds.begin(), myPatchedSpeeds.end(), -1);
00552         if(myPatchedSpeeds.size()!=myNoLanes||i!=myPatchedSpeeds.end()) {
00553             cot << "Warning! Not all lanes are patched! (edge:" << myID << ")." << endl;
00554         }
00555         //
00556         if(DoubleVectorHelper::maxValue(myPatchedSpeeds)!=DoubleVectorHelper::minValue(myPatchedSpeeds)) {
00557             cot << "Warning! Not all lanes have the same speed!! (edge:" << myID << ")." << endl;
00558         }
00559         //
00560 /        // !!! ist natürlich Quatsch - erst recht, wenn Edges zusammengefasst werden
00561         speed = DoubleVectorHelper::sum(myPatchedSpeeds);
00562         speed /= (SUMOReal) myPatchedSpeeds.size();*/
00563 /*        return true;
00564     }
00565     if(myDistrictConnections.size()>0) {
00566         SUMOReal pos = *(myDistrictConnections.begin());
00567 //        if(pos<10) {
00568             NIVissimDistrictConnection *d =
00569                 NIVissimDistrictConnection::dict_findForEdge(myID);
00570             if(d!=0) {
00571                 return true;
00572 //                speed = d->getMeanSpeed();
00573             }
00574 //        }
00575 //        return true;
00576     }
00577     return false;
00578 }
00579 */
00580 
00581 std::pair<NIVissimConnectionCluster*, NBNode*>
00582 NIVissimEdge::getFromNode(NBNodeCont& nc, ConnectionClusters& clusters) {
00583     const SUMOReal MAX_DISTANCE = 10.;
00584     assert(clusters.size()>=1);
00585     const Position& beg = myGeom.getBegin();
00586     NIVissimConnectionCluster* c = *(clusters.begin());
00587     // check whether the edge starts within a already build node
00588     if (c->around(beg, MAX_DISTANCE)) {
00589         clusters.erase(clusters.begin());
00590         return std::pair<NIVissimConnectionCluster*, NBNode*>
00591                (c, c->getNBNode());
00592     }
00593     // check for a parking place at the begin
00594     if (myDistrictConnections.size()>0) {
00595         SUMOReal pos = *(myDistrictConnections.begin());
00596         if (pos<10) {
00597             NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, NODETYPE_NOJUNCTION);
00598             if (!nc.insert(node)) {
00599                 throw 1;
00600             }
00601             while (myDistrictConnections.size()>0&&*(myDistrictConnections.begin())<10) {
00602                 myDistrictConnections.erase(myDistrictConnections.begin());
00603             }
00604             return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node);
00605         }
00606     }
00607     // build a new node for the edge's begin otherwise
00608     NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, NODETYPE_NOJUNCTION);
00609     if (!nc.insert(node)) {
00610         throw 1;
00611     }
00612     return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node);
00613 }
00614 
00615 
00616 std::pair<NIVissimConnectionCluster*, NBNode*>
00617 NIVissimEdge::getToNode(NBNodeCont& nc, ConnectionClusters& clusters) {
00618     const Position& end = myGeom.getEnd();
00619     if (clusters.size()>0) {
00620         const SUMOReal MAX_DISTANCE = 10.;
00621         assert(clusters.size()>=1);
00622         NIVissimConnectionCluster* c = *(clusters.end()-1);
00623         // check whether the edge ends within a already build node
00624         if (c->around(end, MAX_DISTANCE)) {
00625             clusters.erase(clusters.end()-1);
00626             return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
00627         }
00628     }
00629     // check for a parking place at the end
00630     if (myDistrictConnections.size()>0) {
00631         SUMOReal pos = *(myDistrictConnections.end()-1);
00632         if (pos>myGeom.length()-10) {
00633             NBNode* node = new NBNode(toString<int>(myID) + "-end", end, NODETYPE_NOJUNCTION);
00634             if (!nc.insert(node)) {
00635                 throw 1;
00636             }
00637             while (myDistrictConnections.size()>0&&*(myDistrictConnections.end()-1)<myGeom.length()-10) {
00638                 myDistrictConnections.erase(myDistrictConnections.end()-1);
00639             }
00640             return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node);
00641         }
00642     }
00643 
00644     // build a new node for the edge's end otherwise
00645     NBNode* node = new NBNode(toString<int>(myID) + "-end", end, NODETYPE_NOJUNCTION);
00646     if (!nc.insert(node)) {
00647         throw 1;
00648     }
00649     return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node);
00650     /*
00651     if (clusters.size()>0) {
00652     NIVissimConnectionCluster *c = *(clusters.end()-1);
00653     clusters.erase(clusters.end()-1);
00654     return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode());
00655     } else {
00656     // !!! dummy edge?!
00657     return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), (*(myConnectionClusters.begin()))->getNBNode());
00658     }
00659     */
00660 }
00661 
00662 
00663 std::pair<NBNode*, NBNode*>
00664 NIVissimEdge::remapOneOfNodes(NBNodeCont& nc,
00665                               NIVissimDistrictConnection* d,
00666                               NBNode* fromNode, NBNode* toNode) {
00667     std::string nid = "ParkingPlace" + toString<int>(d->getID());
00668     if (d->geomPosition().distanceTo(fromNode->getPosition())
00669             <
00670             d->geomPosition().distanceTo(toNode->getPosition())) {
00671 
00672         NBNode* newNode = new NBNode(nid,
00673                                      fromNode->getPosition(),
00674                                      NODETYPE_NOJUNCTION);
00675         nc.erase(fromNode);
00676         nc.insert(newNode);
00677         return std::pair<NBNode*, NBNode*>(newNode, toNode);
00678     } else {
00679         NBNode* newNode = new NBNode(nid,
00680                                      toNode->getPosition(),
00681                                      NODETYPE_NOJUNCTION);
00682         nc.erase(toNode);
00683         nc.insert(newNode);
00684         return std::pair<NBNode*, NBNode*>(fromNode, newNode);
00685     }
00686 }
00687 
00688 
00689 
00690 std::pair<NBNode*, NBNode*>
00691 NIVissimEdge::resolveSameNode(NBNodeCont& nc, SUMOReal offset,
00692                               NBNode* prevFrom, NBNode* prevTo) {
00693     // check whether the edge is connected to a district
00694     //  use it if so
00695     NIVissimDistrictConnection* d =
00696         NIVissimDistrictConnection::dict_findForEdge(myID);
00697     if (d!=0) {
00698         Position pos = d->geomPosition();
00699         SUMOReal position = d->getPosition();
00700         // the district is at the begin of the edge
00701         if (myGeom.length()-position>position) {
00702             std::string nid = "ParkingPlace" + toString<int>(d->getID());
00703             NBNode* node = nc.retrieve(nid);
00704             if (node==0) {
00705                 node = new NBNode(nid,
00706                                   pos, NODETYPE_NOJUNCTION);
00707                 if (!nc.insert(node)) {
00708                     throw 1;
00709                 }
00710             }
00711             return std::pair<NBNode*, NBNode*>(node, prevTo);
00712         }
00713         // the district is at the end of the edge
00714         else {
00715             std::string nid = "ParkingPlace" + toString<int>(d->getID());
00716             NBNode* node = nc.retrieve(nid);
00717             if (node==0) {
00718                 node = new NBNode(nid,
00719                                   pos, NODETYPE_NOJUNCTION);
00720                 if (!nc.insert(node)) {
00721                     throw 1;
00722                 }
00723             }
00724             assert(node!=0);
00725             return std::pair<NBNode*, NBNode*>(prevFrom, node);
00726         }
00727     }
00728     // otherwise, check whether the edge is some kind of
00729     //  a dead end...
00730     // check which end is nearer to the node centre
00731     if (myConnectionClusters.size()==1) {
00732         NBNode* node = prevFrom; // it is the same as getToNode()
00733 
00734         NIVissimConnectionCluster* c = *(myConnectionClusters.begin());
00735         // no end node given
00736         if (c->around(myGeom.getBegin(), offset) && !c->around(myGeom.getEnd(), offset)) {
00737             NBNode* end = new NBNode(
00738                 toString<int>(myID) + "-End",
00739                 myGeom.getEnd(),
00740                 NODETYPE_NOJUNCTION);
00741             if (!nc.insert(end)) {
00742                 throw 1;
00743             }
00744             return std::pair<NBNode*, NBNode*>(node, end);
00745         }
00746 
00747         // no begin node given
00748         if (!c->around(myGeom.getBegin(), offset) && c->around(myGeom.getEnd(), offset)) {
00749             NBNode* beg = new NBNode(
00750                 toString<int>(myID) + "-Begin",
00751                 myGeom.getBegin(),
00752                 NODETYPE_NOJUNCTION);
00753             if (!nc.insert(beg)) {
00754                 std::cout << "nope, NIVissimDisturbance" << std::endl;
00755                 throw 1;
00756             }
00757             return std::pair<NBNode*, NBNode*>(beg, node);
00758         }
00759 
00760         // "dummy edge" - both points lie within the same cluster
00761         if (c->around(myGeom.getBegin()) && c->around(myGeom.getEnd())) {
00762             return std::pair<NBNode*, NBNode*>(node, node);
00763         }
00764     }
00765     // what to do in other cases?
00766     //  It simply is a dummy edge....
00767     return std::pair<NBNode*, NBNode*>(prevFrom, prevTo);
00768 }
00769 
00770 
00771 
00772 
00773 void
00774 NIVissimEdge::setNodeCluster(int nodeid) {
00775     myNode = nodeid;
00776 }
00777 
00778 
00779 void
00780 NIVissimEdge::buildGeom() {}
00781 
00782 
00783 void
00784 NIVissimEdge::addIncomingConnection(int id) {
00785     myIncomingConnections.push_back(id);
00786 }
00787 
00788 
00789 void
00790 NIVissimEdge::addOutgoingConnection(int id) {
00791     myOutgoingConnections.push_back(id);
00792 }
00793 
00794 
00795 
00796 void
00797 NIVissimEdge::mergedInto(NIVissimConnectionCluster* old,
00798                          NIVissimConnectionCluster* act) {
00799     ConnectionClusters::iterator i=
00800         find(myConnectionClusters.begin(), myConnectionClusters.end(), old);
00801     if (i!=myConnectionClusters.end()) {
00802         myConnectionClusters.erase(i);
00803     }
00804     i = find(myConnectionClusters.begin(), myConnectionClusters.end(), act);
00805     if (i==myConnectionClusters.end()) {
00806         myConnectionClusters.push_back(act);
00807     }
00808 }
00809 
00810 
00811 
00812 void
00813 NIVissimEdge::removeFromConnectionCluster(NIVissimConnectionCluster* c) {
00814     ConnectionClusters::iterator i=
00815         find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
00816     assert(i!=myConnectionClusters.end());
00817     myConnectionClusters.erase(i);
00818 }
00819 
00820 
00821 void
00822 NIVissimEdge::addToConnectionCluster(NIVissimConnectionCluster* c) {
00823     ConnectionClusters::iterator i=
00824         find(myConnectionClusters.begin(), myConnectionClusters.end(), c);
00825     if (i==myConnectionClusters.end()) {
00826         myConnectionClusters.push_back(c);
00827     }
00828 }
00829 
00830 
00831 Position // !!! reference?
00832 NIVissimEdge::getBegin2D() const {
00833     return myGeom[0];
00834 }
00835 
00836 
00837 Position // !!! reference?
00838 NIVissimEdge::getEnd2D() const {
00839     return myGeom[-1];
00840 }
00841 
00842 
00843 SUMOReal
00844 NIVissimEdge::getLength() const {
00845     return myGeom.length();
00846 }
00847 
00848 
00849 void
00850 NIVissimEdge::checkDistrictConnectionExistanceAt(SUMOReal pos) {
00851     if (find(myDistrictConnections.begin(), myDistrictConnections.end(), pos)==myDistrictConnections.end()) {
00852         myDistrictConnections.push_back(pos);
00853         /*        int id = NIVissimConnection::getMaxID() + 1;
00854                 IntVector currentCluster;
00855                 currentCluster.push_back(id);
00856                 myConnectionClusters.push_back(
00857                     new NIVissimConnectionCluster(currentCluster, -1, myID));*/
00858     }
00859 }
00860 
00861 
00862 void
00863 NIVissimEdge::setSpeed(size_t lane, int speedDist) {
00864     while (myPatchedSpeeds.size()<=lane) {
00865         myPatchedSpeeds.push_back(-1);
00866     }
00867     myPatchedSpeeds[lane] = speedDist;
00868 }
00869 
00870 
00871 void
00872 NIVissimEdge::dict_checkEdges2Join() {
00873     // go through the edges
00874     for (DictType::iterator i1=myDict.begin(); i1!=myDict.end(); i1++) {
00875         // retrieve needed values from the first edge
00876         NIVissimEdge* e1 = (*i1).second;
00877         const PositionVector& g1 = e1->getGeometry();
00878         // check all other edges
00879         DictType::iterator i2=i1;
00880         i2++;
00881         for (; i2!=myDict.end(); i2++) {
00882             // retrieve needed values from the second edge
00883             NIVissimEdge* e2 = (*i2).second;
00884             const PositionVector& g2 = e2->getGeometry();
00885             // get the connection description
00886             NIVissimConnection* c = e1->getConnectionTo(e2);
00887             if (c==0) {
00888                 c = e2->getConnectionTo(e1);
00889             }
00890             // the edge must not be a direct contiuation of the other
00891             if (c!=0) {
00892                 if ((c->getFromEdgeID()==e1->getID()&&fabs(c->getFromPosition()-e1->getGeometry().length())<5)
00893                         ||
00894                         (c->getFromEdgeID()==e2->getID()&&fabs(c->getFromPosition()-e2->getGeometry().length())<5)) {
00895 
00896                     continue;
00897                 }
00898             }
00899             // only parallel edges which do end at the same node
00900             //  should be joined
00901             // retrieve the "approximating" lines first
00902             Line l1 = Line(g1.getBegin(), g1.getEnd());
00903             Line l2 = Line(g2.getBegin(), g2.getEnd());
00904             // check for parallelity
00905             //  !!! the usage of an explicit value is not very fine
00906             if (fabs(l1.atan2DegreeAngle()-l2.atan2DegreeAngle())>2.0) {
00907                 // continue if the lines are not parallel
00908                 continue;
00909             }
00910 
00911             // check whether the same node is approached
00912             //  (the distance between the ends should not be too large)
00913             //  !!! the usage of an explicit value is not very fine
00914             if (l1.p2().distanceTo(l2.p2())>10) {
00915                 // continue if the lines do not end at the same length
00916                 continue;
00917             }
00918             // ok, seem to be different lanes for the same edge
00919             //  mark as possibly joined later
00920             e1->addToTreatAsSame(e2);
00921             e2->addToTreatAsSame(e1);
00922         }
00923     }
00924 }
00925 
00926 
00927 bool
00928 NIVissimEdge::addToTreatAsSame(NIVissimEdge* e) {
00929     if (e==this) {
00930         return false;
00931     }
00932     // check whether this edge already knows about the other
00933     if (find(myToTreatAsSame.begin(), myToTreatAsSame.end(), e)==myToTreatAsSame.end()) {
00934         myToTreatAsSame.push_back(e);
00935         return true;
00936     } else {
00937         return false; // !!! check this
00938     }
00939     //
00940     std::vector<NIVissimEdge*>::iterator i;
00941     // add to all other that shall be treated as same
00942     bool changed = true;
00943     while (changed) {
00944         changed = false;
00945         for (i=myToTreatAsSame.begin(); !changed&&i!=myToTreatAsSame.end(); i++) {
00946             changed |= (*i)->addToTreatAsSame(e);
00947         }
00948         for (i=myToTreatAsSame.begin(); !changed&&i!=myToTreatAsSame.end(); i++) {
00949             changed |= e->addToTreatAsSame(*i);
00950         }
00951     }
00952 }
00953 
00954 NIVissimConnection*
00955 NIVissimEdge::getConnectionTo(NIVissimEdge* e) {
00956     IntVector::iterator i;
00957     for (i=myIncomingConnections.begin(); i!=myIncomingConnections.end(); i++) {
00958         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00959         if (c->getFromEdgeID()==e->getID()) {
00960             return c;
00961         }
00962     }
00963     for (i=myOutgoingConnections.begin(); i!=myOutgoingConnections.end(); i++) {
00964         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
00965         if (c->getToEdgeID()==e->getID()) {
00966             return c;
00967         }
00968     }
00969     return 0;
00970 }
00971 
00972 
00973 const std::vector<NIVissimEdge*> &
00974 NIVissimEdge::getToTreatAsSame() const {
00975     return myToTreatAsSame;
00976 }
00977 
00978 
00979 void
00980 NIVissimEdge::reportUnsetSpeeds() throw() {
00981     if (myLanesWithMissingSpeeds.size()==0) {
00982         return;
00983     }
00984     std::ostringstream str;
00985     str << "The following lanes have no explicit speed information:\n  ";
00986     for (std::vector<std::string>::iterator i=myLanesWithMissingSpeeds.begin(); i!=myLanesWithMissingSpeeds.end(); ++i) {
00987         if (i!=myLanesWithMissingSpeeds.begin()) {
00988             str << ", ";
00989         }
00990         str << *i;
00991     }
00992     WRITE_WARNING(str.str());
00993 }
00994 
00995 
00996 NIVissimEdge*
00997 NIVissimEdge::getBestIncoming() const throw() {
00998     for (IntVector::const_iterator i=myIncomingConnections.begin(); i!=myIncomingConnections.end(); ++i) {
00999         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
01000         return NIVissimEdge::dictionary(c->getFromEdgeID());
01001     }
01002     return 0;
01003 }
01004 
01005 
01006 NIVissimEdge*
01007 NIVissimEdge::getBestOutgoing() const throw() {
01008     for (IntVector::const_iterator i=myOutgoingConnections.begin(); i!=myOutgoingConnections.end(); ++i) {
01009         NIVissimConnection* c = NIVissimConnection::dictionary(*i);
01010         return NIVissimEdge::dictionary(c->getToEdgeID());
01011     }
01012     return 0;
01013 }
01014 
01015 
01016 
01017 /****************************************************************************/
01018 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines