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     myAllowed = myTypeCont.getAllowedClasses("");
00129     myNotAllowed = myTypeCont.getDisallowedClasses("");
00130     myCurrentWidth = myTypeCont.getWidth("");
00131     myCurrentOffset = NBEdge::UNSPECIFIED_OFFSET;
00132     myCurrentType = "";
00133     myShape = PositionVector();
00134     myLanesSpread = LANESPREAD_RIGHT;
00135     myLength = NBEdge::UNSPECIFIED_LOADED_LENGTH;
00136     myCurrentStreetName = "";
00137     // check whether a type's values shall be used
00138     if (attrs.hasAttribute(SUMO_ATTR_TYPE)) {
00139         myCurrentType = attrs.getStringReporting(SUMO_ATTR_TYPE, myCurrentID.c_str(), ok);
00140         if (!ok) {
00141             return;
00142         }
00143         if (!myTypeCont.knows(myCurrentType)) {
00144             WRITE_ERROR("Type '" + myCurrentType + "' used by edge '" + myCurrentID + "' was not defined.");
00145             return;
00146         }
00147         myCurrentSpeed = myTypeCont.getSpeed(myCurrentType);
00148         myCurrentPriority = myTypeCont.getPriority(myCurrentType);
00149         myCurrentLaneNo = myTypeCont.getNumLanes(myCurrentType);
00150         myAllowed = myTypeCont.getAllowedClasses(myCurrentType);
00151         myNotAllowed = myTypeCont.getDisallowedClasses(myCurrentType);
00152         myCurrentWidth = myTypeCont.getWidth(myCurrentType);
00153     }
00154     // use values from the edge to overwrite if existing, then
00155     if (myCurrentEdge != 0) {
00156         myIsUpdate = true;
00157         if (!myHaveReportedAboutOverwriting) {
00158             WRITE_MESSAGE("Duplicate edge id occured ('" + myCurrentID + "'); assuming overwriting is wished.");
00159             myHaveReportedAboutOverwriting = true;
00160         }
00161         if (attrs.getOptBoolReporting(SUMO_ATTR_REMOVE, myCurrentID.c_str(), ok, false)) {
00162             myEdgeCont.erase(myDistrictCont, myCurrentEdge);
00163             myCurrentEdge = 0;
00164             return;
00165         }
00166         myCurrentSpeed = myCurrentEdge->getSpeed();
00167         myCurrentPriority = myCurrentEdge->getPriority();
00168         myCurrentLaneNo = myCurrentEdge->getNumLanes();
00169         myCurrentType = myCurrentEdge->getTypeID();
00170         myAllowed = myCurrentEdge->getAllowedVehicleClasses();
00171         myNotAllowed = myCurrentEdge->getDisallowedVehicleClasses();
00172         if (!myCurrentEdge->hasDefaultGeometry()) {
00173             myShape = myCurrentEdge->getGeometry();
00174         }
00175         myCurrentWidth = myCurrentEdge->getWidth();
00176         myCurrentOffset = myCurrentEdge->getOffset();
00177         myLanesSpread = myCurrentEdge->getLaneSpreadFunction();
00178         if (myCurrentEdge->hasLoadedLength()) {
00179             myLength = myCurrentEdge->getLoadedLength();
00180         }
00181         myCurrentStreetName = myCurrentEdge->getStreetName();
00182     }
00183     // speed, priority and the number of lanes have now default values;
00184     // try to read the real values from the file
00185     if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
00186         myCurrentSpeed = attrs.getSUMORealReporting(SUMO_ATTR_SPEED, myCurrentID.c_str(), ok);
00187     }
00188     if (myOptions.getBool("speed-in-kmh")) {
00189         myCurrentSpeed = myCurrentSpeed / (SUMOReal) 3.6;
00190     }
00191     // try to get the number of lanes
00192     if (attrs.hasAttribute(SUMO_ATTR_NOLANES__DEPRECATED)) {
00193         myCurrentLaneNo = attrs.getIntReporting(SUMO_ATTR_NOLANES__DEPRECATED, myCurrentID.c_str(), ok);
00194         if (!myHaveWarnedAboutDeprecatedNoLanes) {
00195             myHaveWarnedAboutDeprecatedNoLanes = true;
00196             WRITE_WARNING("'" + toString(SUMO_ATTR_NOLANES__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_ATTR_NUMLANES) + "' instead.");
00197         }
00198     }
00199     if (attrs.hasAttribute(SUMO_ATTR_NUMLANES)) {
00200         myCurrentLaneNo = attrs.getIntReporting(SUMO_ATTR_NUMLANES, myCurrentID.c_str(), ok);
00201     }
00202     // try to get the priority
00203     if (attrs.hasAttribute(SUMO_ATTR_PRIORITY)) {
00204         myCurrentPriority = attrs.getIntReporting(SUMO_ATTR_PRIORITY, myCurrentID.c_str(), ok);
00205     }
00206     // try to get the width
00207     if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
00208         myCurrentWidth = attrs.getSUMORealReporting(SUMO_ATTR_WIDTH, myCurrentID.c_str(), ok);
00209     }
00210     // try to get the width
00211     if (attrs.hasAttribute(SUMO_ATTR_ENDOFFSET)) {
00212         myCurrentOffset = attrs.getSUMORealReporting(SUMO_ATTR_ENDOFFSET, myCurrentID.c_str(), ok);
00213     }
00214     // try to get the street name
00215     myCurrentStreetName = attrs.getOptStringReporting(SUMO_ATTR_NAME, myCurrentID.c_str(), ok, myCurrentStreetName);
00216 
00217     // try to get the allowed/disallowed classes
00218     if (attrs.hasAttribute(SUMO_ATTR_ALLOW) || attrs.hasAttribute(SUMO_ATTR_DISALLOW)) {
00219         std::string allowS = attrs.hasAttribute(SUMO_ATTR_ALLOW) ? attrs.getStringSecure(SUMO_ATTR_ALLOW, "") : getVehicleClassNames(myAllowed);
00220         std::string disallowS = attrs.hasAttribute(SUMO_ATTR_DISALLOW) ? attrs.getStringSecure(SUMO_ATTR_DISALLOW, "") : getVehicleClassNames(myNotAllowed);
00221         myAllowed.clear();
00222         myNotAllowed.clear();
00223         parseVehicleClasses(allowS, disallowS, myAllowed, myNotAllowed);
00224     }
00225     // try to set the nodes
00226     if (!setNodes(attrs)) {
00227         // return if this failed
00228         return;
00229     }
00230     // try to get the shape
00231     myShape = tryGetShape(attrs);
00232     // try to get the spread type
00233     myLanesSpread = tryGetLaneSpread(attrs);
00234     // try to get the length
00235     myLength = attrs.getOptSUMORealReporting(SUMO_ATTR_LENGTH, myCurrentID.c_str(), ok, myLength);
00236     // insert the parsed edge into the edges map
00237     if (!ok) {
00238         return;
00239     }
00240     // check whether a previously defined edge shall be overwritten
00241     if (myCurrentEdge != 0) {
00242         myCurrentEdge->reinit(myFromNode, myToNode, myCurrentType, myCurrentSpeed,
00243                               myCurrentLaneNo, myCurrentPriority, myShape,
00244                               myCurrentWidth, myCurrentOffset, 
00245                               myCurrentStreetName, myLanesSpread,
00246                               OptionsCont::getOptions().getBool("plain.keep-edge-shape"));
00247     } else {
00248         // the edge must be allocated in dependence to whether a shape is given
00249         if (myShape.size() == 0) {
00250             myCurrentEdge = new NBEdge(myCurrentID, myFromNode, myToNode, myCurrentType, myCurrentSpeed,
00251                                        myCurrentLaneNo, myCurrentPriority, myCurrentWidth, myCurrentOffset,
00252                                        myCurrentStreetName, myLanesSpread);
00253         } else {
00254             myCurrentEdge = new NBEdge(myCurrentID, myFromNode, myToNode, myCurrentType, myCurrentSpeed,
00255                                        myCurrentLaneNo, myCurrentPriority, myCurrentWidth, myCurrentOffset,
00256                                        myShape, myCurrentStreetName, myLanesSpread,
00257                                        OptionsCont::getOptions().getBool("plain.keep-edge-shape"));
00258         }
00259     }
00260     myCurrentEdge->setLoadedLength(myLength);
00261     myCurrentEdge->setVehicleClasses(myAllowed, myNotAllowed);
00262 }
00263 
00264 
00265 void
00266 NIXMLEdgesHandler::addLane(const SUMOSAXAttributes& attrs) {
00267     if (myCurrentEdge == 0) {
00268         if (!OptionsCont::getOptions().isInStringVector("remove-edges.explicit", myCurrentID)) {
00269             WRITE_ERROR("Additional lane information could not been set - the edge with id '" + myCurrentID + "' is not known.");
00270         }
00271         return;
00272     }
00273     bool ok = true;
00274     int lane;
00275     if (attrs.hasAttribute(SUMO_ATTR_ID)) {
00276         lane = attrs.getIntReporting(SUMO_ATTR_ID, myCurrentID.c_str(), ok);
00277         if (!myHaveWarnedAboutDeprecatedLaneId) {
00278             myHaveWarnedAboutDeprecatedLaneId = true;
00279             WRITE_WARNING("'" + toString(SUMO_ATTR_ID) + "' is deprecated, please use '" + toString(SUMO_ATTR_INDEX) + "' instead.");
00280         }
00281     } else {
00282         lane = attrs.getIntReporting(SUMO_ATTR_INDEX, myCurrentID.c_str(), ok);
00283     }
00284     std::vector<std::string> disallowed, allowed, preferred;
00285     SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_DISALLOW, 0, ok, ""), disallowed);
00286     SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_ALLOW, 0, ok, ""), allowed);
00287     SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_PREFER, 0, ok, ""), preferred);
00288     if (!ok) {
00289         return;
00290     }
00291     // check whether this lane exists
00292     if (lane >= (int) myCurrentEdge->getNumLanes()) {
00293         WRITE_ERROR("Lane index is larger than number of lanes (edge '" + myCurrentID + "').");
00294         return;
00295     }
00296     // set information about allowed / disallowed vehicle classes
00297     for (std::vector<std::string>::iterator i = disallowed.begin(); i != disallowed.end(); ++i) {
00298         myCurrentEdge->disallowVehicleClass(lane, getVehicleClassID(*i));
00299     }
00300     for (std::vector<std::string>::iterator i = allowed.begin(); i != allowed.end(); ++i) {
00301         myCurrentEdge->allowVehicleClass(lane, getVehicleClassID(*i));
00302     }
00303     for (std::vector<std::string>::iterator i = preferred.begin(); i != preferred.end(); ++i) {
00304         myCurrentEdge->preferVehicleClass(lane, getVehicleClassID(*i));
00305     }
00306     // try to get the width
00307     if (attrs.hasAttribute(SUMO_ATTR_WIDTH)) {
00308         myCurrentEdge->setWidth(lane, attrs.getSUMORealReporting(SUMO_ATTR_WIDTH, myCurrentID.c_str(), ok));
00309     }
00310     // try to get the end-offset (lane shortened due to pedestrian crossing etc..)
00311     if (attrs.hasAttribute(SUMO_ATTR_ENDOFFSET)) {
00312         myCurrentEdge->setOffset(lane, attrs.getSUMORealReporting(SUMO_ATTR_ENDOFFSET, myCurrentID.c_str(), ok));
00313     }
00314     // try to get lane specific speed (should not occur for german networks)
00315     if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
00316         myCurrentEdge->setSpeed(lane, attrs.getSUMORealReporting(SUMO_ATTR_SPEED, myCurrentID.c_str(), ok));
00317     }
00318 }
00319 
00320 
00321 void NIXMLEdgesHandler::addSplit(const SUMOSAXAttributes& attrs) {
00322     if (myCurrentEdge == 0) {
00323         WRITE_WARNING("Ignoring 'split' because it cannot be assigned to an edge");
00324         return;
00325     }
00326     bool ok = true;
00327     Split e;
00328     e.pos = attrs.getSUMORealReporting(SUMO_ATTR_POSITION, 0, ok);
00329     if (ok) {
00330         if (fabs(e.pos) > myCurrentEdge->getGeometry().length()) {
00331             WRITE_ERROR("Edge '" + myCurrentID + "' has a split at invalid position " + toString(e.pos) + ".");
00332             return;
00333         }
00334         std::vector<Split>::iterator i = find_if(mySplits.begin(), mySplits.end(), split_by_pos_finder(e.pos));
00335         if (i != mySplits.end()) {
00336             WRITE_ERROR("Edge '" + myCurrentID + "' has already a split at position " + toString(e.pos) + ".");
00337             return;
00338         }
00339         e.nameid = (int)e.pos;
00340         if (myCurrentEdge == 0) {
00341             if (!OptionsCont::getOptions().isInStringVector("remove-edges.explicit", myCurrentID)) {
00342                 WRITE_ERROR("Additional lane information could not been set - the edge with id '" + myCurrentID + "' is not known.");
00343             }
00344             return;
00345         }
00346         if (e.pos < 0) {
00347             e.pos += myCurrentEdge->getGeometry().length();
00348         }
00349         std::vector<std::string> lanes;
00350         SUMOSAXAttributes::parseStringVector(attrs.getOptStringReporting(SUMO_ATTR_LANES, 0, ok, ""), lanes);
00351         for (std::vector<std::string>::iterator i = lanes.begin(); i != lanes.end(); ++i) {
00352             try {
00353                 int lane = TplConvert<char>::_2int((*i).c_str());
00354                 e.lanes.push_back(lane);
00355             } catch (NumberFormatException&) {
00356                 WRITE_ERROR("Error on parsing a split (edge '" + myCurrentID + "').");
00357             } catch (EmptyData&) {
00358                 WRITE_ERROR("Error on parsing a split (edge '" + myCurrentID + "').");
00359             }
00360         }
00361         if (e.lanes.empty()) {
00362             for (size_t l = 0; l < myCurrentEdge->getNumLanes(); ++l) {
00363                 e.lanes.push_back((int) l);
00364             }
00365         }
00366         mySplits.push_back(e);
00367     }
00368 }
00369 
00370 
00371 bool
00372 NIXMLEdgesHandler::setNodes(const SUMOSAXAttributes& attrs) {
00373     // the names and the coordinates of the beginning and the end node
00374     // may be found, try
00375     bool ok = true;
00376     std::string begNodeID = myIsUpdate ? myCurrentEdge->getFromNode()->getID() : "";
00377     std::string endNodeID = myIsUpdate ? myCurrentEdge->getToNode()->getID() : "";
00378     std::string oldBegID = begNodeID;
00379     std::string oldEndID = endNodeID;
00380     if (attrs.hasAttribute(SUMO_ATTR_FROMNODE)) {
00381         begNodeID = attrs.getStringReporting(SUMO_ATTR_FROMNODE, 0, ok);
00382         if (!myHaveWarnedAboutDeprecatedFromTo) {
00383             WRITE_WARNING("'" + toString(SUMO_ATTR_FROMNODE) + "' is deprecated; please use '" + toString(SUMO_ATTR_FROM) + "'.");
00384             myHaveWarnedAboutDeprecatedFromTo = true;
00385         }
00386     }
00387     if (attrs.hasAttribute(SUMO_ATTR_TONODE)) {
00388         endNodeID = attrs.getStringReporting(SUMO_ATTR_TONODE, 0, ok);
00389         if (!myHaveWarnedAboutDeprecatedFromTo) {
00390             WRITE_WARNING("'" + toString(SUMO_ATTR_TONODE) + "' is deprecated; please use '" + toString(SUMO_ATTR_TO) + "'.");
00391             myHaveWarnedAboutDeprecatedFromTo = true;
00392         }
00393     }
00394     begNodeID = attrs.hasAttribute(SUMO_ATTR_FROM) ? attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok) : begNodeID;
00395     endNodeID = attrs.hasAttribute(SUMO_ATTR_TO) ? attrs.getStringReporting(SUMO_ATTR_TO, 0, ok) : endNodeID;
00396     if (!ok) {
00397         return false;
00398     }
00399     // or their positions !!! deprecated
00400     SUMOReal begNodeXPos = tryGetPosition(attrs, SUMO_ATTR_XFROM, "XFrom");
00401     SUMOReal begNodeYPos = tryGetPosition(attrs, SUMO_ATTR_YFROM, "YFrom");
00402     SUMOReal endNodeXPos = tryGetPosition(attrs, SUMO_ATTR_XTO, "XTo");
00403     SUMOReal endNodeYPos = tryGetPosition(attrs, SUMO_ATTR_YTO, "YTo");
00404     if (begNodeXPos != SUMOXML_INVALID_POSITION && begNodeYPos != SUMOXML_INVALID_POSITION) {
00405         Position pos(begNodeXPos, begNodeYPos);
00406         NILoader::transformCoordinates(pos);
00407         begNodeXPos = pos.x();
00408         begNodeYPos = pos.y();
00409         if (!myHaveWarnedAboutDeprecatedFromTo) {
00410             WRITE_WARNING("'" + toString(SUMO_ATTR_XFROM) + "' and '" + toString(SUMO_ATTR_YFROM) + "' are deprecated; please define nodes separately.");
00411             myHaveWarnedAboutDeprecatedFromTo = true;
00412         }
00413     }
00414     if (endNodeXPos != SUMOXML_INVALID_POSITION && endNodeYPos != SUMOXML_INVALID_POSITION) {
00415         Position pos(endNodeXPos, endNodeYPos);
00416         NILoader::transformCoordinates(pos);
00417         endNodeXPos = pos.x();
00418         endNodeYPos = pos.y();
00419         if (!myHaveWarnedAboutDeprecatedFromTo) {
00420             WRITE_WARNING("'" + toString(SUMO_ATTR_XTO) + "' and '" + toString(SUMO_ATTR_YTO) + "' are deprecated; please define nodes separately.");
00421             myHaveWarnedAboutDeprecatedFromTo = true;
00422         }
00423     }
00424     // check the obtained values for nodes
00425     myFromNode = insertNodeChecking(Position(begNodeXPos, begNodeYPos), begNodeID, "from");
00426     myToNode = insertNodeChecking(Position(endNodeXPos, endNodeYPos), endNodeID, "to");
00427     if (myFromNode != 0 && myToNode != 0) {
00428         if (myIsUpdate && (myFromNode->getID() != oldBegID || myToNode->getID() != oldEndID)) {
00429             myShape = PositionVector();
00430         }
00431     }
00432     return myFromNode != 0 && myToNode != 0;
00433 }
00434 
00435 
00436 SUMOReal
00437 NIXMLEdgesHandler::tryGetPosition(const SUMOSAXAttributes& attrs, SumoXMLAttr attrID,
00438                                   const std::string& attrName) {
00439     UNUSED_PARAMETER(attrName);
00440     bool ok = true;
00441     return attrs.getOptSUMORealReporting(attrID, myCurrentID.c_str(), ok, SUMOXML_INVALID_POSITION);
00442 }
00443 
00444 
00445 NBNode*
00446 NIXMLEdgesHandler::insertNodeChecking(const Position& pos,
00447                                       const std::string& name, const std::string& dir) {
00448     NBNode* ret = 0;
00449     if (name == "" && (pos.x() == SUMOXML_INVALID_POSITION || pos.y() == SUMOXML_INVALID_POSITION)) {
00450         WRITE_ERROR("Neither the name nor the position of the " + dir + "-node is given for edge '" + myCurrentID + "'.");
00451         return ret;
00452     }
00453     if (name != "") {
00454         if (pos.x() != SUMOXML_INVALID_POSITION && pos.y() != SUMOXML_INVALID_POSITION) {
00455             // the node is named and it has a position given
00456             if (!myNodeCont.insert(name, pos)) {
00457                 WRITE_ERROR("Position of " + dir + "-node '" + name + "' mismatches previous positions.");
00458                 return 0;
00459             }
00460         }
00461         // the node is given by its name
00462         ret = myNodeCont.retrieve(name);
00463         if (ret == 0) {
00464             WRITE_ERROR("Edge's '" + myCurrentID + "' " + dir + "-node '" + name + "' is not known.");
00465         }
00466     } else {
00467         ret = myNodeCont.retrieve(pos);
00468         if (ret == 0) {
00469             ret = new NBNode(myNodeCont.getFreeID(), pos);
00470             if (!myNodeCont.insert(ret)) {
00471                 WRITE_ERROR("Could not insert " + dir + "-node at position " + toString(pos) + ".");
00472                 delete ret;
00473                 return 0;
00474             }
00475         }
00476     }
00477     return ret;
00478 }
00479 
00480 
00481 PositionVector
00482 NIXMLEdgesHandler::tryGetShape(const SUMOSAXAttributes& attrs) {
00483     if (!attrs.hasAttribute(SUMO_ATTR_SHAPE)) {
00484         return myShape;
00485     }
00486     // try to build shape
00487     bool ok = true;
00488     std::string shpdef = attrs.getOptStringReporting(SUMO_ATTR_SHAPE, 0, ok, "");
00489     if (shpdef == "") {
00490         return PositionVector();
00491     }
00492     PositionVector shape = GeomConvHelper::parseShapeReporting(shpdef, attrs.getObjectType(), 0, ok, true);
00493     if (!NILoader::transformCoordinates(shape)) {
00494         WRITE_ERROR("Unable to project coordinates for edge '" + myCurrentID + "'.");
00495     }
00496     return shape;
00497 }
00498 
00499 
00500 LaneSpreadFunction
00501 NIXMLEdgesHandler::tryGetLaneSpread(const SUMOSAXAttributes& attrs) {
00502     bool ok = true;
00503     LaneSpreadFunction result = myLanesSpread;
00504     std::string lsfS = toString(result);
00505     if (attrs.hasAttribute(SUMO_ATTR_SPREADFUNC__DEPRECATED)) {
00506         lsfS = attrs.getStringReporting(SUMO_ATTR_SPREADFUNC__DEPRECATED, myCurrentID.c_str(), ok);
00507         if (!myHaveWarnedAboutDeprecatedSpreadType) {
00508             WRITE_WARNING("'" + toString(SUMO_ATTR_SPREADFUNC__DEPRECATED) + " is deprecated; please use '" + toString(SUMO_ATTR_SPREADTYPE) + "'.");
00509             myHaveWarnedAboutDeprecatedSpreadType = true;
00510         }
00511     } else {
00512         lsfS = attrs.getOptStringReporting(SUMO_ATTR_SPREADTYPE, myCurrentID.c_str(), ok, lsfS);
00513     }
00514     if (SUMOXMLDefinitions::LaneSpreadFunctions.hasString(lsfS)) {
00515         result = SUMOXMLDefinitions::LaneSpreadFunctions.get(lsfS);
00516     } else {
00517         WRITE_WARNING("Ignoring unknown spreadType '" + lsfS + "' for edge '" + myCurrentID + "'.");
00518     }
00519     return result;
00520 }
00521 
00522 
00523 void
00524 NIXMLEdgesHandler::deleteEdge(const SUMOSAXAttributes& attrs) {
00525     bool ok = true;
00526     myCurrentID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok);
00527     if (!ok) {
00528         return;
00529     }
00530     NBEdge* edge = myEdgeCont.retrieve(myCurrentID);
00531     if (edge == 0) {
00532         WRITE_WARNING("Ignoring tag '" + toString(SUMO_TAG_DELETE) + "' for unknown edge '" +
00533                       myCurrentID + "'");
00534         return;
00535     }
00536     myEdgeCont.extract(myDistrictCont, edge, true);
00537 }
00538 
00539 
00540 void
00541 NIXMLEdgesHandler::myEndElement(int element) {
00542     if (element == SUMO_TAG_EDGE && myCurrentEdge != 0) {
00543         if (!myIsUpdate) {
00544             try {
00545                 if (!myEdgeCont.insert(myCurrentEdge)) {
00546                     WRITE_ERROR("Duplicate edge occured. ID='" + myCurrentID + "'");
00547                     delete myCurrentEdge;
00548                 }
00549             } catch (InvalidArgument& e) {
00550                 WRITE_ERROR(e.what());
00551                 throw;
00552             } catch (...) {
00553                 WRITE_ERROR("An important information is missing in edge '" + myCurrentID + "'.");
00554             }
00555         }
00556         if (mySplits.size() != 0) {
00557             std::vector<Split>::iterator i;
00558             NBEdge* e = myCurrentEdge;
00559             SUMOReal length = e->getLength();
00560             sort(mySplits.begin(), mySplits.end(), split_sorter());
00561             unsigned int noLanesMax = e->getNumLanes();
00562             // compute the node positions and sort the lanes
00563             for (i = mySplits.begin(); i != mySplits.end(); ++i) {
00564                 (*i).gpos = e->getGeometry().positionAtLengthPosition((*i).pos);
00565                 sort((*i).lanes.begin(), (*i).lanes.end());
00566                 noLanesMax = MAX2(noLanesMax, (unsigned int)(*i).lanes.size());
00567             }
00568             // split the edge
00569             std::vector<int> currLanes;
00570             for (unsigned int l = 0; l < e->getNumLanes(); ++l) {
00571                 currLanes.push_back(l);
00572             }
00573             std::string edgeid = e->getID();
00574             SUMOReal seen = 0;
00575             for (i = mySplits.begin(); i != mySplits.end(); ++i) {
00576                 const Split& exp = *i;
00577                 assert(exp.lanes.size() != 0);
00578                 if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) {
00579                     std::string nid = edgeid + "." +  toString(exp.nameid);
00580                     NBNode* rn = new NBNode(nid, exp.gpos);
00581                     if (myNodeCont.insert(rn)) {
00582                         //  split the edge
00583                         std::string nid = myCurrentID + "." +  toString(exp.nameid);
00584                         std::string pid = e->getID();
00585                         myEdgeCont.splitAt(myDistrictCont, e, exp.pos - seen, rn,
00586                                            pid, nid, e->getNumLanes(), (unsigned int) exp.lanes.size());
00587                         seen = exp.pos;
00588                         std::vector<int> newLanes = exp.lanes;
00589                         NBEdge* pe = myEdgeCont.retrieve(pid);
00590                         NBEdge* ne = myEdgeCont.retrieve(nid);
00591                         // reconnect lanes
00592                         pe->invalidateConnections(true);
00593                         //  new on right
00594                         unsigned int rightMostP = currLanes[0];
00595                         unsigned int rightMostN = newLanes[0];
00596                         for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) {
00597                             pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true);
00598                         }
00599                         //  new on left
00600                         unsigned int leftMostP = currLanes.back();
00601                         unsigned int leftMostN = newLanes.back();
00602                         for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) {
00603                             pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true);
00604                         }
00605                         //  all other connected
00606                         for (unsigned int l = 0; l < noLanesMax; ++l) {
00607                             if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) {
00608                                 continue;
00609                             }
00610                             if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) {
00611                                 continue;
00612                             }
00613                             pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true);
00614                         }
00615                         // move to next
00616                         e = ne;
00617                         currLanes = newLanes;
00618                     } else {
00619                         WRITE_WARNING("Error on parsing a split (edge '" + myCurrentID + "').");
00620                     }
00621                 }  else if (exp.pos == 0) {
00622                     if (e->getNumLanes() < exp.lanes.size()) {
00623                         e->incLaneNo((int) exp.lanes.size() - e->getNumLanes());
00624                     } else {
00625                         e->decLaneNo(e->getNumLanes() - (int) exp.lanes.size());
00626                     }
00627                     currLanes = exp.lanes;
00628                 } else {
00629                     WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + myCurrentID + "').");
00630                 }
00631             }
00632             // patch lane offsets
00633             e = myEdgeCont.retrieve(edgeid);
00634             i = mySplits.begin();
00635             if ((*i).pos != 0) {
00636                 e = e->getToNode()->getOutgoingEdges()[0];
00637             }
00638             for (; i != mySplits.end(); ++i) {
00639                 unsigned int maxLeft = (*i).lanes.back();
00640                 if (maxLeft < noLanesMax) {
00641                     PositionVector g = e->getGeometry();
00642                     g.move2side(SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft));
00643                     e->setGeometry(g);
00644                 }
00645                 if (e->getToNode()->getOutgoingEdges().size() != 0) {
00646                     e = e->getToNode()->getOutgoingEdges()[0];
00647                 }
00648             }
00649         }
00650     }
00651 }
00652 
00653 /****************************************************************************/
00654 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines