gdal–矢量求交

目录


前言

最近在帮同学写几个小程序,包括矢量数据求交(Intersection)。网上相关文章很少,所以我参考GDAL官网写了一个完整的程序(裁剪、合并、擦除、更新等功能只要修改代码的求交函数部分,下面会有说明)。


代码

#include "gdal_priv.h"  
#include "ogrsf_frmts.h" //for ogr 

bool VectorIntersection(const char *pszSrcShp, const char *pszMethodShp, const char *pszDstShp, const char* pszFormat);

int main()
{
    const char *pszSrcFile = "C:\\Users\\liuwei\\Desktop\\CreateIm\\shpManage\\SrcLayer.shp";//原始文件
    const char *pszMethodFile = "C:\\Users\\liuwei\\Desktop\\CreateIm\\shpManage\\MethodLayer.shp";//用来求交的文件
    const char *pszOutFile = "C:\\Users\\liuwei\\Desktop\\shp\\Intersection.shp";//求交后的结果文件
    VectorIntersection(pszSrcFile, pszMethodFile, pszOutFile, "ESRI Shapefile");//矢量数据求交
    return 0;
}

bool VectorIntersection(const char *pszSrcShp, const char *pszMethodShp, const char *pszDstShp, const char* pszFormat)
{
    GDALAllRegister();
    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");

    //打开原始数据
    GDALDataset *poSrcDS;
    poSrcDS = (GDALDataset*)GDALOpenEx(pszSrcShp, GDAL_OF_VECTOR, NULL, NULL, NULL);
    if (poSrcDS == NULL)
    {
        printf("Open failed.\n");
        exit(1);
    }

    //打开用来求交的数据
    GDALDataset *poMethodDS;
    poMethodDS = (GDALDataset*)GDALOpenEx(pszMethodShp, GDAL_OF_VECTOR, NULL, NULL, NULL);
    if (poMethodDS == NULL)
    {
        printf("Open failed.\n");
        exit(1);
    }

    // 根据Shapefile驱动创建输出矢量文件 
    GDALDriver *poDriver;
    poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);\
    if (poDriver == NULL)
    {
        printf("%s driver not available.\n", pszFormat);
        exit(1);
    }
    //根据文件名创建输出矢量数据集 
    GDALDataset* poDstDS = poDriver->Create(pszDstShp, 0, 0, 0, GDT_Unknown, NULL);
    if (poDstDS == NULL)
    {
        printf("Creation of output file failed.\n");
        exit(1);
    }

    OGRLayer *poSrcLayer = poSrcDS->GetLayer(0);//得到原始数据第一个图层
    if (poSrcLayer == NULL)
    {
        printf("Creation of layer failed.\n");
        GDALClose(poSrcDS); //关闭文件  
        GDALClose(poMethodDS);
        GDALClose(poDstDS);
        exit(1);
    }

    OGRLayer *poMethodLayer = poMethodDS->GetLayer(0);
    if (poMethodLayer == NULL)
    {
        printf("Creation of layer failed.\n");
        GDALClose(poSrcDS); //关闭文件  
        GDALClose(poMethodDS);
        GDALClose(poDstDS);
        exit(1);
    }

    // 定义空间参考,与原始矢量数据相同 
    OGRSpatialReference *pSRS = poSrcLayer->GetSpatialRef();
    OGRLayer *poDstLayer = poDstDS->CreateLayer("NewLayer", pSRS, wkbPolygon, NULL);//创建图层
    if (poDstLayer == NULL)
    {
        printf("Creation of layer failed.\n");
        GDALClose(poSrcDS); //关闭文件  
        GDALClose(poMethodDS);
        GDALClose(poDstDS);
        exit(1);
    }

    poSrcLayer->Intersection(poMethodLayer, poDstLayer, NULL, GDALTermProgress, NULL);//图层求交

    GDALClose(poSrcDS); //关闭文件  
    GDALClose(poMethodDS);
    GDALClose(poDstDS);

    return true;
}

说明

1.实现矢量数据求交需要用到GDAL+Geos,关于环境配置,网上内容太杂,可参考以下博客:GDAL+GEOS(注意:先编译GEOS再编译GDAL,如果之前编译过GDAL了,建议重新解压GDAL再编译,不要在原来的基础上修改nmake.opt后再编译,那样可能还会报错:ERROR 6: GEOS support not enabled.我开始就是因为这报错)。
2.OGR库要添加GEOS库的支持,需要添加geos库的部分头文件的路径,主要是两个文件,一个是capi/geos_c.h,一个是include/geos/version.h。因此添加两个路径capi/和source/headers/就可以了。
3.GDAL集成GEOS(具体步骤参考我上面推荐的博客)需要找到GDAL源代码目录下的nmake.opt文件,用编辑器打开nmake.opt搜索goes,将

# Uncomment for GEOS support (GEOS >= 3.1.0 required)
#GEOS_DIR=C:/warmerda/geos
#GEOS_CFLAGS=-I$(GEOS_DIR)/capi -I$(GEOS_DIR)/source/headers -DHAVE_GEOS
#GEOS_LIB    =$(GEOS_DIR)/source/geos_c_i.lib

修改为:

# Uncomment for GEOS support (GEOS >= 3.1.0 required)
GEOS_DIR=D:\develop\geos-3.4.3
GEOS_CFLAGS = -I$(GEOS_DIR)/capi -I$(GEOS_DIR)/include -DHAVE_GEOS
GEOS_LIB     = $(GEOS_DIR)/src/geos_c_i.lib

4.注意:编译GEOS和GDAL后,记得将GEOS库文件夹下src文件夹中geos_c.dll文件,拷贝到GDAL编译后存放的目录下的bin文件夹中gdal202.dll(202是版本号)的同级目录下,否则会提示你找不到geos_c.dll文件
5.矢量数据裁剪、合并、擦除、更新等功能只需要修改用到的图层操作函数,相应的函数定义如下:这里写图片描述
可参考GDAL官网OGRLayer类中函数说明。将代码中poSrcLayer->Intersection(poMethodLayer, poDstLayer, NULL, GDALTermProgress, NULL)直接修改即可。

转载自:https://blog.csdn.net/secyb/article/details/80246105

You may also like...