已知四角经纬度判断是否有重叠。本来以前有一个依赖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;
}
以上,特此记录。