SUMO - Simulation of Urban MObility
RONetHandler.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00010 // The handler for SUMO-Networks
00011 /****************************************************************************/
00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00014 /****************************************************************************/
00015 //
00016 //   This file is part of SUMO.
00017 //   SUMO is free software: you can redistribute it and/or modify
00018 //   it under the terms of the GNU General Public License as published by
00019 //   the Free Software Foundation, either version 3 of the License, or
00020 //   (at your option) any later version.
00021 //
00022 /****************************************************************************/
00023 
00024 
00025 // ===========================================================================
00026 // included modules
00027 // ===========================================================================
00028 #ifdef _MSC_VER
00029 #include <windows_config.h>
00030 #else
00031 #include <config.h>
00032 #endif
00033 
00034 #include <string>
00035 #include <utils/options/OptionsCont.h>
00036 #include <utils/common/MsgHandler.h>
00037 #include <utils/common/StringTokenizer.h>
00038 #include <utils/common/UtilExceptions.h>
00039 #include <utils/common/ToString.h>
00040 #include <utils/xml/SUMOSAXHandler.h>
00041 #include <utils/xml/SUMOXMLDefinitions.h>
00042 #include "ROEdge.h"
00043 #include "ROLane.h"
00044 #include "RONode.h"
00045 #include "RONet.h"
00046 #include "RONetHandler.h"
00047 #include "ROAbstractEdgeBuilder.h"
00048 
00049 #ifdef CHECK_MEMORY_LEAKS
00050 #include <foreign/nvwa/debug_new.h>
00051 #endif // CHECK_MEMORY_LEAKS
00052 
00053 
00054 // ===========================================================================
00055 // method definitions
00056 // ===========================================================================
00057 RONetHandler::RONetHandler(RONet& net,
00058                            ROAbstractEdgeBuilder& eb)
00059     : SUMOSAXHandler("sumo-network"),
00060       myNet(net), myCurrentName(),
00061       myCurrentEdge(0), myEdgeBuilder(eb),
00062       myHaveWarnedAboutDeprecatedDistrict(false), myHaveWarnedAboutDeprecatedDSource(false), myHaveWarnedAboutDeprecatedDSink(false) {}
00063 
00064 
00065 RONetHandler::~RONetHandler() {}
00066 
00067 
00068 void
00069 RONetHandler::myStartElement(int element,
00070                              const SUMOSAXAttributes& attrs) {
00071     switch (element) {
00072         case SUMO_TAG_EDGE:
00073             // in the first step, we do need the name to allocate the edge
00074             // in the second, we need it to know to which edge we have to add
00075             //  the following edges to
00076             parseEdge(attrs);
00077             break;
00078         case SUMO_TAG_LANE:
00079             if (myProcess) {
00080                 parseLane(attrs);
00081             }
00082             break;
00083         case SUMO_TAG_JUNCTION:
00084             parseJunction(attrs);
00085             break;
00086         case SUMO_TAG_SUCC:
00087             parseConnectingEdge(attrs);
00088             break;
00089         case SUMO_TAG_SUCCLANE:
00090             parseConnectedEdge(attrs);
00091             break;
00092         case SUMO_TAG_CONNECTION:
00093             parseConnection(attrs);
00094             break;
00095         case SUMO_TAG_DISTRICT__DEPRECATED:
00096             if (!myHaveWarnedAboutDeprecatedDistrict) {
00097                 myHaveWarnedAboutDeprecatedDistrict = true;
00098                 WRITE_WARNING("'" + toString(SUMO_TAG_DISTRICT__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_TAG_TAZ) + "'.");
00099             }
00100         case SUMO_TAG_TAZ:
00101             parseDistrict(attrs);
00102             break;
00103         case SUMO_TAG_DSOURCE__DEPRECATED:
00104             if (!myHaveWarnedAboutDeprecatedDSource) {
00105                 myHaveWarnedAboutDeprecatedDSource = true;
00106                 WRITE_WARNING("'" + toString(SUMO_TAG_DSOURCE__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_TAG_TAZSOURCE) + "'.");
00107             }
00108         case SUMO_TAG_TAZSOURCE:
00109             parseDistrictEdge(attrs, true);
00110             break;
00111         case SUMO_TAG_DSINK__DEPRECATED:
00112             if (!myHaveWarnedAboutDeprecatedDSink) {
00113                 myHaveWarnedAboutDeprecatedDSink = true;
00114                 WRITE_WARNING("'" + toString(SUMO_TAG_DSINK__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_TAG_TAZSINK) + "'.");
00115             }
00116         case SUMO_TAG_TAZSINK:
00117             parseDistrictEdge(attrs, false);
00118             break;
00119         default:
00120             break;
00121     }
00122 }
00123 
00124 
00125 void
00126 RONetHandler::parseEdge(const SUMOSAXAttributes& attrs) {
00127     // get the id, report an error if not given or empty...
00128     bool ok = true;
00129     myCurrentName = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00130     if (!ok) {
00131         throw ProcessError();
00132     }
00133     // get the edge
00134     myCurrentEdge = 0;
00135     if (myCurrentName[0] == ':') {
00136         // this is an internal edge - we will not use it
00137         //  !!! recheck this; internal edges may be of importance during the dua
00138         return;
00139     }
00140     std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, myCurrentName.c_str(), ok);
00141     std::string to = attrs.getStringReporting(SUMO_ATTR_TO, myCurrentName.c_str(), ok);
00142     std::string type = attrs.hasAttribute(SUMO_ATTR_FUNCTION) ? attrs.getStringReporting(SUMO_ATTR_FUNCTION, myCurrentName.c_str(), ok) : "";
00143     if (!ok) {
00144         return;
00145     }
00146     RONode* fromNode = myNet.getNode(from);
00147     if (fromNode == 0) {
00148         fromNode = new RONode(from);
00149         myNet.addNode(fromNode);
00150     }
00151     RONode* toNode = myNet.getNode(to);
00152     if (toNode == 0) {
00153         toNode = new RONode(to);
00154         myNet.addNode(toNode);
00155     }
00156     // build the edge
00157     myCurrentEdge = myEdgeBuilder.buildEdge(myCurrentName, fromNode, toNode);
00158     if (myNet.addEdge(myCurrentEdge)) {
00159         // get the type of the edge
00160         myProcess = true;
00161         if (type == "" || type == "normal" || type == "connector") {
00162             myCurrentEdge->setType(ROEdge::ET_NORMAL);
00163         } else if (type == "source") {
00164             myCurrentEdge->setType(ROEdge::ET_SOURCE);
00165         } else if (type == "sink") {
00166             myCurrentEdge->setType(ROEdge::ET_SINK);
00167         } else if (type == "internal") {
00168             myProcess = false;
00169         } else {
00170             WRITE_ERROR("Edge '" + myCurrentName + "' has an unknown type.");
00171             return;
00172         }
00173     } else {
00174         myCurrentEdge = 0;
00175     }
00176 }
00177 
00178 
00179 void
00180 RONetHandler::parseLane(const SUMOSAXAttributes& attrs) {
00181     if (myCurrentEdge == 0) {
00182         // was an internal edge to skip or an error occured
00183         return;
00184     }
00185     bool ok = true;
00186     // get the id, report an error if not given or empty...
00187     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00188     if (!ok) {
00189         return;
00190     }
00191     // get the speed
00192     SUMOReal maxSpeed = attrs.hasAttribute(SUMO_ATTR_SPEED)
00193                         ? attrs.getSUMORealReporting(SUMO_ATTR_SPEED, id.c_str(), ok)
00194                         : attrs.getSUMORealReporting(SUMO_ATTR_MAXSPEED__DEPRECATED, id.c_str(), ok);
00195     SUMOReal length = attrs.getSUMORealReporting(SUMO_ATTR_LENGTH, id.c_str(), ok);
00196     std::string allow = attrs.getOptStringReporting(SUMO_ATTR_ALLOW, id.c_str(), ok, "");
00197     std::string disallow = attrs.getOptStringReporting(SUMO_ATTR_DISALLOW, id.c_str(), ok, "");
00198     if (!ok) {
00199         return;
00200     }
00201     // get the length
00202     // get the vehicle classes
00203     SVCPermissions permissions = parseVehicleClasses(allow, disallow);
00204     if (permissions != SVCFreeForAll) {
00205         myNet.setRestrictionFound();
00206     }
00207     // add when both values are valid
00208     if (maxSpeed > 0 && length > 0 && id.length() > 0) {
00209         myCurrentEdge->addLane(new ROLane(id, length, maxSpeed, permissions));
00210     }
00211 }
00212 
00213 
00214 void
00215 RONetHandler::parseJunction(const SUMOSAXAttributes& attrs) {
00216     bool ok = true;
00217     // get the id, report an error if not given or empty...
00218     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00219     if (!ok) {
00220         return;
00221     }
00222     // get the position of the node
00223     SUMOReal x = attrs.getSUMORealReporting(SUMO_ATTR_X, id.c_str(), ok);
00224     SUMOReal y = attrs.getSUMORealReporting(SUMO_ATTR_Y, id.c_str(), ok);
00225     if (ok) {
00226         RONode* n = myNet.getNode(id);
00227         if (n == 0) {
00228             n = new RONode(id);
00229             myNet.addNode(n);
00230         }
00231         n->setPosition(Position(x, y));
00232     } else {
00233         throw ProcessError();
00234     }
00235 }
00236 
00237 
00238 void
00239 RONetHandler::parseConnectingEdge(const SUMOSAXAttributes& attrs) {
00240     bool ok = true;
00241     std::string id = attrs.getStringReporting(SUMO_ATTR_EDGE, 0, ok);
00242     if (id[0] == ':') {
00243         myCurrentEdge = 0;
00244         return;
00245     }
00246     myCurrentEdge = myNet.getEdge(id);
00247     if (myCurrentEdge == 0) {
00248         throw ProcessError("An unknown edge occured (id='" + id + "').");
00249     }
00250 }
00251 
00252 
00253 void
00254 RONetHandler::parseConnectedEdge(const SUMOSAXAttributes& attrs) {
00255     if (myCurrentEdge == 0) {
00256         // earlier error or internal link
00257         return;
00258     }
00259     bool ok = true;
00260     std::string id = attrs.getStringReporting(SUMO_ATTR_LANE, myCurrentName.c_str(), ok);
00261     if (id == "SUMO_NO_DESTINATION") {
00262         return;
00263     }
00264     ROEdge* succ = myNet.getEdge(id.substr(0, id.rfind('_')));
00265     if (succ != 0) {
00266         // connect edge
00267         myCurrentEdge->addFollower(succ);
00268     } else {
00269         WRITE_ERROR("At edge '" + myCurrentName + "': succeeding edge '" + id + "' does not exist.");
00270     }
00271 }
00272 
00273 
00274 void
00275 RONetHandler::parseConnection(const SUMOSAXAttributes& attrs) {
00276     bool ok = true;
00277     std::string fromID = attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok);
00278     std::string toID = attrs.getStringReporting(SUMO_ATTR_TO, 0, ok);
00279     std::string dir = attrs.getStringReporting(SUMO_ATTR_DIR, 0, ok);
00280     if (fromID[0] == ':') { // skip inner lane connections
00281         return;
00282     }
00283     ROEdge* from = myNet.getEdge(fromID);
00284     ROEdge* to = myNet.getEdge(toID);
00285     if (from == 0) {
00286         throw ProcessError("unknown from-edge '" + fromID + "' in connection");
00287     }
00288     if (to == 0) {
00289         throw ProcessError("unknown to-edge '" + toID + "' in connection");
00290     }
00291     from->addFollower(to, dir);
00292 }
00293 
00294 
00295 void
00296 RONetHandler::parseDistrict(const SUMOSAXAttributes& attrs) {
00297     myCurrentEdge = 0;
00298     bool ok = true;
00299     myCurrentName = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00300     if (!ok) {
00301         return;
00302     }
00303     ROEdge* sink = myEdgeBuilder.buildEdge(myCurrentName + "-sink", 0, 0);
00304     sink->setType(ROEdge::ET_DISTRICT);
00305     myNet.addEdge(sink);
00306     ROEdge* source = myEdgeBuilder.buildEdge(myCurrentName + "-source", 0, 0);
00307     source->setType(ROEdge::ET_DISTRICT);
00308     myNet.addEdge(source);
00309     if (attrs.hasAttribute(SUMO_ATTR_EDGES)) {
00310         std::vector<std::string> desc = StringTokenizer(attrs.getString(SUMO_ATTR_EDGES)).getVector();
00311         for (std::vector<std::string>::const_iterator i = desc.begin(); i != desc.end(); ++i) {
00312             ROEdge* edge = myNet.getEdge(*i);
00313             // check whether the edge exists
00314             if (edge == 0) {
00315                 throw ProcessError("The edge '" + *i + "' within district '" + myCurrentName + "' is not known.");
00316             }
00317             source->addFollower(edge);
00318             edge->addFollower(sink);
00319         }
00320     }
00321 }
00322 
00323 
00324 void
00325 RONetHandler::parseDistrictEdge(const SUMOSAXAttributes& attrs, bool isSource) {
00326     bool ok = true;
00327     std::string id = attrs.getStringReporting(SUMO_ATTR_ID, myCurrentName.c_str(), ok);
00328     ROEdge* succ = myNet.getEdge(id);
00329     if (succ != 0) {
00330         // connect edge
00331         if (isSource) {
00332             myNet.getEdge(myCurrentName + "-source")->addFollower(succ);
00333         } else {
00334             succ->addFollower(myNet.getEdge(myCurrentName + "-sink"));
00335         }
00336     } else {
00337         WRITE_ERROR("At district '" + myCurrentName + "': succeeding edge '" + id + "' does not exist.");
00338     }
00339 }
00340 
00341 
00342 
00343 /****************************************************************************/
00344 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines