dark-panda / ffi-geos

ffi-geos is an implementation of the GEOS Ruby bindings in Ruby via FFI.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Calling coord_seq on a polygon results in runtime error

jamiecook opened this issue · comments

Running on windows 7 with
Ruby version 1.8.7 - ruby
ffi version 1.0.11
GEOS version 3.3.0
ffi-geos version 0.0.4

Should be reproducible by adding an extra check to the geometry_test.rb

def test_coord_seq
  tester = lambda { |expected, g|
    geom = read(g)
    cs = geom.coord_seq
    expected.each_with_index do |c, i|
      assert_equal(c[0], cs.get_x(i))
      assert_equal(c[1], cs.get_y(i))
    end
  }

  tester[[[0, 0]], 'POINT(0 0)']
  tester[[[0, 0], [2, 3]], 'LINESTRING (0 0, 2 3)']
  tester[[[0, 0], [0, 5], [5, 5], [5, 0], [0, 0]], 'LINEARRING(0 0, 0 5, 5 5, 5 0, 0 0)']

  # ADDED TEST
  tester[[[0, 0], [0, 5], [5, 5], [5, 0], [0, 0]], 'POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))']
end

Output from this is shown below:

c:/ruby/lib/ruby/gems/1.8/gems/ffi-geos-0.0.4/lib/ffi-geos/geometry.rb:73: [BUG] Segmentation fault
ruby 1.8.7 (2010-12-23 patchlevel 330) [i386-mingw32]

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
commented

I have been unable to reproduce this error on my machine running WinXP with Ruby 1.8.7-p358 and the current GEOS svn HEAD. I'm getting a RuntimeError exception as expected, but it isn't segfaulting on me, so your error is more serious than just a thrown exception.

Would you be able to try a more recent version of Ruby, as the current patch release in the 1.8.7 series is p358. The most recent version of GEOS is at 3.3.2 as well, so while I doubt that it would really have an affect this particular issue, it might be useful to try the latest GEOS version is well.

Hi, thanks for the quick reply - I've upgraded my ruby to the 358 patch level and am having the same problem.

I actually built the 3.3.2 latest release of geos (2012/01/05 geos-3.3.2.tar.bz2) using the visual studio 2010 compiler.... I don't know why it's reporting as the 3.3.0 release as I don't have any other versions of these libs lying around. Maybe I've made an error in this process. I built using the instructions provided here: http://trac.osgeo.org/geos/wiki/BuildingOnWindowsWithNMake

However, the installation section is blank :) So i just copied and renamed the src/geos.dll and src/geos_c.dll files into the lib directory and added lib to the front [lib/libgeos.dll lib/libgeos.lib lib/libgeos_c.dll etc] and this appears to work perfectly... except for the small problem I am having here with extracting coordinate sequences from a polygon.

If you have any suggestions on how/where to debug this problem I'm happy to do some diagnostics here on my machine.

Okay ... I don't know why mine results in a runtime error when yours doesn't but it seems to me that the code as it is can't return the coordinate sequence of a polygon.

at line 73 of geometry.rb

def coord_seq
  CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle, self.ptr), false)
end

the method GEOSGeom_getCoordSeq_r is from the capi in file geos_ts_c.cpp and it bombs out with an error

handle->ERROR_MESSAGE("Geometry must be a Point or LineString");

This seems to be a limitation of the geos api in which get_CoordSeq_r will only return a singular CS, whereas a polygon is comprised of multiple CS (the shell plus any holes).

sorry, you are expecting a runtime error - you already know everything i just said :)

commented

On my MinGW VM I compiled GEOS using the MinGW environment rather than using Visual Studio, so perhaps you can try that and see if that works. There could be a miscommunication between VS and MinGW going on here.

Yeah, calling coord_seq on a Geos::Polygon is supposed to raise an exception, so even if we prevent the segfaults your code still isn't going to get you your expected results. Instead, you want to be calling polygon.exterior_ring.coord_seq and polygon.interior_rings[n].coord_seq to gather up the appropriate coordinate sequences. That said, I was toying with the idea of returning the exterior ring's coordinate sequence when you call coord_seq on a polygon as a convenience method.

Ah, i think that this explains it...

  1. I was using it wrong (thanks for clarifying the correct syntax)
  2. Some thing is slightly off with the ruby->c->c++ call stack so that
    errors aren't being handled nicely.

I'm pretty confident that 2 is all on me as well so very happy to mark this
issue closed.

Also ... if you do put in that convenience method perhaps a check
num_interior_rings == 0 would be apt?
If you ask for a coord_seq and it strips out half the points that define it
it's a bit counter intuitive, if there is only a simple outer shell then
you would expect to get the points for that.

Might be a bit too smart for it's own good though :)