Polygon area calculation using Latitude and Longitude generated from Cartesian space and a world file

后端 未结 7 1888
孤街浪徒
孤街浪徒 2020-11-27 22:16

Given a series of GPS coordinate pairs, I need to calculate the area of a polygon (n-gon). This is relatively small (not larger than 50,000 sqft). The geocodes are created

相关标签:
7条回答
  • 2020-11-27 22:24

    Thank you Risky Pathak!

    In the spirit of sharing, here's my adaptation in Delphi:

    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;
    
    0 讨论(0)
  • 2020-11-27 22:29

    Adapted RiskyPathak's snippet to 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;
    }
    
    0 讨论(0)
  • 2020-11-27 22:31

    Based on the solution by Risky Pathak here is the solution for SQL (Redshift) to calculate areas for GeoJSON multipolygons (with the assumption that linestring 0 is the outermost polygon)

    create or replace view geo_area_area as 
    with points as (
        select ga.id as key_geo_area
        , ga.name, gag.linestring
        , gag.position
        , radians(gag.longitude) as x
        , radians(gag.latitude) as y
        from geo_area ga
        join geo_area_geometry gag on (gag.key_geo_area = ga.id)
    )
    , polygons as (
        select key_geo_area, name, linestring, position 
        , x
        , lag(x) over (partition by key_geo_area, linestring order by position) as prev_x
        , y
        , lag(y) over (partition by key_geo_area, linestring order by position) as prev_y
        from points
    )
    , area_linestrings as (
        select key_geo_area, name, linestring
        , abs( sum( (x - prev_x) * (2 + sin(y) + sin(prev_y)) ) ) * 6378137 * 6378137 / 2 / 10^6 as area_km_squared
        from polygons
        where position != 0
        group by 1, 2, 3
    )
    select key_geo_area, name
    , sum(case when linestring = 0 then area_km_squared else -area_km_squared end) as area_km_squared
    from area_linestrings
    group by 1, 2
    ;
    
    
    0 讨论(0)
  • 2020-11-27 22:31

    Adapted RiskyPathak's snippet to Ruby

    def deg2rad(input)
      input * Math::PI / 180.0
    end
    
    def polygone_area(coordinates)
      return 0.0 unless coordinates.size > 2
    
      area = 0.0
      coor_p = coordinates.first
      coordinates[1..-1].each{ |coor|
        area += deg2rad(coor[1] - coor_p[1]) * (2 + Math.sin(deg2rad(coor_p[0])) + Math.sin(deg2rad(coor[0])))
        coor_p = coor
      }
    
      (area * 6378137 * 6378137 / 2.0).abs # 6378137 Earth's radius in meters
    end
    
    0 讨论(0)
  • 2020-11-27 22:32

    I am modifying a Google Map so that a user can calculate the area of a polygon by clicking the vertices. It wasn't giving correct areas until I made sure the Math.cos(latAnchor) was in radians first

    So:

    double xPos = (lon-lonAnchor)*( Math.toRadians( 6378137 ) )*Math.cos( latAnchor );
    

    became:

    double xPos = (lon-lonAnchor)*( 6378137*PI/180 ) )*Math.cos( latAnchor*PI/180 );
    

    where lon, lonAnchor and latAnchor are in degrees. Works like a charm now.

    0 讨论(0)
  • 2020-11-27 22:42

    1% error seems a bit high due to just your approximation. Are you comparing against actual measurements or some ideal calculation? Remember that there is error in the GPS as well that might be contributing.

    If you want a more accurate method for doing this there's a good answer at this question. If you're going for a faster way you can use the WGS84 geoid instead of your reference sphere for converting to cartesian coordinates (ECEF). Here's the wiki link for that conversion.

    0 讨论(0)
提交回复
热议问题