ffi-ogr 0.0.1.pre → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -6,33 +6,46 @@ To run: `bin/ogr_console`
6
6
  To read a shapefile:
7
7
 
8
8
  ```ruby
9
+ shp = OGR::ShpReader.new.read './spec/data/ne_110m_coastline/ne_110m_coastline.shp'
10
+ # => #<OGR::DataSource:0x007fba4d19c328 @ptr=#<FFI::AutoPointer address=0x007fba4c4cdc50>>
11
+
12
+ shp.to_geojson '~/Desktop/output.geojson'
13
+ # => Output GeoJSON to specified file
14
+ ```
15
+
16
+ To reproject a shapefile:
9
17
 
18
+ ```ruby
10
19
  shp = OGR::ShpReader.new.read './spec/data/ne_110m_coastline/ne_110m_coastline.shp'
11
- # => #<OGR::DataSource:0x007fba4d19c328 @ds=#<FFI::AutoPointer address=0x007fba4c4cdc50>>
20
+ # => #<OGR::DataSource:0x007fba4d19c328 @ptr=#<FFI::AutoPointer address=0x007fba4c4cdc50>>
21
+
22
+ shp.to_json
23
+ # => Output GeoJSON string
24
+
25
+ shp.to_json true
26
+ # => Output GeoJSON string (pretty print)
12
27
 
13
- shp.to_geojson
14
- # => geojson feature collection from Shapefile
28
+ # from_epsg(integer), from_proj4(string), from_wkt(string)
29
+ new_sr = OGR::SpatialReference.from_epsg 3857
30
+ # => #<OGR::SpatialReference:0x007fd859a0e6f8 @ptr=#<FFI::AutoPointer address=0x007fd85a11c100>>
15
31
 
16
- shp.to_geojson true
17
- # => "pretty print" geojson feature collection from Shapefile
32
+ shp.to_shp '~/Desktop/reprojected_shp.shp', {spatial_ref: new_sr}
33
+ # => Output reprojected SHP to specified file
18
34
  ```
19
35
 
20
36
  A reader may also be inferred by file extension (currently works for shp and json/geojson):
21
37
 
22
38
  ```ruby
23
-
24
39
  shp = OGR::Reader.from_file_type './spec/data/ne_110m_coastline/ne_110m_coastline.shp'
25
-
26
40
  ```
27
41
 
28
42
  To create a shapefile:
29
43
 
30
44
  ```ruby
31
-
32
45
  writer = OGR::ShpWriter.new
33
46
  writer.set_output '~/Documents/shapefiles/my_new.shp'
34
47
 
35
- shp = writer.ds
48
+ shp = writer.ptr
36
49
 
37
50
  # add layer to shp : add_layer(name, geometry_type, spatial_reference)
38
51
  # currently does not handle spatial reference, will automatically be nil
@@ -58,15 +71,12 @@ layer.add_feature feature
58
71
 
59
72
  # sync to disk
60
73
  layer.sync
61
-
62
74
  ```
63
75
 
64
76
  A writer may also be inferred by file extension (currently works for shp and json/geojson):
65
77
 
66
78
  ```ruby
67
-
68
79
  writer = OGR::Writer.from_file_type '~/Documents/shapefiles/my_new.shp'
69
-
70
80
  ```
71
81
 
72
82
  Tested on: MRI 1.9.3-p392 and JRuby 1.7.3
@@ -0,0 +1,30 @@
1
+ module OGR
2
+ class CoordinateTransformation
3
+ attr_accessor :ptr
4
+
5
+ def initialize(ptr)
6
+ @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
7
+ @ptr.autorelease = false
8
+ end
9
+
10
+ def self.release(ptr);end
11
+
12
+ def free
13
+ FFIOGR.OCTDestroyCoordinateTransformation(@ptr)
14
+ end
15
+
16
+ def self.find_transformation(in_sr, out_sr)
17
+ bad_sr = []
18
+
19
+ if !in_sr.instance_of?(OGR::SpatialReference)
20
+ bad_sr << 'Input SR'
21
+ elsif !out_sr.instance_of?(OGR::SpatialReference)
22
+ bad_sr << 'Output SR'
23
+ end
24
+
25
+ raise RuntimeError.new("Invalid Spatial Reference(s): #{bad_sr.join(', ')}") if bad_sr.size > 0
26
+
27
+ FFIOGR.OCTNewCoordinateTransformation(in_sr.ptr, out_sr.ptr)
28
+ end
29
+ end
30
+ end
@@ -2,31 +2,108 @@ module OGR
2
2
  class DataSource
3
3
  include FFIOGR
4
4
 
5
- attr_accessor :ds
5
+ attr_accessor :ptr
6
6
 
7
- def initialize(ptr=nil, auto_free=true)
8
- @ds = FFI::AutoPointer.new(ptr, self.class.method(:release))
9
- @ds.autorelease = auto_free
7
+ def initialize(ptr)
8
+ @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
9
+ @ptr.autorelease = false
10
10
  end
11
11
 
12
- def self.release(ptr)
13
- FFIOGR.OGR_DS_Destroy(ptr)
12
+ def self.release(ptr);end
13
+
14
+ def free
15
+ FFIOGR.OGR_DS_Destroy(@ptr)
16
+ end
17
+
18
+ def copy(output_type, output_path, driver_options=nil)
19
+ driver = OGRGetDriverByName(OGR::DRIVER_TYPES[output_type.downcase])
20
+ new_ds = FFIOGR.OGR_Dr_CopyDataSource(driver, @ptr, File.expand_path(output_path), driver_options)
21
+ FFIOGR.OGR_DS_Destroy(new_ds)
22
+ end
23
+
24
+ def copy_with_transform(output_type, output_path, spatial_ref=nil, driver_options=nil)
25
+ writer = OGR::GenericWriter.new(OGR::DRIVER_TYPES[output_type.downcase])
26
+ writer.set_output(output_path)
27
+ out = writer.ptr
28
+
29
+ layers.each do |layer|
30
+ name = layer.name
31
+ geometry_type = layer.geometry_type
32
+ old_sr = layer.spatial_ref
33
+
34
+ ct = OGR::CoordinateTransformation.find_transformation(old_sr, spatial_ref) unless spatial_ref.nil? || (spatial_ref == old_sr)
35
+
36
+ sr = spatial_ref.nil? ? nil : spatial_ref.ptr
37
+
38
+ new_layer = out.add_layer name, geometry_type, sr, driver_options
39
+
40
+ ptr = layer.ptr
41
+
42
+ layer_definition = FFIOGR.OGR_L_GetLayerDefn(ptr)
43
+ field_count = FFIOGR.OGR_FD_GetFieldCount(layer_definition)
44
+
45
+ for i in (0...field_count)
46
+ fd = FFIOGR.OGR_FD_GetFieldDefn(layer_definition, i)
47
+ name = FFIOGR.OGR_Fld_GetNameRef(fd)
48
+ type = FFIOGR.OGR_Fld_GetType(fd)
49
+
50
+ opts = {}
51
+
52
+ opts[:precision] = FFIOGR.OGR_Fld_GetPrecision(fd) if type == :real
53
+ opts[:width] = FFIOGR.OGR_Fld_GetWidth(fd) if type == :string
54
+
55
+ new_layer.add_field name, type
56
+ end
57
+
58
+ layer.features.each do |feature|
59
+ geometry = OGR::Tools.cast_geometry(feature.geometry)
60
+ geometry.transform ct if ct
61
+
62
+ new_feature = new_layer.create_feature
63
+ new_feature.add_geometry geometry
64
+
65
+ ptr = feature.ptr
66
+ field_count = FFIOGR.OGR_F_GetFieldCount(ptr)
67
+
68
+ for i in (0...field_count)
69
+ fd = FFIOGR.OGR_F_GetFieldDefnRef(ptr, i)
70
+ field_name = FFIOGR.OGR_Fld_GetNameRef(fd)
71
+ field_type = FFIOGR.OGR_Fld_GetType(fd)
72
+
73
+ case field_type
74
+ when :integer
75
+ field_value = FFIOGR.OGR_F_GetFieldAsInteger(ptr, i)
76
+ when :real
77
+ field_value = FFIOGR.OGR_F_GetFieldAsDouble(ptr, i)
78
+ else
79
+ field_value = FFIOGR.OGR_F_GetFieldAsString(ptr, i)
80
+ end
81
+
82
+ new_feature.set_field_value field_name, field_value, field_type
83
+ end
84
+
85
+ new_layer.add_feature new_feature
86
+ end
87
+
88
+ new_layer.sync
89
+ end
90
+ out.free
14
91
  end
15
92
 
16
- def add_layer(name, geometry_type, spatial_ref=nil, options={})
17
- # need to add spatial reference mapping
18
- # need to add options as StringList ...
19
- layer = FFIOGR.OGR_DS_CreateLayer(@ds, name, spatial_ref, geometry_type.to_sym, nil)
93
+ def add_layer(name, geometry_type, spatial_ref=nil, options=nil)
94
+ layer = FFIOGR.OGR_DS_CreateLayer(@ptr, name, spatial_ref, geometry_type.to_sym, options)
20
95
  OGR::Tools.cast_layer(layer)
21
96
  end
22
97
 
98
+ def num_layers
99
+ FFIOGR.OGR_DS_GetLayerCount(@ptr)
100
+ end
101
+
23
102
  def get_layers
24
103
  layers = []
25
104
 
26
- num_layers = OGR_DS_GetLayerCount(@ds)
27
-
28
105
  for i in (0...num_layers) do
29
- layers << OGR::Tools.cast_layer(OGR_DS_GetLayer(@ds, i))
106
+ layers << OGR::Tools.cast_layer(OGR_DS_GetLayer(@ptr, i))
30
107
  end
31
108
 
32
109
  layers
@@ -34,22 +111,84 @@ module OGR
34
111
  alias_method :layers, :get_layers
35
112
 
36
113
  def get_features
37
- layers.map {|l| l.features}.first
114
+ layers.map {|l| l.features}
38
115
  end
39
116
  alias_method :features, :get_features
40
117
 
41
- def get_geometries
42
- features.map {|f| OGR::Tools.cast_geometry(f.geometry)}
118
+ def get_geometries(as_geojson=false)
119
+ unless as_geojson
120
+ features.map {|feature| feature.map {|f| OGR::Tools.cast_geometry(f.geometry)}}
121
+ else
122
+ features.map {|feature| feature.map {|f| OGR::Tools.cast_geometry(f.geometry).to_geojson}}
123
+ end
43
124
  end
44
125
  alias_method :geometries, :get_geometries
45
126
 
46
127
  def get_fields
47
- features.map {|f| f.fields}
128
+ features.map {|feature| feature.map {|f| f.fields}}
48
129
  end
49
130
  alias_method :fields, :get_fields
50
131
 
51
- def to_geojson(pretty=false)
52
- MultiJson.dump({type: 'FeatureCollection', features: features.map {|f| f.to_geojson}}, pretty: pretty)
132
+ def to_shp(output_path, spatial_ref=nil)
133
+ raise RuntimeError.new("Output path not specified.") if output_path.nil?
134
+
135
+ # TODO: handle parsing of spatial_ref -> copy options
136
+
137
+ if spatial_ref.instance_of? OGR::SpatialReference
138
+ copy_with_transform('shapefile', output_path, spatial_ref)
139
+ elsif spatial_ref.nil?
140
+ copy('shapefile', output_path, spatial_ref)
141
+ end
142
+ end
143
+
144
+ def to_geojson(output_path, options=nil)
145
+ raise RuntimeError.new("Output path not specified.") if output_path.nil?
146
+
147
+ unless options.nil?
148
+ spatial_ref = options[:spatial_ref] ? options[:spatial_ref] : nil
149
+
150
+ if options[:bbox]
151
+ # this segfaults -- working on solution
152
+ bbox = FFI::MemoryPointer.from_string "WRITE_BBOX=YES"
153
+ driver_options = FFI::MemoryPointer.new :pointer, 1
154
+ driver_options[0].put_pointer 0, bbox
155
+ else
156
+ driver_options = nil
157
+ end
158
+
159
+ if spatial_ref
160
+ copy_with_transform('geojson', output_path, spatial_ref, driver_options)
161
+ else
162
+ copy('geojson', output_path, driver_options)
163
+ end
164
+ else
165
+ copy('geojson', output_path, nil)
166
+ end
167
+ end
168
+
169
+ def to_json(pretty=false)
170
+ h = {
171
+ type: 'FeatureCollection',
172
+ bbox: nil,
173
+ features: []
174
+ }
175
+
176
+ layers.each do |layer|
177
+ h[:bbox] = layer.envelope.to_a true
178
+ geometry_type = layer.geometry_type.to_s.capitalize
179
+
180
+ layer.features.each do |feature|
181
+ properties = feature.fields
182
+ geometry = OGR::Tools.cast_geometry(feature.geometry).to_geojson
183
+ h[:features] << {type: geometry_type, geometry: geometry, properties: properties}
184
+ end
185
+ end
186
+
187
+ unless pretty
188
+ MultiJson.dump(h)
189
+ else
190
+ MultiJson.dump(h, pretty: true)
191
+ end
53
192
  end
54
193
  end
55
194
  end
@@ -0,0 +1,33 @@
1
+ module OGR
2
+ class Envelope
3
+ attr_accessor :min_x, :max_x, :min_y, :max_y
4
+
5
+ def initialize(env)
6
+ raise RuntimeError.new("Invalid envelope specified") unless env.size == 4
7
+
8
+ @min_x, @max_x = env[0], env[1]
9
+ @min_y, @max_y = env[2], env[3]
10
+ end
11
+
12
+ def to_a(se_nw=false)
13
+ unless se_nw
14
+ [@min_x, @max_x, @min_y, @max_y]
15
+ else
16
+ [@min_x, @min_y, @max_x, @max_y]
17
+ end
18
+ end
19
+
20
+ def to_hash
21
+ {min_x: @min_x, max_x: @max_x, min_y: @min_y, max_y: @max_y}
22
+ end
23
+
24
+ def to_json
25
+ MultiJson.dump(to_hash)
26
+ end
27
+
28
+ def to_polygon
29
+ coords = [[[@min_x, @min_y], [@min_x, @max_y], [@max_x, @max_y], [@max_x, @min_y], [@min_x, @min_y]]]
30
+ OGR::Polygon.create coords
31
+ end
32
+ end
33
+ end
@@ -2,13 +2,16 @@ module OGR
2
2
  class Feature
3
3
  attr_accessor :ptr
4
4
 
5
- def initialize(ptr, auto_free=true)
5
+ def initialize(ptr)
6
6
  @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
7
- @ptr.autorelease = auto_free
7
+ #@ptr = FFI::AutoPointer.new(ptr)
8
+ @ptr.autorelease = false
8
9
  end
9
10
 
10
- def self.release(ptr)
11
- FFIOGR.OGR_F_Destroy(ptr)
11
+ def self.release(ptr);end
12
+
13
+ def free
14
+ FFIOGR.OGR_F_Destroy(@ptr)
12
15
  end
13
16
 
14
17
  def set_field_value(name, value, field_type=nil)
@@ -25,7 +28,10 @@ module OGR
25
28
  when :integer
26
29
  FFIOGR.OGR_F_SetFieldInteger(@ptr, field_index, Integer(value))
27
30
  when :real
28
- FFIOGR.OGR_F_SetFieldDouble(@ptr, field_index, Float(value))
31
+ #dbl_ptr = FFI::MemoryPointer.new(:double, 1)
32
+ #dbl_ptr.write_double(Float(value))
33
+
34
+ FFIOGR.OGR_F_SetFieldDouble(@ptr, field_index, value)
29
35
  when :string
30
36
  FFIOGR.OGR_F_SetFieldString(@ptr, field_index, String(value))
31
37
  when :binary
@@ -34,8 +40,8 @@ module OGR
34
40
  end
35
41
 
36
42
  def add_geometry(geometry)
37
- FFIOGR.OGR_F_SetGeometry(@ptr, geometry.ptr)
38
- #FFIOGR.OGR_F_SetGeometryDirectly(@ptr, geometry.ptr)
43
+ #FFIOGR.OGR_F_SetGeometry(@ptr, geometry.ptr)
44
+ FFIOGR.OGR_F_SetGeometryDirectly(@ptr, geometry.ptr)
39
45
  end
40
46
 
41
47
  def get_geometry
@@ -72,6 +78,13 @@ module OGR
72
78
  end
73
79
  alias_method :fields, :get_fields
74
80
 
81
+ def transform_to(out_sr)
82
+ geom = OGR::Tools.cast_geometry(geometry)
83
+ geom.transform(out_sr)
84
+ p geom.ptr
85
+ add_geometry(geom)
86
+ end
87
+
75
88
  def to_geojson
76
89
  {type: 'Feature', geometry: OGR::Tools.cast_geometry(geometry).to_geojson, properties: fields}
77
90
  end
@@ -1,21 +1,46 @@
1
1
  module OGR
2
2
  class Geometry
3
- attr_reader :ptr
3
+ attr_accessor :ptr
4
4
 
5
- def initialize(ptr, auto_free=true)
5
+ def initialize(ptr)
6
6
  @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
7
- #@ptr.autorelease = auto_free
7
+ #@ptr = FFI::AutoPointer.new(ptr)
8
+ @ptr.autorelease = false
8
9
  end
9
10
 
10
11
  def self.release(ptr);end
11
12
 
13
+ def free
14
+ FFIOGR.OGR_G_DestroyGeometry(@ptr)
15
+ end
16
+
17
+ def self.from_geojson(geojson)
18
+ if geojson.instance_of? String
19
+ geojson = MultiJson.load(geojson)
20
+ end
21
+
22
+ coords = geojson['coordinates']
23
+
24
+ case geojson['type']
25
+ when 'Point'
26
+ OGR::Point.create coords
27
+ when 'LineString'
28
+ OGR::LineString.create coords
29
+ when 'Polygon'
30
+ OGR::Polygon.create coords
31
+ end
32
+ end
33
+
12
34
  def self.create_empty(geometry_type)
13
35
  OGR::Tools.cast_geometry(FFIOGR.OGR_G_CreateGeometry(geometry_type))
14
36
  end
15
37
 
16
38
  def add_geometry(geometry)
17
39
  FFIOGR.OGR_G_AddGeometry(@ptr, geometry.ptr)
18
- #FFIOGR.OGR_G_AddGeometryDirectly(@ptr, geometry.ptr)
40
+ end
41
+
42
+ def add_geometry_directly(geometry)
43
+ FFIOGR.OGR_G_AddGeometryDirectly(@ptr, geometry.ptr)
19
44
  end
20
45
 
21
46
  def add_point(coords)
@@ -44,6 +69,10 @@ module OGR
44
69
  end
45
70
  end
46
71
 
72
+ def is_3d?
73
+ !!(geometry_type.to_s =~ /_25d/)
74
+ end
75
+
47
76
  def flatten
48
77
  FFIOGR.OGR_G_FlattenTo2D(@ptr)
49
78
  end
@@ -53,6 +82,15 @@ module OGR
53
82
  end
54
83
  alias_method :geometry_type, :get_geometry_type
55
84
 
85
+ def get_spatial_ref
86
+ OGR::Tools.cast_spatial_reference(FFIOGR.OGR_G_GetSpatialReference(@ptr))
87
+ end
88
+ alias_method :spatial_ref, :get_spatial_ref
89
+
90
+ def transform(ct)
91
+ FFIOGR.OGR_G_Transform(@ptr, ct)
92
+ end
93
+
56
94
  def get_length
57
95
  FFIOGR.OGR_G_Length(@ptr)
58
96
  end
@@ -68,6 +106,13 @@ module OGR
68
106
  end
69
107
  alias_method :boundary, :get_boundary
70
108
 
109
+ def get_envelope
110
+ envelope = FFI::MemoryPointer.new :pointer, 4
111
+ FFIOGR.OGR_G_GetEnvelope(@ptr, envelope)
112
+ OGR::Envelope.new(envelope.read_array_of_double(4))
113
+ end
114
+ alias_method :envelope, :get_envelope
115
+
71
116
  def to_geojson
72
117
  MultiJson.load(FFIOGR.OGR_G_ExportToJson(@ptr))
73
118
  end
data/lib/ffi-ogr/layer.rb CHANGED
@@ -2,22 +2,57 @@ module OGR
2
2
  class Layer
3
3
  attr_accessor :ptr, :name, :geometry_type
4
4
 
5
- def initialize(ptr, auto_free=true)
5
+ def initialize(ptr)
6
6
  @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
7
- @name = FFIOGR.OGR_L_GetName(@ptr)
8
- @geometry_type = FFIOGR.OGR_L_GetGeomType(@ptr)
9
- #@ptr.autorelease = auto_free
7
+ #@ptr = FFI::AutoPointer.new(ptr)
8
+ @ptr.autorelease = false
10
9
  end
11
10
 
12
11
  def self.release(ptr);end
13
12
 
13
+ def free
14
+ @ptr.free
15
+ end
16
+
14
17
  def sync
15
18
  FFIOGR.OGR_L_SyncToDisk(@ptr)
16
19
  end
17
20
 
18
- def add_field(name, field_type, field_width=32)
21
+ def get_envelope
22
+ envelope = FFI::MemoryPointer.new :pointer, 4
23
+ FFIOGR.OGR_L_GetExtent(@ptr, envelope, 0)
24
+ OGR::Envelope.new(envelope.read_array_of_double(4))
25
+ end
26
+ alias_method :envelope, :get_envelope
27
+
28
+ def get_name
29
+ FFIOGR.OGR_L_GetName(@ptr)
30
+ end
31
+ alias_method :name, :get_name
32
+
33
+ def get_geometry_type
34
+ FFIOGR.OGR_L_GetGeomType(@ptr)
35
+ end
36
+ alias_method :geometry_type, :get_geometry_type
37
+
38
+ def get_spatial_ref
39
+ OGR::Tools.cast_spatial_reference(FFIOGR.OGR_L_GetSpatialRef(@ptr))
40
+ end
41
+ alias_method :spatial_ref, :get_spatial_ref
42
+
43
+ def add_field(name, field_type, options={})
44
+ type = field_type.to_sym
45
+ precision = options[:precision] || 1
46
+ width = options[:width] || 32
47
+
19
48
  field = FFIOGR.OGR_Fld_Create(name, field_type.to_sym)
20
- FFIOGR.OGR_Fld_SetWidth(field, field_width)
49
+
50
+ if type == :real
51
+ FFIOGR.OGR_Fld_SetPrecision(field, precision)
52
+ else
53
+ FFIOGR.OGR_Fld_SetWidth(field, width)
54
+ end
55
+
21
56
  FFIOGR.OGR_L_CreateField(@ptr, field, 1)
22
57
  FFIOGR.OGR_Fld_Destroy(field)
23
58
  end
@@ -0,0 +1,10 @@
1
+ module OGR
2
+ class OptionsStruct < FFI::Struct
3
+ layout :length, :size_t,
4
+ :options, :pointer
5
+
6
+ def to_a
7
+ self[:options].get_array_of_string 0, self[:length]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,81 @@
1
+ module OGR
2
+ class SpatialReference
3
+ attr_accessor :ptr
4
+
5
+ def initialize(ptr)
6
+ @ptr = FFI::AutoPointer.new(ptr, self.class.method(:release))
7
+ @ptr.autorelease = false
8
+ end
9
+
10
+ def self.release(ptr);end
11
+
12
+ def free
13
+ FFIOGR.OSRDestroySpatialReference(@ptr)
14
+ end
15
+
16
+ def self.create
17
+ OGR::Tools.cast_spatial_reference(FFIOGR.OSRNewSpatialReference(nil))
18
+ end
19
+
20
+ def self.from_wkt(wkt)
21
+ sr = OGR::Tools.cast_spatial_reference(FFIOGR.OSRNewSpatialReference(nil))
22
+ sr.import_wkt(wkt)
23
+ sr
24
+ end
25
+
26
+ def self.from_proj4(proj4)
27
+ sr = OGR::Tools.cast_spatial_reference(FFIOGR.OSRNewSpatialReference(nil))
28
+ sr.import_proj4(proj4)
29
+ sr
30
+ end
31
+
32
+ def self.from_epsg(epsg_code)
33
+ sr = OGR::Tools.cast_spatial_reference(FFIOGR.OSRNewSpatialReference(nil))
34
+ sr.import_epsg(epsg_code)
35
+ sr
36
+ end
37
+
38
+ def import_wkt(wkt)
39
+ wkt_ptr = FFI::MemoryPointer.from_string wkt
40
+ wkt_ptr_ptr = FFI::MemoryPointer.new :pointer
41
+ wkt_ptr_ptr.put_pointer 0, wkt_ptr
42
+ FFIOGR.OSRImportFromWkt(@ptr, wkt_ptr_ptr)
43
+ end
44
+
45
+ def import_proj4(proj4)
46
+ FFIOGR.OSRImportFromProj4(@ptr, proj4)
47
+ end
48
+
49
+ def import_epsg(epsg_code)
50
+ FFIOGR.OSRImportFromEPSG(@ptr, epsg_code)
51
+ end
52
+
53
+ def to_wkt(pretty=false)
54
+ ptr = FFI::MemoryPointer.new :pointer
55
+
56
+ unless pretty
57
+ FFIOGR.OSRExportToWkt(@ptr, ptr)
58
+ else
59
+ FFIOGR.OSRExportToPrettyWkt(@ptr, ptr, 4)
60
+ end
61
+ str_ptr = ptr.read_pointer
62
+
63
+ return str_ptr.null? ? nil : str_ptr.read_string
64
+ end
65
+
66
+ def to_proj4
67
+ ptr = FFI::MemoryPointer.new :pointer
68
+ FFIOGR.OSRExportToProj4(@ptr, ptr)
69
+ str_ptr = ptr.read_pointer
70
+ return str_ptr.null? ? nil: str_ptr.read_string
71
+ end
72
+
73
+ def ==(other)
74
+ self.to_wkt == other.to_wkt
75
+ end
76
+
77
+ def find_transformation(out_sr)
78
+ CoordinateTransformation.find_transformation self, out_sr
79
+ end
80
+ end
81
+ end
data/lib/ffi-ogr/tools.rb CHANGED
@@ -1,26 +1,33 @@
1
1
  module OGR
2
2
  module Tools
3
3
  class << self
4
- def cast_data_source(ds_ptr, options={})
5
- options = {auto_free: true}.merge(options)
4
+ def cast_spatial_reference(sr_ptr, auto_free=true)
5
+ raise RuntimeError.new("Spatial Reference pointer is NULL") if sr_ptr.null?
6
+ SpatialReference.new sr_ptr
7
+ end
8
+
9
+ def cast_coordinate_transformation(ct_ptr, auto_free=true)
10
+ raise RuntimeError.new("Coordinate Transformation pointer is NULL") if ct_ptr.null?
11
+ CoordinateTransformation.new ct_ptr
12
+ end
13
+
14
+ def cast_data_source(ds_ptr, auto_free=true)
6
15
  raise RuntimeError.new("Data Source pointer is NULL") if ds_ptr.null?
7
- DataSource.new ds_ptr, options[:auto_free]
16
+ DataSource.new ds_ptr
8
17
  end
9
18
 
10
- def cast_layer(l_ptr, options={})
11
- options = {auto_free: true}.merge(options)
19
+ def cast_layer(l_ptr, auto_free=true)
12
20
  raise RuntimeError.new("Layer pointer is NULL") if l_ptr.null?
13
- Layer.new l_ptr, options[:aut_free]
21
+ Layer.new l_ptr
14
22
  end
15
23
 
16
- def cast_feature(f_ptr, options={})
17
- options = {auto_free: true}.merge(options)
24
+ def cast_feature(f_ptr, auto_free=true)
18
25
  raise RuntimeError.new("Feature pointer is NULL") if f_ptr.null?
19
- Feature.new f_ptr, options[:auto_free]
26
+ Feature.new f_ptr
20
27
  end
21
28
 
22
- def cast_geometry(geom_ptr, options={})
23
- options = {auto_free: true}.merge(options)
29
+ def cast_geometry(geom_ptr, auto_free=true)
30
+ #options = {auto_free: true}.merge(options)
24
31
  raise RuntimeError.new("Geometry pointer is NULL") if geom_ptr.null?
25
32
 
26
33
  geom_type = FFIOGR.OGR_G_GetGeometryType(geom_ptr)
@@ -58,7 +65,7 @@ module OGR
58
65
  OGR::GeometryCollection25D
59
66
  end
60
67
 
61
- klass.new(geom_ptr, options[:auto_free])
68
+ klass.new(geom_ptr)
62
69
  end
63
70
  end
64
71
  end
@@ -1,3 +1,3 @@
1
1
  module OGR
2
- VERSION = '0.0.1.pre'
2
+ VERSION = '0.0.1'
3
3
  end
@@ -2,15 +2,15 @@ module OGR
2
2
  class Writer
3
3
  include OGR::FFIOGR
4
4
 
5
- attr_accessor :ds
5
+ attr_accessor :ptr
6
6
 
7
7
  def initialize;end
8
8
 
9
9
  def set_output(path, options={})
10
10
  path = File.expand_path(path)
11
11
  ds = OGR_Dr_CreateDataSource(@driver, path, nil)
12
- @ds = OGR::Tools.cast_data_source(ds)
13
- @ds
12
+ @ptr = OGR::Tools.cast_data_source(ds)
13
+ @ptr
14
14
  end
15
15
 
16
16
  def self.from_file_type(path)
@@ -36,7 +36,7 @@ module OGR
36
36
  writer = Writer.from_file_type output_path
37
37
  data_source = writer.ds
38
38
 
39
- # @ds -> data_source
39
+ # @ptr -> data_source
40
40
  end
41
41
  end
42
42
  end
data/lib/ffi-ogr.rb CHANGED
@@ -4,6 +4,11 @@ require 'multi_json'
4
4
  module OGR
5
5
  OGR_BASE = File.join(File.dirname(__FILE__), 'ffi-ogr')
6
6
 
7
+ DRIVER_TYPES = {
8
+ 'shapefile' => 'ESRI Shapefile',
9
+ 'geojson' => 'GeoJSON'
10
+ }
11
+
7
12
  autoload :Reader, File.join(OGR_BASE, 'reader')
8
13
  autoload :GenericReader, File.join(OGR_BASE, 'generic_reader')
9
14
  autoload :ShpReader, File.join(OGR_BASE, 'shp_reader')
@@ -34,6 +39,10 @@ module OGR
34
39
  autoload :MultiLineString25D, File.join(OGR_BASE, 'multi_line_string_25d')
35
40
  autoload :MultiPolygon25D, File.join(OGR_BASE, 'multi_polygon_25d')
36
41
  autoload :GeometryCollection25D, File.join(OGR_BASE, 'geometry_collection_25d')
42
+ autoload :Envelope, File.join(OGR_BASE, 'envelope')
43
+ autoload :SpatialReference, File.join(OGR_BASE, 'spatial_reference')
44
+ autoload :CoordinateTransformation, File.join(OGR_BASE, 'coordinate_transformation')
45
+ autoload :OptionsStruct, File.join(OGR_BASE, 'options_struct')
37
46
 
38
47
  module FFIOGR
39
48
  def self.search_paths
@@ -109,12 +118,17 @@ module OGR
109
118
  :right, 2
110
119
  ]
111
120
 
121
+ attach_function :GDALVersionInfo, [:string], :string
122
+
123
+ attach_function :CPLSetConfigOption, [:string, :string], :void
124
+ attach_function :CPLSetThreadLocalConfigOption, [:string, :string], :void
125
+
112
126
  attach_function :OGRRegisterAll, [], :void
113
127
  attach_function :OGR_Dr_GetName, [:pointer], :string
114
128
  attach_function :OGR_Dr_Open, [:pointer, :string, :int], :pointer
115
129
  attach_function :OGR_Dr_TestCapability, [:pointer, :string], :int
116
- attach_function :OGR_Dr_CreateDataSource, [:pointer, :string, :string], :pointer
117
- attach_function :OGR_Dr_CopyDataSource, [:pointer, :pointer, :string, :string], :pointer
130
+ attach_function :OGR_Dr_CreateDataSource, [:pointer, :string, :pointer], :pointer
131
+ attach_function :OGR_Dr_CopyDataSource, [:pointer, :pointer, :string, :pointer], :pointer
118
132
  attach_function :OGR_Dr_DeleteDataSource, [:pointer, :string], :pointer
119
133
  attach_function :OGRGetDriverCount, [], :int
120
134
  attach_function :OGRGetDriver, [:int], :pointer
@@ -127,7 +141,7 @@ module OGR
127
141
  attach_function :OGR_DS_GetLayerByName, [:pointer, :string], :pointer
128
142
  attach_function :OGR_DS_DeleteLayer, [:pointer, :int], :pointer
129
143
  attach_function :OGR_DS_GetDriver, [:pointer], :pointer
130
- attach_function :OGR_DS_CreateLayer, [:pointer, :string, :pointer, :ogr_geometry_type, :string], :pointer
144
+ attach_function :OGR_DS_CreateLayer, [:pointer, :string, :pointer, :ogr_geometry_type, :pointer], :pointer
131
145
  attach_function :OGR_DS_CopyLayer, [:pointer, :pointer, :string, :string], :pointer
132
146
  attach_function :OGR_DS_TestCapability, [:pointer, :string], :int
133
147
  attach_function :OGR_DS_ExecuteSQL, [:pointer, :string, :pointer, :string], :pointer
@@ -195,6 +209,7 @@ module OGR
195
209
  attach_function :OGR_F_GetGeometryRef, [:pointer], :pointer
196
210
  attach_function :OGR_F_GetFID, [:pointer], :long
197
211
  attach_function :OGR_F_SetFID, [:pointer, :long], :pointer
212
+ attach_function :OGR_F_StealGeometry, [:pointer], :pointer
198
213
  attach_function :OGR_F_SetGeometry, [:pointer, :pointer], :pointer
199
214
  attach_function :OGR_F_SetGeometryDirectly, [:pointer, :pointer], :pointer
200
215
  attach_function :OGR_G_CreateFromWkb, [:pointer, :pointer, :pointer, :int], :pointer
@@ -279,13 +294,36 @@ module OGR
279
294
  attach_function :OGR_G_AddGeometryDirectly, [:pointer, :pointer], :pointer
280
295
  attach_function :OGR_G_RemoveGeometry, [:pointer, :int, :int], :pointer
281
296
  attach_function :OGR_F_Destroy, [:pointer], :void
297
+
298
+ # SRS Functions
299
+
300
+ attach_function :OSRNewSpatialReference, [:pointer], :pointer
301
+ attach_function :OSRImportFromWkt, [:pointer, :pointer], :pointer
302
+ attach_function :OSRImportFromProj4, [:pointer, :string], :pointer
303
+ attach_function :OSRImportFromEPSG, [:pointer, :int], :pointer
304
+ attach_function :OSRExportToWkt, [:pointer, :pointer], :pointer
305
+ attach_function :OSRExportToPrettyWkt, [:pointer, :pointer, :int], :pointer
306
+ attach_function :OSRExportToProj4, [:pointer, :pointer], :pointer
307
+ attach_function :OSRDestroySpatialReference, [:pointer], :void
308
+ attach_function :OCTNewCoordinateTransformation, [:pointer, :pointer], :pointer
309
+ attach_function :OCTDestroyCoordinateTransformation, [:pointer], :void
310
+
311
+ OGRRegisterAll() # register all available OGR drivers
282
312
  end
283
313
 
284
314
  class << self
315
+ def gdal_version
316
+ FFIOGR.GDALVersionInfo('RELEASE_NAME')
317
+ end
318
+
285
319
  def to_binary(data)
286
320
  buf = FFI::MemoryPointer.new(:char, value.size)
287
321
  buf.put_bytes(0, data)
288
322
  buf
289
323
  end
324
+
325
+ def string_to_pointer(str)
326
+ FFI::MemoryPointer.from_string(str)
327
+ end
290
328
  end
291
329
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-ogr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre
5
- prerelease: 6
4
+ version: 0.0.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Scooter Wadsworth
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-28 00:00:00.000000000 Z
12
+ date: 2013-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 1.5.0
21
+ version: 1.6.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,23 +26,23 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 1.5.0
29
+ version: 1.6.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: multi_json
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ! '>='
35
+ - - '='
36
36
  - !ruby/object:Gem::Version
37
- version: '0'
37
+ version: 1.7.2
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ! '>='
43
+ - - '='
44
44
  - !ruby/object:Gem::Version
45
- version: '0'
45
+ version: 1.7.2
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rake
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -85,7 +85,9 @@ extra_rdoc_files: []
85
85
  files:
86
86
  - README.md
87
87
  - bin/ogr_console
88
+ - lib/ffi-ogr/coordinate_transformation.rb
88
89
  - lib/ffi-ogr/data_source.rb
90
+ - lib/ffi-ogr/envelope.rb
89
91
  - lib/ffi-ogr/feature.rb
90
92
  - lib/ffi-ogr/generic_reader.rb
91
93
  - lib/ffi-ogr/generic_writer.rb
@@ -105,6 +107,7 @@ files:
105
107
  - lib/ffi-ogr/multi_point_25d.rb
106
108
  - lib/ffi-ogr/multi_polygon.rb
107
109
  - lib/ffi-ogr/multi_polygon_25d.rb
110
+ - lib/ffi-ogr/options_struct.rb
108
111
  - lib/ffi-ogr/point.rb
109
112
  - lib/ffi-ogr/point_25d.rb
110
113
  - lib/ffi-ogr/polygon.rb
@@ -113,6 +116,7 @@ files:
113
116
  - lib/ffi-ogr/shapefile.rb
114
117
  - lib/ffi-ogr/shp_reader.rb
115
118
  - lib/ffi-ogr/shp_writer.rb
119
+ - lib/ffi-ogr/spatial_reference.rb
116
120
  - lib/ffi-ogr/tools.rb
117
121
  - lib/ffi-ogr/version.rb
118
122
  - lib/ffi-ogr/writer.rb