Map 使用笛卡尔空间和世界文件生成的纬度和经度计算多边形面积
给定一系列GPS坐标对,我需要计算多边形(n-gon)的面积。这相对较小(不超过50000平方英尺)。地理编码是通过对世界文件中的数据应用仿射变换创建的 我尝试使用两步方法,将地理代码转换为笛卡尔坐标:Map 使用笛卡尔空间和世界文件生成的纬度和经度计算多边形面积,map,geocoding,latitude-longitude,area,Map,Geocoding,Latitude Longitude,Area,给定一系列GPS坐标对,我需要计算多边形(n-gon)的面积。这相对较小(不超过50000平方英尺)。地理编码是通过对世界文件中的数据应用仿射变换创建的 我尝试使用两步方法,将地理代码转换为笛卡尔坐标: double xPos = (lon-lonAnchor)*( Math.toRadians( 6378137 ) )*Math.cos( latAnchor ); double yPos = (lat-latAnchor)*( Math.toRadians( 6378137 ) ); 然后我
double xPos = (lon-lonAnchor)*( Math.toRadians( 6378137 ) )*Math.cos( latAnchor );
double yPos = (lat-latAnchor)*( Math.toRadians( 6378137 ) );
然后我用一个计算来确定面积
问题是结果的准确性有点差(大约1%)。有什么可以改进的吗
谢谢。1%的误差似乎有点高,因为只是您的近似值。您是在与实际测量值还是一些理想的计算值进行比较?请记住,GPS中也存在可能是原因之一的错误
若你们想要一个更准确的方法来做这件事,在这个问题上有一个很好的答案。如果您想以更快的方式进行转换,可以使用WGS84大地水准面而不是参考球体来转换为笛卡尔坐标(ECEF)。这是转换的方法。我正在修改谷歌地图,以便用户可以计算面积 通过单击顶点创建多边形的顶点。它没有给出正确的答案 区域,直到我确定Math.cos(latAnchor)首先以弧度为单位 因此: 成为:
double xPos = (lon-lonAnchor)*( 6378137*PI/180 ) )*Math.cos( latAnchor*PI/180 );
其中lon、lonAnchor和latAnchor以度为单位。现在工作起来很有魅力。我在互联网上查看了各种多边形面积公式(或代码),但没有找到一个好的或易于实现的公式 现在,我已经编写了计算地球表面上绘制的多边形面积的代码片段。多边形可以有n个顶点,每个顶点都有自己的经纬度 要点不多
private static double CalculatePolygonArea(IList<MapPoint> coordinates)
{
double area = 0;
if (coordinates.Count > 2)
{
for (var i = 0; i < coordinates.Count - 1; i++)
{
MapPoint p1 = coordinates[i];
MapPoint p2 = coordinates[i + 1];
area += ConvertToRadian(p2.Longitude - 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;
}
专用静态双计算多边形区域(IList坐标)
{
双面积=0;
如果(坐标数>2)
{
对于(变量i=0;i
基于Risky Pathak的解决方案,这里是SQL(红移)计算面积的解决方案(假设linestring 0是最外层的多边形)
将RiskyPathak的代码片段改编为PHP
function CalculatePolygonArea($coordinates) {
$area = 0;
$coordinatesCount = sizeof($coordinates);
if ($coordinatesCount > 2) {
for ($i = 0; $i < $coordinatesCount - 1; $i++) {
$p1 = $coordinates[$i];
$p2 = $coordinates[$i + 1];
$p1Longitude = $p1[0];
$p2Longitude = $p2[0];
$p1Latitude = $p1[1];
$p2Latitude = $p2[1];
$area += ConvertToRadian($p2Longitude - $p1Longitude) * (2 + sin(ConvertToRadian($p1Latitude)) + sin(ConvertToRadian($p2Latitude)));
}
$area = $area * 6378137 * 6378137 / 2;
}
return abs(round(($area));
}
function ConvertToRadian($input) {
$output = $input * pi() / 180;
return $output;
}
函数计算多边形区域($coordinates){
$area=0;
$CoordinateCount=sizeof($coordinates);
如果($CoordinateCount>2){
对于($i=0;$i<$CoordinateCount-1;$i++){
$p1=$coordinates[$i];
$p2=$coordinates[$i+1];
$p1经度=$p1[0];
$p2经度=$p2[0];
$p1纬度=$p1[1];
$p2纬度=$p2[1];
$area+=convertoradian($p2经度-$p1经度)*(2+sin(convertoradian($p1经度))+sin(convertoradian($p2经度));
}
$area=$area*6378137*6378137/2;
}
返回abs(圆形($area));
}
函数转换器半径($input){
$output=$input*pi()/180;
返回$output;
}
谢谢你
本着分享的精神,以下是我在德尔福的改编:
interface
uses
System.Math;
TMapGeoPoint = record
Latitude: Double;
Longitude: Double;
end;
function AreaInAcres(AGeoPoints: TList<TMapGeoPoint>): Double;
implementation
function AreaInAcres(AGeoPoints: TList<TMapGeoPoint>): Double;
var
Area: Double;
i: Integer;
P1, P2: TMapGeoPoint;
begin
Area := 0;
// We need at least 2 points
if (AGeoPoints.Count > 2) then
begin
for I := 0 to AGeoPoints.Count - 1 do
begin
P1 := AGeoPoints[i];
if i < AGeoPoints.Count - 1 then
P2 := AGeoPoints[i + 1]
else
P2 := AGeoPoints[0];
Area := Area + DegToRad(P2.Longitude - P1.Longitude) * (2 +
Sin(DegToRad(P1.Latitude)) + Sin(DegToRad(P2.Latitude)));
end;
Area := Area * 6378137 * 6378137 / 2;
end;
Area := Abs(Area); //Area (in sq meters)
// 1 Square Meter = 0.000247105 Acres
result := Area * 0.000247105;
end;
接口
使用
系统数学;
TMapGeoPoint=记录
纬度:双倍;
经度:双倍;
结束;
功能区域索引(AGeoPoints:TList):双精度;
实施
功能区域索引(AGeoPoints:TList):双精度;
变量
面积:双;
i:整数;
P1,P2:TMapGeoPoint;
开始
面积:=0;
//我们至少需要2分
如果(AGeoPoints.Count>2),则
开始
对于I:=0到AGeoPoints.Count-1 do
开始
P1:=年龄点[i];
如果我
将RiskyPathak的代码片段改编成Ruby
def deg2rad(输入)
输入*数学::PI/180.0
结束
def polygone_区域(坐标)
返回0.0,除非坐标.size>2
面积=0.0
coor_p=坐标。首先
坐标[1..-1]。每个{coor|
面积+=deg2rad(coor[1]-coor_p[1])*(2+数学sin(deg2rad(coor_p[0]))+数学sin(deg2rad(coor[0]))
coor_p=coor
}
(面积*6378137*6378137/2.0)。以米为单位的地球半径
结束
我正在与已知区域的实际测量值进行比较。有趣的是,如果我通过哈弗森方法运行GPS坐标,我会得到非常精确的距离计算,从而产生精确的周长值。很抱歉响应太晚,最终使用了带有proj4 java库的WGs84大地水准面。效果很好,感谢帮助。我尝试了你的代码,但出现了问题。有什么想法吗?请参阅:你已经输入了“area=area*R*R/2在for循环内部,而它应该在循环外部。我认为您应该将p1.经度
和p2.经度
也转换为弧度。在进行此修改后,我得到了与google.maps.geometry.sphereal.computeArea
函数非常相似的结果。经过更正后,这看起来很好。而且非常相似作为开放层中的getGeodesicArea
(减去投影pa
function CalculatePolygonArea($coordinates) {
$area = 0;
$coordinatesCount = sizeof($coordinates);
if ($coordinatesCount > 2) {
for ($i = 0; $i < $coordinatesCount - 1; $i++) {
$p1 = $coordinates[$i];
$p2 = $coordinates[$i + 1];
$p1Longitude = $p1[0];
$p2Longitude = $p2[0];
$p1Latitude = $p1[1];
$p2Latitude = $p2[1];
$area += ConvertToRadian($p2Longitude - $p1Longitude) * (2 + sin(ConvertToRadian($p1Latitude)) + sin(ConvertToRadian($p2Latitude)));
}
$area = $area * 6378137 * 6378137 / 2;
}
return abs(round(($area));
}
function ConvertToRadian($input) {
$output = $input * pi() / 180;
return $output;
}
interface
uses
System.Math;
TMapGeoPoint = record
Latitude: Double;
Longitude: Double;
end;
function AreaInAcres(AGeoPoints: TList<TMapGeoPoint>): Double;
implementation
function AreaInAcres(AGeoPoints: TList<TMapGeoPoint>): Double;
var
Area: Double;
i: Integer;
P1, P2: TMapGeoPoint;
begin
Area := 0;
// We need at least 2 points
if (AGeoPoints.Count > 2) then
begin
for I := 0 to AGeoPoints.Count - 1 do
begin
P1 := AGeoPoints[i];
if i < AGeoPoints.Count - 1 then
P2 := AGeoPoints[i + 1]
else
P2 := AGeoPoints[0];
Area := Area + DegToRad(P2.Longitude - P1.Longitude) * (2 +
Sin(DegToRad(P1.Latitude)) + Sin(DegToRad(P2.Latitude)));
end;
Area := Area * 6378137 * 6378137 / 2;
end;
Area := Abs(Area); //Area (in sq meters)
// 1 Square Meter = 0.000247105 Acres
result := Area * 0.000247105;
end;