我有一个Lat / Long坐标列表,它代表一个多边形和一个单独的Lat / Long,我知道它包含在多边形内。
如何确定从单个Lat / Long到多边形最近边缘的距离?是否有一个已知的Java库?
答案 0 :(得分:1)
我建议使用以下解决方案,这也适用于北极周围的多边形,其中经度和纬度差的计算没有意义。
该解决方案使用World Geodetic System 84将地球上的点的经度和纬度转换为三维坐标。使用这些三维点,您可以计算一个点在三维空间中由另外两个点定义的线上的投影。
这是进行计算的代码。它使用Java 8中提供的类javafx.geometry.Point3D
。
/** 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
&#39;点,您可以找到由边缘点定义的最近的线并扩展到无穷大。如果是凹面多边形,可能不是您想要的,如图所示。
考虑到到多边形边缘的距离必须至少与到最近边缘点的距离一样长,您可以得到到边缘的距离:
Math.max(calculateDistanceToLine(x, edgePoint1, edgePoint2),
Math.min(x.distance(edgePoint1), x.distance(edgePoint2)));
请注意,此计算也不会产生地球表面上的距离,而是直接穿过地球的距离。无论如何,它应该足以选择最短的距离。
函数latLonToPoint3D
是我找到here函数的修改版本。
答案 1 :(得分:0)
你可以循环遍历所有边缘并计算两点之间的距离,如下所示:
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;
}
我希望这适合你,这是“简单的”矢量数学。
答案 2 :(得分:0)
检查Single Separate Lat / Long,查看列表中最近的坐标。
然后收集连接到该坐标的两个点(最接近您的单点的点)所以现在你有4个点。
singlePoint,nearestPointToSinglePoint,neighbor1,neighbor2。我假设你在这一点上有一些基本的触发经验(没有双关语意)。你应该从这里做的是可视化2个三角形。 (singlePoint,nearestPointToSinglePoint,neighbor1)和(singlePoint,nearestPointToSinglePoint,neighbor2)。
此时,从SinglePoint计算三角形的高度作为参考。您现在距离最近的2个边缘有2个距离。比较,享受你的结果。