SUMO - Simulation of Urban MObility

NIXMLEdgesHandler.cpp

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