GDAL庫中對於矢量數據的讀取中可以設置一些過濾器來對矢量圖形進行篩選,對於Shapefile格式來說,如果數據量太大,設置這個過濾器時間慢的簡直無法忍受。好在GDAL1.10版本開始支持讀取Shapefile文件的空間索引文件(.sbn / .sbx)來進行加速。下面就同樣的數據同樣的代碼來對GDAL1.9.0和GDAL1.11.0兩個版本進行測試時間,比較下速度(看到結果你肯定會張大嘴巴的~~)。
首先是測試代碼,功能很簡單,兩個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)。