gdal 删除矢量文件feature的方法(C++)

gdal 删除矢量文件feature的方法(C++)

GIS中经常会需要对矢量文件进行处理(增删改查),使用gdal能很方便的完成这些操作。对于删除矢量文件中不满足要求的feature,我一直用的是deletefeature()的方法,在qgis里打开显示是正确删除的,一直以为没有问题,但是今天把写好的算法集成给其他同事的时候,他在arcmap里打开矢量文件后发现目标feature没有被删除。然而同一个文件在qgis里打开后,显示目标feature确实是被删除了,amazing!!!。查找了一下原因,原来DeleteFeature()方法只是标记为删除(Marked delete),最后需要使用ExecuteSQL再执行一下。具体过程如下:

1、只用DeleteFeature()方法

原始矢量数据
gdal 删除矢量文件feature的方法(C++)_第1张图片
任务需求:删除面积小于50的feature

	
#include
#include

int main()
{
	//矢量文件
	const char *m_input_vector="seaice.shp";

	GDALAllRegister();
	//支持中文路径
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
	
	//打开数据
	GDALDataset *in_poDS;
	in_poDS = (GDALDataset*)GDALOpenEx(m_input_vector, GDAL_OF_UPDATE, NULL, NULL, NULL);
	if (in_poDS == NULL)
	{
		std::cout << "open failed!" << std::endl;
	}

	OGRLayer *in_poLayer;
	GIntBig feature_nums;
	
	//获取图层
	in_poLayer = in_poDS->GetLayer(0);
	//获取feature个数
	feature_nums = in_poLayer->GetFeatureCount();
	std::cout << feature_nums << std::endl;
	//筛选出面积小于50的feature(注意:无论是使用空间或者属性过滤之后,必须使用getnextfeature()来获取feature,不能用getfeature(id)来获取feature。)
	in_poLayer->SetAttributeFilter("Area < 50");
	feature_nums = in_poLayer->GetFeatureCount();
	std::cout << feature_nums << std::endl;
	
	OGRFeature *po_feat = in_poLayer->GetNextFeature();
	while (po_feat)
	{
		in_poLayer->DeleteFeature(po_feat->GetFID());
		po_feat = in_poLayer->GetNextFeature();
	}
	GDALClose(in_poDS);
	return 0;
}

qgis打开发现只有两个feature了
gdal 删除矢量文件feature的方法(C++)_第2张图片
arcmap打开发现还是原来的feature
gdal 删除矢量文件feature的方法(C++)_第3张图片
在代码中遍历执行过上述删除操作的矢量文件

#include
#include

int main()
{
	const char *m_input_vector="seaice.shp";

	GDALAllRegister();
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");

	GDALDataset *in_poDS;
	in_poDS = (GDALDataset*)GDALOpenEx(m_input_vector, GDAL_OF_UPDATE, NULL, NULL, NULL);
	if (in_poDS == NULL)
	{
		std::cout << "open failed!" << std::endl;
	}

	OGRLayer *in_poLayer;
	GIntBig feature_nums;

	in_poLayer = in_poDS->GetLayer(0);
	feature_nums = in_poLayer->GetFeatureCount();
	std::cout << feature_nums << std::endl;
	
	for (int i = 0; i < feature_nums; i++)
	{
		OGRFeature *po_feat = in_poLayer->GetFeature(i);	
	}
	return 0;
}

gdal 删除矢量文件feature的方法(C++)_第4张图片
可以看到执行删除后的矢量文件的feature数量还是10,被删除的feature只是提示marked delete,而没有真正删除feature。

2、彻底删除feature()

需要在关闭数据前更新一下数据集

	
#include
#include

int main()
{
	//矢量文件
	const char *m_input_vector="seaice.shp";

	GDALAllRegister();
	//支持中文路径
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
	
	//打开数据
	GDALDataset *in_poDS;
	in_poDS = (GDALDataset*)GDALOpenEx(m_input_vector, GDAL_OF_UPDATE, NULL, NULL, NULL);
	if (in_poDS == NULL)
	{
		std::cout << "open failed!" << std::endl;
	}

	OGRLayer *in_poLayer;
	GIntBig feature_nums;
	//获取图层
	in_poLayer = in_poDS->GetLayer(0);
	//获取feature个数
	feature_nums = in_poLayer->GetFeatureCount();
	std::cout << feature_nums << std::endl;
	//筛选出面积小于50的feature(注意:无论是使用空间或者属性过滤之后,必须使用getnextfeature()来获取feature,不能用getfeature(id)来获取feature。)
	in_poLayer->SetAttributeFilter("Area < 50");
	feature_nums = in_poLayer->GetFeatureCount();
	std::cout << feature_nums << std::endl;
	
	OGRFeature *po_feat = in_poLayer->GetNextFeature();
	while (po_feat)
	{
		in_poLayer->DeleteFeature(po_feat->GetFID());
		po_feat = in_poLayer->GetNextFeature();
	}
	std::string sql;
	sql = "REPACK " + std::string(in_poLayer->GetName());
	in_poDS->ExecuteSQL(sql.data(), NULL, NULL);
	GDALClose(in_poDS);
	return 0;
}

在arcgis中打开处理后的矢量文件,可以看到面积小于50的feature被彻底删除了。
gdal 删除矢量文件feature的方法(C++)_第5张图片

参考

1、https://stackoverflow.com/questions/34950627/how-to-delete-feature-from-shapefile-using-gdal-c
2、https://www.cnblogs.com/bobird/articles/3224908.html

你可能感兴趣的:(遥感图像处理)