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