使用纬度和经度计算多边形面积
Polygon area calculation using Latitude and Longitude
我正在使用在此 post 中找到的解决方案:
Polygon area calculation using Latitude and Longitude generated from Cartesian space and a world file
有问题,因为我得到的值不是真实的。例如,我们知道一个足球场应该有 5,300.00 平方米左右,对吗?但计算结果为 5,759,154.21.
这是代码:
private static double CalculatePolygonArea(IList<Position> coordinates)
{
double area = 0;
if (coordinates.Count > 2)
{
for (var i = 0; i < coordinates.Count - 1; i++)
{
Position p1 = coordinates[i];
Position p2 = coordinates[i + 1];
area += (ConvertToRadian(p2.Longitude) - ConvertToRadian(p1.Longitude)) * (2 + Math.Sin(ConvertToRadian(p1.Latitude)) + Math.Sin(ConvertToRadian(p2.Latitude)));
}
area = area * 6378137 * 6378137 / 2;
}
return Math.Abs(area);
}
private static double ConvertToRadian(double input)
{
return input * Math.PI / 180;
}
这里有什么问题吗?有帮助吗?
您使用的面积计算完全错误....:-/
我使用 Google 的 Android Maps Utils 中的 SphericalUtil.ComputeSignedArea
方法。
注意:Google 的 Java 代码在 Apache 许可证版本 2.0 下,我将其转换为 C#。
在我的一个应用程序中查找那个足球场,我得到:4,461,不完全是实际 5,531,但对于使用 Google 地图照片来说还不错。 ..
这里只是 ComputeSignedArea
:
public static class SphericalUtil
{
const double EARTH_RADIUS = 6371009;
static double ToRadians(double input)
{
return input / 180.0 * Math.PI;
}
public static double ComputeSignedArea(IList<LatLng> path)
{
return ComputeSignedArea(path, EARTH_RADIUS);
}
static double ComputeSignedArea(IList<LatLng> path, double radius)
{
int size = path.Count;
if (size < 3) { return 0; }
double total = 0;
var prev = path[size - 1];
double prevTanLat = Math.Tan((Math.PI / 2 - ToRadians(prev.Latitude)) / 2);
double prevLng = ToRadians(prev.Longitude);
foreach (var point in path)
{
double tanLat = Math.Tan((Math.PI / 2 - ToRadians(point.Latitude)) / 2);
double lng = ToRadians(point.Longitude);
total += PolarTriangleArea(tanLat, lng, prevTanLat, prevLng);
prevTanLat = tanLat;
prevLng = lng;
}
return total * (radius * radius);
}
static double PolarTriangleArea(double tan1, double lng1, double tan2, double lng2)
{
double deltaLng = lng1 - lng2;
double t = tan1 * tan2;
return 2 * Math.Atan2(t * Math.Sin(deltaLng), 1 + t * Math.Cos(deltaLng));
}
}
我正在使用在此 post 中找到的解决方案: Polygon area calculation using Latitude and Longitude generated from Cartesian space and a world file
有问题,因为我得到的值不是真实的。例如,我们知道一个足球场应该有 5,300.00 平方米左右,对吗?但计算结果为 5,759,154.21.
这是代码:
private static double CalculatePolygonArea(IList<Position> coordinates)
{
double area = 0;
if (coordinates.Count > 2)
{
for (var i = 0; i < coordinates.Count - 1; i++)
{
Position p1 = coordinates[i];
Position p2 = coordinates[i + 1];
area += (ConvertToRadian(p2.Longitude) - ConvertToRadian(p1.Longitude)) * (2 + Math.Sin(ConvertToRadian(p1.Latitude)) + Math.Sin(ConvertToRadian(p2.Latitude)));
}
area = area * 6378137 * 6378137 / 2;
}
return Math.Abs(area);
}
private static double ConvertToRadian(double input)
{
return input * Math.PI / 180;
}
这里有什么问题吗?有帮助吗?
您使用的面积计算完全错误....:-/
我使用 Google 的 Android Maps Utils 中的 SphericalUtil.ComputeSignedArea
方法。
注意:Google 的 Java 代码在 Apache 许可证版本 2.0 下,我将其转换为 C#。
在我的一个应用程序中查找那个足球场,我得到:4,461,不完全是实际 5,531,但对于使用 Google 地图照片来说还不错。 ..
这里只是 ComputeSignedArea
:
public static class SphericalUtil
{
const double EARTH_RADIUS = 6371009;
static double ToRadians(double input)
{
return input / 180.0 * Math.PI;
}
public static double ComputeSignedArea(IList<LatLng> path)
{
return ComputeSignedArea(path, EARTH_RADIUS);
}
static double ComputeSignedArea(IList<LatLng> path, double radius)
{
int size = path.Count;
if (size < 3) { return 0; }
double total = 0;
var prev = path[size - 1];
double prevTanLat = Math.Tan((Math.PI / 2 - ToRadians(prev.Latitude)) / 2);
double prevLng = ToRadians(prev.Longitude);
foreach (var point in path)
{
double tanLat = Math.Tan((Math.PI / 2 - ToRadians(point.Latitude)) / 2);
double lng = ToRadians(point.Longitude);
total += PolarTriangleArea(tanLat, lng, prevTanLat, prevLng);
prevTanLat = tanLat;
prevLng = lng;
}
return total * (radius * radius);
}
static double PolarTriangleArea(double tan1, double lng1, double tan2, double lng2)
{
double deltaLng = lng1 - lng2;
double t = tan1 * tan2;
return 2 * Math.Atan2(t * Math.Sin(deltaLng), 1 + t * Math.Cos(deltaLng));
}
}