已知四角经纬度判断是否有重叠(不用geos库)

48 篇文章 2 订阅
13 篇文章 1 订阅

已知四角经纬度判断是否有重叠。本来以前有一个依赖geos库的代码,但是现在用的gdal又没有geos库,无赖之下网上搜索了一些资料重新写了一个。
四角经纬度的多边形可以分为两种类型:1、四角为矩形,这个判断比较简单;2、四角不为矩形,可能是平行四边形或者其他形状的四边形;

两个四角均为矩形,判断是否重叠

//这个程序我没有验证,但是获取四角重叠位置的经纬度是准确的,应该是没有问题

	//1、先获取重叠区域的左上角坐标和右下角坐标
	double src_leftTopX = SrcImg4C_lng[0];
	double src_leftTopY = SrcImg4C_lat[0];
	double src_rightBottomX = SrcImg4C_lng[2];
	double src_rightBottomY = SrcImg4C_lat[2];

	double dst_leftTopX = DstImg4C_lng[0];
	double dst_leftTopY = DstImg4C_lat[0];
	double dst_rightBottomX = DstImg4C_lng[2];
	double dst_rightBottomY = DstImg4C_lat[2];

	double x[4] = { src_leftTopX,src_rightBottomX,dst_leftTopX,dst_rightBottomX };//x轴矩阵
	double y[4] = { src_leftTopY,src_rightBottomY,dst_leftTopY,dst_rightBottomY };
	std::sort(x, x + 4);//排序
	std::sort(y, y + 4);

	double ROI_leftTopX = x[1];//重叠区域的左上角和右下角坐标
	double ROI_leftTopY = y[2];
	double ROI_rightBottomX = x[2];
	double ROI_rightBottomY = y[1];

	//2、再开始判断四角是否都是某一个的,由于是double类型,所以不能直接判断等于0
	if (fabs(ROI_leftTopX - src_leftTopX) < 1e-9&&fabs(ROI_leftTopY - src_leftTopY) < 1e-9)
	{//则说明这两个是src影像
		return false;
	}
	if (fabs(ROI_leftTopX - dst_leftTopX) < 1e-9&&fabs(ROI_leftTopY - dst_leftTopY) < 1e-9)
	{//则说明这两个是dst影像
		return false;
	}
	return true;

两个四角为平行四边形或者其他多边形,判断是否重叠

这里我参考了一个链接:判断两条线段是否相交以及点是否在四边形内的C++算法

上面文章里面有判断线是否有相交算法、点是否在面内算法。据此我整理了一下

下面代码是上面博客的核心代码,我增加了一个Line结构体,方便管理

struct Point
{
	double x, y;
};

struct Line
{

	Line(Point p1, Point p2)
	{
		StartP = p1;
		EndP = p2;
	}

	Point StartP;
	Point EndP;
};

struct LinePara
{
	float a;
	float b;
	float c;//变量满足等式ax + by + c = 0
};

double determinant(double v1, double v2, double v3, double v4)  // 行列式
{
	return (v1*v4 - v2 * v3);
}

//判断两条直线是否相交,用线的结构体
bool intersect(Line A, Line B)
{
	return intersect(A.StartP, A.EndP, B.StartP, B.EndP);
}
//判断两条直线是否相交,用点的结构体
bool intersect(Point aa, Point bb, Point cc, Point dd)
{
	double delta = determinant(bb.x - aa.x, cc.x - dd.x, bb.y - aa.y, cc.y - dd.y);
	if (delta <= (1e-6) && delta >= -(1e-6))  // delta=0,表示两线段重合或平行
	{
		return false;
	}
	double namenda = determinant(cc.x - aa.x, cc.x - dd.x, cc.y - aa.y, cc.y - dd.y) / delta;
	if (namenda > 1 || namenda < 0)
	{
		return false;
	}
	double miu = determinant(bb.x - aa.x, cc.x - aa.x, bb.y - aa.y, cc.y - aa.y) / delta;
	if (miu > 1 || miu < 0)
	{
		return false;
	}
	return true;
}

//判断点是否在四边形内(凸四边形)
// 获取直线参数  
void getLinePara(Point p1, Point p2, LinePara & LP)
{
	LP.a = p2.y - p1.y;
	LP.b = p1.x - p2.x;
	LP.c = p1.y * (p2.x - p1.x) - p1.x * (p2.y - p1.y);
}

float eval(LinePara LP, Point p)
{
	return (LP.a * p.x + LP.b * p.y + LP.c);
}

bool PointInQuad(vector<struct Point> quad, Point srcpt)
{
	if (quad.size() < 4)
		return false;
	Point p_a, p_b, p_c, p_d;
	p_a = quad[0];
	p_b = quad[1];
	p_c = quad[2];
	p_d = quad[3];

	LinePara line_a2b;
	getLinePara(p_a, p_b, line_a2b);
	LinePara line_b2c;
	getLinePara(p_b, p_c, line_b2c);
	LinePara line_c2d;
	getLinePara(p_c, p_d, line_c2d);
	LinePara line_d2a;
	getLinePara(p_d, p_a, line_d2a);

	float df1, df2, df3, df4;
	df1 = eval(line_a2b, srcpt);
	df2 = eval(line_b2c, srcpt);
	df3 = eval(line_c2d, srcpt);
	df4 = eval(line_d2a, srcpt);
	if ((df1 > 0 && df2 > 0 && df3 > 0 && df4 > 0) || (df1 < 0 && df2 < 0 && df3 < 0 && df4 < 0))	// 在同侧
		return true;

	return false;
}

下面这个函数才是我真正整合的,已知四角经纬度,判断是否有重叠,有重叠返回true,没有重叠返回false


bool Is4CImgOverlap_NoGeos(double* SrcImg4C_lng, double*SrcImg4C_lat, double*DstImg4C_lng, double*DstImg4C_lat)
{//判断四角是否重叠,不带geos库的函数。zph 2022.6.8
	//原理是四个多边形边线既不相交,四个顶点又不属于包含关系,则肯定没有重叠

	Point Src_P1, Src_P2, Src_P3, Src_P4;
	Src_P1.x = SrcImg4C_lng[0];
	Src_P2.x = SrcImg4C_lng[1];
	Src_P3.x = SrcImg4C_lng[2];
	Src_P4.x = SrcImg4C_lng[3];

	Src_P1.y = SrcImg4C_lat[0];
	Src_P2.y = SrcImg4C_lat[1];
	Src_P3.y = SrcImg4C_lat[2];
	Src_P4.y = SrcImg4C_lat[3];

	Point Dst_P1, Dst_P2, Dst_P3, Dst_P4;
	Dst_P1.x = DstImg4C_lng[0];
	Dst_P2.x = DstImg4C_lng[1];
	Dst_P3.x = DstImg4C_lng[2];
	Dst_P4.x = DstImg4C_lng[3];

	Dst_P1.y = DstImg4C_lat[0];
	Dst_P2.y = DstImg4C_lat[1];
	Dst_P3.y = DstImg4C_lat[2];
	Dst_P4.y = DstImg4C_lat[3];

	Line Src_L1(Src_P1, Src_P2);
	Line Src_L2(Src_P2, Src_P3);
	Line Src_L3(Src_P3, Src_P4);
	Line Src_L4(Src_P4, Src_P1);

	Line Dst_L1(Dst_P1, Dst_P2);
	Line Dst_L2(Dst_P2, Dst_P3);
	Line Dst_L3(Dst_P3, Dst_P4);
	Line Dst_L4(Dst_P4, Dst_P1);
	//bool IsLineInterSect = true;
	//先判断四条线是否有相交,如果有一条线相交则可以说明有重叠
	if (intersect(Src_L1, Dst_L1) || intersect(Src_L1, Dst_L2) || intersect(Src_L1, Dst_L3) || intersect(Src_L1, Dst_L4) ||
		intersect(Src_L2, Dst_L1) || intersect(Src_L2, Dst_L2) || intersect(Src_L2, Dst_L3) || intersect(Src_L2, Dst_L4)||
		intersect(Src_L3, Dst_L1) || intersect(Src_L3, Dst_L2) || intersect(Src_L3, Dst_L3) || intersect(Src_L3, Dst_L4)||
		intersect(Src_L4, Dst_L1) || intersect(Src_L4, Dst_L2) || intersect(Src_L4, Dst_L3) || intersect(Src_L4, Dst_L4)) 
	{//如果有一条线相交了则说明重叠
		return true;
	}
	//再判断是否属于包含关系,如果某四个点都在四边形里面
	vector<struct Point> Src_Quad;
	vector<struct Point> Dst_Quad;
	Src_Quad.push_back(Src_P1);
	Src_Quad.push_back(Src_P2);
	Src_Quad.push_back(Src_P3);
	Src_Quad.push_back(Src_P4);

	Dst_Quad.push_back(Dst_P1);
	Dst_Quad.push_back(Dst_P2);
	Dst_Quad.push_back(Dst_P3);
	Dst_Quad.push_back(Dst_P4);
	if (PointInQuad(Dst_Quad, Src_P1) && PointInQuad(Dst_Quad, Src_P2) && PointInQuad(Dst_Quad, Src_P3) && PointInQuad(Dst_Quad, Src_P4))
	{
		return true;
	}
	if (PointInQuad(Src_Quad, Dst_P1) && PointInQuad(Src_Quad, Dst_P2) && PointInQuad(Src_Quad, Dst_P3) && PointInQuad(Src_Quad, Dst_P4))
	{
		return true;
	}

	//两个对比完后则说明有重叠
	return false;
}

以上,特此记录。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值