SUMO - Simulation of Urban MObility

NIImporter_ArcView.cpp

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