rgeo-geojson icon indicating copy to clipboard operation
rgeo-geojson copied to clipboard

Fail to decode polygons with overlapping areas

Open aelesbao opened this issue 7 years ago • 3 comments

I've noticed a problem when trying to decode areas with "bowtie" like shapes:

geojson = '{"type":"Polygon","coordinates":[[[40.1605224609375,50.48547354578499],[41.890869140625,49.75642885858046],[41.8963623046875,50.447011182312195],[40.1495361328125,50.025387620270244],[40.1605224609375,50.48547354578499]]]}'
polygon = RGeo::GeoJSON.decode(geojson, json_parser: :json)
# => returns nil

And, as you can see here, this is a valid Geo JSON Polygon.

Debugging the code, we could check that lib/rgeo/geo_json/coder.rb @ line 246 calls

ring = @geo_factory.linear_ring(points)

Which actually raises an RGeo::Error::InvalidGeometry: LinearRing failed ring test and returns nil.

Version tested: 0.4.3

aelesbao avatar Jul 04 '17 16:07 aelesbao

+1 here

vitorreis avatar Nov 07 '17 09:11 vitorreis

+1 Version 2.1.1 problem still exists

gydroperit avatar Aug 15 '19 08:08 gydroperit

I could indeed reproduce this issue by forcing the simple_factory (the geos based one does not reproduce).

geojson = '{"type":"Polygon","coordinates":[[[40.1605224609375,50.48547354578499],[41.890869140625,49.75642885858046],[41.8963623046875,50.447011182312195],[40.1495361328125,50.025387620270244],[40.1605224609375,50.48547354578499]]]}'
polygon = RGeo::GeoJSON.decode(geojson, geo_factory: RGeo::Cartesian.simple_factory)

With that said, it looks like a geojson accepts complex polygons (https://tools.ietf.org/html/rfc7946#section-3.1.6). Hence we may considere setting uses_lenient_assertions for the coder geo_factory. This would make the polygon not compliant with OGC as mentioned in rgeo. However, I don't know yet enough about RGeo's codebase to make that decision globally. @keithdoggett what is your opinion on that one ?

Locally, a quick fix is:

geojson = <<~JSON
{
  "type":"Polygon",
  "coordinates": [[
    [40.1605224609375,50.48547354578499],
    [41.890869140625,49.75642885858046],
    [41.8963623046875,50.447011182312195],
    [40.1495361328125,50.025387620270244],
    [40.1605224609375,50.48547354578499]
  ]]
}
JSON
polygon = RGeo::GeoJSON.decode(geojson, geo_factory: RGeo::Cartesian.simple_factory(uses_lenient_assertions: true))

puts polygon

And for convenience:

# in some init file
GEOJSON_CODER = RGeo::GeoJSON.coder(geo_factory: RGeo::Cartesian.simple_factory(uses_lenient_assertions: true))

# later
geojson = <<~JSON
{
  "type":"Polygon",
  "coordinates": [[
    [40.1605224609375,50.48547354578499],
    [41.890869140625,49.75642885858046],
    [41.8963623046875,50.447011182312195],
    [40.1495361328125,50.025387620270244],
    [40.1605224609375,50.48547354578499]
  ]]
}
JSON
GEOJSON_CODER.decode(geojson)

This might as well be a bit related with rgeo/rgeo#228, since it depends on the is_simple? method. However, the fact that geos is giving varying behaviors for the is_simple? method is already tracked in https://github.com/rgeo/rgeo/issues/218.

EDIT: sorry for the quick close/reopen, but I think we may be able to handle this issue here

BuonOmo avatar Nov 04 '20 21:11 BuonOmo