|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00011 // Importer for networks stored in ArcView-shape format 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 <utils/common/MsgHandler.h> 00037 #include <utils/common/ToString.h> 00038 #include <utils/common/TplConvert.h> 00039 #include <utils/common/StringUtils.h> 00040 #include <utils/options/OptionsCont.h> 00041 #include <utils/geom/GeomHelper.h> 00042 #include <netbuild/NBNetBuilder.h> 00043 #include <netbuild/NBHelpers.h> 00044 #include <netbuild/NBEdge.h> 00045 #include <netbuild/NBEdgeCont.h> 00046 #include <netbuild/NBTypeCont.h> 00047 #include <netbuild/NBNode.h> 00048 #include <netbuild/NBNodeCont.h> 00049 #include <netimport/NINavTeqHelper.h> 00050 #include <utils/geom/GeoConvHelper.h> 00051 #include <utils/common/FileHelpers.h> 00052 #include "NILoader.h" 00053 #include "NIImporter_ArcView.h" 00054 00055 #ifdef HAVE_GDAL 00056 #include <ogrsf_frmts.h> 00057 #endif 00058 00059 #ifdef CHECK_MEMORY_LEAKS 00060 #include <foreign/nvwa/debug_new.h> 00061 #endif // CHECK_MEMORY_LEAKS 00062 00063 00064 // =========================================================================== 00065 // method definitions 00066 // =========================================================================== 00067 // --------------------------------------------------------------------------- 00068 // static methods (interface in this case) 00069 // --------------------------------------------------------------------------- 00070 void 00071 NIImporter_ArcView::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { 00072 if (!oc.isSet("shapefile-prefix")) { 00073 return; 00074 } 00075 // check whether the correct set of entries is given 00076 // and compute both file names 00077 std::string dbf_file = oc.getString("shapefile-prefix") + ".dbf"; 00078 std::string shp_file = oc.getString("shapefile-prefix") + ".shp"; 00079 std::string shx_file = oc.getString("shapefile-prefix") + ".shx"; 00080 // check whether the files do exist 00081 if (!FileHelpers::exists(dbf_file)) { 00082 WRITE_ERROR("File not found: " + dbf_file); 00083 } 00084 if (!FileHelpers::exists(shp_file)) { 00085 WRITE_ERROR("File not found: " + shp_file); 00086 } 00087 if (!FileHelpers::exists(shx_file)) { 00088 WRITE_ERROR("File not found: " + shx_file); 00089 } 00090 if (MsgHandler::getErrorInstance()->wasInformed()) { 00091 return; 00092 } 00093 // load the arcview files 00094 NIImporter_ArcView loader(oc, 00095 nb.getNodeCont(), nb.getEdgeCont(), nb.getTypeCont(), 00096 dbf_file, shp_file, oc.getBool("speed-in-kmh")); 00097 loader.load(); 00098 } 00099 00100 00101 00102 // --------------------------------------------------------------------------- 00103 // loader methods 00104 // --------------------------------------------------------------------------- 00105 NIImporter_ArcView::NIImporter_ArcView(const OptionsCont& oc, 00106 NBNodeCont& nc, 00107 NBEdgeCont& ec, 00108 NBTypeCont& tc, 00109 const std::string& dbf_name, 00110 const std::string& shp_name, 00111 bool speedInKMH) 00112 : myOptions(oc), mySHPName(shp_name), 00113 myNameAddition(0), 00114 myNodeCont(nc), myEdgeCont(ec), myTypeCont(tc), 00115 mySpeedInKMH(speedInKMH), 00116 myRunningNodeID(0) { 00117 UNUSED_PARAMETER(dbf_name); 00118 } 00119 00120 00121 NIImporter_ArcView::~NIImporter_ArcView() {} 00122 00123 00124 void 00125 NIImporter_ArcView::load() { 00126 #ifdef HAVE_GDAL 00127 PROGRESS_BEGIN_MESSAGE("Loading data from '" + mySHPName + "'"); 00128 OGRRegisterAll(); 00129 OGRDataSource* poDS = OGRSFDriverRegistrar::Open(mySHPName.c_str(), FALSE); 00130 if (poDS == NULL) { 00131 WRITE_ERROR("Could not open shape description '" + mySHPName + "'."); 00132 return; 00133 } 00134 00135 // begin file parsing 00136 OGRLayer* poLayer = poDS->GetLayer(0); 00137 poLayer->ResetReading(); 00138 00139 // build coordinate transformation 00140 OGRSpatialReference* origTransf = poLayer->GetSpatialRef(); 00141 OGRSpatialReference destTransf; 00142 // use wgs84 as destination 00143 destTransf.SetWellKnownGeogCS("WGS84"); 00144 OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(origTransf, &destTransf); 00145 if (poCT == NULL) { 00146 if (myOptions.isSet("shapefile.guess-projection")) { 00147 OGRSpatialReference origTransf2; 00148 origTransf2.SetWellKnownGeogCS("WGS84"); 00149 poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf); 00150 } 00151 if (poCT == 0) { 00152 WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed."); 00153 } 00154 } 00155 00156 OGRFeature* poFeature; 00157 poLayer->ResetReading(); 00158 while ((poFeature = poLayer->GetNextFeature()) != NULL) { 00159 // read in edge attributes 00160 std::string id = 00161 myOptions.isSet("shapefile.street-id") 00162 ? poFeature->GetFieldAsString((char*)(myOptions.getString("shapefile.street-id").c_str())) 00163 : poFeature->GetFieldAsString("LINK_ID"); 00164 id = StringUtils::prune(id); 00165 if (id == "") { 00166 WRITE_ERROR("Could not obtain edge id."); 00167 return; 00168 } 00169 std::string name = 00170 myOptions.isSet("shapefile.street-id") 00171 ? poFeature->GetFieldAsString((char*) myOptions.getString("shapefile.street-id").c_str()) 00172 : poFeature->GetFieldAsString("ST_NAME"); 00173 name = StringUtils::prune(StringUtils::replace(name, "&", "&")); 00174 00175 std::string from_node = 00176 myOptions.isSet("shapefile.from-id") 00177 ? poFeature->GetFieldAsString((char*)(myOptions.getString("shapefile.from-id").c_str())) 00178 : poFeature->GetFieldAsString("REF_IN_ID"); 00179 from_node = StringUtils::prune(from_node); 00180 std::string to_node = 00181 myOptions.isSet("shapefile.to-id") 00182 ? poFeature->GetFieldAsString((char*) myOptions.getString("shapefile.to-id").c_str()) 00183 : poFeature->GetFieldAsString("NREF_IN_ID"); 00184 to_node = StringUtils::prune(to_node); 00185 if (from_node == "" || to_node == "") { 00186 from_node = toString(myRunningNodeID++); 00187 to_node = toString(myRunningNodeID++); 00188 } 00189 00190 std::string type; 00191 if (myOptions.isSet("shapefile.type-id") && poFeature->GetFieldIndex(myOptions.getString("shapefile.type-id").c_str())>=0) { 00192 type = poFeature->GetFieldAsString(myOptions.getString("shapefile.type-id").c_str()); 00193 } else if(poFeature->GetFieldIndex("ST_TYP_AFT")>=0) { 00194 type = poFeature->GetFieldAsString("ST_TYP_AFT"); 00195 } 00196 SUMOReal width = myTypeCont.getWidth(type); 00197 SUMOReal speed = getSpeed(*poFeature, id); 00198 unsigned int nolanes = getLaneNo(*poFeature, id, speed); 00199 int priority = getPriority(*poFeature, id); 00200 if (nolanes == 0 || speed == 0) { 00201 if (myOptions.getBool("shapefile.use-defaults-on-failure")) { 00202 nolanes = myTypeCont.getNumLanes(""); 00203 speed = myTypeCont.getSpeed(""); 00204 } else { 00205 OGRFeature::DestroyFeature(poFeature); 00206 WRITE_ERROR("The description seems to be invalid. Please recheck usage of types."); 00207 return; 00208 } 00209 } 00210 if (mySpeedInKMH) { 00211 speed = speed / (SUMOReal) 3.6; 00212 } 00213 00214 00215 // read in the geometry 00216 OGRGeometry* poGeometry = poFeature->GetGeometryRef(); 00217 OGRwkbGeometryType gtype = poGeometry->getGeometryType(); 00218 assert(gtype == wkbLineString); 00219 OGRLineString* cgeom = (OGRLineString*) poGeometry; 00220 if (poCT != 0) { 00221 // try transform to wgs84 00222 cgeom->transform(poCT); 00223 } 00224 00225 PositionVector shape; 00226 for (int j = 0; j < cgeom->getNumPoints(); j++) { 00227 Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j)); 00228 if (!NILoader::transformCoordinates(pos)) { 00229 WRITE_WARNING("Unable to project coordinates for edge '" + id + "'."); 00230 } 00231 shape.push_back_noDoublePos(pos); 00232 } 00233 00234 // build from-node 00235 NBNode* from = myNodeCont.retrieve(from_node); 00236 if (from == 0) { 00237 Position from_pos = shape[0]; 00238 from = myNodeCont.retrieve(from_pos); 00239 if (from == 0) { 00240 from = new NBNode(from_node, from_pos); 00241 if (!myNodeCont.insert(from)) { 00242 WRITE_ERROR("Node '" + from_node + "' could not be added"); 00243 delete from; 00244 continue; 00245 } 00246 } 00247 } 00248 // build to-node 00249 NBNode* to = myNodeCont.retrieve(to_node); 00250 if (to == 0) { 00251 Position to_pos = shape[-1]; 00252 to = myNodeCont.retrieve(to_pos); 00253 if (to == 0) { 00254 to = new NBNode(to_node, to_pos); 00255 if (!myNodeCont.insert(to)) { 00256 WRITE_ERROR("Node '" + to_node + "' could not be added"); 00257 delete to; 00258 continue; 00259 } 00260 } 00261 } 00262 00263 if (from == to) { 00264 WRITE_WARNING("Edge '" + id + "' connects identical nodes, skipping."); 00265 continue; 00266 } 00267 00268 // retrieve the information whether the street is bi-directional 00269 std::string dir; 00270 int index = poFeature->GetDefnRef()->GetFieldIndex("DIR_TRAVEL"); 00271 if (index >= 0 && poFeature->IsFieldSet(index)) { 00272 dir = poFeature->GetFieldAsString(index); 00273 } 00274 // add positive direction if wanted 00275 if (dir == "B" || dir == "F" || dir == "" || myOptions.getBool("shapefile.all-bidirectional")) { 00276 if (myEdgeCont.retrieve(id) == 0) { 00277 LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LANESPREAD_RIGHT : LANESPREAD_CENTER; 00278 NBEdge* edge = new NBEdge(id, from, to, type, speed, nolanes, priority, width, -1, shape, "", spread); 00279 myEdgeCont.insert(edge); 00280 checkSpread(edge); 00281 } 00282 } 00283 // add negative direction if wanted 00284 if (dir == "B" || dir == "T" || myOptions.getBool("shapefile.all-bidirectional")) { 00285 id = "-" + id; 00286 if (myEdgeCont.retrieve(id) == 0) { 00287 LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LANESPREAD_RIGHT : LANESPREAD_CENTER; 00288 NBEdge* edge = new NBEdge(id, to, from, type, speed, nolanes, priority, width, -1, shape.reverse(), "", spread); 00289 myEdgeCont.insert(edge); 00290 checkSpread(edge); 00291 } 00292 } 00293 // 00294 OGRFeature::DestroyFeature(poFeature); 00295 } 00296 PROGRESS_DONE_MESSAGE(); 00297 #else 00298 WRITE_ERROR("SUMO was compiled without GDAL support."); 00299 #endif 00300 } 00301 00302 #ifdef HAVE_GDAL 00303 SUMOReal 00304 NIImporter_ArcView::getSpeed(OGRFeature& poFeature, const std::string& edgeid) { 00305 if (myOptions.isSet("shapefile.type-id")) { 00306 return myTypeCont.getSpeed(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str()))); 00307 } 00308 // try to get definitions as to be found in SUMO-XML-definitions 00309 // idea by John Michael Calandrino 00310 int index = poFeature.GetDefnRef()->GetFieldIndex("speed"); 00311 if (index >= 0 && poFeature.IsFieldSet(index)) { 00312 return (SUMOReal) poFeature.GetFieldAsDouble(index); 00313 } 00314 index = poFeature.GetDefnRef()->GetFieldIndex("SPEED"); 00315 if (index >= 0 && poFeature.IsFieldSet(index)) { 00316 return (SUMOReal) poFeature.GetFieldAsDouble(index); 00317 } 00318 // try to get the NavTech-information 00319 index = poFeature.GetDefnRef()->GetFieldIndex("SPEED_CAT"); 00320 if (index >= 0 && poFeature.IsFieldSet(index)) { 00321 std::string def = poFeature.GetFieldAsString(index); 00322 return NINavTeqHelper::getSpeed(edgeid, def); 00323 } 00324 return -1; 00325 } 00326 00327 00328 unsigned int 00329 NIImporter_ArcView::getLaneNo(OGRFeature& poFeature, const std::string& edgeid, 00330 SUMOReal speed) { 00331 if (myOptions.isSet("shapefile.type-id")) { 00332 return (unsigned int) myTypeCont.getNumLanes(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str()))); 00333 } 00334 // try to get definitions as to be found in SUMO-XML-definitions 00335 // idea by John Michael Calandrino 00336 int index = poFeature.GetDefnRef()->GetFieldIndex("nolanes"); 00337 if (index >= 0 && poFeature.IsFieldSet(index)) { 00338 return (unsigned int) poFeature.GetFieldAsInteger(index); 00339 } 00340 index = poFeature.GetDefnRef()->GetFieldIndex("NOLANES"); 00341 if (index >= 0 && poFeature.IsFieldSet(index)) { 00342 return (unsigned int) poFeature.GetFieldAsInteger(index); 00343 } 00344 index = poFeature.GetDefnRef()->GetFieldIndex("rnol"); 00345 if (index >= 0 && poFeature.IsFieldSet(index)) { 00346 return (unsigned int) poFeature.GetFieldAsInteger(index); 00347 } 00348 index = poFeature.GetDefnRef()->GetFieldIndex("LANE_CAT"); 00349 if (index >= 0 && poFeature.IsFieldSet(index)) { 00350 std::string def = poFeature.GetFieldAsString(index); 00351 return NINavTeqHelper::getLaneNumber(edgeid, def, speed); 00352 } 00353 return 0; 00354 } 00355 00356 00357 int 00358 NIImporter_ArcView::getPriority(OGRFeature& poFeature, const std::string& /*edgeid*/) { 00359 if (myOptions.isSet("shapefile.type-id")) { 00360 return myTypeCont.getPriority(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str()))); 00361 } 00362 // try to get definitions as to be found in SUMO-XML-definitions 00363 // idea by John Michael Calandrino 00364 int index = poFeature.GetDefnRef()->GetFieldIndex("priority"); 00365 if (index >= 0 && poFeature.IsFieldSet(index)) { 00366 return poFeature.GetFieldAsInteger(index); 00367 } 00368 index = poFeature.GetDefnRef()->GetFieldIndex("PRIORITY"); 00369 if (index >= 0 && poFeature.IsFieldSet(index)) { 00370 return poFeature.GetFieldAsInteger(index); 00371 } 00372 // try to determine priority from NavTechs FUNC_CLASS attribute 00373 index = poFeature.GetDefnRef()->GetFieldIndex("FUNC_CLASS"); 00374 if (index >= 0 && poFeature.IsFieldSet(index)) { 00375 return poFeature.GetFieldAsInteger(index); 00376 } 00377 return 0; 00378 } 00379 00380 void 00381 NIImporter_ArcView::checkSpread(NBEdge* e) { 00382 NBEdge* ret = e->getToNode()->getConnectionTo(e->getFromNode()); 00383 if (ret != 0) { 00384 e->setLaneSpreadFunction(LANESPREAD_RIGHT); 00385 ret->setLaneSpreadFunction(LANESPREAD_RIGHT); 00386 } 00387 } 00388 00389 00390 #endif 00391 00392 00393 00394 /****************************************************************************/ 00395