scooterw / ffi-ogr

Convenient Ruby wrapper for OGR
MIT License
13 stars 5 forks source link

Clean up DataSource#to_x methods ... #4

Closed scooterw closed 10 years ago

scooterw commented 11 years ago

There is a lot of repetition in these methods that can be refactored and cleaned up. Get to cleaning.

scooterw commented 10 years ago

Started with a30215e

scooterw commented 10 years ago

OGR::DataSource#to_geojson needs attention.

ajturner commented 10 years ago

quick related question - naming output layers, it should work to call OGR.read(query_url).to_shp('myfile',{nln: 'My Layer'}) to add this flag? but that doesn't work, any suggestions?

scooterw commented 10 years ago

It has an "options" hash, but it is named spatial_ref (arguably improperly), but it only looks for hash[:spatial_ref] right now. All other values are simply ignored. I really need to flesh this out to accept a full options hash. I am assuming that nln is related to the ogr2ogr option to rename the output layer? I'll have to do a C-API dive to figure out how to accomplish this. I will start by adding the options hash.

ajturner commented 10 years ago

these Ruby FFI Recipes may be relevant and helpful.

Specifically running into two issues:

  1. Layer naming so that it's not always OGRGeoJSON - even when KML output
  2. KML needs an SRS in to properly export out as EPSG:4326

So this is what I have so far but it's not working:

require './lib/ffi-ogr'
r = OGR.read('http://services1.arcgis.com/p84PN4WZvOWzi2j2/arcgis/rest/services/CityBoundary/FeatureServer/0/query?f=json&layer=0&outFields=%2A&where=1%3D1')
strptrs = []
strptrs << FFI::MemoryPointer.from_string("nln")
strptrs << FFI::MemoryPointer.from_string("CityBoundary")
strptrs << FFI::MemoryPointer.from_string("s_srs")
strptrs << FFI::MemoryPointer.from_string("EPSG:3857")
strptrs << nil

# Now load all the pointers into a native memory block
argv = FFI::MemoryPointer.new(:pointer, strptrs.length)
strptrs.each_with_index do |p, i|
 argv[i].put_pointer(0,  p)
end

r.to_shp('CityBoundary.shp', argv)
r.to_kml('CityBoundary.kml', argv)
ajturner commented 10 years ago

ok - this works (with some minor changes to data_source.rb to pass through"

require './lib/ffi-ogr'
r = OGR.read('http://services1.arcgis.com/p84PN4WZvOWzi2j2/arcgis/rest/services/CityBoundary/FeatureServer/0/query?f=json&layer=0&outFields=%2A&where=1%3D1')
strptrs = []
strptrs << FFI::MemoryPointer.from_string("GEOMETRY=AS_WKT")
strptrs << nil

argv = FFI::MemoryPointer.new(:pointer, strptrs.length)
strptrs.each_with_index do |p, i|
 argv[i].put_pointer(0,  p)
end

r.to_csv('CityBoundary.csv', argv)

still doesn't resolve passing in SRS. Diving through docs to see how that works from the ogr command-line into the C options.

scooterw commented 10 years ago

I've been looking at the source for ogr2ogr to see how these things are done there. It's going to take me a bit of time to sift through the code and compare with the OGR C-API docs to determine how best to accomplish this here. I would rather spend more time up front and come up with something simple.

ajturner commented 10 years ago

indeed @scooterw - from looking at the code I think LAYER_NAME and SRC_SRS should work, but they're not. I'm also reaching out to the #gdal IRC and mailing list to see if @warmerdam has suggestions. (as well as namedropping him here ;)

scooterw commented 10 years ago

@ajturner I've added the ability to pass in driver options in a Ruby hash format. For instance, if you wanted to pass in the write_bbox option to the GeoJSON driver, you have a few options:

options = {write_bbox: true}
data_source.to_geojson '/path/to/output.geojson', options

It will turn the key(s) to strings, and capitalize them, and will convert true/false into "YES"/"NO", and will capitalize passed in string values as well, putting them together with an "=" ... so {write_bbox: true} becomes "WRITE_BBOX=YES" ... {"write_bbox" => "yes"} or {"write_bbox" => true}, etc should also work.

Driver options seem to be specific to the individual drivers, and I'm just not seeing what I need to do to make the KML driver handle reprojections. I have seen documentation that indicates that the optionally compiled libkml driver has more features, and may allow for this. That said, since I upgraded to Mavericks, brew does not seem to respect the --enable-unsupported flag, so I am missing some of the drivers like the FileGDB, and LibKML drivers.

I am investigating some workarounds, but this should make it easier to try driver options in the meantime.

scooterw commented 10 years ago

Closing this issue. LIBKML fixes are in master.