我有一個Lat/Long座標列表,它表示一個多邊形和一個單獨的Lat/Long,我知道它包含在多邊形中。Lat/Long與由Lat/Longs組成的多邊形的最近邊之間的距離是多少?
如何確定從單個經緯度到多邊形最近邊緣的距離?有沒有一個已知的Java庫?
我有一個Lat/Long座標列表,它表示一個多邊形和一個單獨的Lat/Long,我知道它包含在多邊形中。Lat/Long與由Lat/Longs組成的多邊形的最近邊之間的距離是多少?
如何確定從單個經緯度到多邊形最近邊緣的距離?有沒有一個已知的Java庫?
你可以通過你所有的邊圈和計算這樣兩個點之間的距離:我希望這對你的作品,這是「簡單的」矢量數學
function double calculateDistance(
double edgeLat1, double edgeLng1,
double edgeLat2, double edgeLng2,
double pointLat, double pointLng) {
//calculate straight/edge
double mS = (edgeLng2 - edgeLng1)/(edgeLat2- edgeLat2);
double tS = edgeLng1 - edgeLng1 * mS;
//calculate helper straight
double mH = -mS;
double tH = pointLng - mH * pointLat;
//calcuate straight intersection
xI = (tH - tS)/(mS - mH);
yI = mH * xI - tH;
//calculate distance
/* in degree
double dInDegree = Math.sqrt((pointLat - xI) * (pointLat - xI)
+ (pointLng - yI) * (pointLng - yI));
return dInDegree;
*/
//in meter
double R = 6371000; // m
double dLat = (pointLat-xI).toRad();
double dLon = (pointLng-yI).toRad();
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(x1.toRad()) * Math.cos(pointLat.toRad()) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double distanceInMeter = R * c;
return distanceInMeter;
}
。
檢查單個單獨緯度/長度,查找列表中存在的最近座標。
然後收集連接到該座標的兩個點(離您的單點最近的那個點)所以現在您有4個點。
singlePoint,closestPointToSinglePoint,neighbor1,neighbor2。我假設你在這一點上有一些基本的觸發經驗(沒有雙關意圖)。你應該從這裏做什麼是可視化2個三角形。 (singlePoint,closestPointToSinglePoint,neighbor1)和(singlePoint,closestPointToSinglePoint,neighbor2)。
此時,計算單點的三角形高度作爲參考。你現在有2個距離到2個最近的邊緣。比較,並享受您的結果。
爲了便於說明,請使用Edge(Neighbor#和closestPointToSinglePoint之間的邊)作爲計算的基礎。 Area = 1/2 Base *高度。所以對於高度= h = 2 * A/b – Lencalot
我建議下面的解決方案,它也適用於圍繞北極的多邊形,其中經度和緯度差異的計算沒有意義。
該解決方案通過使用World Geodetic System 84將地球上各點的經緯度轉換爲三維座標。使用這些三維點,您可以計算三維空間中由另外兩個點定義的線上一點的投影。
這是執行計算的代碼。它使用類javafx.geometry.Point3D
,提供的Java 8
/** Semi-major axis of earth in meter */
public static final double WGS84_A = 6378137.0;
/** Semi-minor axis of earth in meter */
public static final double WGS84_B = 6356752.314245;
/** Eccentricity of earth */
public static final double WGS84_E =
Math.sqrt((WGS84_A * WGS84_A)/(WGS84_B * WGS84_B) - 1);
public static final double DEGREES_TO_RADIANS = Math.PI/180;
/**
* Calculates a three-dimensional point in the
* World Geodetic System (WGS84) from latitude and longitude.
*/
public static Point3D latLonToPoint3D(double lat, double lon) {
double clat = Math.cos(lat * DEGREES_TO_RADIANS);
double slat = Math.sin(lat * DEGREES_TO_RADIANS);
double clon = Math.cos(lon * DEGREES_TO_RADIANS);
double slon = Math.sin(lon * DEGREES_TO_RADIANS);
double N = WGS84_A/Math.sqrt(1.0 - WGS84_E * WGS84_E * slat * slat);
double x = N * clat * clon;
double y = N * clat * slon;
double z = N * (1.0 - WGS84_E * WGS84_E) * slat;
return new Point3D(x, y, z);
}
/**
* Calculates distance of projection p of vector a on vector b.
*
* Use formula for projection, with p being the projection point:
* <p>
* p = a X b/|b|^2 * b
* </p>
* X being the dot product, * being multiplication of vector and constant
*/
public static Point3D calculateProjection(Point3D a, Point3D b) {
return b.multiply(a.dotProduct(b)/(b.dotProduct(b)));
}
/**
* Calculates shortest distance of vector x and the line defined by
* the vectors a and b.
*/
public static double calculateDistanceToLine(Point3D x, Point3D a, Point3D b) {
Point3D projectionOntoLine =
calculateProjection(x.subtract(a), b.subtract(a)).add(a);
return projectionOntoLine.distance(x);
}
通過調用calculateDistanceToLine
用點和多邊形細分點,你能夠找到的邊緣點定義和擴展到無窮遠最近的線路。如果是凹多邊形,這可能不是你想要的,就像你在圖片中看到的那樣。
考慮到多邊形邊緣的距離必須至少只要到最近的邊緣點的距離,你可以得到的距離邊緣爲:
Math.max(calculateDistanceToLine(x, edgePoint1, edgePoint2),
Math.min(x.distance(edgePoint1), x.distance(edgePoint2)));
注意,這個計算結果也不是地球表面的距離,而是直接穿過地球的距離。無論如何,它應該足以選擇最短的距離。
函數latLonToPoint3D
是我找到的函數的修改版本here。
這找到最近的角落,而不是最近的邊緣。如果提問者關心固定單位的距離(例如公里/英里)而不是緯度/經度,這也可能是錯誤的。 – Sbodd
對不起,花了這麼長時間,但我沒有能夠做到這一點。在我的第一個答案之前,我無法閱讀;)現在它應該適合你! –