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