我有两组位置说A(20K位置)和B(2k位置)。我希望根据它们的纬度和经度,将集合A中所有位置的地图设置为集合B中的最近位置。
java或R中是否有任何解决方案 Java解决方案首选。
答案 0 :(得分:2)
来自@rosscova的回答
取点,但作为矩阵
pointsA <- as.matrix(data.frame( lat = c( 10, 12, 20 ), lon = c( 12, 17, 10 ) ))
pointsB <- as.matrix(data.frame( lat = c( 11, 15 ), lon = c( 15, 15 ) ))
然后,在处理坐标时,您可能更喜欢使用Great Circle(WGS84椭球)距离而不是欧几里德。我通常使用 sp 包中的 spDists 功能
library( sp )
out_Dists <- spDists(x = pointsA, y = pointsB, longlat = TRUE, segments = FALSE, diagonal = FALSE)
并最后使用应用功能,并在行上使用 which.min 来获取最近的 pointB 到 pointA 强>
pointsA[ apply(out_Dists, 1, which.min), ]
答案 1 :(得分:1)
我同意@STaefi的评论,在你要求其他人为你编写代码之前,至少要显示一些一点的工作是个好主意。话虽如此,你的问题引起了我的兴趣,足以抓住我几分钟的时间,所以这是myEnterFunction()
中的方法。请注意,这只是将距离视为坐标的R
函数,除了在赤道以外的任何地方都不准确。如果您需要更高的准确度,则需要对其进行修改以适应。
采用一个小的假设数据集:
sqrt(a^2+b^2)
编写一个计算最近点的函数:
pointsA <- data.frame( lat = c( 10, 12, 20 ), lon = c( 12, 17, 10 ) )
pointsB <- data.frame( lat = c( 11, 15 ), lon = c( 15, 15 ) )
我们可以在closest_point <- function( lat1, lon1, lat2, lon2 ) {
x_dist <- abs( lon1 - lon2 )
y_dist <- abs( lat1 - lat2 )
dist <- sqrt( x_dist ^ 2 + y_dist ^ 2 )
closest <- data.frame( lat = lat2[ which.min( dist ) ],
lon = lon2[ which.min( dist ) ] )
return( closest )
}
的单个点上执行该功能,返回距pointsA
最近的点:
pointsB
或者,我们可以将其应用于closest_point( pointsA[1,"lat"], pointsA[1,"lon"], pointsB[,"lat"], pointsB[,"lon"] )
# lat lon
# 1 11 15
的所有点,并为pointsA
pointsB
的最近点
pointsA
答案 2 :(得分:0)
这是Java中的一个。通过将纬度和经度转换为标准化矢量表示来简化数学运算,并注意到两个矢量越接近它们的点积(当它们相等时接近一个)。
这假设地球是球形的。如果你想要&#34;完美&#34;结果您需要使用更接近的近似值来转换坐标(例如,WGS84)。
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.Math.*;
public class LatLong {
public static void main(String[] args) throws Exception {
// A random lat/long
double[] target = randLatLong();
// Transform to ECEF vector
double[] targetv = toEcef(target);
// 2000 random candidates
List<double[]> b = Stream.generate(LatLong::randLatLong).limit(2000).collect(Collectors.toList());
// Transform candidates to ECEF representation
List<double[]> bv = b.stream().map(LatLong::toEcef).collect(Collectors.toList());
// Find the closest candidate to the target
int i = closest(targetv, bv);
System.out.println("Closest point to " + target[0] + ", " + target[1] + " is " + b.get(i)[0] + ", " + b.get(i)[1]);
}
// index of closest vector to target from list of candidates
public static int closest(double[] target, List<double[]> candidates) {
double p = Double.MIN_VALUE;
int closest = -1;
for (int i = 0; i < candidates.size(); i++) {
double next = dotProduct(target, candidates.get(i));
if (next > p) {
p = next;
closest = i;
}
}
return closest;
}
// dot product of two 3vectors
public static double dotProduct(double[] v1, double[] v2) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
// lat/long in degrees to normalised ECEF vector
public static double[] toEcef(double[] latLong) {
return toEcef(toRadians(latLong[0]), toRadians(latLong[1]));
}
// lat/long in radians to normalised ECEF vector
public static double[] toEcef(double φ, double λ) {
return new double[] {cos(φ) * cos(λ), cos(φ) * sin(λ), sin(φ)};
}
// A random lat/long
public static double[] randLatLong() {
return new double[] {Math.random() * 180 - 90, Math.random() * 360 - 180};
}
}