|
SUMO - Simulation of Urban MObility
|
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