gdal 根据坐标点求服务区(服务区最小单位是米)

(1) 根据shp文件删选出来一坐标点为中心传入长度为半径的polygon所有拐点和道路信息
(2) 通过删选出来的道路信息构建Graph;
(3) 通过删选出来的拐点和中心点来求Graph最短路径
(4) 根据最短路径来求和半径的关系删选出在半径内的所有点
(5) 根据点求出最小凸包(凸包就是服务区范围)
一下是代码声明:

class TDServiceArea :public TDconversionBase
{
public:
	bool process(LayerPathInfoV1 layerpathinfo, LayerPathInfoV1 armlayerpathinfo,std::vector<std::string> vecinpout,std::vector<double> servicescope);
protected:
	void calsingleFeature(OGRFeature * ogrfeature, int flags_cal) override;
	void allcalsingleFeature() override;
private:
	std::map<int, std::vector<OGRPoint*>> m_RangePoint;
	std::map<int, std::vector<OGRFeature*>> m_RangeLine;
	std::vector<OGRPoint*> m_inputInfo;
	std::vector<double> m_params;
	std::map<int, GNMGraph> m_graph;
	std::map<int,std::map<TDOGRPoint, int>> m_mapPointindex;
	std::map<int,std::map<int, TDOGRPoint>> m_mapindexPoint;
	std::map<int,std::vector<OGRLineString>> m_tempOGRLine;
	double calPathLength(GNMPATH indexinfo, std::vector<OGRLineString> tempOGRLine);
	void makegraph();
	int getIndexData(OGRPoint * ppoint, int num);
};

实现:

#include "TDServiceArea.h"
#include "TDAPICommon.h"
#include <algorithm>
#include "TDAPICommon.h"
bool TDServiceArea::process(LayerPathInfoV1 layerpathinfo, LayerPathInfoV1 armlayerpathinfo, std::vector<std::string> vecinpout, std::vector<double> servicescope)
{
	std::for_each(vecinpout.begin(), vecinpout.end(), [&](std::string & ogrstr) {
		auto pgeoms = OGRGeometryFactory::createFromGeoJson(ogrstr.c_str());
		m_inputInfo.push_back(dynamic_cast<OGRPoint*>(pgeoms));
	});
	m_params = servicescope;
	return process_allwrite(layerpathinfo,armlayerpathinfo);
}
void TDServiceArea::calsingleFeature(OGRFeature * ogrfeature, int flags_cal)
{
	IF_NULL_RETRUN(ogrfeature)
	auto pgeoms = ogrfeature->GetGeometryRef()->toLineString();
	IF_NULL_RETRUN(pgeoms)
	int num = 0;
	std::for_each(m_inputInfo.begin(), m_inputInfo.end(), [&](OGRPoint * ppoint) {
		IF_NULL_RETRUN(ppoint)
		bool flags = false;
		for (int i = 0; i < pgeoms->getNumPoints(); i++)
		{
			OGRPoint *temppoint = new OGRPoint();
			pgeoms->getPoint(i,temppoint);
			if(TDAPICommon::computeDistanceBearing(*temppoint, *ppoint, pmoSourceSRS) <= m_params[num])
			{
				m_RangePoint[num].push_back(temppoint);
				flags = true;
			}
			//道路拐点在距离范围内
		}
		if (flags)
		{
			m_RangeLine[num].push_back(ogrfeature);
		}
		num++;
	});
}
void TDServiceArea::allcalsingleFeature()
{
	makegraph();
	std::for_each(m_RangePoint.begin(), m_RangePoint.end(), [&](std::map<int, std::vector<OGRPoint*>>::value_type &pointinfo) {
		auto ogrindex = getIndexData(m_inputInfo[pointinfo.first], pointinfo.first);
		OGRMultiPoint ogrmultipoint;
		std::for_each(pointinfo.second.begin(), pointinfo.second.end(), [&](OGRPoint * ppoint) {
			auto tempindex = getIndexData(ppoint, pointinfo.first);
			auto paths = m_graph[pointinfo.first].DijkstraShortestPath(ogrindex, tempindex);
			if (calPathLength(paths, m_tempOGRLine[pointinfo.first]) < m_params[pointinfo.first])
			{
				ogrmultipoint.addGeometry(ppoint);
			}
		});
		OGRFeature * feature = new OGRFeature(m_ogrfeaturedefn);
		feature->SetGeometry(ogrmultipoint.ConvexHull());
		//feature->SetGeometry(&ogrmultipoint);
		m_cachevector.push_back(feature);
	});
}
double TDServiceArea::calPathLength(GNMPATH indexinfo, std::vector<OGRLineString> tempOGRLine)
{
	double length = 0;
	std::for_each(indexinfo.begin(), indexinfo.end(), [&](EDGEVERTEXPAIR & indexit) {
		if (indexit.first != -1 && indexit.second != -1)
		{
			OGRLineString  ogrlinestring;
			ogrlinestring = tempOGRLine[indexit.second];
			auto geomNum = ogrlinestring.getNumPoints();
			for (int i = 0; i < geomNum -1; i++)
			{
				OGRPoint p1, p2;
				ogrlinestring.getPoint(i, &p1);
				ogrlinestring.getPoint(i+1, &p2);
				length += TDAPICommon::computeDistanceBearing(p1, p2, pmoSourceSRS);
			}
		}
	});
	return length;
}
int TDServiceArea::getIndexData(OGRPoint * ppoint,int num)
{
	int beginFID = 0;
	double beginlangPath = 0.0;
	auto fun2 = [&](double &ogrlang, OGRPoint & it, OGRPoint & it1, int innum, int & autnum)
	{
		if (TDAPICommon::computeDistanceBearing(it, it1, pmoSourceSRS) < ogrlang)
		{
			ogrlang = TDAPICommon::computeDistanceBearing(it, it1, pmoSourceSRS);
			autnum = innum;
		}
	};
	auto fun1 = [&](OGRPoint & it, int num, OGRPoint & beginPoint) {
		fun2(beginlangPath, beginPoint, it, num, beginFID);
	};
	auto fun = [&](OGRPoint indexPoint) {
		int indexnum = 0;
		std::for_each(m_mapindexPoint[num].begin(), m_mapindexPoint[num].end(), [&](std::map<int, TDOGRPoint>::value_type &it) {
			if (indexnum == 0)
			{
				beginlangPath = TDAPICommon::computeDistanceBearing(indexPoint, it.second, pmoSourceSRS);
			}
			fun1(it.second, it.first, indexPoint);
			indexnum++;
		});
	};
	fun(*ppoint);
	return beginFID;
}
void TDServiceArea::makegraph()
{
	int num = 0;
	std::for_each(m_RangeLine.begin(), m_RangeLine.end(), [&](std::map<int, std::vector<OGRFeature*>>::value_type & it) {
		int FDID = 0;
		int lineFDID = 0;
		std::for_each(it.second.begin(), it.second.end(), [&](OGRFeature* feature) {
			OGRMultiLineString  mpl;
			if (feature->GetGeometryRef()->getGeometryType() == wkbMultiLineString)
				mpl = (*feature->GetGeometryRef()->toMultiLineString());
			else if (feature->GetGeometryRef()->getGeometryType() == wkbLineString)
				mpl.addGeometry(feature->GetGeometryRef()->toLineString());
			auto geomNum = mpl.getNumGeometries();
			for (int i = 0; i < geomNum; i++)
			{
				OGRPoint pt; TDOGRPoint pts;
				auto lineString = mpl.getGeometryRef(i)->toLineString();
				auto numpoint = lineString->getNumPoints();
				for (int j = 0; j < numpoint; j++)
				{
					lineString->getPoint(j, &pt);
					pts.setX(pt.getX());
					pts.setY(pt.getY());
					if (m_mapPointindex[num].find(pts) == m_mapPointindex[num].end())
					{
						m_mapPointindex[num][pts] = FDID;
						m_mapindexPoint[num][FDID] = pts;
						m_graph[num].AddVertex(FDID);
						FDID++;
					}
				}
				for (int j = 0; j < numpoint - 1; j++)
				{
					OGRLineString ogrlinestring;
					OGRPoint *pt1 = new OGRPoint(), *pt2 = new OGRPoint();
					lineString->getPoint(j, pt1);
					ogrlinestring.addPoint(pt1);
					lineString->getPoint(j + 1, pt2);
					ogrlinestring.addPoint(pt2);
					m_tempOGRLine[num].push_back(ogrlinestring);
					lineFDID++;
				}
			}
		});
		lineFDID = 0;
		std::for_each(m_tempOGRLine[num].begin(), m_tempOGRLine[num].end(), [&](OGRLineString & ogrlinestring) {
			OGRPoint pt, pt1;
			ogrlinestring.getPoint(0, &pt);
			TDOGRPoint pts;
			pts.setX(pt.getX());
			pts.setY(pt.getY());
			auto beginindex = m_mapPointindex[num][pts];
			ogrlinestring.getPoint(1, &pt1);
			pts.setX(pt1.getX());
			pts.setY(pt1.getY());
			auto endindex = m_mapPointindex[num][pts];
			m_graph[num].AddEdge(lineFDID, beginindex, endindex, true, TDAPICommon::computeDistanceBearing(pt, pt1, pmoSourceSRS), TDAPICommon::computeDistanceBearing(pt, pt1, pmoSourceSRS));
			lineFDID++;
		});
		num++;
	});
}

坐标点椭球距离计算公式:

double TDAPICommon::computeDistanceBearing(const OGRPoint &p1, const OGRPoint &p2, OGRSpatialReference * psrs,double *course1, double *course2)
{
	if (CommonDoubleNear(p1.getX(), p2.getX()) && CommonDoubleNear(p1.getY(), p2.getY()))
		return 0;
	// ellipsoid
	double mSemiMajor = psrs->GetSemiMajor();
	double mSemiMinor = psrs->GetSemiMinor();
	double mInvFlattening = 1 / psrs->GetInvFlattening();

	double p1_lat = DEG2RAD(p1.getY()), p1_lon = DEG2RAD(p1.getX());
	double p2_lat = DEG2RAD(p2.getY()), p2_lon = DEG2RAD(p2.getX());

	double L = p2_lon - p1_lon;
	double U1 = atan((1 - mInvFlattening) * tan(p1_lat));
	double U2 = atan((1 - mInvFlattening) * tan(p2_lat));
	double sinU1 = sin(U1), cosU1 = cos(U1);
	double sinU2 = sin(U2), cosU2 = cos(U2);
	double lambda = L;
	double lambdaP = 2 * M_PI;

	double sinLambda = 0;
	double cosLambda = 0;
	double sinSigma = 0;
	double cosSigma = 0;
	double sigma = 0;
	double alpha = 0;
	double cosSqAlpha = 0;
	double cos2SigmaM = 0;
	double C = 0;
	double tu1 = 0;
	double tu2 = 0;

	int iterLimit = 20;
	while (abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0)
	{
		sinLambda = sin(lambda);
		cosLambda = cos(lambda);
		tu1 = (cosU2 * sinLambda);
		tu2 = (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
		sinSigma = sqrt(tu1 * tu1 + tu2 * tu2);
		cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
		sigma = atan2(sinSigma, cosSigma);
		alpha = asin(cosU1 * cosU2 * sinLambda / sinSigma);
		cosSqAlpha = cos(alpha) * cos(alpha);
		cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
		C = mInvFlattening / 16 * cosSqAlpha * (4 + mInvFlattening * (4 - 3 * cosSqAlpha));
		lambdaP = lambda;
		lambda = L + (1 - C) * mInvFlattening * sin(alpha) *
			(sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
	}

	if (iterLimit == 0)
		return -1;  // formula failed to converge

	double uSq = cosSqAlpha * (mSemiMajor * mSemiMajor - mSemiMinor * mSemiMinor) / (mSemiMinor * mSemiMinor);
	double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
	double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
	double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
		B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
	double s = mSemiMinor * A * (sigma - deltaSigma);

	if (course1)
	{
		*course1 = atan2(tu1, tu2);
	}
	if (course2)
	{
		// PI is added to return azimuth from P2 to P1
		*course2 = atan2(cosU1 * sinLambda, -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda) + M_PI;
	}
	return s;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值