SUMO - Simulation of Urban MObility
NIXMLEdgesHandler.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00011 // Importer for network edges stored in XML
00012 /****************************************************************************/
00013 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00014 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00015 /****************************************************************************/
00016 //
00017 //   This file is part of SUMO.
00018 //   SUMO is free software: you can redistribute it and/or modify
00019 //   it under the terms of the GNU General Public License as published by
00020 //   the Free Software Foundation, either version 3 of the License, or
00021 //   (at your option) any later version.
00022 //
00023 /****************************************************************************/
00024 
00025 
00026 // ===========================================================================
00027 // included modules
00028 // ===========================================================================
00029 #ifdef _MSC_VER
00030 #include <windows_config.h>
00031 #else
00032 #include <config.h>
00033 #endif
00034 
00035 #include <string>
00036 #include <iostream>
00037 #include <map>
00038 #include <cmath>
00039 #include <xercesc/sax/HandlerBase.hpp>
00040 #include <xercesc/sax/AttributeList.hpp>
00041 #include <xercesc/sax/SAXParseException.hpp>
00042 #include <xercesc/sax/SAXException.hpp>
00043 #include <utils/xml/SUMOSAXHandler.h>
00044 #include <netbuild/NBNodeCont.h>
00045 #include <netbuild/NBTypeCont.h>
00046 #include <utils/xml/SUMOXMLDefinitions.h>
00047 #include <utils/common/MsgHandler.h>
00048 #include <utils/common/TplConvert.h>
00049 #include <utils/common/StringTokenizer.h>
00050 #include <utils/geom/GeomConvHelper.h>
00051 #include <utils/common/ToString.h>
00052 #include <utils/options/OptionsCont.h>
00053 #include <utils/geom/GeoConvHelper.h>
00054 #include "NILoader.h"
00055 #include "NIXMLEdgesHandler.h"
00056 
00057 #ifdef CHECK_MEMORY_LEAKS
00058 #include <foreign/nvwa/debug_new.h>
00059 #endif // CHECK_MEMORY_LEAKS
00060 
00061 
00062 // ===========================================================================
00063 // used constants
00064 // ===========================================================================
00065 const SUMOReal SUMOXML_INVALID_POSITION = -999999.;
00066 
00067 // ===========================================================================
00068 // method definitions
00069 // ===========================================================================
00070 NIXMLEdgesHandler::NIXMLEdgesHandler(NBNodeCont& nc,
00071                                      NBEdgeCont& ec,
00072                                      NBTypeCont& tc,
00073                                      NBDistrictCont& dc,
00074                                      OptionsCont& options)
00075     : SUMOSAXHandler("xml-edges - file"),
00076       myOptions(options),
00077       myNodeCont(nc), myEdgeCont(ec), myTypeCont(tc), myDistrictCont(dc),
00078       myCurrentEdge(0), myHaveReportedAboutOverwriting(false),
00079       myHaveWarnedAboutDeprecatedSpreadType(false),
00080       myHaveWarnedAboutDeprecatedFromTo(false),
00081       myHaveWarnedAboutDeprecatedNoLanes(false),
00082       myHaveWarnedAboutDeprecatedLaneId(false) {}
00083 
00084 
00085 NIXMLEdgesHandler::~NIXMLEdgesHandler() {}
00086 
00087 
00088 void
00089 NIXMLEdgesHandler::myStartElement(int element,
00090                                   const SUMOSAXAttributes& attrs) {
00091     switch (element) {
00092         case SUMO_TAG_EDGE:
00093             addEdge(attrs);
00094             break;
00095         case SUMO_TAG_LANE:
00096             addLane(attrs);
00097             break;
00098         case SUMO_TAG_SPLIT:
00099             addSplit(attrs);
00100             break;
00101         case SUMO_TAG_DELETE:
00102             deleteEdge(attrs);
00103             break;
00104         default:
00105             break;
00106     }
00107 }
00108 
00109 
00110 void
00111 NIXMLEdgesHandler::addEdge(const SUMOSAXAttributes& attrs) {
00112     myIsUpdate = false;
00113     bool ok = true;
00114     // initialise the edge
00115     myCurrentEdge = 0;
00116     mySplits.clear();
00117     // get the id, report an error if not given or empty...
00118     myCurrentID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00119     if (!ok) {
00120         return;
00121     }
00122     myCurrentEdge = myEdgeCont.retrieve(myCurrentID);
00123     // check deprecated (unused) attributes
00124     // use default values, first
00125     myCurrentSpeed = myTypeCont.getSpeed("");
00126     myCurrentPriority = myTypeCont.getPriority("");
00127     myCurrentLaneNo = myTypeCont.getNumLanes("");
00128     myPermissions = myTypeCont.getPermissions("");
00129     myCurrentWidth = myTypeCont.getWidth("");
00130     myCurrentOffset = NBEdge::UNSPECIFIED_OFFSET;
00131     myCurrentType = "";
00132     myShape = PositionVector();
00133     myLanesSpread = LANESPREAD_RIGHT;
00134     myLength = NBEdge::UNSPECIFIED_LOADED_LENGTH;
00135     myCurrentStreetName = "";
00136     // check whether a type's values shall be used
00137     if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
00138         myCurrentType = attrs.getStringReporting(SUMO_ATTR_TYPE, myCurrentID.c_str(), ok);
00139         if (!ok) {
00140             return;
00141         }
00142         if (!myTypeCont.knows(myCurrentType)) {
00143             WRITE_ERROR("Type '" + myCurrentType + "' used by edge '" + myCurrentID + "' was not defined.");
00144             return;
00145         }
00146         myCurrentSpeed = myTypeCont.getSpeed(myCurrentType);
00147         myCurrentPriority = myTypeCont.getPriority(myCurrentType);
00148         myCurrentLaneNo = myTypeCont.getNumLanes(myCurrentType);
00149         myPermissions = myTypeCont.getPermissions(myCurrentType);
00150         myCurrentWidth = myTypeCont.getWidth(myCurrentType);
00151     }
00152     // use values from the edge to overwrite if existing, then
00153     if (myCurrentEdge != 0) {
00154         myIsUpdate = true;
00155         if (!myHaveReportedAboutOverwriting) {
00156             WRITE_MESSAGE("Duplicate edge id occured ('" + myCurrentID + "'); assuming overwriting is wished.");
00157             myHaveReportedAboutOverwriting = true;
00158         }
00159         if (attrs.getOptBoolReporting(SUMO_ATTR_REMOVE, myCurrentID.c_str(), ok, false)) {
00160             myEdgeCont.erase(myDistrictCont, myCurrentEdge);
00161             myCurrentEdge = 0;
00162             return;
00163         }
00164         myCurrentSpeed = myCurrentEdge->getSpeed();
00165         myCurrentPriority = myCurrentEdge->getPriority();
00166         myCurrentLaneNo = myCurrentEdge->getNumLanes();
00167         myCurrentType = myCurrentEdge->getTypeID();
00168         myPermissions = myCurrentEdge->getPermissions();
00169         if (!myCurrentEdge->hasDefaultGeometry()) {
00170             myShape = myCurrentEdge->getGeometry();
00171         }
00172         myCurrentWidth = myCurrentEdge->getWidth();
00173         myCurrentOffset = myCurrentEdge->getOffset();
00174         myLanesSpread = myCurrentEdge->getLaneSpreadFunction();
00175         if (myCurrentEdge->hasLoadedLength()) {
00176             myLength = myCurrentEdge->getLoadedLength();
00177         }
00178         myCurrentStreetName = myCurrentEdge->getStreetName();
00179     }
00180     // speed, priority and the number of lanes have now default values;
00181     // try to read the real values from the file
00182     if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
00183         myCurrentSpeed = attrs.getSUMORealReporting(SUMO_ATTR_SPEED, myCurrentID.c_str(), ok);
00184     }
00185     if (myOptions.getBool("speed-in-kmh")) {
00186         myCurrentSpeed = myCurrentSpeed / (SUMOReal) 3.6;
00187     }
00188     // try to get the number of lanes
00189     if (attrs.hasAttribute(SUMO_ATTR_NOLANES__DEPRECATED)) {
00190         myCurrentLaneNo = attrs.getIntReporting(SUMO_ATTR_NOLANES__DEPRECATED, myCurrentID.c_str(), ok);
00191         if (!myHaveWarnedAboutDeprecatedNoLanes) {
00192             myHaveWarnedAboutDeprecatedNoLanes = true;
00193             WRITE_WARNING("'" + toString(SUMO_ATTR_NOLANES__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_ATTR_NUMLANES) + "' instead.");
00194         }
00195     }
00196     if (attrs.hasAttribute(SUMO_ATTR_NUMLANES)) {
00197         myCurrentLaneNo = attrs.getIntReporting(SUMO_ATTR_NUMLANES, myCurrentID.c_str(), ok);
00198     }
00199     // try to get the priority
00200     if (attrs.hasAttribute(SUMO_ATTR_PRIORITY)) {
00201         myCurrentPriority = attrs.getIntReporting(SUMO_ATTR_PRIORITY, myCurrentID.c_str(), ok);
00202     }
00203     // try to get the width
00204     if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
00205         myCurrentWidth = attrs.getSUMORealReporting(SUMO_ATTR_WIDTH, myCurrentID.c_str(), ok);
00206     }
00207     // try to get the width
00208     if (attrs.hasAttribute(SUMO_ATTR_ENDOFFSET)) {
00209         myCurrentOffset = attrs.getSUMORealReporting(SUMO_ATTR_ENDOFFSET, myCurrentID.c_str(), ok);
00210     }
00211     // try to get the street name
00212     myCurrentStreetName = attrs.getOptStringReporting(SUMO_ATTR_NAME, myCurrentID.c_str(), ok, myCurrentStreetName);
00213 
00214     // try to get the allowed/disallowed classes
00215     if (attrs.hasAttribute(SUMO_ATTR_ALLOW) || attrs.hasAttribute(SUMO_ATTR_DISALLOW)) {
00216         std::string allowS = attrs.hasAttribute(SUMO_ATTR_ALLOW) ? attrs.getStringSecure(SUMO_ATTR_ALLOW, "") : "";
00217         std::string disallowS = attrs.hasAttribute(SUMO_ATTR_DISALLOW) ? attrs.getStringSecure(SUMO_ATTR_DISALLOW, "") : "";
00218         // XXX matter of interpretation: should updated permissions replace or extend previously set permissions?
00219         myPermissions = parseVehicleClasses(allowS, disallowS);
00220     }
00221     // try to set the nodes
00222     if (!setNodes(attrs)) {
00223         // return if this failed
00224         return;
00225     }
00226     // try to get the shape
00227     myShape = tryGetShape(attrs);
00228     // try to get the spread type
00229     myLanesSpread = tryGetLaneSpread(attrs);
00230     // try to get the length
00231     myLength = attrs.getOptSUMORealReporting(SUMO_ATTR_LENGTH, myCurrentID.c_str(), ok, myLength);
00232     // insert the parsed edge into the edges map
00233     if (!ok) {
00234         return;
00235     }
00236     // check whether a previously defined edge shall be overwritten
00237     if (myCurrentEdge != 0) {
00238         myCurrentEdge->reinit(myFromNode, myToNode, myCurrentType, myCurrentSpeed,
00239                               myCurrentLaneNo, myCurrentPriority, myShape,
00240                               myCurrentWidth, myCurrentOffset, 
00241                               myCurrentStreetName, myLanesSpread,
00242                               OptionsCont::getOptions().getBool("plain.keep-edge-shape"));
00243     } else {
00244         // the edge must be allocated in dependence to whether a shape is given
00245         if (myShape.size() == 0) {
00246             myCurrentEdge = new NBEdge(myCurrentID, myFromNode, myToNode, myCurrentType, myCurrentSpeed,
00247                                        myCurrentLaneNo, myCurrentPriority, myCurrentWidth, myCurrentOffset,
00248                                        myCurrentStreetName, myLanesSpread);
00249         } else {
00250             myCurrentEdge = new NBEdge(myCurrentID, myFromNode, myToNode, myCurrentType, myCurrentSpeed,
00251                                        myCurrentLaneNo, myCurrentPriority, myCurrentWidth, myCurrentOffset,
00252                                        myShape, myCurrentStreetName, myLanesSpread,
00253                                        OptionsCont::getOptions().getBool("plain.keep-edge-shape"));
00254         }
00255     }
00256     myCurrentEdge->setLoadedLength(myLength);
00257     myCurrentEdge->setPermissions(myPermissions);
00258 }
00259 
00260 
00261 void
00262 NIXMLEdgesHandler::addLane(const SUMOSAXAttributes& attrs) {
00263     if (myCurrentEdge == 0) {
00264         if (!OptionsCont::getOptions().isInStringVector("remove-edges.explicit", myCurrentID)) {
00265             WRITE_ERROR("Additional lane information could not been set - the edge with id '" + myCurrentID + "' is not known.");
00266         }
00267         return;
00268     }
00269     bool ok = true;
00270     int lane;
00271     if (attrs.hasAttribute(SUMO_ATTR_ID)) {
00272         lane = attrs.getIntReporting(SUMO_ATTR_ID, myCurrentID.c_str(), ok);
00273         if (!myHaveWarnedAboutDeprecatedLaneId) {
00274             myHaveWarnedAboutDeprecatedLaneId = true;
00275             WRITE_WARNING("'" + toString(SUMO_ATTR_ID) + "' is deprecated, please use '" + toString(SUMO_ATTR_INDEX) + "' instead.");
00276         }
00277     } else {
00278         lane = attrs.getIntReporting(SUMO_ATTR_INDEX, myCurrentID.c_str(), ok);
00279     }
00280     std::string allowed, disallowed, preferred;
00281     allowed    = attrs.getOptStringReporting(SUMO_ATTR_ALLOW, 0, ok, "");
00282     disallowed = attrs.getOptStringReporting(SUMO_ATTR_DISALLOW, 0, ok, "");
00283     preferred  = attrs.getOptStringReporting(SUMO_ATTR_PREFER, 0, ok, "");
00284     if (!ok) {
00285         return;
00286     }
00287     // check whether this lane exists
00288     if (lane >= (int) myCurrentEdge->getNumLanes()) {
00289         WRITE_ERROR("Lane index is larger than number of lanes (edge '" + myCurrentID + "').");
00290         return;
00291     }
00292     // set information about allowed / disallowed vehicle classes
00293     myCurrentEdge->setPermissions(parseVehicleClasses(allowed, disallowed), lane);
00294     myCurrentEdge->setPreferredVehicleClass(parseVehicleClasses(preferred), lane);
00295     // try to get the width
00296     if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
00297         myCurrentEdge->setWidth(lane, attrs.getSUMORealReporting(SUMO_ATTR_WIDTH, myCurrentID.c_str(), ok));
00298     }
00299     // try to get the end-offset (lane shortened due to pedestrian crossing etc..)
00300     if (attrs.hasAttribute(SUMO_ATTR_ENDOFFSET)) {
00301         myCurrentEdge->setOffset(lane, attrs.getSUMORealReporting(SUMO_ATTR_ENDOFFSET, myCurrentID.c_str(), ok));
00302     }
00303     // try to get lane specific speed (should not occur for german networks)
00304     if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
00305         myCurrentEdge->setSpeed(lane, attrs.getSUMORealReporting(SUMO_ATTR_SPEED, myCurrentID.c_str(), ok));
00306     }
00307 }
00308 
00309 
00310 void NIXMLEdgesHandler::addSplit(const SUMOSAXAttributes& attrs) {
00311     if (myCurrentEdge == 0) {
00312         WRITE_WARNING("Ignoring 'split' because it cannot be assigned to an edge");
00313         return;
00314     }
00315     bool ok = true;
00316     Split e;
00317     e.pos = attrs.getSUMORealReporting(SUMO_ATTR_POSITION, 0, ok);
00318     if (ok) {
00319         if (fabs(e.pos) > myCurrentEdge->getGeometry().length()) {
00320             WRITE_ERROR("Edge '" + myCurrentID + "' has a split at invalid position " + toString(e.pos) + ".");
00321             return;
00322         }
00323         std::vector<Split>::iterator i = find_if(mySplits.begin(), mySplits.end(), split_by_pos_finder(e.pos));
00324         if (i != mySplits.end()) {
00325             WRITE_ERROR("Edge '" + myCurrentID + "' has already a split at position " + toString(e.pos) + ".");
00326             return;
00327         }
00328         e.nameid = (int)e.pos;
00329         if (myCurrentEdge == 0) {
00330             if (!OptionsCont::getOptions().isInStringVector("remove-edges.explicit", myCurrentID)) {
00331                 WRITE_ERROR("Additional lane information could not been set - the edge with id '" + myCurrentID + "' is not known.");
00332             }
00333             return;
00334         }
00335         if (e.pos < 0) {
00336             e.pos += myCurrentEdge->getGeometry().length();
00337         }
00338         std::vector<std::string> lanes;
00339         SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_LANES, 0, ok, ""), lanes);
00340         for (std::vector<std::string>::iterator i = lanes.begin(); i != lanes.end(); ++i) {
00341             try {
00342                 int lane = TplConvert<char>::_2int((*i).c_str());
00343                 e.lanes.push_back(lane);
00344             } catch (NumberFormatException&) {
00345                 WRITE_ERROR("Error on parsing a split (edge '" + myCurrentID + "').");
00346             } catch (EmptyData&) {
00347                 WRITE_ERROR("Error on parsing a split (edge '" + myCurrentID + "').");
00348             }
00349         }
00350         if (e.lanes.empty()) {
00351             for (size_t l = 0; l < myCurrentEdge->getNumLanes(); ++l) {
00352                 e.lanes.push_back((int) l);
00353             }
00354         }
00355         mySplits.push_back(e);
00356     }
00357 }
00358 
00359 
00360 bool
00361 NIXMLEdgesHandler::setNodes(const SUMOSAXAttributes& attrs) {
00362     // the names and the coordinates of the beginning and the end node
00363     // may be found, try
00364     bool ok = true;
00365     std::string begNodeID = myIsUpdate ? myCurrentEdge->getFromNode()->getID() : "";
00366     std::string endNodeID = myIsUpdate ? myCurrentEdge->getToNode()->getID() : "";
00367     std::string oldBegID = begNodeID;
00368     std::string oldEndID = endNodeID;
00369     if (attrs.hasAttribute(SUMO_ATTR_FROMNODE)) {
00370         begNodeID = attrs.getStringReporting(SUMO_ATTR_FROMNODE, 0, ok);
00371         if (!myHaveWarnedAboutDeprecatedFromTo) {
00372             WRITE_WARNING("'" + toString(SUMO_ATTR_FROMNODE) + "' is deprecated; please use '" + toString(SUMO_ATTR_FROM) + "'.");
00373             myHaveWarnedAboutDeprecatedFromTo = true;
00374         }
00375     }
00376     if (attrs.hasAttribute(SUMO_ATTR_TONODE)) {
00377         endNodeID = attrs.getStringReporting(SUMO_ATTR_TONODE, 0, ok);
00378         if (!myHaveWarnedAboutDeprecatedFromTo) {
00379             WRITE_WARNING("'" + toString(SUMO_ATTR_TONODE) + "' is deprecated; please use '" + toString(SUMO_ATTR_TO) + "'.");
00380             myHaveWarnedAboutDeprecatedFromTo = true;
00381         }
00382     }
00383     begNodeID = attrs.hasAttribute(SUMO_ATTR_FROM) ? attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok) : begNodeID;
00384     endNodeID = attrs.hasAttribute(SUMO_ATTR_TO) ? attrs.getStringReporting(SUMO_ATTR_TO, 0, ok) : endNodeID;
00385     if (!ok) {
00386         return false;
00387     }
00388     // or their positions !!! deprecated
00389     SUMOReal begNodeXPos = tryGetPosition(attrs, SUMO_ATTR_XFROM, "XFrom");
00390     SUMOReal begNodeYPos = tryGetPosition(attrs, SUMO_ATTR_YFROM, "YFrom");
00391     SUMOReal endNodeXPos = tryGetPosition(attrs, SUMO_ATTR_XTO, "XTo");
00392     SUMOReal endNodeYPos = tryGetPosition(attrs, SUMO_ATTR_YTO, "YTo");
00393     if (begNodeXPos != SUMOXML_INVALID_POSITION && begNodeYPos != SUMOXML_INVALID_POSITION) {
00394         Position pos(begNodeXPos, begNodeYPos);
00395         NILoader::transformCoordinates(pos);
00396         begNodeXPos = pos.x();
00397         begNodeYPos = pos.y();
00398         if (!myHaveWarnedAboutDeprecatedFromTo) {
00399             WRITE_WARNING("'" + toString(SUMO_ATTR_XFROM) + "' and '" + toString(SUMO_ATTR_YFROM) + "' are deprecated; please define nodes separately.");
00400             myHaveWarnedAboutDeprecatedFromTo = true;
00401         }
00402     }
00403     if (endNodeXPos != SUMOXML_INVALID_POSITION && endNodeYPos != SUMOXML_INVALID_POSITION) {
00404         Position pos(endNodeXPos, endNodeYPos);
00405         NILoader::transformCoordinates(pos);
00406         endNodeXPos = pos.x();
00407         endNodeYPos = pos.y();
00408         if (!myHaveWarnedAboutDeprecatedFromTo) {
00409             WRITE_WARNING("'" + toString(SUMO_ATTR_XTO) + "' and '" + toString(SUMO_ATTR_YTO) + "' are deprecated; please define nodes separately.");
00410             myHaveWarnedAboutDeprecatedFromTo = true;
00411         }
00412     }
00413     // check the obtained values for nodes
00414     myFromNode = insertNodeChecking(Position(begNodeXPos, begNodeYPos), begNodeID, "from");
00415     myToNode = insertNodeChecking(Position(endNodeXPos, endNodeYPos), endNodeID, "to");
00416     if (myFromNode != 0 && myToNode != 0) {
00417         if (myIsUpdate && (myFromNode->getID() != oldBegID || myToNode->getID() != oldEndID)) {
00418             myShape = PositionVector();
00419         }
00420     }
00421     return myFromNode != 0 && myToNode != 0;
00422 }
00423 
00424 
00425 SUMOReal
00426 NIXMLEdgesHandler::tryGetPosition(const SUMOSAXAttributes& attrs, SumoXMLAttr attrID,
00427                                   const std::string& attrName) {
00428     UNUSED_PARAMETER(attrName);
00429     bool ok = true;
00430     return attrs.getOptSUMORealReporting(attrID, myCurrentID.c_str(), ok, SUMOXML_INVALID_POSITION);
00431 }
00432 
00433 
00434 NBNode*
00435 NIXMLEdgesHandler::insertNodeChecking(const Position& pos,
00436                                       const std::string& name, const std::string& dir) {
00437     NBNode* ret = 0;
00438     if (name == "" && (pos.x() == SUMOXML_INVALID_POSITION || pos.y() == SUMOXML_INVALID_POSITION)) {
00439         WRITE_ERROR("Neither the name nor the position of the " + dir + "-node is given for edge '" + myCurrentID + "'.");
00440         return ret;
00441     }
00442     if (name != "") {
00443         if (pos.x() != SUMOXML_INVALID_POSITION && pos.y() != SUMOXML_INVALID_POSITION) {
00444             // the node is named and it has a position given
00445             if (!myNodeCont.insert(name, pos)) {
00446                 WRITE_ERROR("Position of " + dir + "-node '" + name + "' mismatches previous positions.");
00447                 return 0;
00448             }
00449         }
00450         // the node is given by its name
00451         ret = myNodeCont.retrieve(name);
00452         if (ret == 0) {
00453             WRITE_ERROR("Edge's '" + myCurrentID + "' " + dir + "-node '" + name + "' is not known.");
00454         }
00455     } else {
00456         ret = myNodeCont.retrieve(pos);
00457         if (ret == 0) {
00458             ret = new NBNode(myNodeCont.getFreeID(), pos);
00459             if (!myNodeCont.insert(ret)) {
00460                 WRITE_ERROR("Could not insert " + dir + "-node at position " + toString(pos) + ".");
00461                 delete ret;
00462                 return 0;
00463             }
00464         }
00465     }
00466     return ret;
00467 }
00468 
00469 
00470 PositionVector
00471 NIXMLEdgesHandler::tryGetShape(const SUMOSAXAttributes& attrs) {
00472     if (!attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
00473         return myShape;
00474     }
00475     // try to build shape
00476     bool ok = true;
00477     std::string shpdef = attrs.getOptStringReporting(SUMO_ATTR_SHAPE, 0, ok, "");
00478     if (shpdef == "") {
00479         return PositionVector();
00480     }
00481     PositionVector shape = GeomConvHelper::parseShapeReporting(shpdef, attrs.getObjectType(), 0, ok, true);
00482     if (!NILoader::transformCoordinates(shape)) {
00483         WRITE_ERROR("Unable to project coordinates for edge '" + myCurrentID + "'.");
00484     }
00485     return shape;
00486 }
00487 
00488 
00489 LaneSpreadFunction
00490 NIXMLEdgesHandler::tryGetLaneSpread(const SUMOSAXAttributes& attrs) {
00491     bool ok = true;
00492     LaneSpreadFunction result = myLanesSpread;
00493     std::string lsfS = toString(result);
00494     if (attrs.hasAttribute(SUMO_ATTR_SPREADFUNC__DEPRECATED)) {
00495         lsfS = attrs.getStringReporting(SUMO_ATTR_SPREADFUNC__DEPRECATED, myCurrentID.c_str(), ok);
00496         if (!myHaveWarnedAboutDeprecatedSpreadType) {
00497             WRITE_WARNING("'" + toString(SUMO_ATTR_SPREADFUNC__DEPRECATED) + " is deprecated; please use '" + toString(SUMO_ATTR_SPREADTYPE) + "'.");
00498             myHaveWarnedAboutDeprecatedSpreadType = true;
00499         }
00500     } else {
00501         lsfS = attrs.getOptStringReporting(SUMO_ATTR_SPREADTYPE, myCurrentID.c_str(), ok, lsfS);
00502     }
00503     if (SUMOXMLDefinitions::LaneSpreadFunctions.hasString(lsfS)) {
00504         result = SUMOXMLDefinitions::LaneSpreadFunctions.get(lsfS);
00505     } else {
00506         WRITE_WARNING("Ignoring unknown spreadType '" + lsfS + "' for edge '" + myCurrentID + "'.");
00507     }
00508     return result;
00509 }
00510 
00511 
00512 void
00513 NIXMLEdgesHandler::deleteEdge(const SUMOSAXAttributes& attrs) {
00514     bool ok = true;
00515     myCurrentID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00516     if (!ok) {
00517         return;
00518     }
00519     NBEdge* edge = myEdgeCont.retrieve(myCurrentID);
00520     if (edge == 0) {
00521         WRITE_WARNING("Ignoring tag '" + toString(SUMO_TAG_DELETE) + "' for unknown edge '" +
00522                       myCurrentID + "'");
00523         return;
00524     }
00525     myEdgeCont.extract(myDistrictCont, edge, true);
00526 }
00527 
00528 
00529 void
00530 NIXMLEdgesHandler::myEndElement(int element) {
00531     if (element == SUMO_TAG_EDGE && myCurrentEdge != 0) {
00532         if (!myIsUpdate) {
00533             try {
00534                 if (!myEdgeCont.insert(myCurrentEdge)) {
00535                     WRITE_ERROR("Duplicate edge occured. ID='" + myCurrentID + "'");
00536                     delete myCurrentEdge;
00537                 }
00538             } catch (InvalidArgument& e) {
00539                 WRITE_ERROR(e.what());
00540                 throw;
00541             } catch (...) {
00542                 WRITE_ERROR("An important information is missing in edge '" + myCurrentID + "'.");
00543             }
00544         }
00545         if (mySplits.size() != 0) {
00546             std::vector<Split>::iterator i;
00547             NBEdge* e = myCurrentEdge;
00548             SUMOReal length = e->getLength();
00549             sort(mySplits.begin(), mySplits.end(), split_sorter());
00550             unsigned int noLanesMax = e->getNumLanes();
00551             // compute the node positions and sort the lanes
00552             for (i = mySplits.begin(); i != mySplits.end(); ++i) {
00553                 (*i).gpos = e->getGeometry().positionAtLengthPosition((*i).pos);
00554                 sort((*i).lanes.begin(), (*i).lanes.end());
00555                 noLanesMax = MAX2(noLanesMax, (unsigned int)(*i).lanes.size());
00556             }
00557             // split the edge
00558             std::vector<int> currLanes;
00559             for (unsigned int l = 0; l < e->getNumLanes(); ++l) {
00560                 currLanes.push_back(l);
00561             }
00562             std::string edgeid = e->getID();
00563             SUMOReal seen = 0;
00564             for (i = mySplits.begin(); i != mySplits.end(); ++i) {
00565                 const Split& exp = *i;
00566                 assert(exp.lanes.size() != 0);
00567                 if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) {
00568                     std::string nid = edgeid + "." +  toString(exp.nameid);
00569                     NBNode* rn = new NBNode(nid, exp.gpos);
00570                     if (myNodeCont.insert(rn)) {
00571                         //  split the edge
00572                         std::string nid = myCurrentID + "." +  toString(exp.nameid);
00573                         std::string pid = e->getID();
00574                         myEdgeCont.splitAt(myDistrictCont, e, exp.pos - seen, rn,
00575                                            pid, nid, e->getNumLanes(), (unsigned int) exp.lanes.size());
00576                         seen = exp.pos;
00577                         std::vector<int> newLanes = exp.lanes;
00578                         NBEdge* pe = myEdgeCont.retrieve(pid);
00579                         NBEdge* ne = myEdgeCont.retrieve(nid);
00580                         // reconnect lanes
00581                         pe->invalidateConnections(true);
00582                         //  new on right
00583                         unsigned int rightMostP = currLanes[0];
00584                         unsigned int rightMostN = newLanes[0];
00585                         for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) {
00586                             pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true);
00587                         }
00588                         //  new on left
00589                         unsigned int leftMostP = currLanes.back();
00590                         unsigned int leftMostN = newLanes.back();
00591                         for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) {
00592                             pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true);
00593                         }
00594                         //  all other connected
00595                         for (unsigned int l = 0; l < noLanesMax; ++l) {
00596                             if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) {
00597                                 continue;
00598                             }
00599                             if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) {
00600                                 continue;
00601                             }
00602                             pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true);
00603                         }
00604                         // move to next
00605                         e = ne;
00606                         currLanes = newLanes;
00607                     } else {
00608                         WRITE_WARNING("Error on parsing a split (edge '" + myCurrentID + "').");
00609                     }
00610                 }  else if (exp.pos == 0) {
00611                     if (e->getNumLanes() < exp.lanes.size()) {
00612                         e->incLaneNo((int) exp.lanes.size() - e->getNumLanes());
00613                     } else {
00614                         e->decLaneNo(e->getNumLanes() - (int) exp.lanes.size());
00615                     }
00616                     currLanes = exp.lanes;
00617                 } else {
00618                     WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + myCurrentID + "').");
00619                 }
00620             }
00621             // patch lane offsets
00622             e = myEdgeCont.retrieve(edgeid);
00623             i = mySplits.begin();
00624             if ((*i).pos != 0) {
00625                 e = e->getToNode()->getOutgoingEdges()[0];
00626             }
00627             for (; i != mySplits.end(); ++i) {
00628                 unsigned int maxLeft = (*i).lanes.back();
00629                 if (maxLeft < noLanesMax) {
00630                     PositionVector g = e->getGeometry();
00631                     g.move2side(SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft));
00632                     e->setGeometry(g);
00633                 }
00634                 if (e->getToNode()->getOutgoingEdges().size() != 0) {
00635                     e = e->getToNode()->getOutgoingEdges()[0];
00636                 }
00637             }
00638         }
00639     }
00640 }
00641 
00642 /****************************************************************************/
00643 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines