前言
一直在做Qt + GDAL的程序,因为接触到GDAL的时候比较晚,GDAL已经更新到了2.x,在参考各种文章时由于GDAL本身的更新换代,以至于很多涉及到矢量的代码已经用其他的代码代替,所以在做的时候费了很大的劲(翻阅GDAL原始文档简直是折磨),在这里想在李民录大神的代码上做一些更新,以适应更新的GDAL代码。
参考文档:
https://blog.csdn.net/ivan_ljf/article/details/9470419
https://www.cnblogs.com/carfield/archive/2013/06/08/3126614.html
http://www.cnblogs.com/yhlx125/archive/2012/12/22/2816049.html
代码的更新部分
GDAL主要对OGR类库进行了调整,这部分也是进行矢量数据处理时主要用到的类库,我会在说明之后,同时在代码中对更新部分进行标注:
- OGRDataSource :原网址:https://www.gdal.org/classOGRDataSource.html ;简单来说就是,OGRDataSource类已经几乎被舍弃不用了,GDAL鼓励使用新的GDALDataSet类,如果在代码中使用旧的类的话,会存在一些类型无法转换的问题。
- OGRSFDriver :原网址:https://www.gdal.org/classOGRSFDriver.html ;这个类将来会被GDALDriver类替代;
- OGRSFDriverRegistrar :原网址:https://www.gdal.org/classOGRSFDriverRegistrar.html ;这个类将来会被GDALDriverManager类替代;
栅格矢量化代码片段
int Raster2shp::ImagePolygonize(const char* pszSrcFile, const char* pszDstFile, const char* pszFormat, processsform *pProgress)
{
if (pProgress != NULL)
{
pProgress->ReSetProcess();
pProgress->SetProgressTip("开始计算栅格矢量化...");
}
GDALAllRegister();
OGRRegisterAll();
GDALDataset* poSrcDS = (GDALDataset*) GDALOpen(pszSrcFile, GA_ReadOnly); //打开栅格图像
if (poSrcDS == NULL)
{
if (pProgress != NULL)
pProgress->SetProgressTip("不能打开指定文件,请检查文件是否存在!");
return 0;
}
/*
*此处,参考李民录老师的代码为:
*OGRSFDriver* poDriver = OGRSFDriverRegistrar::GetRegistrar()->
*GetDriverByName(pszFormat);
*这里会报这样的错误:error: C2440: “初始化”: 无法从“GDALDriver *”转换为“OGRSFDriver *”
*所以,我们用GDALDriver替代,但是GDALDriver类中没有定义GetRegistrar()方法,查阅了原始文档,发现可以用同作用的GetGDALDriverManager()方法进行获取驱动。
*/
GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
if (poDriver == NULL)
{
if (pProgress != NULL)
pProgress->SetProgressTip("不能创建指定类型文件!");
GDALClose((GDALDatasetH)poSrcDS);
return 0;
}
/*
*此处,参考李民录老师的代码为:
*OGRDataSource* poDstDS = poDriver->CreateDataSource(pszDstFile, NULL);
*上面的代码,我们将OGRDriver替代为GDALDriver,在这个类中没有CreateDataSource()的定义,
*可以用这个类中的
*Create (const char *pszName, int nXSize, int nYSize, int nBands, GDALDataType eType, char **papszOptions)
*替代,这个方法主要用于创建栅格文件的新数据集,其中nXSize,nYSize,nBands,都是对栅格文件的描述,**都置零后台会默认创建矢量数据集**
*/
GDALDataset* poDstDS = poDriver->Create(pszDstFile,0,0,0,GDT_Unknown, NULL); //创建输出矢量文件
if (poDstDS == NULL)
{
if (pProgress != NULL)
pProgress->SetProgressTip("不能创建指定类型文件!");
GDALClose((GDALDatasetH)poSrcDS);
return 0;
}
OGRSpatialReference *poSpatialRef = new OGRSpatialReference(poSrcDS->GetProjectionRef());
OGRLayer* poLayer = poDstDS->CreateLayer("Result", poSpatialRef, wkbPolygon, NULL);
if (poLayer == NULL)
{
if (pProgress != NULL)
pProgress->SetProgressTip("创建矢量图层失败!");
GDALClose((GDALDatasetH)poSrcDS);
GDALClose(poDstDS);
OSRDestroySpatialReference(poSpatialRef);
poSpatialRef = NULL;
return 0;
}
OGRFieldDefn ofieldDef("DN", OFTInteger); //创建属性表,只有一个字段即“DN”,里面保存对应的栅格的像元值
if (poLayer->CreateField(&ofieldDef) != OGRERR_NONE)
{
if (pProgress != NULL)
pProgress->SetProgressTip("创建矢量图层属性表失败!");
GDALClose((GDALDatasetH)poSrcDS);
GDALClose(poDstDS);
OSRDestroySpatialReference(poSpatialRef);
poSpatialRef = NULL;
return 0;
}
GDALRasterBandH hSrcBand = (GDALRasterBandH) poSrcDS->GetRasterBand(1); //获取图像的第一个波段
if (GDALPolygonize(hSrcBand, NULL, (OGRLayerH)poLayer, 0, NULL, NULL, pProgress) != CE_None)//调用栅格矢量化
{
if (pProgress != NULL)
pProgress->SetProgressTip("计算失败!");
GDALClose((GDALDatasetH)poSrcDS);
GDALClose(poDstDS);
/*这里在李民录老师的代码中是:delete poSpatialRef; 在我的程序运行过程中,会从此处跳出,然
*后我去找了替代的方法,OGRSpatialReference(OGR空间
*参考系统)的析构函数,这个类没有被替代掉,但是依然会跳出,所以直接被我注释掉了,这里由
*于不会进入if条件语句所以没有进行注释
*/
OSRDestroySpatialReference(poSpatialRef);
poSpatialRef = NULL;
return 0;
}
GDALClose((GDALDatasetH)poSrcDS); //关闭文件
GDALClose(poDstDS);
// OSRDestroySpatialReference(poSpatialRef);
poSpatialRef = NULL;
if (pProgress != NULL)
pProgress->SetProgressTip("计算成功!");
return 1;
}
结束语
这是我写的第一篇文档,如有纰漏,欢迎指正,另外,仔细看注释!!!