GDAL对空间数据的管理

使用GDAL可以很方便的对空间数据进行管理(这里的管理主要是指复制、移动和删除)。有人可能会说这个功能不用GDAL也能很方便的实现,其实不然。很多的空间数据不是由一个单一的文件组成,而是由一些列文件共同组成,相信大家都对Erdas的img格式比较熟悉吧,这种图像格式,对于小图像来说一般常用就只有两个,那就是img和rrd格式,如果对于一个超级大的img格式,那么一个数据可能就会有四个文件组成,后缀名分别是img、ige、rrd、rge。如果对这个数据进行复制的话,你需要写四个复制语句,同样对于矢量数据中最常用Shapfile格式,一个shp文件最少也有有三个文件组成shp、shx、dbf,常用的还有prj等其他的。对于这样的数据进行管理,还是比较繁琐的,好在GDAL中提供了相关的函数,只要一个函数,该文件所有的相关文件都会被进行管理。

下面分别对栅格数据和矢量数据进行说明。主要用到的类就是两个驱动类,GDALDirver(http://www.gdal.org/classGDALDriver.html)和 OGRSFDriver(http://www.gdal.org/ogr/classOGRSFDriver.html)。

一、栅格数据格式 

1、复制数据

用到的函数是CopyFiles,函数原型是:

CPLErr GDALDriver::CopyFiles(const char *pszNewName, const char *pszOldName)	
参数pszNewName是复制后新栅格数据的路径,pszOldName是原始图像数据的路径。比如我要复制一个img文件【C:\Test.img】到【D:\New.img】,可以这样写:

pDriver->CopyFiles("D:\\New.img", "C:\\Test.img");
执行完之后,你会发现,不但把img文件复制过去,同时还把rrd文件复制过去了。 这里还有一点需要说明一下,不要以为img文件找对应的rrd是根据文件名查找的(当然这样大多数情况下是对的),其实在img文件中保存了rrd文件的路径和名称,感兴趣的同学可以看看Erdas的HFA文件格式说明。

2、移动数据

移动数据用到的函数是Rename,函数原型是:

CPLErr GDALDriver::Rename(const char *pszNewName, const char *pszOldName)

参数pszNewName是移动后新栅格数据的路径,pszOldName是原始图像数据的路径。比如我要移动一个img文件从【C:\Test.img】到【D:\New.img】,可以这样写:

pDriver->Rename("D:\\New.img", "C:\\Test.img");
同上,移动后,所有的相关文件都会被移动过去。

3、删除数据

删除数据用到的函数是Delete,函数原型是:

CPLErr GDALDriver::Delete(const char *	pszFilename) 
删除数据只有一个参数,就是要删除的图像的路径,调用该函数后,和该图像依赖的所有的文件均会被删除。

二、矢量数据格式

矢量数据中,OGR库中只提供了删除数据的函数,至于移动和拷贝暂时还没有,不过自己通过OGRDataSource实现一个也不是很难,下面就只对删除数据的接口做一个说明。

删除数据用到的函数是DeleteDataSource,函数原型是:

OGRErr OGRSFDriver::DeleteDataSource(const char * pszDataSource ) 
参数依旧是矢量数据的路径。没什么好说的。

下面是我根据上面的函数写的几个我自己常用的函数,用来删除数据的,希望对大家有用。函数的说明以及参数都在注视里面,后面就不多说了。

头文件:

	/**
	* @brief 判断该文件是否为图像数据
	* @param strFileName	文件路径
	* @return 成功返回true,否则false
	*/
	bool IsRasterFile(string strFileName);

	/**
	* @brief 判断该文件是否为矢量数据
	* @param strFileName	文件路径
	* @return 成功返回true,否则false
	*/
	bool IsVectorFile(string strFileName);

	/**
	* @brief 删除栅格图像
	* @param pszFile			图像路径
	* @return 是否删除成功,成功为RE_SUCCESS
	*/
	int RasterDelete(const char* pszFile);

	/**
	* @brief 重命名栅格图像
	* @param pszOldFile			原始图像路径
	* @param pszNewFile			新图像路径
	* @return 是否删除成功,成功为RE_SUCCESS
	*/
	int RasterRename(const char* pszOldFile, const char* pszNewFile);

	/**
	* @brief 删除矢量数据
	* @param pszFile			矢量路径
	* @return 是否删除成功,成功为RE_SUCCESS
	*/
	int VectorDelete(const char* pszFile);

	/**
	* @brief 重命名矢量数据
	* @param pszOldFile			原始矢量路径
	* @param pszNewFile			新矢量路径
	* @return 是否删除成功,成功为RE_SUCCESS
	*/
	int VectorRename(const char* pszOldFile, const char* pszNewFile);

源文件:
int RasterDelete(const char* pszFile)
{
	path fp = pszFile;
	if (!exists(fp))	//文件不存在,直接返回
		return RE_SUCCESS;

	GDALAllRegister();

	//打开图像
	GDALDataset *pDS = (GDALDataset *)GDALOpen(pszFile, GA_ReadOnly);
	if (pDS == NULL)
		return remove(pszFile);

	GDALDriver *pDriver = pDS->GetDriver();
	if( pDriver == NULL )
	{
		GDALClose((GDALDatasetH) pDS);
		return remove(pszFile);
	}

	GDALClose((GDALDatasetH) pDS);

	if(pDriver->Delete(pszFile) == CE_None)
		return RE_SUCCESS;
	else
		return remove(pszFile);
}

int RasterRename(const char* pszOldFile, const char* pszNewFile)
{
	path fp = pszOldFile;
	if (!exists(fp))	//文件不存在,直接返回
		return RE_FILENOTEXIST;

	GDALAllRegister();

	//打开图像
	GDALDataset *pDS = (GDALDataset *)GDALOpen(pszOldFile, GA_ReadOnly);
	if (pDS == NULL)
		return rename(pszOldFile, pszNewFile);

	GDALDriver *pDriver = pDS->GetDriver();
	if( pDriver == NULL )
	{
		GDALClose((GDALDatasetH) pDS);
		return remove(pszOldFile);
	}

	GDALClose((GDALDatasetH) pDS);

	if(pDriver->Rename(pszNewFile, pszOldFile) == CE_None)
		return RE_SUCCESS;
	else
		return rename(pszOldFile, pszNewFile);
}

int VectorDelete(const char* pszFile)
{
	path fp = pszFile;
	if (!exists(fp))	//文件不存在,直接返回
		return RE_SUCCESS;

	OGRRegisterAll();

	//打开矢量
	OGRDataSource *poDS = OGRSFDriverRegistrar::Open(pszFile, FALSE );
	if( poDS == NULL )
		return remove(pszFile);

	OGRSFDriver *poDriver = poDS->GetDriver();
	if( poDriver == NULL )
	{
		OGRDataSource::DestroyDataSource( poDS );
		return remove(pszFile);
	}

	OGRDataSource::DestroyDataSource( poDS );
	if(poDriver->DeleteDataSource(pszFile) == OGRERR_NONE)
		return RE_SUCCESS;
	else
		return remove(pszFile);
}

int VectorRename(const char* pszOldFile, const char* pszNewFile)
{
	path fp = pszOldFile;
	if (!exists(fp))	//文件不存在,直接返回
		return RE_FILENOTEXIST;

	OGRRegisterAll();

	//打开矢量
	OGRDataSource *poDS = OGRSFDriverRegistrar::Open(pszOldFile, FALSE );
	if( poDS == NULL )
		return rename(pszOldFile, pszNewFile);

	OGRSFDriver *poDriver = poDS->GetDriver();
	if( poDriver == NULL )
	{
		OGRDataSource::DestroyDataSource( poDS );
		return rename(pszOldFile, pszNewFile);
	}

	OGRDataSource* poNewDS = poDriver->CopyDataSource(poDS, pszNewFile, NULL);
	if (poNewDS == NULL)
	{
		OGRDataSource::DestroyDataSource( poDS );
		return rename(pszOldFile, pszNewFile);
	}

	OGRDataSource::DestroyDataSource( poDS );
	OGRDataSource::DestroyDataSource( poNewDS );

	if(poDriver->DeleteDataSource(pszOldFile) == OGRERR_NONE)
		return RE_SUCCESS;
	else
		return rename(pszOldFile, pszNewFile);
}

bool IsRasterFile(string strFileName)
{
	string strExt = CPLGetExtension(strFileName.c_str());
	to_lower(strExt);
	if(strExt == "rrd" || strExt == "aux"|| strExt=="ovr")
		return false;

	GDALAllRegister();
	GDALDatasetH hDS = GDALOpen(strFileName.c_str(), GA_ReadOnly);
	if(hDS == NULL)
		return false;

	GDALClose(hDS);
	return true;
}

bool IsVectorFile(string strFileName)
{
	string strExt = CPLGetExtension(strFileName.c_str());
	to_lower(strExt);
	if(strExt == "dbf" || strExt == "shx")
		return false;

	OGRRegisterAll();
	OGRDataSource *poDS = OGRSFDriverRegistrar::Open(strFileName.c_str(), FALSE );
	if( poDS == NULL )
		return false;

	OGRDataSource::DestroyDataSource( poDS );
	return true;
}
这里需要说明一下,返回值的定义可以参考我之前的博客,还有就是用到了Boost库中的 filesystem库和 algorithm库,要不然可能编译不过去。BOOST库的头文件具体是:

#include "boost/algorithm/string.hpp"
#include "boost/filesystem.hpp"
using namespace boost;
using namespace boost::filesystem;

你可能感兴趣的:(GDAL对空间数据的管理)