C++、GDAL下shp转栅格

问题说明

相关代码下载地址:https://download.csdn.net/download/gainichengyichongfu/18383717?spm=1001.2014.3001.5503
这里贴的是除多边形之外的函数(如点、线等),要丰富一点的可以去上述地址下载~

我要做的

我的目标是:根据由多张图像拼起来的shp文件,生成每张图像参与拼接的二值图像( 0 表示不参与拼接,255 表示参与拼接);最后生成一张拼接大图
如(我这里还经过了去云的操作,所以拼接大图里面没有云了,这些细节就不要在意了哈~)
在这里插入图片描述

输入数据

我的输入shp文件如下(这是由多张图像拼起来的结果图,每个多边形表示不同影像的参与拼接的部分):
在这里插入图片描述
里面由一个图层、多个多边形组成,其中一个多边形信息如下:
在这里插入图片描述
可以看到数据类型是多边形,对应的影像名称 “F:\test_data\CST-testdata\1-GF1-7\DataWithSimuClouds-Nocolor-shape\GF1B_PMS_E112.7_N23.0_20191207_L1A1227736448.tif”

对应的影像图 “F:\test_data\CST-testdata\1-GF1-7\DataWithSimuClouds-Nocolor-shape\GF1B_PMS_E112.7_N23.0_20191207_L1A1227736448.tif” 如下:
在这里插入图片描述

我希望可以生成这个影像对应的二值化栅格图,如下:
在这里插入图片描述

下面开始讲述如何实现!

方法实现

main主函数

里面使用到了两个函数
(1)shpread(shpName, ValidMaskList, PolygonPoint);
(2)PolygonRasterize(PolygonPoint, ImgList, ValidMaskList, pdriver);

GDALAllRegister();
GDALDriver *pdriver = GetGDALDriverManager()->GetDriverByName("GTiff");//注册驱动
string strpath = "F:\\test_data\\CST-testdata\\1-GF1-7\\DataWithSimuClouds-Nocolor-shape";
string shpName = strpath + "\\result\\project.shp";
vector<string> ValidMaskList;
vector<string> ImgList;
vector<string> PolygonPoint;//云掩膜文件名

shpread(shpName, ValidMaskList, PolygonPoint);
PolygonRasterize(PolygonPoint, ImgList, ValidMaskList, pdriver);

(1)shpread(shpName, ValidMaskList, PolygonPoint);

里面使用到的函数 void shpread(string file_path_name, vector &Masklist, vector &PolygonPoint);--------这个函数的目的是:将多边形的各个拐点读取出来,存在point容器里面;因为后面需要多边形的所有拐点来生成二值的mask栅格文件

shpread函数里面有用到了函数 int Get_Polygon(OGRGeometry *poGeometry, vector& OuterRing, vector<vector>& InteriorRing);,我都放在下面了

声明:由于我确定我的shp文件存储的多个多边形,所以不必要的代码我都注释掉了,不必要的输出也省略了

//读shp文件到对应的point容器
void shpread(string file_path_name, vector<string> &Masklist, vector<string> &PolygonPoint)
{
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");	// 支持中文路径
	CPLSetConfigOption("SHAPE_ENCODING", "");			//属性表支持中文字段


	GDALDataset *poDS = (GDALDataset*)GDALOpenEx(file_path_name.c_str(), GDAL_OF_VECTOR, NULL, NULL, NULL);
	if (poDS == NULL)
	{
		printf("Open failed.\n");
		exit(1);
	}
	//cout << "Open successfully!" << endl;

	//获取图层数量
	//cout << "<--------获取图层数量-------->" << endl;
	//int LayerCount = poDS->GetLayerCount();
	//cout << "图层数量: " << LayerCount << endl;

	//获取shp图层
	//cout << "<--------获取shp图层-------->" << endl;
	OGRLayer  *poLayer = poDS->GetLayer(0);  //	 根据序号获取相应shp图层,这里表示第一层
	//OGRLayer  *poLayer = poDS->GetLayerByName("point");		//根据名称获取相应图层

	//获取当前图层的属性表结构
	//cout << "<--------获取当前图层的属性表结构-------->" << endl;
	OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();

	//重置要素读取顺序
	//cout << "<--------重置要素读取顺序-------->" << endl;
	poLayer->ResetReading();	// ResetReading() 函数功能为把要素读取顺序重置为从第一个开始

	//设置要素指针
	//cout << "<--------设置要素指针-------->" << endl;
	OGRFeature *poFeature;		//用于获取图层上的要素

	//创建文件存放数据
	string shpname = string(file_path_name).substr(string(file_path_name).find_last_of("/") + 1);
	shpname = shpname.substr(0, shpname.find_last_of(".")) + "_";
	string attrfile = shpname + "attrfile_shp.txt";			// 属性文件
	string datafile = shpname + "datafile_shp.txt";			// 数据文件
	//cout << attrfile << ' ' << datafile << endl;
	fstream tmpfile(attrfile, ios::out);
	fstream tmpdatafile(datafile, ios::out);

	int num = 0;		//用于标记第几个要素
	string finename;
	while ((poFeature = poLayer->GetNextFeature()) != NULL)
	{
		//cout << "图层属性->" << endl;
		int aa = poFDefn->GetFieldCount();
		for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++)
		{
			OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);

			//cout << poFieldDefn->GetNameRef() << ": ";		// 属性表字段名
			switch (poFieldDefn->GetType())			// 不同数据类型按不同方式,根据字段号获取相应字段的数据
			{
			case OFTInteger:
				//printf("%d,", poFeature->GetFieldAsInteger(iField));
				tmpfile << poFeature->GetFieldAsInteger(iField) << "\t";		// 写入文件
				break;
			case OFTInteger64:
				//printf(CPL_FRMT_GIB ",", poFeature->GetFieldAsInteger64(iField));
				tmpfile << poFeature->GetFieldAsInteger64(iField) << "\t";		// 写入文件
				break;
			case OFTReal:
				//printf("%.3f,", poFeature->GetFieldAsDouble(iField));
				tmpfile << poFeature->GetFieldAsDouble(iField) << "\t";		// 写入文件
				break;
			case OFTString:
				//printf("%s,", poFeature->GetFieldAsString(iField));
				tmpfile << poFeature->GetFieldAsString(iField) << "\t";		// 写入文件
				finename = poFeature->GetFieldAsString(iField);
				finename = finename + ".mask";
				Masklist.push_back(finename);
				break;
			default:
				//printf("%s,", poFeature->GetFieldAsString(iField));
				tmpfile << poFeature->GetFieldAsString(iField) << "\t";		// 写入文件
				break;
			}
			/*printf("\n");*/
		}
		tmpfile << endl;

		string polypoint = "POLYGON ((";
		OGRGeometry *poGeometry = poFeature->GetGeometryRef();
		//判断当前要素的几何类型,是否为点图层,利用 getGeometryType() 函数获取要素类型

		if (poGeometry != NULL)
		{
			auto GeometryType = wkbFlatten(poGeometry->getGeometryType());	// getGeometryType() 返回的类型可能会有2.5D类型,通过宏 wkbFlatten 转换为2D类型
			if (GeometryType == wkbPoint) return;
			else if (GeometryType == wkbLineString)	return;
			else if (GeometryType == wkbMultiPoint)	return;
			else if (GeometryType == wkbMultiLineString) return;
			else if (GeometryType == wkbGeometryCollection)	 return; //cout << "几何体集合图层要素" << endl;
			else if (GeometryType == wkbNone) return; //cout << "该数据只有属性表" << endl;
			else if (GeometryType == wkbPolygon)		// 3
			{
				//cout << "多边形图层要素" << endl;
				vector<XYZInfo> OuterRing;
				vector<vector<XYZInfo>> InteriorRing;
				Get_Polygon(poGeometry,OuterRing, InteriorRing);

				// 将数据写入文件
				tmpdatafile << "<----- 第" + to_string(1 + num++) + "个要素(多边形) ---->" << endl;
				tmpdatafile << "外环数据" << endl;
				//cout << "数据个数:" << OuterRing.size() << endl;
				for (int j = 0; j < OuterRing.size(); j++)
				{
					//tmpdatafile << OuterRing[j].x << "\t" << OuterRing[j].y << "\t" << OuterRing[j].z << endl;		// 写入文件
					//tmpdatafile << OuterRing[j].x << "\t" << OuterRing[j].y << "\t" << endl;//不关心Z坐标
					polypoint = polypoint + DoubleToString(OuterRing[j].x) + " " + DoubleToString(OuterRing[j].y);
					if (j < OuterRing.size() - 1) polypoint = polypoint + ",";
					if (j == OuterRing.size() - 1) polypoint = polypoint + "))";
				}
				tmpdatafile << polypoint.c_str() << endl;//不关心Z坐标

				tmpdatafile << "内环数据" << endl;
				for (int i = 0; i < InteriorRing.size(); i++)
				{
					for (int k = 0; k < InteriorRing[i].size(); k++)
						tmpdatafile << InteriorRing[i][k].x << "\t" << InteriorRing[i][k].y << "\t" << endl;//不关心Z坐标
						//tmpdatafile << InteriorRing[i][k].x << "\t" << InteriorRing[i][k].y << "\t" << InteriorRing[i][k].z << endl;		// 写入文件
					tmpdatafile << endl;
				}
			}
			//else if (GeometryType == wkbMultiPolygon)		// 6
			//{
			//	//cout << "多边形集合图层要素" << endl;
			//	//获取数据
			//	vector<vector<XYZInfo>> OuterRingVec;
			//	vector<vector<vector<XYZInfo>>> InteriorRingVec;
			//	Get_MultiPolygon(poGeometry, OuterRingVec, InteriorRingVec);

			//	// 将数据写入文件
			//	OGRMultiPolygon *MultiPolygon = (OGRMultiPolygon *)poGeometry;
			//	int NumMPolygon = MultiPolygon->getNumGeometries();
			//	vector<XYZInfo> xyz;
			//	tmpdatafile << "<----- 第" + to_string(1 + num++) + "个要素(多边形集合) ---->" << endl;
			//	for (int k = 0; k < OuterRingVec.size(); k++)
			//	{
			//		tmpdatafile << "外环" + to_string(k) << endl;
			//		for (int j = 0; j < OuterRingVec[k].size(); j++)
			//		{
			//			tmpdatafile << OuterRingVec[k][j].x << "\t" << OuterRingVec[k][j].y << "\t" << OuterRingVec[k][j].z << endl;		// 写入文件
			//		}

			//		for (int i = 0; i < InteriorRingVec[k].size(); i++)
			//		{
			//			tmpdatafile << "内环" + to_string(i + 1) << endl;
			//			for (int j = 0; j < InteriorRingVec[k][i].size(); j++)
			//				tmpdatafile << InteriorRingVec[k][i][j].x << "\t" << InteriorRingVec[k][i][j].y << "\t" << InteriorRingVec[k][i][j].z << endl;		// 写入文件
			//		}
			//		tmpdatafile << endl;
			//	}
			//}

		}
		else
		{
			printf("no  geometry\n");
		}
		//polypoint = polypoint + "))";

		PolygonPoint.push_back(polypoint);
		OGRFeature::DestroyFeature(poFeature);
	}
	tmpfile.close();

	GDALClose(poDS);
	return;

}







//参数1是外环数据,是一个坐标名到坐标值vec的map,参数2是内环数据,比参数1多了一层编号映射
int Get_Polygon(OGRGeometry *poGeometry,vector<XYZInfo>& OuterRing, vector<vector<XYZInfo>>& InteriorRing)
{
	OGRPolygon *poPolygon = (OGRPolygon*)poGeometry;//将几何结构转换成多边形类型
	OGRLinearRing *pOGRLinearRing = poPolygon->getExteriorRing();
	//获取外环数据
	XYZInfo outring;
	for (int i = 0; i < pOGRLinearRing->getNumPoints(); i++)
	{
		outring.x = pOGRLinearRing->getX(i);
		outring.y = pOGRLinearRing->getY(i);
		outring.z = pOGRLinearRing->getZ(i);
		OuterRing.push_back(outring);
	}

	//获取内环数据(一个外环包含若干个内环)
	for (int i = 0; i < poPolygon->getNumInteriorRings(); i++)
	{
		vector<XYZInfo> Ringvec;
		pOGRLinearRing = poPolygon->getInteriorRing(i);
		for (int j = 0; j < pOGRLinearRing->getNumPoints(); j++)
		{
			XYZInfo intrring;
			intrring.x = pOGRLinearRing->getX(j);
			intrring.y = pOGRLinearRing->getY(j);
			intrring.z = pOGRLinearRing->getZ(j);
			Ringvec.push_back(intrring);
		}
		InteriorRing.push_back(Ringvec);
	}
	return 0;
}

(2)PolygonRasterize(PolygonPoint, ImgList, ValidMaskList, pdriver);

接下来是函数 void PolygonRasterize(vector PolygonPoint, vector ImgList, vector Masklist, GDALDriver *pdriver);//循环处理shp里面的每个多边形文件,主要函数是其同名函数

里面使用到的同名函数 void PolygonRasterize(string Geomrtry, string ImgList, string MaskList, GDALDriver *pdriver);//根据多边形的顶点生成mask

函数我都放在下面了

void PolygonRasterize(vector<string> PolygonPoint, vector<string> ImgList, vector<string> Masklist, GDALDriver *pdriver)//根据多边形的顶点生成mask
{
	for (int i = 0; i < ImgList.size(); i++)
	{
		PolygonRasterize(PolygonPoint[i], ImgList[i], Masklist[i], pdriver);
	}
}



void PolygonRasterize(string Geomrtry, string ImgList, string MaskList, GDALDriver *pdriver)//根据多边形的顶点生成mask
{
	GDALDataset* pInDataset = (GDALDataset*)GDALOpen(ImgList.c_str(), GA_ReadOnly);
	int Width = pInDataset->GetRasterXSize();
	int Height = pInDataset->GetRasterYSize();
	double dGeoTrans[6] = {};
	pInDataset->GetGeoTransform(dGeoTrans);
	const char* cProjectionRef = pInDataset->GetProjectionRef();
	GDALDataset* pOutDataset = pdriver->Create(MaskList.c_str(), Width, Height, 1, GDT_Byte, NULL);
	pOutDataset->SetGeoTransform(dGeoTrans);
	pOutDataset->SetProjection(cProjectionRef);

	OGRGeometryH hGeometry;
	char *pWKT = (char*)Geomrtry.c_str();
	OGR_G_CreateFromWkt(& pWKT, NULL, &hGeometry);
	int iBand[1] = { 1 };
	double dBurnValue[1] = { 255 };
	CPLErr err = GDALRasterizeGeometries((GDALDatasetH)pOutDataset, 1, iBand, 1, &hGeometry, NULL, NULL, dBurnValue, NULL, NULL, NULL);

	GDALClose(pInDataset);
	pInDataset = NULL;
	GDALClose(pOutDataset);
	pOutDataset = NULL;
	pWKT = NULL;
	delete[] pWKT;
	pWKT = NULL;
}

通过上述可以通过shp的多边形文件,得到对应的二值的栅格文件,如:

在这里插入图片描述

若直接裁剪影像也是一样的道理,稍微改改就行了

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小于等于大于

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值