如何筛选大不列颠岛本土范围内的英国OS格网参考坐标?
改进OS格网坐标校验:精准筛选大不列颠岛本土坐标
嗨,我懂你现在的困扰——用简单矩形范围校验OS格网坐标实在太粗糙了,会把爱尔兰海、北海甚至部分海外区域的坐标误判为有效。下面给你几个不需要外部库或网络服务的可行方案,精度比矩形校验高得多:
方案1:分区域细化边界范围
OS格网是按100km正方形划分字母区域的,我们可以针对每个大不列颠岛覆盖的区域,设置更精准的东向/北向边界,而不是用统一的矩形。
比如,我们可以把有效区域拆分为多个子范围,每个子范围对应OS格网的一个字母区块的有效部分:
public static boolean isValidGB(int easting, int northing) { // 先快速排除完全超出OS格网理论范围的坐标 if (easting < 0 || easting > 700000 || northing < 0 || northing > 1300000) { return false; } // 按100km区块划分(东向/北向每100000为一个区间) int eBlock = easting / 100000; int nBlock = northing / 100000; // 针对每个区块设置精准边界 switch (eBlock) { case 0: // 苏格兰西部区块 return northing >= 600000 && northing <= 1250000; case 1: // 苏格兰中北部、英格兰西北部区块 if (northing >= 1000000) return true; // 北部区域全有效 return northing >= 300000 && northing <= 950000; case 2: // 英格兰中北部区块 return northing >= 200000 && northing <= 1000000; case 3: // 英格兰中西部、威尔士区块 if (northing >= 500000) return true; // 北部区域全有效 return northing >= 100000 && northing <= 450000; // 威尔士核心区域 case 4: // 英格兰南部、威尔士南部区块 return northing >= 0 && northing <= 500000; case 5: // 英格兰东南部区块 return northing >= 0 && northing <= 550000; case 6: // 英格兰最东南部区块 return northing >= 100000 && northing <= 500000; default: return false; } }
这个方案比矩形校验精准很多,因为它针对每个区块的实际地理覆盖调整了边界,直接排除了海洋区域。
方案2:射线法多边形点-in-区域判断
如果需要极致精准,我们可以用射线法判断坐标是否在大不列颠岛的轮廓多边形内部。这个算法纯代码实现,不需要任何外部依赖:
首先,你需要提前定义大不列颠岛的简化轮廓顶点数组(可根据需求细化顶点,让轮廓更贴合实际地理边界),然后用射线法判断点是否在多边形内:
// 大不列颠岛简化轮廓的OS格网坐标顶点(示例,可根据需要补充细化) private static final int[][] GB_POLYGON = { {0, 600000}, {100000, 1250000}, {300000, 1000000}, {650000, 550000}, {600000, 0}, {300000, 100000}, {100000, 300000}, {0, 600000} }; public static boolean pointInPolygon(int easting, int northing) { int vertexCount = GB_POLYGON.length; boolean isInside = false; // 遍历多边形的每条边 for (int i = 0, j = vertexCount - 1; i < vertexCount; j = i++) { int xi = GB_POLYGON[i][0], yi = GB_POLYGON[i][1]; int xj = GB_POLYGON[j][0], yj = GB_POLYGON[j][1]; // 判断点是否与当前边相交 boolean intersects = ((yi > northing) != (yj > northing)) && (easting < (xj - xi) * (northing - yi) / (yj - yi) + xi); if (intersects) isInside = !isInside; } return isInside; }
你可以补充更多顶点让轮廓更精准,这样就能彻底排除所有海洋区域的坐标。
方案3:混合策略(性能+精度兼顾)
如果要处理的坐标量很大,单独用多边形判断可能性能不足,我们可以结合两种方案:
- 先用分区域校验快速过滤掉完全不在大不列颠岛的坐标;
- 对剩下的边缘区域坐标(比如靠近海岸线的区块),再用多边形校验确认。
示例代码:
public static boolean isValidGBHybrid(int easting, int northing) { // 第一步:分区域快速过滤 if (!isValidGB(easting, northing)) { return false; } // 第二步:对边缘区块进行多边形校验 int eBlock = easting / 100000; int nBlock = northing / 100000; if ((eBlock == 0 || eBlock == 6) || (nBlock == 0 || nBlock >= 12)) { return pointInPolygon(easting, northing); } // 核心区域直接返回有效 return true; }
这个方案在保证精度的同时,大大提升了处理大量坐标的性能。
内容的提问来源于stack exchange,提问作者simonalexander2005
相关产品推荐
相关产品推荐

