SUMO - Simulation of Urban MObility

NIImporter_ArcView.cpp

Go to the documentation of this file.
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, "&", "&amp;"));
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines