GDAL库中对于矢量数据的读取中能够设置一些过滤器来对矢量图形进行筛选。对于Shapefile格式来说。假设数据量太大,设置这个过滤器时间慢的简直无法忍受。好在GDAL1.10版本号開始支持读取Shapefile文件的空间索引文件(.sbn / .sbx)来进行加速。以下就相同的数据相同的代码来对GDAL1.9.0和GDAL1.11.0两个版本号进行測试时间,比較下速度(看到结果你肯定会张大嘴巴的~~)。
首先是測试代码,功能非常easy。两个shp文件。一个点文件,一个面文件。面文件非常大。须要依据点文件里的点来查询到相应的面文件里的图形。
在此感谢“午夜风”提供的数据进行測试。图1是使用ArcMap打开两个数据显示的效果,图2是两个数据的数据量以及要素个数。
图1 使用ArcMap打开的效果
图2 两个数据的数据量和要素个数
以下是測试代码,仅仅贴出来关键部分的函数。
void SearchSampleDataFromSHP_liml()
{
const char* pszPoints = "C:\\Users\\LiMinlu\\Desktop\\SHP\\C5Pointnew.shp";
const char* pszPolygs = "C:\\Users\\LiMinlu\\Desktop\\SHP\\C5.shp"; // 注冊驱动以及配置项
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
CPLSetConfigOption("SHAPE_ENCODING","");
OGRRegisterAll(); //打开两个数据
OGRSFDriver* poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("ESRI Shapefile"); OGRDataSource* pPntDS = poDriver->Open(pszPoints, false);
if (pPntDS==NULL)
{
cout<<"打开文件:" <<pszPoints << "失败"<<endl;
return ;
} OGRDataSource* pPlgDS = poDriver->Open(pszPolygs, false);
if (pPlgDS==NULL)
{
cout<<"打开文件:" <<pszPolygs << "失败"<<endl;
return ;
} OGRFeature *pPntFeature = NULL, *pPlgFeature = NULL; OGRLayer* pPntLayer = pPntDS->GetLayer(0);
pPntLayer->ResetReading();
pPntFeature = pPntLayer->GetFeature(0); int nFeildCount = pPntFeature->GetFieldCount();
int nFeatureCount = pPntLayer->GetFeatureCount(); OGRLayer* pPlgLayer = pPlgDS->GetLayer(0);
pPlgLayer->ResetReading();
pPlgFeature = pPlgLayer->GetFeature(0); int nPlgFeildCount = pPlgFeature->GetFieldCount(); for (int i=0;i<nFeatureCount; i++)
{
pPntFeature = pPntLayer->GetFeature(i);
double dValue = pPntFeature->GetFieldAsDouble(nFeildCount-1);
OGRPoint *pPoint = (OGRPoint *)pPntFeature->GetGeometryRef(); //设置面图层的过滤属性
pPlgLayer->ResetReading();
pPlgLayer->SetSpatialFilter((OGRGeometry*)pPoint); pPlgFeature = pPlgLayer->GetNextFeature(); if(pPlgFeature == NULL)
{
OGRFeature::DestroyFeature(pPntFeature);
continue;
} OGRFeature::DestroyFeature(pPntFeature);
OGRFeature::DestroyFeature(pPlgFeature);
} OGRDataSource::DestroyDataSource(pPntDS);
OGRDataSource::DestroyDataSource(pPlgDS);
}
以下是main函数以及输出时间的一个小函数。
void ShowTime()
{
time_t t = time(0);
char tmp[64];
strftime( tmp, sizeof(tmp), "%Y/%m/%d %X", localtime(&t) );
puts( tmp );
} int _tmain(int argc, _TCHAR* argv[])
{
ShowTime();
SearchSampleDataFromSHP_liml();
ShowTime(); system("pause");
return 0;
}
首先来看看使用GDAL1.9.0版本号的时间。处理时间如图3所看到的。(注意。以下測试时间所有使用Release版本号进行測试所得)
图3 使用GDAL1.9.0所用时间
再看看GDAL1.11.0所用的时间,处理时间如图4所看到的。
图4 使用GDAL1.11.0所用时间
由上面两个处理时间能够看到,在GDAL1.11.0版本号处理时间大幅度提高(100倍啊)。所以用到了空间索引这块的同学还是将GDAL的版本号更新一下吧。
我们知道shapefile文件一般必须的是3个文件,后缀名是shp、dbf和shx。假设数据有投影信息的话再加一个prj文件。这样的标准的shp文件是我们经常使用的,使用GDAL创建的话也会生成这么几个文件。可是当用ArcMap打开的时候,会自己主动多出来几个文件。后缀名是sbn和sbx。可能还有个xml文件。如图2所看到的。这两个文件就是ArcMap自己主动生成的空间索引文件(ESRI spatial index files)。
依照GDAL的官方文档说明,眼下GDAL库仅仅支持读取空间索引文件,还不支持创建,所以假设要处理大数据量的shp文件,能够先用ArcMap打开让其创建好空间索引文件再用GDAL处理。
此外GDAL还支持读写UMN MapServer使用的四叉树索引文件(.qix)。
详细能够參考GDAL官网中的Shapefile格式页面(网址是:http://www.gdal.org/drv_shapefile.html)。