4

In a Ruby-on-Rails application, I need the area in square meters (or any other surface measure, be it ares, hectares, square kilometers, but not in pseudo surface measure like square degrees) of a geographic polygon.

The application already uses rgeo and PostGIS (via the activerecord-postgis-adapter) and already requires rgeo's optional libGEOS support. So I'd like to make use of these tools for the area calculation, too.

I can use PostGIS (via the activerecord-postgis-adapter) to compute the area of any rgeo geometry:

def calculate_area(geometry)
  ActiveRecord::Base.connection.execute("
  SELECT
    ST_Area(
      geography(
        ST_Transform(
          ST_GeomFromText('#{geometry.as_json}', #{geometry.srid}),
          4326
        )
      )
    ) AS area;
  ")[0]['area'].to_f
end

(Nesting ST_Area()'s argument in geography() is what causes the result to be in square meters.)

However, having to extract the result from execute()'s return value and having the lengthy SQL code embedded in Ruby is rather ugly.

Also, rgeo already provides an area method on the RGeo::Feature::Surface module, which RGeo::Feature::Polygon includes. Its default implementation just isn't all that useful:

srs_db = RGeo::CoordSys::SRSDatabase::ActiveRecordTable.new
wgs84_factory = RGeo::Geographic.spherical_factory(srid: 4326, srs_database: srs_db)

# 1/8 of the Earth, should be around 6.4e13 sqm
polygon = wgs84_factory.parse_wkt('POLYGON ((0 0, 0 90, 90 0, 0 0))')

polygon.area # RGeo::Error::UnsupportedOperation: Method Surface#area not defined.

I have installed rgeo such that it can use libGEOS, which I can verify like so:

RGeo::GEOS.supported? # true

Thus, I thought that I might be luckier with a GEOS-specific factory:

geos_wgs84_factory = RGeo::Geos.factory(srid: 4326, srs_database: srs_db)
geos_polygon = RGeo::Feature.cast(polygon, geos_wgs84_factory)
geos_polygon.area # 4050.0

Well, that's the area in square degrees (90° ⨉ 90° / 2). How can I get the area in square meters without calculating it myself and without longish SQL?

Must I convert my polygon to an area-preserving projected coordinate reference system? (Those seem to come with a working area method in rgeo.) That'd feel kinda wrong to me, but maybe it's still the right thing to do.

das-g
  • 1,445
  • 2
  • 11
  • 33

2 Answers2

4

Yes, if you want ST_Area() on a bare geometry to return a planar area, you need to use an area-preserving CRS. GEOS is not magic, it just works in whatever units are handed to it, assuming cartesian math, so the expectation in a planar CRS if you want useful areas/lengths etc.

Paul Ramsey
  • 19,865
  • 1
  • 47
  • 57
0

Get the geometry from json, convert it to a projected CRS, and then do your calculation on the converted geometry.

gavit
  • 101
  • 1