Map 使用笛卡尔空间和世界文件生成的纬度和经度计算多边形面积

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 ) ); 然后我

给定一系列GPS坐标对,我需要计算多边形(n-gon)的面积。这相对较小(不超过50000平方英尺)。地理编码是通过对世界文件中的数据应用仿射变换创建的

我尝试使用两步方法,将地理代码转换为笛卡尔坐标:

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个顶点,每个顶点都有自己的经纬度

要点不多

  • 此函数的数组输入将有“n+1”个元素。最后一个元素的值与第一个元素的值相同
  • 我已经编写了非常基本的C#代码,这样人们也可以用其他语言进行修改
  • 6378137是以米为单位的地球半径值
  • 输出面积以平方米为单位

    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;