Java实现经纬度是否在矩形区域内的判断及重复坐标处理
问题分析与解决方案
关于重复的第五个坐标
那个和第一个重复的坐标完全没用,它只是用来表示矩形路径闭合的,直接忽略就行,你的代码问题和它无关。
原代码的核心问题
- 顶点顺序错误:你给的四个顶点顺序不是矩形的连续顶点(顺时针/逆时针相邻),导致拆分的三角形逻辑完全错误,面积求和自然不对。比如你选的
(x3,y3)是(1,5),它和(x2,y2)=(4,2)并不是矩形的相邻顶点,计算PBC的面积毫无意义。 - 矩形面积计算未取绝对值:原代码计算
ABCD面积时没加绝对值,结果可能是负数,和后面取了绝对值的三角形面积无法匹配。 - 浮点数直接用
==比较:浮点数计算存在精度丢失,直接用==判断相等会导致误判。
解决方案
方案1:修正面积法(适用于任意方向的矩形)
先把顶点按顺时针/逆时针连续排列,修正面积计算逻辑,并用精度阈值判断相等:
public class Main { public static void main(String[] args) { // 按顺时针顺序排列的矩形顶点:(1,2) → (4,2) → (4,5) → (1,5) → (1,2) int x1 = 1, y1 = 2; int x2 = 4, y2 = 2; int x3 = 4, y3 = 5; int x4 = 1, y4 = 5; // 重复的第五个坐标直接忽略 int x5 = 1, y5 = 2; // 待检测的点 int x = 2, y = 2; if (checkPointByArea(x1, y1, x2, y2, x3, y3, x4, y4, x, y)) { System.out.println("Yes, given point lies inside rectangle"); } else { System.out.println("No, given point does not lie inside rectangle"); } } // 计算三角形面积(带绝对值) static float triangleArea(int x1, int y1, int x2, int y2, int x3, int y3) { return (float) Math.abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0); } // 用面积法判断点是否在矩形内 static boolean checkPointByArea(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int x, int y) { // 计算矩形面积:拆分为两个三角形的面积之和 float rectArea = triangleArea(x1, y1, x2, y2, x3, y3) + triangleArea(x1, y1, x3, y3, x4, y4); // 计算点与矩形四条边组成的四个三角形面积之和 float sumTriArea = triangleArea(x, y, x1, y1, x2, y2) + triangleArea(x, y, x2, y2, x3, y3) + triangleArea(x, y, x3, y3, x4, y4) + triangleArea(x, y, x4, y4, x1, y1); // 用精度阈值判断面积是否相等,避免浮点数精度问题 return Math.abs(rectArea - sumTriArea) < 1e-6; } }
方案2:轴对齐矩形快速判断(适用于你的例子,效率更高)
如果你的矩形是轴对齐的(即边平行于x/y轴),直接判断点的坐标是否在矩形的x、y范围内即可,比面积法简单高效:
public class Main { public static void main(String[] args) { int x1 = 1, y1 = 2; int x2 = 4, y2 = 2; int x3 = 1, y3 = 5; int x4 = 4, y4 = 5; // 待检测的点 int x = 2, y = 2; if (checkPointByAxisAligned(x1, y1, x2, y2, x3, y3, x4, y4, x, y)) { System.out.println("Yes, given point lies inside rectangle"); } else { System.out.println("No, given point does not lie inside rectangle"); } } // 轴对齐矩形的点判断 static boolean checkPointByAxisAligned(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int x, int y) { // 计算x的最小和最大值 int xMin = Math.min(Math.min(x1, x2), Math.min(x3, x4)); int xMax = Math.max(Math.max(x1, x2), Math.max(x3, x4)); // 计算y的最小和最大值 int yMin = Math.min(Math.min(y1, y2), Math.min(y3, y4)); int yMax = Math.max(Math.max(y1, y2), Math.max(y3, y4)); // 判断点是否在范围内(包含边界) return x >= xMin && x <= xMax && y >= yMin && y <= yMax; } }
关于经纬度的注意事项
如果是实际的地理经纬度(球面坐标),不能直接用平面矩形判断,需要考虑球面投影或使用地理范围判断的专用方法,但如果你的场景是把经纬度当作平面坐标处理,上面的代码可以直接使用。
内容的提问来源于stack exchange,提问作者Sammy65
相关产品推荐
相关产品推荐

