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 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