osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00020 #include <osgEarth/Registry>
00021 #include <osgEarth/FileUtils>
00022 #include <osgEarthFeatures/FeatureSource>
00023 #include <osgEarthFeatures/Filter>
00024 #include <osgEarthFeatures/BufferFilter>
00025 #include <osgEarthFeatures/ScaleFilter>
00026 #include "OGRFeatureOptions"
00027 #include "FeatureCursorOGR"
00028 #include <osgEarthFeatures/OgrUtils>
00029 #include <osg/Notify>
00030 #include <osgDB/FileNameUtils>
00031 #include <osgDB/FileUtils>
00032 #include <list>
00033 #include <ogr_api.h>
00034 
00035 #define LC "[OGR FeatureSource] "
00036 
00037 using namespace osgEarth;
00038 using namespace osgEarth::Features;
00039 using namespace osgEarth::Drivers;
00040 
00041 #define OGR_SCOPED_LOCK GDAL_SCOPED_LOCK
00042 
00048 class OGRFeatureSource : public FeatureSource
00049 {
00050 public:
00051     OGRFeatureSource( const OGRFeatureOptions& options ) : FeatureSource( options ),
00052       _dsHandle( 0L ),
00053       _layerHandle( 0L ),
00054       _ogrDriverHandle( 0L ),
00055       _options( options ),
00056       _featureCount(-1),
00057       _needsSync(false),
00058       _writable(false)
00059     {
00060         _geometry = 
00061             _options.geometry().valid() ? _options.geometry().get() :
00062             _options.geometryConfig().isSet() ? parseGeometry( *_options.geometryConfig() ) :
00063             _options.geometryUrl().isSet() ? parseGeometryUrl( *_options.geometryUrl() ) :
00064             0L;
00065     }
00066 
00068     virtual ~OGRFeatureSource()
00069     {       
00070         OGR_SCOPED_LOCK;
00071 
00072         if ( _layerHandle )
00073         {
00074             if (_needsSync)
00075             {
00076                 OGR_L_SyncToDisk( _layerHandle ); // for writing only
00077                 const char* name = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle ) );
00078                 std::stringstream buf;
00079                 buf << "REPACK " << name; 
00080                 std::string bufStr;
00081                 bufStr = buf.str();
00082                 OGR_DS_ExecuteSQL( _dsHandle, bufStr.c_str(), 0L, 0L );
00083             }
00084             _layerHandle = 0L;
00085         }
00086 
00087         if ( _dsHandle )
00088         {
00089             OGRReleaseDataSource( _dsHandle );
00090             _dsHandle = 0L;
00091         }
00092     }
00093 
00094     //override
00095     void initialize( const std::string& referenceURI )
00096     {
00097         if ( _options.url().isSet() )
00098         {
00099             _source = osgEarth::getFullPath( referenceURI, _options.url()->full() );
00100         }
00101         else if ( _options.connection().isSet() )
00102         {
00103             _source = _options.connection().value();
00104         }
00105     }
00106 
00109     const FeatureProfile* createFeatureProfile()
00110     {
00111         FeatureProfile* result = 0L;
00112 
00113         // see if we have a custom profile.
00114         osg::ref_ptr<const Profile> profile;
00115         if ( _options.profile().isSet() )
00116         {
00117             profile = Profile::create( *_options.profile() );
00118         }
00119 
00120         if ( _geometry.valid() )
00121         {
00122             // if the user specified explicit geometry/profile, use that:
00123             GeoExtent ex;
00124             if ( profile.valid() )
00125             {
00126                 ex = profile->getExtent();
00127             }
00128 
00129             if ( !ex.isValid() )
00130             {
00131                 // default to WGS84 Lat/Long
00132                 ex = osgEarth::Registry::instance()->getGlobalGeodeticProfile()->getExtent();
00133             }
00134             result = new FeatureProfile( ex );
00135         }
00136 
00137         else if ( !_source.empty() )
00138         {
00139             // otherwise, assume we're loading from the URL:
00140             OGR_SCOPED_LOCK;
00141 
00142             // load up the driver, defaulting to shapefile if unspecified.
00143             std::string driverName = _options.ogrDriver().value();
00144             if ( driverName.empty() )
00145                 driverName = "ESRI Shapefile";
00146             _ogrDriverHandle = OGRGetDriverByName( driverName.c_str() );
00147 
00148             // attempt to open the dataset:
00149             int openMode = _options.openWrite().isSet() && _options.openWrite().value() ? 1 : 0;
00150 
00151                 _dsHandle = OGROpenShared( _source.c_str(), openMode, &_ogrDriverHandle );
00152                 if ( _dsHandle )
00153                 {
00154                 if (openMode == 1) _writable = true;
00155 
00156                         _layerHandle = OGR_DS_GetLayer( _dsHandle, 0 ); // default to layer 0 for now
00157                 if ( _layerHandle )
00158                 {                    
00159                     GeoExtent extent;
00160 
00161                     // if the user provided a profile, user that:
00162                     if ( profile.valid() )
00163                     {
00164                         result = new FeatureProfile( profile->getExtent() );
00165                     }
00166 
00167                     else
00168                     {
00169                         // extract the SRS and Extent:                
00170                         OGRSpatialReferenceH srHandle = OGR_L_GetSpatialRef( _layerHandle );
00171                         if ( srHandle )
00172                         {
00173                             osg::ref_ptr<SpatialReference> srs = SpatialReference::createFromHandle( srHandle, false );
00174                             if ( srs.valid() )
00175                             {
00176                                 // extract the full extent of the layer:
00177                                 OGREnvelope env;
00178                                 if ( OGR_L_GetExtent( _layerHandle, &env, 1 ) == OGRERR_NONE )
00179                                 {
00180                                     GeoExtent extent( srs.get(), env.MinX, env.MinY, env.MaxX, env.MaxY );
00181                                     
00182                                     // got enough info to make the profile!
00183                                     result = new FeatureProfile( extent );
00184                                 }
00185                             }
00186                         }
00187                     }
00188 
00189                     // assuming we successfully opened the layer, build a spatial index if requested.
00190                     if ( _options.buildSpatialIndex() == true )
00191                     {
00192                         OE_INFO << LC << "Building spatial index for " << getName() << std::endl;
00193                         std::stringstream buf;
00194                         const char* name = OGR_FD_GetName( OGR_L_GetLayerDefn( _layerHandle ) );
00195                         buf << "CREATE SPATIAL INDEX ON " << name; 
00196                                             std::string bufStr;
00197                                             bufStr = buf.str();
00198                         OGR_DS_ExecuteSQL( _dsHandle, bufStr.c_str(), 0L, 0L );
00199                     }
00200 
00201                     //Get the feature count
00202                     _featureCount = OGR_L_GetFeatureCount( _layerHandle, 1 );
00203 
00204                     initSchema();
00205 
00206                     OGRwkbGeometryType wkbType = OGR_FD_GetGeomType( OGR_L_GetLayerDefn( _layerHandle ) );
00207                     if (
00208                         wkbType == wkbPolygon ||
00209                         wkbType == wkbPolygon25D )
00210                     {
00211                         _geometryType = Geometry::TYPE_POLYGON;
00212                     }
00213                     else if (
00214                         wkbType == wkbLineString ||
00215                         wkbType == wkbLineString25D )
00216                     {
00217                         _geometryType = Geometry::TYPE_LINESTRING;
00218                     }
00219                     else if (
00220                         wkbType == wkbLinearRing )
00221                     {
00222                         _geometryType = Geometry::TYPE_RING;
00223                     }
00224                     else if ( 
00225                         wkbType == wkbPoint ||
00226                         wkbType == wkbPoint25D )
00227                     {
00228                         _geometryType = Geometry::TYPE_POINTSET;
00229                     }
00230                     else if (
00231                         wkbType == wkbGeometryCollection ||
00232                         wkbType == wkbGeometryCollection25D ||
00233                         wkbType == wkbMultiPoint ||
00234                         wkbType == wkbMultiPoint25D ||
00235                         wkbType == wkbMultiLineString ||
00236                         wkbType == wkbMultiLineString25D ||
00237                         wkbType == wkbMultiPolygon ||
00238                         wkbType == wkbMultiPolygon25D )
00239                     {
00240                         _geometryType = Geometry::TYPE_MULTI;
00241                     }
00242                 }
00243                 }
00244             else
00245             {
00246                 OE_INFO << LC << "failed to open dataset \"" << _source << "\"" << std::endl;
00247             }
00248         }
00249         else
00250         {
00251             OE_INFO << LC 
00252                 << "Feature Source: no valid source data available" << std::endl;
00253         }
00254 
00255         return result;
00256     }
00257 
00258 
00259     //override
00260     FeatureCursor* createFeatureCursor( const Symbology::Query& query )
00261     {
00262         if ( _geometry.valid() )
00263         {
00264             return new GeometryFeatureCursor(
00265                 _geometry.get(),
00266                 getFeatureProfile(),
00267                 _options.filters() );
00268                 //getFilters() );
00269         }
00270         else
00271         {
00272             OGR_SCOPED_LOCK;
00273 
00274             // Each cursor requires its own DS handle so that multi-threaded access will work.
00275             // The cursor impl will dispose of the new DS handle.
00276 
00277                 OGRDataSourceH dsHandle = OGROpenShared( _source.c_str(), 0, &_ogrDriverHandle );
00278                 if ( dsHandle )
00279                 {
00280                 OGRLayerH layerHandle = OGR_DS_GetLayer( dsHandle, 0 );
00281 
00282                 return new FeatureCursorOGR( 
00283                     dsHandle,
00284                     layerHandle, 
00285                     getFeatureProfile(),
00286                     query, 
00287                     _options.filters() );
00288             }
00289             else
00290             {
00291                 return 0L;
00292             }
00293         }
00294     }
00295 
00296     virtual bool deleteFeature(FeatureID fid)
00297     {
00298         if (_writable && _layerHandle)
00299         {
00300             if (OGR_L_DeleteFeature( _layerHandle, fid ) == OGRERR_NONE)
00301             {
00302                 _needsSync = true;
00303                 return true;
00304             }            
00305         }
00306         return false;
00307     }
00308 
00309     virtual int getFeatureCount() const
00310     {
00311         return _featureCount;
00312     }
00313 
00314     virtual Feature* getFeature( FeatureID fid )
00315     {
00316         Feature* result = NULL;
00317         OGRFeatureH handle = OGR_L_GetFeature( _layerHandle, fid);
00318         if (handle)
00319         {
00320             result = OgrUtils::createFeature( handle );
00321             OGR_F_Destroy( handle );
00322         }
00323         return result;
00324     }
00325 
00326     virtual bool isWritable() const
00327     {
00328         return _writable;
00329     }
00330 
00331     const FeatureSchema& getSchema() const
00332     {
00333         return _schema;
00334     } 
00335 
00336     virtual bool insertFeature(Feature* feature)
00337     {
00338         OGR_SCOPED_LOCK;
00339         OGRFeatureH feature_handle = OGR_F_Create( OGR_L_GetLayerDefn( _layerHandle ) );
00340         if ( feature_handle )
00341         {
00342             const AttributeTable& attrs = feature->getAttrs();
00343 
00344             // assign the attributes:
00345             int num_fields = OGR_F_GetFieldCount( feature_handle );
00346             for( int i=0; i<num_fields; i++ )
00347             {
00348                 OGRFieldDefnH field_handle_ref = OGR_F_GetFieldDefnRef( feature_handle, i );
00349                 std::string name = OGR_Fld_GetNameRef( field_handle_ref );
00350                 int field_index = OGR_F_GetFieldIndex( feature_handle, name.c_str() );
00351 
00352                 AttributeTable::const_iterator a = attrs.find( toLower(name) );
00353                 if ( a != attrs.end() )
00354                 {
00355                     switch( OGR_Fld_GetType(field_handle_ref) )
00356                     {
00357                     case OFTInteger:
00358                         OGR_F_SetFieldInteger( feature_handle, field_index, a->second.getInt(0) );
00359                         break;
00360                     case OFTReal:
00361                         OGR_F_SetFieldDouble( feature_handle, field_index, a->second.getDouble(0.0) );
00362                         break;
00363                     case OFTString:
00364                         OGR_F_SetFieldString( feature_handle, field_index, a->second.getString().c_str() );
00365                         break;
00366                     }
00367                 }
00368             }
00369 
00370             //    std::string value = feature->getAttr( name );
00371             //    if (!value.empty())
00372             //    {
00373             //        switch( OGR_Fld_GetType( field_handle_ref ) )
00374             //        {
00375             //        case OFTInteger:
00376             //            OGR_F_SetFieldInteger( feature_handle, field_index, as<int>(value, 0) );
00377             //            break;
00378             //        case OFTReal:
00379             //            OGR_F_SetFieldDouble( feature_handle, field_index, as<double>(value, 0.0) );
00380             //            break;
00381             //        case OFTString:
00382             //            OGR_F_SetFieldString( feature_handle, field_index, value.c_str() );
00383             //            break;                    
00384             //        }
00385             //    }
00386             //}
00387 
00388             // assign the geometry:
00389             OGRFeatureDefnH def = ::OGR_L_GetLayerDefn( _layerHandle );
00390 
00391             OGRwkbGeometryType reported_type = OGR_FD_GetGeomType( def );
00392 
00393             OGRGeometryH ogr_geometry = OgrUtils::createOgrGeometry( feature->getGeometry(), reported_type );
00394             if ( OGR_F_SetGeometryDirectly( feature_handle, ogr_geometry ) != OGRERR_NONE )
00395             {
00396                 OE_WARN << LC << "OGR_F_SetGeometryDirectly failed!" << std::endl;
00397             }
00398 
00399             if ( OGR_L_CreateFeature( _layerHandle, feature_handle ) != OGRERR_NONE )
00400             {
00401                 //TODO: handle error better
00402                 OE_WARN << LC << "OGR_L_CreateFeature failed!" << std::endl;
00403                 OGR_F_Destroy( feature_handle );
00404                 return false;
00405             }
00406 
00407             // clean up the feature
00408             OGR_F_Destroy( feature_handle );
00409         }
00410         else
00411         {
00412             //TODO: handle error better
00413             OE_WARN << LC << "OGR_F_Create failed." << std::endl;
00414             return false;
00415         }
00416 
00417         return true;
00418     }
00419 
00420     virtual osgEarth::Symbology::Geometry::Type getGeometryType() const
00421     {
00422         return _geometryType;
00423     }
00424 
00425 protected:
00426 
00427     // parses an explicit WKT geometry string into a Geometry.
00428     Symbology::Geometry* parseGeometry( const Config& geomConf )
00429     {
00430         return OgrUtils::createGeometryFromWKT( geomConf.value() );
00431     }
00432 
00433     // read the WKT geometry from a URL, then parse into a Geometry.
00434     Symbology::Geometry* parseGeometryUrl( const std::string& geomUrl )
00435     {
00436         std::string wkt;
00437         if ( HTTPClient::readString( geomUrl, wkt ) == HTTPClient::RESULT_OK )
00438         {
00439             Config conf( "geometry", wkt );
00440             return parseGeometry( conf );
00441         }
00442         return 0L;
00443     }
00444 
00445     void initSchema()
00446     {
00447         OGRFeatureDefnH layerDef =  OGR_L_GetLayerDefn( _layerHandle );
00448         for (int i = 0; i < OGR_FD_GetFieldCount( layerDef ); i++)
00449         {
00450             OGRFieldDefnH fieldDef = OGR_FD_GetFieldDefn( layerDef, i );
00451             std::string name;
00452             name = std::string( OGR_Fld_GetNameRef( fieldDef ) );
00453             OGRFieldType ogrType = OGR_Fld_GetType( fieldDef );
00454             _schema[ name ] = OgrUtils::getAttributeType( ogrType );
00455         }
00456     }
00457 
00458 
00459 
00460 
00461 
00462 private:
00463     std::string _source;
00464     OGRDataSourceH _dsHandle;
00465     OGRLayerH _layerHandle;
00466     OGRSFDriverH _ogrDriverHandle;
00467     osg::ref_ptr<Symbology::Geometry> _geometry; // explicit geometry.
00468     const OGRFeatureOptions _options;
00469     int _featureCount;
00470     bool _needsSync;
00471     bool _writable;
00472     FeatureSchema _schema;
00473     Geometry::Type _geometryType;
00474 };
00475 
00476 
00477 class OGRFeatureSourceFactory : public FeatureSourceDriver
00478 {
00479 public:
00480     OGRFeatureSourceFactory()
00481     {
00482         supportsExtension( "osgearth_feature_ogr", "OGR feature driver for osgEarth" );
00483     }
00484 
00485     virtual const char* className()
00486     {
00487         return "OGR Feature Reader";
00488     }
00489 
00490     virtual ReadResult readObject(const std::string& file_name, const Options* options) const
00491     {
00492         if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
00493             return ReadResult::FILE_NOT_HANDLED;
00494 
00495         return ReadResult( new OGRFeatureSource( getFeatureSourceOptions(options) ) );
00496     }
00497 };
00498 
00499 REGISTER_OSGPLUGIN(osgearth_feature_ogr, OGRFeatureSourceFactory)
00500 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines