问题是给定一个经纬度坐标点A,以及坐标围成的区域坐标数组,判断该点在不在此区域。
思路是这样的:
将区域放入x-y坐标轴中,取A的x或者y坐标,向一个方向画射线,若是与区域的交点为奇数时,则A点在该区域(这个的前提A点的x或者y坐标就在区域的范围内,要排除A在区域的边界上或者顶点上)
若是A点非要在顶点上或者边界上,为了避免问题就要在判断A点x或者y轴范围的时候取一个实点一个虚点,例如:[4,5)。然后利用直线公式获取交点的y或者x轴坐标,然后判断点是否在射线的那个方向(画的x轴射线现在就获取y坐标,画的用y轴射线现在就获取x坐标)这样如果交点的数量还是奇数就说明A点在区域内。
1.把区域放入x-y坐标轴中,就是这样:
手绘的不要太在意细节。
2.判断A点x或者y坐标就在区域的范围内
这样两边都比较一下是因为不能够确定点集合中的点位大小是不是按顺序排列的。
ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1)
3.利用公式获取A点的y或者x坐标
直线公式:(y-y1)/(y2-y1)=(x-x1)/(x2-x1)
4.判断是否在所选的一侧
这一步比较大小就好了,应该都明白。
付一下代码:
/**
* 判断某个点是否在一个经纬度围成的多边形中
* @param ALon 经度
* @param ALat 纬度
* @param ps 点集合
* @return
*/
public boolean isPtInPoly (double ALon , double ALat , Ponits[] ps) {
int iSum, iCount, iIndex;
double dLon1 = 0, dLon2 = 0, dLat1 = 0, dLat2 = 0, dLon;
if (ps.length < 3) {
return false;
}
iSum = 0;
iCount = ps.length;
for (iIndex = 0; iIndex<iCount;iIndex++) {
//按顺序取出数组中的两个点,若是最后一个点就与第一个点组合
if (iIndex == iCount - 1) {
dLon1 = ps[iIndex].getX();
dLat1 = ps[iIndex].getY();
dLon2 = ps[0].getX();
dLat2 = ps[0].getY();
} else {
dLon1 = ps[iIndex].getX();
dLat1 = ps[iIndex].getY();
dLon2 = ps[iIndex + 1].getX();
dLat2 = ps[iIndex + 1].getY();
}
//判断A点是否在边的两端点的水平平行线之间
if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1))) {
if (Math.abs(dLat1 - dLat2) > 0) {
//得到 A点向左射线与边的交点的x坐标:
dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat) ) / (dLat1 - dLat2);
// 如果交点在A点左侧(说明是做射线与边的交点)则交点数加一:
if (dLon < ALon) {
iSum++;
}
}
}
}
//判断能否被2 整除,是否为奇数
if ((iSum % 2) != 0) {
return true;
}
return false;
}