Search code examples
ruby-on-railsrubypostgisgeosrgeo

Getting InvalidGeometry: LinearRing failed ring test after upgrading rgeo gem


After upgrading the rgeo gem from 0.6.0 to 2.1.1, we've started to get 'LinearRing failed ring test' on certain geometries that never caused us problems before. (The geometry data is generated from external sources outside of our control, and stored in PostGIS table.)

rgeo initializer:

GEO_FACTORY = RGeo::Geographic.simple_mercator_factory
PROJECTION_FACTORY = GEO_FACTORY.projection_factory
RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config|
  config.default = PROJECTION_FACTORY
end

Example code:

district = District.first
# Convert projected geometry to geographic geometry
geographic_geometry = GEO_FACTORY.unproject(district.geometry)

RGeo::Error::InvalidGeometry: LinearRing failed ring test

I also tried initializing the factory with the following options, but the errors persisted:

FACTORY = RGeo::Geographic.simple_mercator_factory(uses_lenient_assertions:true)
FACTORY = RGeo::Geographic.simple_mercator_factory(lenient_multi_polygon_assertions:true)

I've inspected some of these geometries where that are failing the LinearRing test, and it appears they are failing for a variety of reasons. Some possibly violate ring winding order, while with others I couldn't perceive the exact problem. But the point is, these are all geometries that we were able to work with before, and now are raising errors. I'd like to understand how we can return to the more lenient mode.

NOTES:

  • This is only happening on my Macbook (GEOS version 3.8.0), but not on our Linux production server (GEOS version 3.5.0)

REFERENCES:


Solution

  • This doesn't appear to be an issue with the rgeo gem but rather the underlying geos library on your mac.

    There appears to be a difference in the way that geos 3.8.x (3.8.1 is the latest version in Homebrew circa 4/13/2020) and earlier versions of the geos library handle the is_simple calculation that determines Polygon validity. This affects any RGeo factory (most of them but not RGeo::Geographic.spherical_factory or RGeo::Cartesian.simple_factory) backed by the CAPI.

    If you download version 3.5.x of geos from https://trac.osgeo.org/geos/ and build it with cmake (takes a while but installs cleanly) you should have consistent behavior between your production and local development environments.

    If you were using the simple_mercator factory I doubt that differences in how spherical coordinates (implemented in pure ruby) are validated explain the differences in behavior that you see.

    See this issue: https://github.com/rgeo/rgeo/issues/218