Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent behavior between Ruby and C implementations #173

Open
wenley opened this issue Sep 8, 2017 · 3 comments
Open

Inconsistent behavior between Ruby and C implementations #173

wenley opened this issue Sep 8, 2017 · 3 comments
Labels

Comments

@wenley
Copy link

wenley commented Sep 8, 2017

A friend and I were using the gem and noticed a difference in behavior between our two machines: mine was using the C implementations whereas his was sticking with Ruby. This by itself is not an issue.

However, we found out that the two implementations have different behaviors when calling the #boundary method on a POLYGON object. The Ruby implementation returns a MULTILINESTRING whereas the C implementation returns a simple LINESTRING. This caused an exception because the former responds to the #first method and the latter does not.

Code to reproduce the issue

require 'rgeo'
require 'rgeo-geojson'

json = <<-JSON
{
 "type": "Polygon",
 "coordinates": [
   [[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]
 ]
}
JSON

ruby_factory = RGeo::Cartesian.simple_factory(srid: 4326)
c_factory = RGeo::Geos::CAPIFactory.create

ruby_obj = RGeo::GeoJSON.decode(
 json,
 json_parser: :json,
 geo_factory: ruby_factory,
)
c_obj = RGeo::GeoJSON.decode(
 json,
 json_parser: :json,
 geo_factory: c_factory,
)

puts "RUBY OBJECT"
puts ruby_obj.class
puts ruby_obj
puts ruby_obj.boundary

puts "C OBJECT"
puts c_obj.class
puts c_obj
puts c_obj.boundary

The output:

RUBY OBJECT
RGeo::Cartesian::PolygonImpl
POLYGON ((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0))
MULTILINESTRING ((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0))
C OBJECT
RGeo::Geos::CAPIPolygonImpl
POLYGON ((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0))
LINESTRING (102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0)
@teeparham teeparham added the bug label Sep 8, 2017
@fergyfresh
Copy link
Contributor

fergyfresh commented Jan 17, 2018

@teeparham do you think this is at all related to the fact that multi_line_string.rb's C binding doesn't exist in the ext folder.

My thought process is that the features are expanded by the FeatureCollection class in ruby and I'm thinking since the multi_line_string.[c|h] (C implementation of the multi_line_string.rb) doesn't exist it is defaulting to the plain old line_string.[h|c] in https://github.com/rgeo/rgeo/tree/master/ext/geos_c_impl.

I pulled the thread as much as I could and that seems to be the biggest hole based on my understanding of the C APIs.

Either way I plan on trying my fix and reporting back later today.

@rossi-jeff
Copy link

is there a way to specify to not use the c api under any circumstances, the ruby api works fine for development, but then the c api is broken in production.

@keithdoggett
Copy link
Member

The issue is that the C API will return either a multi_linestring or linestring depending on the precence of interior rings or not.

For example:

c_factory = RGeo::Geos.factory
poly = c_factory.parse_wkt("POLYGON ((-120.0 60.0, 120.0 60.0, 120.0 -60.0, -120.0 -60.0, -120.0 60.0), (-60.0 30.0, 60.0 30.0, 60.0 -30.0, -60.0 -30.0, -60.0 30.0))")
poly.boundary
=> #<RGeo::Geos::CAPIMultiLineStringImpl "MULTILINESTRING ((-120.0 60.0, 120.0 60.0, 120.0 -60.0, -120.0 -60.0, -120.0 60.0), (-60.0 30.0, 60.0 30.0, 60.0 -30.0, -60.0 -30.0, -60.0 30.0))"> 

Per the OGC SFS boundaries for Polygons should work as follows:

The boundary of a Polygon consists of a set of LinearRings that make up its exterior and interior boundaries

So it seems like the boundary method should return a collection, but libgeos does not do that by default. It's possible to modify the C API implementation in RGeo to match the Ruby implementation or vice versa. A decision just has to be made on whether its better to mirror libgeos or base things more closely off of the OGC SFS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants