【发布时间】:2012-05-21 06:59:57
【问题描述】:
我有大量的经度和纬度,我想快速找出在某个经度纬度的 5 公里半径范围内的经度和纬度。
我应该能够非常快速地执行 n 个产品,而不是使用数据结构(这将是矫枉过正)。我刚刚做错了什么,似乎看不到什么。
我一直在尝试用 Java 实现这个:
final List<CoOrds> coOrds = Create20x20Grid();
// Determine point X (centre of earth)
final Vector2 X = new Vector2(0,0);
// My CoOrd I want to check
final double srclon = coOrds.get(0).getLongitude();
final double srclat = coOrds.get(0).getLatitude();
final Vector2 A = new Vector2(srclon, srclat, true);
final double brng = 0;
final double d = 5;
final double R = 6371.1;
double dist = 0;
dist = d / R; // convert dist to angular distance in radians
final double lat1 = Math.toRadians(srclat);
final double lon1 = Math.toRadians(srclon);
final double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist)+ Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(lat1),Math.cos(dist) - Math.sin(lat1) * Math.sin(lat2));
// normalise to -180..+180º
lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
//Create another point which is the distance is d away from your point
final Vector2 B = new Vector2(Math.toDegrees(lon2),Math.toDegrees(lat2), true);
// Create a vector from X->A
final Vector2 X_A = new Vector2((A.getX() - X.getX()),(A.getY() - X.getY()));
// Create a vector from X->B
final Vector2 X_B = new Vector2((B.getX() - X.getX()),(B.getY() - X.getY()));
// Normalize XA
final Vector2 nX_A = X_A.normalize();
// Normalize XB
final Vector2 nX_B = X_B.normalize();
// Calculate the Dot Product
final Double Alpha = nX_A.dot(nX_B);
int count = 0;
for (final CoOrds c : coOrds) {
final Vector2 P = c.getPosition();
final Vector2 X_P = new Vector2((P.getX() - X.getX()),(P.getY() - X.getY()));
final Vector2 nX_P = X_P.normalize());
final Double Beta = nX_A.dot(nX_P);
if (Beta < Alpha) {
System.out.println(count + " -- " + Beta + " : " + Alpha);
count++;
}
}
System.out.println("Number of CoOrds within Distance : " + count);
新点 P 是正确的,因为我已将其加载到 Google 地图中,但我不完全确定我的计算是否正确。
我创建了一个自定义 Vector2 类,用于存储经度和纬度。它还将它们转换为笛卡尔:
private void convertSphericalToCartesian(final double latitude, final double longitude) {
x = (earthRadius * Math.cos(latitude) * Math.cos(longitude)) ;
y = (earthRadius * Math.cos(latitude) * Math.sin(longitude)) ;
}
点积:
public double dot(final Vector2 v2) {
return ((getX() * v2.getX()) + (getY() * v2.getY()));
}
标准化:
public Vector2 normalize() {
final double num2 = (getX() * getX()) + (getY() * getY());
final double num = 1d / Math.sqrt(num2);
double a = x;
double b = y;
a *= num;
b *= num;
return new Vector2(a, b);
}
对此的任何帮助将不胜感激
我用过这个网站:http://www.movable-type.co.uk/scripts/latlong.html 帮我计算B点。
我用过这个网站:http://rbrundritt.wordpress.com/2008/10/14/conversion-between-spherical-and-cartesian-coordinates-systems/ 帮助我将球坐标转换为笛卡尔坐标。
谢谢
[编辑]
我目前正在运行的测试用例是:
0-0-0
2-2-0
1-2-0
上面是一个由 9 个点组成的网格。我正在检查的点是“1”。我希望它能够返回所有点“2”。但它正在返回网格中的所有点。我已经手动检查了谷歌地图上的距离,它应该只返回点“2”。
谢谢
【问题讨论】:
-
欢迎来到 Stack Overflow!让陌生人通过检查发现代码中的错误是没有效率的。您应该使用调试器或打印语句来识别(或至少隔离)问题,然后返回一个更具体的问题(一旦将其缩小到 10 行 test-case)。
-
是什么让您认为您的代码有问题?
-
您是在问如何检查您的代码是否正确?
-
对不起,我是新手。基本上我已经建立了一个20x20的测试网格,每个点之间的距离是1km。当我选择一个点来查看 1 公里内有哪些点时,它会返回全部 400。当它实际上应该返回 8 时。
-
@Sonil - 这是很好的信息。将其添加到您的问题中,以便读者知道您的要求。您的第一步似乎是证明您的公式是正确的。用众所周知的答案选择 2 分(不是全部 400 - 这太难了!)并运行您的计算。如果它有效,您就会知道问题出在其他地方。
标签: java math geometry coordinates