2009-01-28 21:16:31 +01:00
/*****************************************************************************
2011-11-14 04:37:50 +01:00
*
2009-01-28 21:16:31 +01:00
* This file is part of Mapnik ( c + + mapping toolkit )
*
2014-11-20 15:25:50 +01:00
* Copyright ( C ) 2014 Artem Pavlenko
2009-01-28 21:16:31 +01:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-12 00:06:48 +02:00
2009-01-28 21:16:31 +01:00
# include "ogr_datasource.hpp"
# include "ogr_featureset.hpp"
2009-05-12 00:06:48 +02:00
# include "ogr_index_featureset.hpp"
2012-01-18 00:43:01 +01:00
# include <gdal_version.h>
2009-05-12 00:06:48 +02:00
// mapnik
2012-04-08 02:20:56 +02:00
# include <mapnik/debug.hpp>
2012-03-07 19:16:41 +01:00
# include <mapnik/boolean.hpp>
2009-05-12 00:06:48 +02:00
# include <mapnik/geom_util.hpp>
2012-04-08 02:20:56 +02:00
# include <mapnik/timer.hpp>
2013-06-03 06:09:21 +02:00
# include <mapnik/utils.hpp>
2015-02-10 00:46:00 +01:00
# include <mapnik/util/trim.hpp>
2009-01-28 21:16:31 +01:00
2009-03-30 22:19:57 +02:00
// boost
2014-10-22 01:37:27 +02:00
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wunused-local-typedef"
2009-05-12 00:06:48 +02:00
# include <boost/algorithm/string.hpp>
2014-10-22 01:37:27 +02:00
# pragma GCC diagnostic pop
2009-03-30 22:19:57 +02:00
2012-04-08 02:45:01 +02:00
// stl
# include <fstream>
2012-12-07 08:06:12 +01:00
# include <sstream>
2012-04-08 02:45:01 +02:00
# include <stdexcept>
2009-01-28 21:16:31 +01:00
using mapnik : : datasource ;
using mapnik : : parameters ;
DATASOURCE_PLUGIN ( ogr_datasource )
2009-12-16 21:02:06 +01:00
using mapnik : : box2d ;
2009-01-28 21:16:31 +01:00
using mapnik : : coord2d ;
using mapnik : : query ;
using mapnik : : featureset_ptr ;
using mapnik : : layer_descriptor ;
using mapnik : : attribute_descriptor ;
using mapnik : : datasource_exception ;
2009-05-12 00:06:48 +02:00
using mapnik : : filter_in_box ;
using mapnik : : filter_at_point ;
2009-01-28 21:16:31 +01:00
2012-12-17 19:03:07 +01:00
ogr_datasource : : ogr_datasource ( parameters const & params )
2011-11-14 04:37:50 +01:00
: datasource ( params ) ,
extent_ ( ) ,
type_ ( datasource : : Vector ) ,
2014-06-26 11:51:24 +02:00
desc_ ( ogr_datasource : : name ( ) , * params . get < std : : string > ( " encoding " , " utf-8 " ) ) ,
2011-11-14 04:37:50 +01:00
indexed_ ( false )
2009-01-28 21:16:31 +01:00
{
2012-12-17 19:03:07 +01:00
init ( params ) ;
}
ogr_datasource : : ~ ogr_datasource ( )
{
// free layer before destroying the datasource
layer_ . free_layer ( ) ;
2014-06-03 05:25:32 +02:00
# if GDAL_VERSION_MAJOR >= 2
2014-06-03 04:33:49 +02:00
GDALClose ( ( GDALDatasetH ) dataset_ ) ;
# else
2012-12-17 19:03:07 +01:00
OGRDataSource : : DestroyDataSource ( dataset_ ) ;
2014-06-03 04:33:49 +02:00
# endif
2012-12-17 19:03:07 +01:00
}
void ogr_datasource : : init ( mapnik : : parameters const & params )
{
# ifdef MAPNIK_STATS
mapnik : : progress_timer __stats__ ( std : : clog , " ogr_datasource::init " ) ;
# endif
// initialize ogr formats
2014-06-03 04:33:49 +02:00
// NOTE: in GDAL >= 2.0 this is the same as GDALAllRegister()
2012-12-17 19:03:07 +01:00
OGRRegisterAll ( ) ;
2013-05-17 17:24:32 +02:00
2011-10-22 02:27:06 +02:00
boost : : optional < std : : string > file = params . get < std : : string > ( " file " ) ;
boost : : optional < std : : string > string = params . get < std : : string > ( " string " ) ;
2014-08-25 20:59:32 +02:00
if ( ! string ) string = params . get < std : : string > ( " inline " ) ;
2011-10-22 02:27:06 +02:00
if ( ! file & & ! string )
{
throw datasource_exception ( " missing <file> or <string> parameter " ) ;
}
2009-01-28 21:16:31 +01:00
2011-10-22 02:27:06 +02:00
if ( string )
{
2011-11-14 04:37:50 +01:00
dataset_name_ = * string ;
2011-10-22 02:27:06 +02:00
}
else
{
boost : : optional < std : : string > base = params . get < std : : string > ( " base " ) ;
if ( base )
{
dataset_name_ = * base + " / " + * file ;
}
else
{
dataset_name_ = * file ;
}
}
2012-12-17 19:03:07 +01:00
std : : string driver = * params . get < std : : string > ( " driver " , " " ) ;
2011-10-29 00:16:34 +02:00
if ( ! driver . empty ( ) )
{
2014-06-03 05:25:32 +02:00
# if GDAL_VERSION_MAJOR >= 2
2014-06-03 04:33:49 +02:00
unsigned int nOpenFlags = GDAL_OF_READONLY | GDAL_OF_VECTOR ;
2014-06-25 10:01:20 +02:00
const char * papszAllowedDrivers [ ] = { driver . c_str ( ) , nullptr } ;
dataset_ = reinterpret_cast < gdal_dataset_type > ( GDALOpenEx ( dataset_name_ . c_str ( ) , nOpenFlags , papszAllowedDrivers , nullptr , nullptr ) ) ;
2014-06-03 04:33:49 +02:00
# else
2011-10-29 00:16:34 +02:00
OGRSFDriver * ogr_driver = OGRSFDriverRegistrar : : GetRegistrar ( ) - > GetDriverByName ( driver . c_str ( ) ) ;
2013-11-27 16:52:47 +01:00
if ( ogr_driver & & ogr_driver ! = nullptr )
2011-10-29 00:16:34 +02:00
{
2014-06-25 10:01:20 +02:00
dataset_ = ogr_driver - > Open ( ( dataset_name_ ) . c_str ( ) , false ) ;
2011-10-29 00:16:34 +02:00
}
2014-06-03 04:33:49 +02:00
# endif
2011-10-29 00:16:34 +02:00
}
else
{
// open ogr driver
2014-06-03 05:25:32 +02:00
# if GDAL_VERSION_MAJOR >= 2
2014-06-25 10:01:20 +02:00
dataset_ = reinterpret_cast < gdal_dataset_type > ( OGROpen ( dataset_name_ . c_str ( ) , false , nullptr ) ) ;
2014-06-03 05:25:32 +02:00
# else
2014-06-25 10:01:20 +02:00
dataset_ = OGRSFDriverRegistrar : : Open ( dataset_name_ . c_str ( ) , false ) ;
2014-06-03 05:25:32 +02:00
# endif
2011-10-29 00:16:34 +02:00
}
2011-10-22 02:27:06 +02:00
if ( ! dataset_ )
{
const std : : string err = CPLGetLastErrorMsg ( ) ;
if ( err . size ( ) = = 0 )
{
throw datasource_exception ( " OGR Plugin: connection failed: " + dataset_name_ + " was not found or is not a supported format " ) ;
}
else
{
throw datasource_exception ( " OGR Plugin: " + err ) ;
}
}
// initialize layer
2012-12-17 19:03:07 +01:00
boost : : optional < std : : string > layer_by_name = params . get < std : : string > ( " layer " ) ;
2013-10-09 16:32:47 +02:00
boost : : optional < mapnik : : value_integer > layer_by_index = params . get < mapnik : : value_integer > ( " layer_by_index " ) ;
2012-12-17 19:03:07 +01:00
boost : : optional < std : : string > layer_by_sql = params . get < std : : string > ( " layer_by_sql " ) ;
2011-10-24 11:53:33 +02:00
int passed_parameters = 0 ;
passed_parameters + = layer_by_name ? 1 : 0 ;
passed_parameters + = layer_by_index ? 1 : 0 ;
passed_parameters + = layer_by_sql ? 1 : 0 ;
2011-10-22 02:27:06 +02:00
2011-10-24 11:53:33 +02:00
if ( passed_parameters > 1 )
2011-10-22 02:27:06 +02:00
{
2011-10-24 11:53:33 +02:00
throw datasource_exception ( " OGR Plugin: you can only select an ogr layer by name "
" ('layer' parameter), by number ('layer_by_index' parameter), "
" or by sql ('layer_by_sql' parameter), "
" do not supply 2 or more of them at the same time " ) ;
2011-10-22 02:27:06 +02:00
}
if ( layer_by_name )
{
2011-10-24 11:53:33 +02:00
layer_name_ = * layer_by_name ;
2011-10-24 12:05:01 +02:00
layer_ . layer_by_name ( dataset_ , layer_name_ ) ;
2011-10-22 02:27:06 +02:00
}
else if ( layer_by_index )
{
2013-03-19 22:01:48 +01:00
int num_layers = dataset_ - > GetLayerCount ( ) ;
2011-10-22 02:27:06 +02:00
if ( * layer_by_index > = num_layers )
{
2014-04-23 00:31:19 +02:00
std : : ostringstream s ;
s < < " OGR Plugin: only " < < num_layers < < " layer(s) exist, cannot find layer by index ' " < < * layer_by_index < < " ' " ;
2011-10-22 02:27:06 +02:00
throw datasource_exception ( s . str ( ) ) ;
}
2011-10-24 12:05:01 +02:00
layer_ . layer_by_index ( dataset_ , * layer_by_index ) ;
2011-10-24 11:53:33 +02:00
layer_name_ = layer_ . layer_name ( ) ;
}
else if ( layer_by_sql )
{
2012-04-08 02:20:56 +02:00
# ifdef MAPNIK_STATS
2012-12-17 19:03:07 +01:00
mapnik : : progress_timer __stats_sql__ ( std : : clog , " ogr_datasource::init(layer_by_sql) " ) ;
2012-04-08 02:20:56 +02:00
# endif
2011-10-24 12:05:01 +02:00
layer_ . layer_by_sql ( dataset_ , * layer_by_sql ) ;
2011-10-24 11:53:33 +02:00
layer_name_ = layer_ . layer_name ( ) ;
2011-10-22 02:27:06 +02:00
}
else
{
2012-12-07 08:06:12 +01:00
std : : string s ( " OGR Plugin: missing <layer> or <layer_by_index> or <layer_by_sql> parameter, available layers are: " ) ;
2011-10-22 02:27:06 +02:00
unsigned num_layers = dataset_ - > GetLayerCount ( ) ;
bool layer_found = false ;
2012-10-09 22:47:24 +02:00
std : : vector < std : : string > layer_names ;
2011-10-22 02:27:06 +02:00
for ( unsigned i = 0 ; i < num_layers ; + + i )
{
OGRLayer * ogr_layer = dataset_ - > GetLayer ( i ) ;
OGRFeatureDefn * ogr_layer_def = ogr_layer - > GetLayerDefn ( ) ;
if ( ogr_layer_def ! = 0 )
{
layer_found = true ;
2012-10-09 22:47:24 +02:00
layer_names . push_back ( std : : string ( " ' " ) + ogr_layer_def - > GetName ( ) + std : : string ( " ' " ) ) ;
2011-10-22 02:27:06 +02:00
}
}
if ( ! layer_found )
{
2012-12-07 08:06:12 +01:00
s + = " None (no layers were found in dataset) " ;
2011-10-22 02:27:06 +02:00
}
2012-10-09 22:47:24 +02:00
else
{
2012-12-07 08:06:12 +01:00
s + = boost : : algorithm : : join ( layer_names , " , " ) ;
2012-10-09 22:47:24 +02:00
}
2011-10-22 02:27:06 +02:00
2012-12-07 08:06:12 +01:00
throw datasource_exception ( s ) ;
2011-10-22 02:27:06 +02:00
}
2011-10-24 11:53:33 +02:00
if ( ! layer_ . is_valid ( ) )
2011-10-22 02:27:06 +02:00
{
2014-04-23 00:31:19 +02:00
std : : ostringstream s ;
s < < " OGR Plugin: " ;
2011-10-22 02:27:06 +02:00
if ( layer_by_name )
{
2012-03-05 07:28:02 +01:00
s < < " cannot find layer by name ' " < < * layer_by_name ;
2011-10-22 02:27:06 +02:00
}
else if ( layer_by_index )
{
2012-03-05 07:28:02 +01:00
s < < " cannot find layer by index number ' " < < * layer_by_index ;
2011-10-22 02:27:06 +02:00
}
2011-10-24 11:53:33 +02:00
else if ( layer_by_sql )
{
2012-03-05 07:28:02 +01:00
s < < " cannot find layer by sql query ' " < < * layer_by_sql ;
2011-10-24 11:53:33 +02:00
}
2011-10-22 02:27:06 +02:00
2012-03-05 07:28:02 +01:00
s < < " ' in dataset ' " < < dataset_name_ < < " ' " ;
2011-10-22 02:27:06 +02:00
2012-03-05 07:28:02 +01:00
throw datasource_exception ( s . str ( ) ) ;
2011-10-22 02:27:06 +02:00
}
2011-10-24 11:53:33 +02:00
// work with real OGR layer
OGRLayer * layer = layer_ . layer ( ) ;
2011-10-22 02:27:06 +02:00
// initialize envelope
2014-08-12 20:44:34 +02:00
boost : : optional < std : : string > ext = params . get < std : : string > ( " extent " ) ;
if ( ext & & ! ext - > empty ( ) )
{
extent_ . from_string ( * ext ) ;
}
else
{
OGREnvelope envelope ;
2014-08-13 08:09:42 +02:00
OGRErr e = layer - > GetExtent ( & envelope ) ;
if ( e = = OGRERR_FAILURE )
{
2014-08-16 04:48:27 +02:00
if ( layer - > GetFeatureCount ( ) = = 0 )
{
2014-08-19 06:33:18 +02:00
MAPNIK_LOG_ERROR ( ogr ) < < " could not determine extent, layer ' " < < layer - > GetLayerDefn ( ) - > GetName ( ) < < " ' appears to have no features " ;
2014-08-16 04:48:27 +02:00
}
else
{
std : : ostringstream s ;
2014-08-19 06:33:18 +02:00
s < < " OGR Plugin: Cannot determine extent for layer ' " < < layer - > GetLayerDefn ( ) - > GetName ( ) < < " '. Please provide a manual extent string (minx,miny,maxx,maxy). " ;
2014-08-16 04:48:27 +02:00
throw datasource_exception ( s . str ( ) ) ;
}
2014-08-13 08:09:42 +02:00
}
2014-08-12 20:44:34 +02:00
extent_ . init ( envelope . MinX , envelope . MinY , envelope . MaxX , envelope . MaxY ) ;
}
2011-10-22 02:27:06 +02:00
// scan for index file
// TODO - layer names don't match dataset name, so this will break for
// any layer types of ogr than shapefiles, etc
// fix here and in ogrindex
size_t breakpoint = dataset_name_ . find_last_of ( " . " ) ;
if ( breakpoint = = std : : string : : npos )
{
breakpoint = dataset_name_ . length ( ) ;
}
index_name_ = dataset_name_ . substr ( 0 , breakpoint ) + " .ogrindex " ;
2013-06-03 06:09:21 +02:00
# if defined (_WINDOWS)
std : : ifstream index_file ( mapnik : : utf8_to_utf16 ( index_name_ ) , std : : ios : : in | std : : ios : : binary ) ;
# else
2011-10-24 11:53:33 +02:00
std : : ifstream index_file ( index_name_ . c_str ( ) , std : : ios : : in | std : : ios : : binary ) ;
2013-06-03 06:09:21 +02:00
# endif
2011-10-22 02:27:06 +02:00
if ( index_file )
{
indexed_ = true ;
index_file . close ( ) ;
}
#if 0
// TODO - enable this warning once the ogrindex tool is a bit more stable/mature
else
{
2012-04-09 03:00:51 +02:00
MAPNIK_LOG_DEBUG ( ogr ) < < " ogr_datasource: no ogrindex file found for " < < dataset_name_
< < " , use the 'ogrindex' program to build an index for faster rendering " ;
2011-10-22 02:27:06 +02:00
}
# endif
2012-04-08 02:20:56 +02:00
# ifdef MAPNIK_STATS
2012-12-17 19:03:07 +01:00
mapnik : : progress_timer __stats2__ ( std : : clog , " ogr_datasource::init(get_column_description) " ) ;
2012-04-08 02:20:56 +02:00
# endif
2011-10-22 02:27:06 +02:00
// deal with attributes descriptions
2011-10-24 11:53:33 +02:00
OGRFeatureDefn * def = layer - > GetLayerDefn ( ) ;
2011-10-22 02:27:06 +02:00
if ( def ! = 0 )
{
const int fld_count = def - > GetFieldCount ( ) ;
for ( int i = 0 ; i < fld_count ; i + + )
{
OGRFieldDefn * fld = def - > GetFieldDefn ( i ) ;
const std : : string fld_name = fld - > GetNameRef ( ) ;
const OGRFieldType type_oid = fld - > GetType ( ) ;
switch ( type_oid )
{
case OFTInteger :
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : Integer ) ) ;
break ;
case OFTReal :
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : Double ) ) ;
break ;
case OFTString :
case OFTWideString : // deprecated
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : String ) ) ;
break ;
case OFTBinary :
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : Object ) ) ;
break ;
case OFTIntegerList :
case OFTRealList :
case OFTStringList :
case OFTWideStringList : // deprecated !
2012-04-09 03:00:51 +02:00
MAPNIK_LOG_WARN ( ogr ) < < " ogr_datasource: Unhandled type_oid= " < < type_oid ;
2011-10-22 02:27:06 +02:00
break ;
2009-01-28 21:16:31 +01:00
2011-10-22 02:27:06 +02:00
case OFTDate :
case OFTTime :
case OFTDateTime : // unhandled !
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : Object ) ) ;
2012-04-09 12:05:49 +02:00
MAPNIK_LOG_WARN ( ogr ) < < " ogr_datasource: Unhandled type_oid= " < < type_oid ;
2011-10-22 02:27:06 +02:00
break ;
}
}
}
2015-02-10 00:46:00 +01:00
mapnik : : parameters & extra_params = desc_ . get_extra_parameters ( ) ;
OGRSpatialReference * srs_ref = layer - > GetSpatialRef ( ) ;
char * srs_output = NULL ;
if ( srs_ref & & srs_ref - > exportToProj4 ( & srs_output ) = = OGRERR_NONE ) {
extra_params [ " proj4 " ] = mapnik : : util : : trim_copy ( srs_output ) ;
}
CPLFree ( srs_output ) ;
2009-01-28 21:16:31 +01:00
}
2012-07-21 03:34:41 +02:00
const char * ogr_datasource : : name ( )
2009-01-28 21:16:31 +01:00
{
2011-10-22 02:27:06 +02:00
return " ogr " ;
2009-01-28 21:16:31 +01:00
}
2012-01-17 07:09:46 +01:00
mapnik : : datasource : : datasource_t ogr_datasource : : type ( ) const
2009-01-28 21:16:31 +01:00
{
2011-10-22 02:27:06 +02:00
return type_ ;
2009-01-28 21:16:31 +01:00
}
2009-12-16 21:02:06 +01:00
box2d < double > ogr_datasource : : envelope ( ) const
2009-01-28 21:16:31 +01:00
{
2011-10-22 02:27:06 +02:00
return extent_ ;
2009-01-28 21:16:31 +01:00
}
2015-03-24 12:13:31 +01:00
boost : : optional < mapnik : : datasource_geometry_t > ogr_datasource : : get_geometry_type ( ) const
2012-01-17 07:09:46 +01:00
{
2015-03-24 12:13:31 +01:00
boost : : optional < mapnik : : datasource_geometry_t > result ;
2012-01-17 07:09:46 +01:00
if ( dataset_ & & layer_ . is_valid ( ) )
{
OGRLayer * layer = layer_ . layer ( ) ;
// NOTE: wkbFlatten macro in ogr flattens 2.5d types into base 2d type
2012-01-18 00:43:01 +01:00
# if GDAL_VERSION_NUM < 1800
switch ( wkbFlatten ( layer - > GetLayerDefn ( ) - > GetGeomType ( ) ) )
# else
2012-04-08 02:20:56 +02:00
switch ( wkbFlatten ( layer - > GetGeomType ( ) ) )
2012-01-18 00:43:01 +01:00
# endif
2012-02-02 02:37:35 +01:00
{
case wkbPoint :
case wkbMultiPoint :
result . reset ( mapnik : : datasource : : Point ) ;
break ;
case wkbLinearRing :
case wkbLineString :
case wkbMultiLineString :
result . reset ( mapnik : : datasource : : LineString ) ;
break ;
case wkbPolygon :
case wkbMultiPolygon :
result . reset ( mapnik : : datasource : : Polygon ) ;
break ;
case wkbGeometryCollection :
2015-03-24 12:13:31 +01:00
result . reset ( mapnik : : datasource_geometry_t : : Collection ) ;
2012-02-02 02:37:35 +01:00
break ;
case wkbNone :
case wkbUnknown :
2012-01-17 07:09:46 +01:00
{
// fallback to inspecting first actual geometry
// TODO - csv and shapefile inspect first 4 features
if ( dataset_ & & layer_ . is_valid ( ) )
{
2013-01-04 03:00:28 +01:00
layer = layer_ . layer ( ) ;
2012-04-12 22:04:59 +02:00
// only new either reset of setNext
//layer->ResetReading();
layer - > SetNextByIndex ( 0 ) ;
2012-10-21 05:16:17 +02:00
OGRFeature * poFeature ;
2013-11-27 16:52:47 +01:00
while ( ( poFeature = layer - > GetNextFeature ( ) ) ! = nullptr )
2012-01-17 07:09:46 +01:00
{
2012-10-21 05:16:17 +02:00
OGRGeometry * geom = poFeature - > GetGeometryRef ( ) ;
2012-01-17 07:09:46 +01:00
if ( geom & & ! geom - > IsEmpty ( ) )
{
switch ( wkbFlatten ( geom - > getGeometryType ( ) ) )
{
case wkbPoint :
case wkbMultiPoint :
result . reset ( mapnik : : datasource : : Point ) ;
break ;
case wkbLinearRing :
case wkbLineString :
case wkbMultiLineString :
result . reset ( mapnik : : datasource : : LineString ) ;
break ;
case wkbPolygon :
case wkbMultiPolygon :
result . reset ( mapnik : : datasource : : Polygon ) ;
break ;
case wkbGeometryCollection :
2015-03-24 12:13:31 +01:00
result . reset ( mapnik : : datasource_geometry_t : : Collection ) ;
2012-01-17 07:09:46 +01:00
break ;
default :
break ;
}
}
2012-10-21 05:16:17 +02:00
OGRFeature : : DestroyFeature ( poFeature ) ;
break ;
2012-01-17 07:09:46 +01:00
}
}
break ;
}
2012-02-02 02:37:35 +01:00
default :
break ;
}
2012-01-17 07:09:46 +01:00
}
2012-02-02 02:37:35 +01:00
2012-01-17 07:09:46 +01:00
return result ;
}
2009-01-28 21:16:31 +01:00
layer_descriptor ogr_datasource : : get_descriptor ( ) const
{
2011-10-22 02:27:06 +02:00
return desc_ ;
2009-01-28 21:16:31 +01:00
}
2012-01-20 18:29:17 +01:00
void validate_attribute_names ( query const & q , std : : vector < attribute_descriptor > const & names )
2009-01-28 21:16:31 +01:00
{
2012-01-20 18:29:17 +01:00
std : : set < std : : string > const & attribute_names = q . property_names ( ) ;
std : : set < std : : string > : : const_iterator pos = attribute_names . begin ( ) ;
std : : set < std : : string > : : const_iterator end_names = attribute_names . end ( ) ;
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
for ( ; pos ! = end_names ; + + pos )
2011-10-22 02:27:06 +02:00
{
2012-01-20 18:29:17 +01:00
bool found_name = false ;
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
std : : vector < attribute_descriptor > : : const_iterator itr = names . begin ( ) ;
std : : vector < attribute_descriptor > : : const_iterator end = names . end ( ) ;
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
for ( ; itr ! = end ; + + itr )
2012-02-02 02:37:35 +01:00
{
2012-01-20 18:29:17 +01:00
if ( itr - > get_name ( ) = = * pos )
2011-12-05 22:57:00 +01:00
{
2012-02-02 02:37:35 +01:00
found_name = true ;
2012-01-20 18:29:17 +01:00
break ;
2011-12-05 22:57:00 +01:00
}
2012-01-20 18:29:17 +01:00
}
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
if ( ! found_name )
{
2014-04-23 00:31:19 +02:00
std : : ostringstream s ;
s < < " OGR Plugin: no attribute named ' " < < * pos < < " '. Valid attributes are: " ;
2013-01-04 03:00:28 +01:00
std : : vector < attribute_descriptor > : : const_iterator e_itr = names . begin ( ) ;
std : : vector < attribute_descriptor > : : const_iterator e_end = names . end ( ) ;
for ( ; e_itr ! = e_end ; + + e_itr )
2011-12-05 22:57:00 +01:00
{
2013-01-04 03:00:28 +01:00
s < < e_itr - > get_name ( ) < < std : : endl ;
2011-12-05 22:57:00 +01:00
}
2012-01-20 18:29:17 +01:00
throw mapnik : : datasource_exception ( s . str ( ) ) ;
2011-12-05 22:57:00 +01:00
}
2012-01-20 18:29:17 +01:00
}
}
2011-12-05 22:57:00 +01:00
2012-01-20 18:29:17 +01:00
featureset_ptr ogr_datasource : : features ( query const & q ) const
{
2012-04-08 02:20:56 +02:00
# ifdef MAPNIK_STATS
mapnik : : progress_timer __stats__ ( std : : clog , " ogr_datasource::features " ) ;
# endif
2012-01-20 18:29:17 +01:00
if ( dataset_ & & layer_ . is_valid ( ) )
{
2012-02-02 02:37:35 +01:00
// First we validate query fields: https://github.com/mapnik/mapnik/issues/792
2012-01-20 18:29:17 +01:00
std : : vector < attribute_descriptor > const & desc_ar = desc_ . get_descriptors ( ) ;
// feature context (schema)
2013-09-20 15:00:11 +02:00
mapnik : : context_ptr ctx = std : : make_shared < mapnik : : context_type > ( ) ;
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
std : : vector < attribute_descriptor > : : const_iterator itr = desc_ar . begin ( ) ;
std : : vector < attribute_descriptor > : : const_iterator end = desc_ar . end ( ) ;
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
for ( ; itr ! = end ; + + itr ) ctx - > push ( itr - > get_name ( ) ) ; // TODO only push query attributes
2012-02-02 02:37:35 +01:00
validate_attribute_names ( q , desc_ar ) ;
2011-10-24 11:53:33 +02:00
OGRLayer * layer = layer_ . layer ( ) ;
2009-01-28 21:16:31 +01:00
2009-05-12 00:06:48 +02:00
if ( indexed_ )
{
filter_in_box filter ( q . get_bbox ( ) ) ;
2011-11-14 04:37:50 +01:00
2012-01-20 17:07:29 +01:00
return featureset_ptr ( new ogr_index_featureset < filter_in_box > ( ctx ,
2011-10-24 11:53:33 +02:00
* layer ,
2011-10-22 02:27:06 +02:00
filter ,
index_name_ ,
2012-04-09 03:00:51 +02:00
desc_ . get_encoding ( ) ) ) ;
2009-05-12 00:06:48 +02:00
}
else
{
2012-07-21 04:01:09 +02:00
return featureset_ptr ( new ogr_featureset ( ctx ,
2011-10-24 11:53:33 +02:00
* layer ,
2009-05-12 00:06:48 +02:00
q . get_bbox ( ) ,
2012-04-09 03:00:51 +02:00
desc_ . get_encoding ( ) ) ) ;
2009-05-12 00:06:48 +02:00
}
2011-10-22 02:27:06 +02:00
}
2011-10-24 11:53:33 +02:00
2011-10-22 02:27:06 +02:00
return featureset_ptr ( ) ;
2009-01-28 21:16:31 +01:00
}
2012-09-28 15:12:10 +02:00
featureset_ptr ogr_datasource : : features_at_point ( coord2d const & pt , double tol ) const
2009-01-28 21:16:31 +01:00
{
2012-04-08 02:20:56 +02:00
# ifdef MAPNIK_STATS
mapnik : : progress_timer __stats__ ( std : : clog , " ogr_datasource::features_at_point " ) ;
# endif
2011-10-24 11:53:33 +02:00
if ( dataset_ & & layer_ . is_valid ( ) )
2011-10-22 02:27:06 +02:00
{
2012-01-20 18:29:17 +01:00
std : : vector < attribute_descriptor > const & desc_ar = desc_ . get_descriptors ( ) ;
// feature context (schema)
2013-09-20 15:00:11 +02:00
mapnik : : context_ptr ctx = std : : make_shared < mapnik : : context_type > ( ) ;
2012-02-02 02:37:35 +01:00
2012-01-20 18:29:17 +01:00
std : : vector < attribute_descriptor > : : const_iterator itr = desc_ar . begin ( ) ;
std : : vector < attribute_descriptor > : : const_iterator end = desc_ar . end ( ) ;
for ( ; itr ! = end ; + + itr ) ctx - > push ( itr - > get_name ( ) ) ;
2012-02-02 02:37:35 +01:00
2011-10-24 11:53:33 +02:00
OGRLayer * layer = layer_ . layer ( ) ;
2012-02-02 02:37:35 +01:00
2009-05-12 00:06:48 +02:00
if ( indexed_ )
{
2013-05-17 17:24:32 +02:00
filter_at_point filter ( pt , tol ) ;
2012-02-02 02:37:35 +01:00
2012-01-20 17:07:29 +01:00
return featureset_ptr ( new ogr_index_featureset < filter_at_point > ( ctx ,
2011-10-24 11:53:33 +02:00
* layer ,
2009-05-12 00:06:48 +02:00
filter ,
index_name_ ,
2012-04-08 02:20:56 +02:00
desc_ . get_encoding ( ) ) ) ;
2009-05-12 00:06:48 +02:00
}
else
{
2013-05-22 12:07:55 +02:00
mapnik : : box2d < double > bbox ( pt , pt ) ;
bbox . pad ( tol ) ;
2012-01-20 17:07:29 +01:00
return featureset_ptr ( new ogr_featureset ( ctx ,
2011-10-24 11:53:33 +02:00
* layer ,
2013-05-22 12:07:55 +02:00
bbox ,
2012-04-08 02:20:56 +02:00
desc_ . get_encoding ( ) ) ) ;
2009-05-12 00:06:48 +02:00
}
2011-10-22 02:27:06 +02:00
}
2011-10-24 11:53:33 +02:00
2011-10-22 02:27:06 +02:00
return featureset_ptr ( ) ;
2009-01-28 21:16:31 +01:00
}