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