Search code examples
ruby-on-railspostgresqlactiverecordgeometrypostgis

Active Record and PostGIS ST_BUFFER: LinearRing failed ring test


An app I'm working on has a regions table containing a geometry column called polygon. The app is using PostGIS via the activerecord-postgis-adapter gem. Active Record migrations involving geometry columns result in a schema that shows:

t.geometry "polygon", limit: {:srid=>0, :type=>"geometry"}

Users can store circles, rectangles, and polygons via a Leaflet.js map in the front end. When a circle is created, the browser request includes the center and radius (in meters).

To create a circle, the app stores the center and radius along with a polygon. To save the polygon, the Region model uses the following method:

def uncached_circle(coordinates, radius)
  ActiveRecord::Base.connection.execute("
    SELECT ST_Buffer(ST_GeomFromText('#{uncached_point(coordinates.first)}')::geography, #{radius}, 'quad_segs=8')::geometry AS circle;
  ")[0]["circle"]
end

I'm having a few problems, the most pressing of which is that certain circles fail with a LinearRing failed ring test error. For example, these request parameters:

{"name"=>"New Orleans, LA", "coordinates"=>[{"lat"=>29.9510658, "lng"=>-90.0715323}], "radius"=>25000, "shape"=>"circle", "format"=>:json, "region"=>{"name"=>"New Orleans, LA", "shape"=>"circle"}}

...produce this query from the aforementioned method:

SELECT ST_Buffer(ST_GeomFromText('POINT(29.9510658 -90.0715323)')::geography, 25000, 'quad_segs=8')::geometry AS circle;

...which fails with the LinearRing error. Another circle centered in Boston (for example) passes.

I rely on the polygon representation of the circle to conduct intersection tests with other circles.

I'm not experienced with PostGIS and am unable to get around this issue after a lot of research and a variety of attempts. The closest I can get is to wrap the circle creation queries in ST_MakeValid, which I view as a code smell.

Can anyone diagnose what I've done wrong? Happy to provide more detail as needed. Thank you.


Solution

  • I believe you're switching the order of the coordinate pairs. It should be lon,lat instead of lat,lon.

    So, try your query using POINT(-90.0715323 29.9510658) and not POINT(29.9510658 -90.0715323):

    SELECT 
      ST_Buffer('POINT(-90.0715323 29.9510658)'::geography, 
                25000, 
                'quad_segs=8')::geometry AS circle;
    

    enter image description here

    Further reading: WGS84 (EPSG:4326)