class OGR::DataSource

Attributes

ptr[RW]

Public Class Methods

new(ptr) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 7
def initialize(ptr)
  @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
  @ptr.autorelease = false
end
release(ptr) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 12
def self.release(ptr);end

Public Instance Methods

add_layer(name, geometry_type, spatial_ref=nil, options=nil) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 97
def add_layer(name, geometry_type, spatial_ref=nil, options=nil)
  layer = FFIOGR.OGR_DS_CreateLayer(@ptr, name, spatial_ref, geometry_type.to_sym, options)
  OGR::Tools.cast_layer(layer)
end
copy(driver_name, output_path, driver_options=nil) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 18
def copy(driver_name, output_path, driver_options=nil)
  driver = OGRGetDriverByName driver_name
  new_ds = FFIOGR.OGR_Dr_CopyDataSource(driver, @ptr, File.expand_path(output_path), driver_options)
  FFIOGR.OGR_DS_Destroy(new_ds)
end
copy_with_transform(driver_name, output_path, spatial_ref=nil, driver_options=nil) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 24
def copy_with_transform(driver_name, output_path, spatial_ref=nil, driver_options=nil)
  writer = OGR::Writer.new driver_name
  writer.set_output(output_path)
  out = writer.ptr

  layers.each do |layer|
    name = layer.name
    geometry_type = layer.geometry_type
    old_sr = layer.spatial_ref

    ct = OGR::CoordinateTransformation.find_transformation(old_sr, spatial_ref) unless spatial_ref.nil? || (spatial_ref == old_sr)

    sr = spatial_ref.nil? ? nil : spatial_ref.ptr

    new_layer = out.add_layer name, geometry_type, sr, driver_options

    ptr = layer.ptr

    layer_definition = FFIOGR.OGR_L_GetLayerDefn(ptr)
    field_count = FFIOGR.OGR_FD_GetFieldCount(layer_definition)

    for i in (0...field_count)
      fd = FFIOGR.OGR_FD_GetFieldDefn(layer_definition, i)
      name = FFIOGR.OGR_Fld_GetNameRef(fd)
      type = FFIOGR.OGR_Fld_GetType(fd)

      opts = {}.tap do |o|
        case type
        when :real
          o[:precision] = FFIOGR.OGR_Fld_GetPrecision fd
        when :string
          o[:width] = FFIOGR.OGR_Fld_GetWidth fd
        end
      end

      new_layer.add_field name, type, opts
    end

    layer.features.each do |feature|
      geometry = OGR::Tools.cast_geometry(feature.geometry)
      geometry.transform ct if ct

      new_feature = new_layer.create_feature
      new_feature.add_geometry geometry

      ptr = feature.ptr
      field_count = FFIOGR.OGR_F_GetFieldCount(ptr)

      for i in (0...field_count)
        fd = FFIOGR.OGR_F_GetFieldDefnRef(ptr, i)
        field_name = FFIOGR.OGR_Fld_GetNameRef(fd)
        field_type = FFIOGR.OGR_Fld_GetType(fd)

        case field_type
        when :integer
          field_value = FFIOGR.OGR_F_GetFieldAsInteger(ptr, i)
        when :real
          field_value = FFIOGR.OGR_F_GetFieldAsDouble(ptr, i)
        else
          field_value = FFIOGR.OGR_F_GetFieldAsString(ptr, i)
        end

        new_feature.set_field_value field_name, field_value, field_type
      end

      new_layer.add_feature new_feature
    end

    new_layer.sync
  end
  out.free
end
features()
Alias for: get_features
fields()
Alias for: get_fields
free() click to toggle source
# File lib/ffi-ogr/data_source.rb, line 14
def free
  FFIOGR.OGR_DS_Destroy(@ptr)
end
geometries(as_geojson=false)
Alias for: get_geometries
get_features() click to toggle source
# File lib/ffi-ogr/data_source.rb, line 117
def get_features
  layers.map {|l| l.features}
end
Also aliased as: features
get_fields() click to toggle source
# File lib/ffi-ogr/data_source.rb, line 131
def get_fields
  features.map {|feature| feature.map {|f| f.fields}}
end
Also aliased as: fields
get_geometries(as_geojson=false) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 122
def get_geometries(as_geojson=false)
  unless as_geojson
    features.map {|feature| feature.map {|f| OGR::Tools.cast_geometry(f.geometry)}}
  else
    features.map {|feature| feature.map {|f| OGR::Tools.cast_geometry(f.geometry).to_geojson}}
  end
end
Also aliased as: geometries
get_layers() click to toggle source
# File lib/ffi-ogr/data_source.rb, line 106
def get_layers
  layers = []

  for i in (0...num_layers) do
    layers << OGR::Tools.cast_layer(OGR_DS_GetLayer(@ptr, i))
  end

  layers
end
Also aliased as: layers
layers()
Alias for: get_layers
num_layers() click to toggle source
# File lib/ffi-ogr/data_source.rb, line 102
def num_layers
  FFIOGR.OGR_DS_GetLayerCount(@ptr)
end
parse_driver_options(options) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 176
def parse_driver_options(options)
  tf_values = {
    true => "YES",
    false => "NO"
  }

  pointers = [].tap do |ptrs|
    options.each do |k,v|
      tf_value = tf_values[v] || v
      ptrs << FFI::MemoryPointer.from_string("#{k.to_s.upcase}=#{tf_value.upcase}")
    end
  end

  pointers << nil

  driver_options = FFI::MemoryPointer.new :pointer, pointers.size

  pointers.each_with_index do |ptr, i|
    driver_options[i].put_pointer 0, ptr
  end

  driver_options
end
to_csv(output_path, options={}) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 160
def to_csv(output_path, options={})
  to_format('csv', output_path)
end
to_format(format, output_path, options={}) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 136
def to_format(format, output_path, options={})
  raise RuntimeError.new("Output path not specified.") if output_path.nil?

  spatial_ref = options.delete :spatial_ref

  driver_options = parse_driver_options options

  driver_name = OGR::DRIVER_TYPES[format]

  unless spatial_ref
    copy driver_name, output_path, driver_options
  else
    if spatial_ref.instance_of? OGR::SpatialReference
      copy_with_transform driver_name, output_path, spatial_ref, driver_options
    else
      raise RuntimeError.new("Invalid spatial reference specified.")
    end
  end
end
to_geojson(output_path, options={}) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 172
def to_geojson(output_path, options={})
  to_format('geojson', output_path, options)
end
to_json(pretty=false) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 200
def to_json(pretty=false)
  h = {
    type: 'FeatureCollection',
    features: []
  }

  layers.each do |layer|
    h[:features].tap do |features|
      layer.features.each do |feature|
        features << {
          type: 'Feature',
          geometry: OGR::Tools.cast_geometry(feature.geometry).to_geojson,
          properties: feature.fields
        }
      end
    end
  end

  unless pretty
    MultiJson.dump(h)
  else
    MultiJson.dump(h, pretty: true)
  end
end
to_kml(output_path, options={}) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 164
def to_kml(output_path, options={})
  format = OGR.drivers.include?('LIBKML') ? 'kml' : 'kml_lite'

  warn "GDAL is compiled without LIBKML support. Without LIBKML support KML output will always be in EPSG:4326" if format == 'kml_lite'

  to_format(format, output_path, options)
end
to_shp(output_path, options={}) click to toggle source
# File lib/ffi-ogr/data_source.rb, line 156
def to_shp(output_path, options={})
  to_format('shapefile', output_path)
end