ffi-ogr 0.0.1.pre → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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