私は2つの場所のセットがA(20Kの場所)とB(2kの場所)と言います。私は緯度と経度に基づいて、セットAのすべてのロケーションのセットを、セットBの最も近いロケーションにマップしたいと考えています。緯度と経度に基づいて最も近い位置に地図を表示
JavaまたはRには解決策がありますか。 Javaソリューションが優先されます。
私は2つの場所のセットがA(20Kの場所)とB(2kの場所)と言います。私は緯度と経度に基づいて、セットAのすべてのロケーションのセットを、セットBの最も近いロケーションにマップしたいと考えています。緯度と経度に基づいて最も近い位置に地図を表示
JavaまたはRには解決策がありますか。 Javaソリューションが優先されます。
私はコメントに@STaefiに同意します。少なくとも小文字のビットを表示してから、他の人にコードを書くように依頼することをお勧めします。あなたの問題は、私の時間の数分をつかむのに十分なほど興味をそそられているので、ここには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
または、我々はポイントを取るが、マトリックスとして@rosscova
からの回答からもpointsA
closest.points <- lapply(seq_len(nrow(pointsA)),
function(x) {
closest_point(lat1 = pointsA[x,"lat"],
lon1 = pointsA[x,"lon"],
lat2 = pointsB[,"lat"],
lon2 = pointsB[,"lon"])
})
closest.points <- do.call(rbind, closest.points)
closest.points
# lat lon
# 1 11 15
# 2 11 15
# 3 15 15
内の各点についてpointsB
から最も近い点を返し、pointsA
からすべてのポイントに適用することができます座標を扱うとき
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)))
次に、あなたの代わりに、ユークリッド距離グレートサークル(WGS84楕円体)を使用することを好むことがあります。私は通常に最も近いpointBを取得するには、行を超えるwhich.minで関数を適用を使用してSPパッケージから
library(sp)
out_Dists <- spDists(x = pointsA, y = pointsB, longlat = TRUE, segments = FALSE, diagonal = FALSE)
と終わりをspDists機能を使用しますpointA
pointsA[ apply(out_Dists, 1, which.min), ]
私の解決策よりもはるかに良い、spDistsを使用して素晴らしいアイデア。私は出力よりも有用かもしれない参照ではなく、ポイントを出力するように編集しました。 – rosscova
ありがとう!はい、必要な出力が場所の地図でなければならないので、より便利です。 OPの返事を待ってみましょう! –
'apply(out_Dists、1、which.min)'から返されたベクトルは、MARGIN 1を使って参照するdata.frame 'pointsA'のような長さ3になるので、私は再度答えを編集しました。マージン2はdf点Bへの参照を修正する。 –
ここはJavaのものです。緯度と経度を正規化されたベクトル表現に変換することによって数学は単純化され、2つのベクトルが大きいほど、そのドット積は大きくなる(それらが等しいときに近づく)。
これは、地球が球形であることを前提としています。 「完璧な」結果が必要な場合は、より近似した座標を変換する必要があります(たとえば、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};
}
}
私はすべての点についてすべての距離を計算する必要があると思います。私が考えることができる他のすべてのアイデアは、まず距離が必要です... – IQV
これらの位置は、メモリ内でダイナミックにセットAとセットBになっていますか?それとも、データベースの中にそれらを持っているのでしょうか?あなたのアプリが実行されるたびにマップメモリを構築する必要がある場合は、パフォーマンスが非常に良い必要があります。しかし、1回の操作しかできず、マップをどこかに残すことができれば、非常に最適化する必要はありません。それは簡単です。集合Aのすべての場所がBのそれらの場所との最小距離を計算するので、 'O(n * n)'からでしょう – STaefi
プラス誰もあなたのためにそれを書いてくれません。あなた自身でそれを行う必要がありますし、何か問題があれば、助けを得るために[MCVE]を提供する必要があります。 – STaefi