shp写+shplib

     最近在搞一个模块,要用到shp的读写,发现读取shp这部分,大兄弟们~都已经给出自己的经验,但是在写shp这部分却没有相关参考,

导致自己花了一段时间在研究shp上,根据很多朋友给出的shp文件结构,哪几个字节代表什么意思,慢慢摸索,然后简易实现了shp的写

操作,但是这任然不能满足项目需要,简直就是弱鸡呀~~,后来不得不寻求三方库。

  下面把shp的写操作贴上来,满足内部带有 环*n的多边形,三方库用的shplib。然后把自己之前摸索写的代码贴出来,其实都是按照什

么字节代表什么意思来写入,但是总归考虑不够全面,既是一个教训,也算是一个总结吧。

  主要是几个shplib库函数的使用,但是重点是要准备这些函数的参数,也就是顶点序列,因为要满足带环的多边形,所以要求外环顶点

顺时针,内环为逆时针,顺时针还是逆时针的判断我这里用到了CGAL,当然也有其他方法。然后要注意顶点首尾相连,即同一个点

bool writeToShp(string outPutShpFile, vector<Polygon_with_holes_2> vecQueryPolygon, std::string strResultPath, double offx, double offy)
{
	//输出的shp
	string shpFileName = outPutShpFile;
	string tmp = outPutShpFile.substr(0,outPutShpFile.find_last_of("\."));
	string dbfFileName = tmp + ".dbf";

	SHPHandle hShp = SHPCreate(shpFileName.c_str(), SHPT_POLYGON);
	DBFHandle hDbf = DBFCreate(dbfFileName.c_str());
	if (NULL == hShp || NULL == hDbf)
	{
		return false;
	}

	//
	Pwh_list_2 resPolygonList;
	for (size_t i = 0; i < vecQueryPolygon.size(); i++)
	{
		resPolygonList.push_back(Polygon_with_holes_2(vecQueryPolygon[i]));
	}

	//含有几个部分
	//int nNumPart = 0; //= resPolygonList.size();

	//每个部分起始点索引
	//int* nPanStart = new int[nNumPart]; 
	//memset(nPanStart, 0, nNumPart);
	//nPanStart[0] = 0;

	//int cnt = 0;
	//int nNumTotalPoint = 0;
	//Pwh_list_2::const_iterator ita;
	//for (ita = resPolygonList.begin(); ita != resPolygonList.end(); ita++)
	//{
	//	//外环
	//	Polygon_with_holes_2 poly_hole_2 = *ita;
	//	Polygon_2 resPolygon = poly_hole_2.outer_boundary();

	//	int nNumPoint_outer = resPolygon.size() + 1;//外环点数量,首尾点相同,加上尾点

	//	int nNumPoint_inner = 0;//内环
	//	for (Polygon_with_holes_2::Hole_iterator itr = poly_hole_2.holes_begin(); itr != poly_hole_2.holes_end(); itr++)
	//	{
	//		Polygon_2 innerPoly = *itr;
	//		nNumPoint_inner += innerPoly.size() + 1;
	//	}

	//	//当前部分所有点的量
	//	nNumTotalPoint += nNumPoint_outer + nNumPoint_inner;

	//	if (cnt == (nNumPart - 1))
	//		break;
	//
	//	cnt++;
	//	nPanStart[cnt] = nNumTotalPoint;
	//}


	vector <int> vecPolygonHasProblem;

	int nField = 0;
	
	//it,每个部分
	int cntex = 0;
	Pwh_list_2::const_iterator it;
	for (it = resPolygonList.begin(); it != resPolygonList.end(); it++)
	{

		cntex++;
		//当前部分外环
		Polygon_with_holes_2 poly_hole_2 = *it;
		Polygon_2 resPolygon = poly_hole_2.outer_boundary(); 

		//外环顺时针
		//if (cntex == 99)
		//{
		//	PrintPolygon(resPolygon, "c:/before.txt");
		//}
		//makePolygonClockWise(resPolygon);
		if (resPolygon.is_counterclockwise_oriented())
		{
			std::vector<Point_2> pts;
			pts.reserve(resPolygon.size() + 1);
			pts.push_back(resPolygon[0]);
			for (int j = resPolygon.size() - 1; j >= 0; j--)
			{
				pts.push_back(resPolygon[j]);
			}
			pts.pop_back();
			resPolygon = Polygon_2(pts.begin(), pts.end());
		}
		//PrintPolygon(resPolygon, "c:/after.txt");

		//外环点数量,首尾点相同,加上尾点
		int nNumPoint_outer = resPolygon.size() + 1;

		//
		int nNumPart = 1;
		int nNumPoint_inner = 0;//内环点数量
		for (Polygon_with_holes_2::Hole_iterator itr = poly_hole_2.holes_begin(); itr != poly_hole_2.holes_end(); itr++)
		{
			Polygon_2 innerPoly = *itr;
			nNumPoint_inner += innerPoly.size() + 1;
			nNumPart++;
		}

		//当前多边形由几个小部分组成,比如内部存在环
		int* nPanStart = new int[nNumPart];
		memset(nPanStart, 0, nNumPart);
		nPanStart[0] = 0;

		//当前部分所有点
		int nNumTotalPoint = nNumPoint_outer + nNumPoint_inner;
		vector <double> vecX;
		vector <double> vecY;
		vecX.reserve(nNumTotalPoint);
		vecY.reserve(nNumTotalPoint);

		double* pdx = new double[nNumTotalPoint];
		double* pdy = new double[nNumTotalPoint];
		memset(pdx, 0, nNumTotalPoint);
		memset(pdy, 0, nNumTotalPoint);

		int nNumPoint_current = 0;
		//取得外环所有点
		for (size_t i = 0; i < nNumPoint_outer - 1; i++)
		{
			pdx[i + nNumPoint_current] = resPolygon[i].hx().doubleValue() + offx;
			pdy[i + nNumPoint_current] = resPolygon[i].hy().doubleValue() + offy;

			vecX.push_back(resPolygon[i].hx().doubleValue() + offx);
			vecY.push_back(resPolygon[i].hy().doubleValue() + offy);

			//vecDD.push_back(pdx[i + nNumPoint_current]);
			if (resPolygon.size() - 1 == i)
			{
				pdx[i + nNumPoint_current + 1] = resPolygon[0].hx().doubleValue() + offx;
				pdy[i + nNumPoint_current + 1] = resPolygon[0].hy().doubleValue() + offy;

				//vecDD.push_back(pdx[i + nNumPoint_current]);
				vecX.push_back(resPolygon[0].hx().doubleValue() + offx);
				vecY.push_back(resPolygon[0].hy().doubleValue() + offy);
			}
		}

		//ofstream fout("c:/a.txt");
		//for (size_t i = 0; i < nNumPoint_outer; i++)
		//{
		//	fout << "\t" << pdx[i + nNumPoint_current] << "\t" << pdy[i + nNumPoint_current] << "\n";

		//}
		//fout.close();

		//
		nNumPoint_current += nNumPoint_outer;

		//取得内环所有点
		int cnt = 1;
		int nNumPoint_in = 0;
		for (Polygon_with_holes_2::Hole_iterator itr = poly_hole_2.holes_begin(); itr != poly_hole_2.holes_end(); itr++)
		{
			nPanStart[cnt] = nNumPoint_current;

			Polygon_2 innerPoly = *itr;
			//内环逆时针
			//PrintPolygon(innerPoly, "c:/before.txt");
			//kePolygonCounterClockWise(innerPoly);
			if (innerPoly.is_clockwise_oriented())//如果是顺时针就将其逆时针
			{
				std::vector<Point_2> pts;
				pts.reserve(innerPoly.size());
				pts.push_back(innerPoly[0]);
				for (int j = innerPoly.size() - 1; j >= 0; j--)
				{
					pts.push_back(innerPoly[j]);
				}
				pts.pop_back();
				innerPoly = Polygon_2(pts.begin(), pts.end());
			}
			//PrintPolygon(innerPoly, "c:/after.txt");

			nNumPoint_in += innerPoly.size() + 1;
			for (size_t i = 0; i < /*nNumPoint_in - 1*/innerPoly.size(); i++)
			{
				pdx[i + nNumPoint_current] = innerPoly[i].hx().doubleValue() + offx;
				pdy[i + nNumPoint_current] = innerPoly[i].hy().doubleValue() + offy;

				//vecDD.push_back(pdx[i + nNumPoint_current]);
				vecX.push_back(resPolygon[i].hx().doubleValue() + offx);
				vecY.push_back(resPolygon[i].hy().doubleValue() + offy);

				if (innerPoly.size() - 1 == i)
				{
					pdx[i + nNumPoint_current + 1] = innerPoly[0].hx().doubleValue() + offx;
					pdy[i + nNumPoint_current + 1] = innerPoly[0].hy().doubleValue() + offy;

					//vecDD.push_back(pdx[i + nNumPoint_current + 1]);
					vecX.push_back(resPolygon[0].hx().doubleValue() + offx);
					vecY.push_back(resPolygon[0].hy().doubleValue() + offy);
				}

			}

			nNumPoint_current += /*nNumPoint_in*/innerPoly.size() + 1;
			cnt++;
		}

		//判断当前多边形,不满足条件的将不被写入shp
		vector<Point_2> pts;
		pts.reserve(nNumTotalPoint);
		for (int i = 0; i < nNumTotalPoint; i++)
		{
			pts.push_back(Point_2(vecX[i] - offx, vecY[i] - offy));//svn
		}

		如果is_simple,Polygon_hole2_将为空
		//Polygon_with_holes_2 Polygon_hole2_ = createPolywithHole(pts);
		//if (Polygon_hole2_.is_unbounded())
		//{
		//	for (int j = 0; j < nNumTotalPoint; j++)
		//	{
		//		pdx[j] = 0;
		//		pdy[j] = 0;
		//	}
		//	vecX.clear();
		//	vecY.clear();

		//	vector <double>().swap(vecX);
		//	vector <double>().swap(vecY);
		//	vector<Point_2>().swap(pts);

		//	vecPolygonHasProblem.push_back(cntex - 1);
		//	//ofs << "ID:"<<cntex - 1 << endl;

		//	continue;
		//}
		

		//shp,创建记录 
		SHPObject* ishpobj = SHPCreateObject(SHPT_POLYGON, -1/*-1 means unknown*/, nNumPart, nPanStart, NULL, nNumTotalPoint, pdx, pdy, NULL, NULL);

		//shp,重新计算包围盒
		SHPComputeExtents(ishpobj);

		//shp,写入记录
		SHPWriteObject(hShp, -1, ishpobj);

		nField++;
		
	}

	//dbf,添加字段
	int ifield = DBFAddNativeFieldType(hDbf, "ID", 'N', 6, 2);

	//dbf,写入字段值
	int nrecordCnt = 0;
	for (int i = 0; i < nField; i++)
	{
		DBFWriteIntegerAttribute(hDbf, i, ifield, i);
		nrecordCnt = DBFGetRecordCount(hDbf);
	}

	//关闭
	SHPClose(hShp);
	DBFClose(hDbf);

	将不能处理的polygon的ID输入文本
	//string strTip = strResultPath + "tip.txt";
	//FILE* fp = fopen(strTip.c_str(), "a+");
	//if (fp == NULL)
	//{
	//	cout << "文件打开失败:" << strTip << endl;
	//	return false;
	//}

	//ofstream ofs;
	//ofs.open(strTip, ios::app);

	//char buf[256];
	//time_t tt = time(NULL);//返回的只是一个时间戳
	//tm* t = localtime(&tt);
	//sprintf_s(buf, sizeof(buf), "%d-%02d-%02d %02d:%02d:%02d\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

	//ofs << buf;
	//memset(buf, 0, 256);
	//
	//ofs << "数目:" << vecPolygonHasProblem.size() << endl;
	//for (int q = 0; q < vecPolygonHasProblem.size(); q++)
	//{
	//	ofs << "ID:" << vecPolygonHasProblem[q] << endl;
	//}

	//ofs << endl;
	//ofs.close();
	//

	return true;

}

  另外说一下shp的读操作,很多三方库也有,比如osg的shp插件,能满足一般需要,但是还是有某些地方不太完善,不过仍然值得学习,比如

代码风格,模板的使用等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值