ffi-gdal 1.0.0.beta5 → 1.0.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -3
  3. data/.rubocop.yml +7 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +1 -1
  6. data/History.md +143 -1
  7. data/README.md +5 -11
  8. data/Rakefile +2 -60
  9. data/TODO.md +10 -0
  10. data/examples/geometries.rb +4 -6
  11. data/examples/gridding.rb +99 -98
  12. data/examples/ogr_layer_to_layer.rb +0 -2
  13. data/examples/raster_erasing.rb +47 -0
  14. data/examples/remove_small_polygons.rb +62 -0
  15. data/examples/testing_gdal.rb +0 -3
  16. data/examples/warping.rb +140 -0
  17. data/ffi-gdal.gemspec +5 -2
  18. data/lib/ext/error_symbols.rb +1 -1
  19. data/lib/ext/ffi_library_function_checks.rb +3 -2
  20. data/lib/ext/float_ext.rb +2 -2
  21. data/lib/ext/narray_ext.rb +1 -1
  22. data/lib/ext/numeric_as_data_type.rb +1 -1
  23. data/lib/ext/to_bool.rb +2 -2
  24. data/lib/ffi/cpl/conv.rb +1 -3
  25. data/lib/ffi/cpl/error.rb +0 -3
  26. data/lib/ffi/cpl/minixml.rb +17 -21
  27. data/lib/ffi/cpl/progress.rb +27 -0
  28. data/lib/ffi/cpl/string.rb +0 -8
  29. data/lib/ffi/cpl/vsi.rb +0 -1
  30. data/lib/ffi/cpl/xml_node.rb +0 -1
  31. data/lib/ffi/cpl.rb +15 -0
  32. data/lib/ffi/gdal/alg.rb +72 -54
  33. data/lib/ffi/gdal/gdal.rb +669 -672
  34. data/lib/ffi/gdal/grid.rb +141 -24
  35. data/lib/ffi/gdal/grid_data_metrics_options.rb +1 -1
  36. data/lib/ffi/gdal/grid_moving_average_options.rb +1 -1
  37. data/lib/ffi/gdal/matching.rb +0 -2
  38. data/lib/ffi/gdal/transformer_info.rb +1 -1
  39. data/lib/ffi/gdal/version.rb +1 -1
  40. data/lib/ffi/gdal/vrt.rb +0 -2
  41. data/lib/ffi/gdal/warp_options.rb +12 -14
  42. data/lib/ffi/gdal/warper.rb +61 -6
  43. data/lib/ffi/gdal.rb +18 -3
  44. data/lib/ffi/ogr/api.rb +10 -21
  45. data/lib/ffi/ogr/core.rb +9 -12
  46. data/lib/ffi/ogr/featurestyle.rb +0 -5
  47. data/lib/ffi/ogr/geocoding.rb +0 -1
  48. data/lib/ffi/ogr/srs_api.rb +0 -4
  49. data/lib/ffi/ogr/style_value.rb +1 -2
  50. data/lib/ffi/ogr.rb +15 -12
  51. data/lib/ffi-gdal.rb +5 -3
  52. data/lib/gdal/color_entry.rb +1 -0
  53. data/lib/gdal/color_interpretation.rb +2 -2
  54. data/lib/gdal/color_table.rb +14 -14
  55. data/lib/gdal/color_table_mixins/extensions.rb +4 -4
  56. data/lib/gdal/cpl_error_handler.rb +12 -14
  57. data/lib/gdal/data_type.rb +13 -12
  58. data/lib/gdal/dataset.rb +170 -94
  59. data/lib/gdal/dataset_mixins/algorithm_methods.rb +47 -21
  60. data/lib/gdal/dataset_mixins/extensions.rb +32 -61
  61. data/lib/gdal/dataset_mixins/matching.rb +0 -2
  62. data/lib/gdal/dataset_mixins/warp_methods.rb +42 -0
  63. data/lib/gdal/driver.rb +62 -47
  64. data/lib/gdal/driver_mixins/extensions.rb +2 -7
  65. data/lib/gdal/environment_methods.rb +13 -10
  66. data/lib/gdal/exceptions.rb +24 -2
  67. data/lib/gdal/geo_transform.rb +10 -16
  68. data/lib/gdal/geo_transform_mixins/extensions.rb +58 -3
  69. data/lib/gdal/grid.rb +62 -109
  70. data/lib/gdal/{grid_types → grid_algorithms}/data_metrics_base.rb +1 -3
  71. data/lib/gdal/{grid_types → grid_algorithms}/inverse_distance_to_a_power.rb +2 -4
  72. data/lib/gdal/{grid_types → grid_algorithms}/metric_average_distance.rb +2 -2
  73. data/lib/gdal/{grid_types → grid_algorithms}/metric_average_distance_pts.rb +2 -2
  74. data/lib/gdal/{grid_types → grid_algorithms}/metric_count.rb +2 -2
  75. data/lib/gdal/{grid_types → grid_algorithms}/metric_maximum.rb +2 -2
  76. data/lib/gdal/{grid_types → grid_algorithms}/metric_minimum.rb +2 -2
  77. data/lib/gdal/{grid_types → grid_algorithms}/metric_range.rb +2 -2
  78. data/lib/gdal/{grid_types → grid_algorithms}/moving_average.rb +2 -4
  79. data/lib/gdal/{grid_types → grid_algorithms}/nearest_neighbor.rb +2 -4
  80. data/lib/gdal/grid_algorithms.rb +22 -0
  81. data/lib/gdal/gridder/point_extracting.rb +89 -0
  82. data/lib/gdal/gridder.rb +294 -0
  83. data/lib/gdal/gridder_options.rb +273 -0
  84. data/lib/gdal/internal_helpers.rb +132 -23
  85. data/lib/gdal/major_object.rb +13 -10
  86. data/lib/gdal/merger.rb +130 -0
  87. data/lib/gdal/options.rb +3 -2
  88. data/lib/gdal/raster_attribute_table.rb +74 -51
  89. data/lib/gdal/raster_attribute_table_mixins/extensions.rb +21 -3
  90. data/lib/gdal/raster_band.rb +139 -167
  91. data/lib/gdal/raster_band_classifier.rb +19 -18
  92. data/lib/gdal/raster_band_mixins/algorithm_extensions.rb +107 -0
  93. data/lib/gdal/raster_band_mixins/algorithm_methods.rb +79 -40
  94. data/lib/gdal/raster_band_mixins/coloring_extensions.rb +84 -0
  95. data/lib/gdal/raster_band_mixins/extensions.rb +34 -169
  96. data/lib/gdal/raster_band_mixins/io_extensions.rb +180 -0
  97. data/lib/gdal/rpc_info.rb +1 -2
  98. data/lib/gdal/transformer.rb +1 -6
  99. data/lib/gdal/transformers/approximate_transformer.rb +0 -4
  100. data/lib/gdal/transformers/base_general_image_projection_transformer.rb +0 -6
  101. data/lib/gdal/transformers/gcp_transformer.rb +2 -6
  102. data/lib/gdal/transformers/general_image_projection_transformer.rb +8 -7
  103. data/lib/gdal/transformers/general_image_projection_transformer2.rb +1 -1
  104. data/lib/gdal/transformers/geolocation_transformer.rb +0 -4
  105. data/lib/gdal/transformers/reprojection_transformer.rb +0 -8
  106. data/lib/gdal/transformers/rpc_transformer.rb +0 -4
  107. data/lib/gdal/transformers/tps_transformer.rb +1 -3
  108. data/lib/gdal/version_info.rb +7 -8
  109. data/lib/gdal/virtual_dataset.rb +2 -4
  110. data/lib/gdal/warp_operation.rb +17 -14
  111. data/lib/gdal/warp_options.rb +132 -0
  112. data/lib/gdal.rb +41 -2
  113. data/lib/ogr/coordinate_transformation.rb +79 -32
  114. data/lib/ogr/data_source.rb +17 -14
  115. data/lib/ogr/data_source_extensions.rb +1 -5
  116. data/lib/ogr/driver.rb +11 -14
  117. data/lib/ogr/envelope.rb +1 -1
  118. data/lib/ogr/envelope_extensions.rb +23 -6
  119. data/lib/ogr/error_handling.rb +3 -3
  120. data/lib/ogr/exceptions.rb +6 -0
  121. data/lib/ogr/feature.rb +25 -38
  122. data/lib/ogr/feature_definition.rb +6 -8
  123. data/lib/ogr/feature_definition_extensions.rb +2 -6
  124. data/lib/ogr/feature_extensions.rb +71 -41
  125. data/lib/ogr/field.rb +16 -15
  126. data/lib/ogr/field_definition.rb +4 -4
  127. data/lib/ogr/geocoder.rb +5 -5
  128. data/lib/ogr/geometries/geometry_collection.rb +4 -1
  129. data/lib/ogr/geometries/geometry_collection_25d.rb +12 -0
  130. data/lib/ogr/geometries/line_string.rb +30 -8
  131. data/lib/ogr/geometries/line_string_25d.rb +21 -0
  132. data/lib/ogr/geometries/linear_ring.rb +10 -1
  133. data/lib/ogr/geometries/multi_line_string.rb +2 -1
  134. data/lib/ogr/geometries/multi_line_string_25d.rb +13 -0
  135. data/lib/ogr/geometries/multi_point.rb +2 -1
  136. data/lib/ogr/geometries/multi_point_25d.rb +14 -0
  137. data/lib/ogr/geometries/multi_polygon.rb +3 -2
  138. data/lib/ogr/geometries/multi_polygon_25d.rb +13 -0
  139. data/lib/ogr/geometries/point.rb +20 -23
  140. data/lib/ogr/geometries/point_25d.rb +48 -0
  141. data/lib/ogr/geometries/polygon.rb +4 -1
  142. data/lib/ogr/geometries/polygon_25d.rb +14 -0
  143. data/lib/ogr/geometry.rb +125 -93
  144. data/lib/ogr/geometry_field_definition.rb +7 -5
  145. data/lib/ogr/geometry_mixins/container_mixins.rb +23 -0
  146. data/lib/ogr/geometry_mixins/extensions.rb +111 -0
  147. data/lib/ogr/geometry_types/container.rb +10 -3
  148. data/lib/ogr/geometry_types/curve.rb +68 -23
  149. data/lib/ogr/geometry_types/surface.rb +0 -9
  150. data/lib/ogr/internal_helpers.rb +3 -3
  151. data/lib/ogr/layer.rb +4 -5
  152. data/lib/ogr/layer_mixins/extensions.rb +242 -17
  153. data/lib/ogr/layer_mixins/ogr_feature_methods.rb +11 -11
  154. data/lib/ogr/layer_mixins/ogr_field_methods.rb +6 -11
  155. data/lib/ogr/layer_mixins/ogr_layer_method_methods.rb +18 -18
  156. data/lib/ogr/layer_mixins/ogr_query_filter_methods.rb +0 -2
  157. data/lib/ogr/layer_mixins/ogr_sql_methods.rb +1 -1
  158. data/lib/ogr/spatial_reference.rb +12 -37
  159. data/lib/ogr/spatial_reference_mixins/coordinate_system_getter_setters.rb +53 -55
  160. data/lib/ogr/spatial_reference_mixins/exporters.rb +18 -49
  161. data/lib/ogr/spatial_reference_mixins/parameter_getter_setters.rb +10 -29
  162. data/lib/ogr/style_table.rb +2 -2
  163. data/lib/ogr/style_table_extensions.rb +3 -1
  164. data/lib/ogr/style_tool.rb +8 -14
  165. data/lib/ogr.rb +39 -1
  166. data/spec/ffi-gdal_spec.rb +18 -1
  167. data/spec/integration/gdal/color_table_info_spec.rb +49 -33
  168. data/spec/integration/gdal/dataset_info_spec.rb +294 -45
  169. data/spec/integration/gdal/driver_info_spec.rb +139 -31
  170. data/spec/integration/gdal/geo_transform_info_spec.rb +197 -26
  171. data/spec/integration/gdal/gridder_spec.rb +329 -0
  172. data/spec/integration/gdal/raster_attribute_table_info_spec.rb +216 -11
  173. data/spec/integration/gdal/raster_band_algorithms_spec.rb +33 -0
  174. data/spec/integration/gdal/raster_band_info_spec.rb +240 -271
  175. data/spec/integration/ogr/layer_spec.rb +3 -1
  176. data/spec/spec_helper.rb +15 -6
  177. data/spec/support/images/osgeo/gdal/data/hfa/float-rle.img +0 -0
  178. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.lgo +31 -0
  179. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.tif +0 -0
  180. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.tif.msk +0 -0
  181. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.txt +10 -0
  182. data/spec/support/images/osgeo/geotiff/gdal_eg/cea.tif +0 -0
  183. data/spec/support/images/osgeo/geotiff/gdal_eg/cea.txt +84 -0
  184. data/spec/support/images/osgeo/geotiff/zi_imaging/image0.lgo +45 -0
  185. data/spec/support/images/osgeo/geotiff/zi_imaging/image0.tif +0 -0
  186. data/spec/support/integration_help.rb +32 -2
  187. data/spec/support/shared_examples/gdal/major_object_examples.rb +0 -6
  188. data/spec/support/shared_examples/ogr/a_geometry.rb +1 -1
  189. data/spec/unit/ffi/gdal_spec.rb +1 -1
  190. data/spec/unit/gdal/color_entry_spec.rb +1 -0
  191. data/spec/unit/gdal/color_interpretation_spec.rb +1 -0
  192. data/spec/unit/gdal/dataset_spec.rb +53 -2
  193. data/spec/unit/gdal/geo_transform_mixins/extensions_spec.rb +67 -0
  194. data/spec/unit/gdal/geo_transform_spec.rb +1 -1
  195. data/spec/unit/gdal/grid_spec.rb +83 -0
  196. data/spec/unit/gdal/gridder/point_extracting_spec.rb +99 -0
  197. data/spec/unit/gdal/gridder_options_spec.rb +183 -0
  198. data/spec/unit/gdal/gridder_spec.rb +140 -0
  199. data/spec/unit/gdal/internal_helpers_spec.rb +166 -2
  200. data/spec/unit/gdal/major_object_spec.rb +2 -0
  201. data/spec/unit/gdal/options_spec.rb +1 -0
  202. data/spec/unit/gdal/raster_band_classifier_spec.rb +70 -12
  203. data/spec/unit/gdal/raster_band_mixins/extensions_spec.rb +71 -0
  204. data/spec/unit/gdal/raster_band_mixins/io_extensions_spec.rb +133 -0
  205. data/spec/unit/gdal/raster_band_spec.rb +1 -0
  206. data/spec/unit/gdal/rpc_info_spec.rb +1 -0
  207. data/spec/unit/gdal/version_info_spec.rb +2 -0
  208. data/spec/unit/gdal/warp_operation_spec.rb +1 -0
  209. data/spec/unit/ogr/coordinate_transformation_spec.rb +102 -0
  210. data/spec/unit/ogr/data_source_spec.rb +12 -0
  211. data/spec/unit/ogr/feature_extensions_spec.rb +88 -0
  212. data/spec/unit/ogr/feature_spec.rb +30 -46
  213. data/spec/unit/ogr/geometries/geometry_collection_25d_spec.rb +23 -0
  214. data/spec/unit/ogr/geometries/geometry_collection_spec.rb +3 -3
  215. data/spec/unit/ogr/geometries/line_string_25d_spec.rb +23 -0
  216. data/spec/unit/ogr/geometries/line_string_spec.rb +2 -2
  217. data/spec/unit/ogr/geometries/linear_ring_spec.rb +2 -2
  218. data/spec/unit/ogr/geometries/multi_line_string_25d_spec.rb +23 -0
  219. data/spec/unit/ogr/geometries/multi_point_25d_spec.rb +23 -0
  220. data/spec/unit/ogr/geometries/multi_polygon_25d_spec.rb +23 -0
  221. data/spec/unit/ogr/geometries/point_25d_spec.rb +23 -0
  222. data/spec/unit/ogr/geometries/point_spec.rb +14 -24
  223. data/spec/unit/ogr/geometries/polygon_25d_spec.rb +23 -0
  224. data/spec/unit/ogr/geometries/polygon_spec.rb +1 -1
  225. data/spec/unit/ogr/geometry_field_definition_spec.rb +1 -1
  226. data/spec/unit/ogr/geometry_spec.rb +196 -30
  227. data/spec/unit/ogr/internal_helpers_spec.rb +20 -9
  228. data/spec/unit/ogr/layer_mixins/ogr_feature_methods_spec.rb +14 -6
  229. data/spec/unit/ogr/spatial_reference_mixins/exporters_spec.rb +9 -1
  230. data/spec/unit/ogr/spatial_reference_mixins/parameter_getter_setters_spec.rb +2 -1
  231. data/spec/unit/ogr/style_table_spec.rb +1 -1
  232. data/tmp/.keep +0 -0
  233. metadata +121 -19
  234. data/examples/points.txt +0 -127
  235. data/lib/gdal/grid_types.rb +0 -22
  236. data/lib/ogr/geometries/point_extensions.rb +0 -32
  237. data/lib/ogr/geometry_extensions.rb +0 -59
@@ -1,7 +1,5 @@
1
- require_relative '../ffi/gdal/vrt'
2
- require_relative '../ffi/cpl/minixml'
1
+ require_relative '../gdal'
3
2
  require_relative 'major_object'
4
- require_relative 'options'
5
3
 
6
4
  module GDAL
7
5
  class VirtualDataset
@@ -25,7 +23,7 @@ module GDAL
25
23
  FFI::CPL::MiniXML.CPLSerializeXMLTree(xml_node)
26
24
  end
27
25
 
28
- # @param data_type [FFI::GDAL::DataType]
26
+ # @param data_type [FFI::GDAL::GDAL::DataType]
29
27
  # @param options [Hash]
30
28
  # @return [Boolean]
31
29
  def add_band(data_type, **options)
@@ -1,19 +1,21 @@
1
- require_relative '../ffi/gdal/warper'
1
+ require_relative '../gdal'
2
2
 
3
3
  module GDAL
4
4
  class WarpOperation
5
5
  # @return [FFI::Pointer]
6
6
  attr_reader :c_pointer
7
7
 
8
- # @param warp_options [FFI::GDAL::WarpOptions]
8
+ # @param warp_options [GDAL::WarpOptions]
9
9
  def initialize(warp_options)
10
- @c_pointer = FFI::GDAL::Warper.GDALCreateWarpOperation(warp_options)
11
-
12
- ObjectSpace.define_finalizer self, -> { destroy! }
10
+ @c_pointer = FFI::GDAL::Warper.GDALCreateWarpOperation(warp_options.c_struct)
11
+ raise GDAL::Error, 'Unable to create warp operation' if @c_pointer.null?
13
12
  end
14
13
 
15
14
  def destroy!
15
+ return unless @c_pointer
16
+
16
17
  FFI::GDAL::Warper.GDALDestroyWarpOperation(@c_pointer)
18
+ @c_pointer = nil
17
19
  end
18
20
 
19
21
  # @param x_offset [Fixnum] X offset of the destination image.
@@ -28,15 +30,16 @@ module GDAL
28
30
  y_size)
29
31
  end
30
32
 
31
- # @param _x_offset [Fixnum] X offset of the destination image.
32
- # @param _y_offset [Fixnum] Y offset of the destination image.
33
- # @param _x_size [Fixnum] X size (width) of the destination image.
34
- # @param _y_size [Fixnum] Y size (height) of the destination image.
35
- # @todo Implement
36
- def chunk_and_warp_multi(_x_offset, _y_offset, _x_size, _y_size)
37
- fail NotImplementedError, '#chunk_and_warp_multi not yet implemented.'
38
-
39
- FFI::GDAL::Warper.GDALChunkAndWarpMulti(@c_pointer)
33
+ # @param x_offset [Fixnum] X offset of the destination image.
34
+ # @param y_offset [Fixnum] Y offset of the destination image.
35
+ # @param x_size [Fixnum] X size (width) of the destination image.
36
+ # @param y_size [Fixnum] Y size (height) of the destination image.
37
+ def chunk_and_warp_multi(x_offset, y_offset, x_size, y_size)
38
+ FFI::GDAL::Warper.GDALChunkAndWarpMulti(@c_pointer,
39
+ x_offset,
40
+ y_offset,
41
+ x_size,
42
+ y_size)
40
43
  end
41
44
 
42
45
  # @param destination_x_offset [Fixnum] X offset of the destination image.
@@ -0,0 +1,132 @@
1
+ require_relative '../gdal'
2
+
3
+ module GDAL
4
+ class WarpOptions
5
+ attr_reader :c_struct
6
+
7
+ def initialize(options = {})
8
+ @c_struct = FFI::GDAL::WarpOptions.new
9
+
10
+ options.keys do |k|
11
+ @c_struct[k] = options[k]
12
+ end
13
+ end
14
+
15
+ def c_pointer
16
+ @c_struct.to_ptr
17
+ end
18
+
19
+ # @param options [Hash]
20
+ def warp_operation_options=(options)
21
+ @c_struct[:warp_operation_options] = GDAL::Options.pointer(options)
22
+ end
23
+
24
+ # @param limit [Float]
25
+ def warp_memory_limit=(limit)
26
+ @c_struct[:warp_memory_limit] = limit
27
+ end
28
+
29
+ # @param algorithm_type [FFI::GDAL::Warper::ResampleAlg]
30
+ def resample_algorithm=(algorithm_type)
31
+ @c_struct[:resample_alg] = algorithm_type
32
+ end
33
+
34
+ # @param data_type [FFI::GDAL::GDAL::DataType]
35
+ def working_data_type=(data_type)
36
+ @c_struct[:working_data_type] = data_type
37
+ end
38
+
39
+ # @param dataset [GDAL::Dataset]
40
+ def source_dataset=(dataset)
41
+ @c_struct[:source_dataset] = dataset.c_pointer
42
+ end
43
+
44
+ # @param dataset [GDAL::Dataset]
45
+ def destination_dataset=(dataset)
46
+ @c_struct[:destination_dataset] = dataset.c_pointer
47
+ end
48
+
49
+ # @param count [Fixnum]
50
+ def band_count=(count)
51
+ @c_struct[:band_count] = count
52
+ end
53
+
54
+ # @param band_numbers [Array<Fixnum>]
55
+ def source_bands=(band_numbers)
56
+ bands_ptr = FFI::MemoryPointer.new(:pointer, band_numbers.length)
57
+ bands_ptr.write_array_of_int(band_numbers)
58
+
59
+ @c_struct[:source_bands] = bands_ptr
60
+ end
61
+
62
+ # @param band_numbers [Array<Fixnum>]
63
+ def destination_bands=(band_numbers)
64
+ bands_ptr = FFI::MemoryPointer.new(:pointer, band_numbers.length)
65
+ bands_ptr.write_array_of_int(band_numbers)
66
+
67
+ @c_struct[:destination_bands] = bands_ptr
68
+ end
69
+
70
+ def transformer_arg=(transformation_object)
71
+ @c_struct[:transformer_arg] = transformation_object.c_pointer
72
+
73
+ @c_struct[:transformer] = transformation_object.function
74
+ end
75
+
76
+ def transformer=(transformer)
77
+ @c_struct[:transformer] = transformer
78
+ end
79
+
80
+ def progress_formatter=(output_proc)
81
+ @c_struct[:progress] = output_proc
82
+ end
83
+
84
+ def cutline_geometry=(geometry)
85
+ raise 'Not a geom' unless geometry.is_a?(OGR::Geometry)
86
+
87
+ @c_struct[:cutline] = geometry.c_pointer
88
+ # @c_struct[:cutline] = geometry.clone.c_pointer
89
+ end
90
+
91
+ def cutline_blend_distance=(distance)
92
+ @c_struct[:cutline_blend_distance] = distance
93
+ end
94
+
95
+ def source_no_data_real=(values)
96
+ values_ptr = FFI::MemoryPointer.new(:double, values.length)
97
+ values_ptr.write_array_of_double(values)
98
+
99
+ @c_struct[:source_no_data_real] = values_ptr
100
+ end
101
+
102
+ def source_no_data_imaginary=(values)
103
+ values_ptr = FFI::MemoryPointer.new(:double, values.length)
104
+ values_ptr.write_array_of_double(values)
105
+
106
+ @c_struct[:source_no_data_imaginary] = values_ptr
107
+ end
108
+
109
+ def destination_no_data_real=(values)
110
+ values_ptr = FFI::MemoryPointer.new(:double, values.length)
111
+ values_ptr.write_array_of_double(values)
112
+
113
+ @c_struct[:destination_no_data_real] = values_ptr
114
+ end
115
+
116
+ def destination_no_data_imaginary=(values)
117
+ values_ptr = FFI::MemoryPointer.new(:double, values.length)
118
+ values_ptr.write_array_of_double(values)
119
+
120
+ @c_struct[:destination_no_data_imaginary] = values_ptr
121
+ end
122
+
123
+ # Used for getting attributes of the internal WarpOptions struct.
124
+ #
125
+ # @param meth [Symbol] The FFI::GDAL::WarpOptions key.
126
+ def method_missing(meth)
127
+ super unless FFI::GDAL::WarpOptions.members.include?(meth)
128
+
129
+ @c_struct[meth]
130
+ end
131
+ end
132
+ end
data/lib/gdal.rb CHANGED
@@ -1,4 +1,41 @@
1
- require_relative 'ffi/gdal'
1
+ require_relative 'ffi-gdal'
2
+
3
+ module GDAL
4
+ class << self
5
+ # Use when you want something quick and easy for when you need something
6
+ # quick for a +FFI::GDAL::GDALProgressFunc+. Outputs the duration and
7
+ # percentage completed.
8
+ #
9
+ # @return [Proc] A Proc that works for a +GDALProgressFunc+ callback.
10
+ def simple_progress_formatter
11
+ start = Time.now
12
+
13
+ lambda do |d, _, _|
14
+ print "Duration: #{(Time.now - start).to_f.round(2)}s\t| #{(d * 100).round(2)}%\r"
15
+ true
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def gdal_require(path)
22
+ File.expand_path(path, __dir__)
23
+ end
24
+ end
25
+
26
+ # Autoload just the core GDAL object types.
27
+ autoload :ColorTable, gdal_require('gdal/color_table')
28
+ autoload :Dataset, gdal_require('gdal/dataset')
29
+ autoload :DataType, gdal_require('gdal/data_type')
30
+ autoload :Driver, gdal_require('gdal/driver')
31
+ autoload :GeoTransform, gdal_require('gdal/geo_transform')
32
+ autoload :Logger, gdal_require('gdal/logger')
33
+ autoload :Options, gdal_require('gdal/options')
34
+ autoload :RasterAttributeTable, gdal_require('gdal/raster_attribute_table')
35
+ autoload :RasterBand, gdal_require('gdal/raster_band')
36
+ end
37
+
38
+ require_relative 'gdal/exceptions'
2
39
  require_relative 'gdal/version_info'
3
40
  require_relative 'gdal/environment_methods'
4
41
  require_relative 'gdal/internal_helpers'
@@ -10,8 +47,10 @@ module GDAL
10
47
  include InternalHelpers
11
48
 
12
49
  # Register all drivers!
13
- ::FFI::GDAL.GDALAllRegister
50
+ ::FFI::GDAL::GDAL.GDALAllRegister
14
51
 
52
+ # We define our own error handler so we can turn GDAL errors into Ruby
53
+ # exceptions.
15
54
  FFI_GDAL_ERROR_HANDLER = GDAL::CPLErrorHandler.handle_error
16
55
  ::FFI::CPL::Error.CPLSetErrorHandler(FFI_GDAL_ERROR_HANDLER)
17
56
  end
@@ -1,5 +1,6 @@
1
1
  require 'narray'
2
- require_relative '../ffi/ogr/srs_api'
2
+ require_relative '../ogr'
3
+ require_relative '../gdal'
3
4
 
4
5
  module OGR
5
6
  class CoordinateTransformation
@@ -7,7 +8,10 @@ module OGR
7
8
  # @return [String]
8
9
  def self.proj4_normalize(proj4_source)
9
10
  if GDAL._supported?(:OCTProj4Normalize)
10
- FFI::GDAL.OCTProj4Normalize(proj4_source)
11
+ FFI::GDAL::GDAL.OCTProj4Normalize(proj4_source)
12
+ else
13
+ raise OGR::UnsupportedOperation,
14
+ 'Your version of GDAL/OGR does not support OCTProj4Normalize'
11
15
  end
12
16
  end
13
17
 
@@ -20,33 +24,94 @@ module OGR
20
24
  # @return [FFI::Pointer] C pointer that represents the CoordinateTransformation.
21
25
  attr_reader :c_pointer
22
26
 
27
+ # @param source_srs [OGR::SpatialReference]
28
+ # @param destination_srs [OGR::SpatialReference]
23
29
  def initialize(source_srs, destination_srs)
24
30
  source_ptr = GDAL._pointer(OGR::SpatialReference, source_srs)
25
31
  destination_ptr = GDAL._pointer(OGR::SpatialReference, destination_srs)
26
32
  @c_pointer = FFI::OGR::SRSAPI.OCTNewCoordinateTransformation(source_ptr, destination_ptr)
27
33
 
28
- if @c_pointer.null?
29
- fail OGR::Failure, 'Unable to create coordinate transformation'
30
- end
31
-
32
- close_me = -> { destroy! }
33
- ObjectSpace.define_finalizer self, close_me
34
+ raise OGR::Failure, 'Unable to create coordinate transformation' if @c_pointer.null?
34
35
  end
35
36
 
36
- # Deletes the object and deallocates all related resources.
37
+ # Deletes the object and deallocates all related C resources.
37
38
  def destroy!
39
+ return unless @c_pointer
40
+
38
41
  FFI::OGR::SRSAPI.OCTDestroyCoordinateTransformation(@c_pointer)
42
+ @c_pointer = nil
39
43
  end
40
44
 
41
- # Transforms points in the +source_srs+ space to points in the
42
- # +destination_space+ (given in .create).
45
+ # Transforms points in the +#source_coordinate_system+ space to points in the
46
+ # +#destination_coordinate_system+ (given in {#initialize}).
43
47
  #
44
48
  # @param x_vertices [Array<Float>]
45
49
  # @param y_vertices [Array<Float>]
46
50
  # @param z_vertices [Array<Float>]
47
- # @return [Array<Array<Float>,Array<Float>,Array<Float>>] [[x1, y1], [x2,
48
- # y2], etc]
51
+ # @return [Array<Array<Float>,Array<Float>,Array<Float>>] [[x1, x2, etc], [y1, y2, etc]]
52
+ # Will include a 3rd array of Z values if z vertices are given.
49
53
  def transform(x_vertices, y_vertices, z_vertices = [])
54
+ _transform(x_vertices, y_vertices, z_vertices) do |point_count, x_ptr, y_ptr, z_ptr|
55
+ FFI::OGR::SRSAPI.OCTTransform(@c_pointer, point_count, x_ptr, y_ptr, z_ptr)
56
+ end
57
+ end
58
+
59
+ # @param x_vertices [Array<Float>]
60
+ # @param y_vertices [Array<Float>]
61
+ # @param z_vertices [Array<Float>]
62
+ # @return [Hash{points => Array<Array<Float>,Array<Float>,Array<Float>>, success_at => Array}]
63
+ # [[x1, y1], [x2, y2], etc]
64
+ def transform_ex(x_vertices, y_vertices, z_vertices = [])
65
+ success_ptr = nil
66
+
67
+ point_array = _transform(x_vertices, y_vertices, z_vertices) do |point_count, x_ptr, y_ptr, z_ptr|
68
+ success_ptr = FFI::MemoryPointer.new(:bool, point_count)
69
+ FFI::OGR::SRSAPI.OCTTransformEx(@c_pointer, point_count, x_ptr, y_ptr, z_ptr, success_ptr)
70
+ end
71
+
72
+ successes = success_ptr.read_array_of_type(FFI::Type::BOOL, :read_char, point_array.first.length).map do |value|
73
+ !value.zero?
74
+ end
75
+
76
+ { points: point_array, successes: successes }
77
+ end
78
+
79
+ private
80
+
81
+ # @param x_vertices [Array<Float>]
82
+ # @param y_vertices [Array<Float>]
83
+ # @param z_vertices [Array<Float>]
84
+ # @yieldparam point_count [Fixnum]
85
+ # @yieldparam x_ptr [FFI::MemortyPointer]
86
+ # @yieldparam y_ptr [FFI::MemortyPointer]
87
+ # @yieldparam z_ptr [FFI::MemortyPointer]
88
+ # @yieldreturn [Boolean]
89
+ # @return [Array<Array<Float>,Array<Float>,Array<Float>>] [[x1, x2, etc], [y1, y2, etc]]
90
+ # Will include a 3rd array of Z values if z vertices are given.
91
+ def _transform(x_vertices, y_vertices, z_vertices = [])
92
+ x_ptr, y_ptr, z_ptr = init_transform_pointers(x_vertices, y_vertices, z_vertices)
93
+ point_count = [x_vertices.length, y_vertices.length, z_vertices.length].max
94
+
95
+ result = yield point_count, x_ptr, y_ptr, z_ptr
96
+
97
+ # TODO: maybe this should raise?
98
+ return false unless result
99
+
100
+ x_vals = x_ptr.read_array_of_double(x_vertices.size)
101
+ y_vals = y_ptr.read_array_of_double(y_vertices.size)
102
+ z_vals = z_vertices.empty? ? nil : z_ptr.read_array_of_double(z_vertices.size)
103
+
104
+ points = [x_vals, y_vals]
105
+ points << z_vals unless z_vertices.empty?
106
+
107
+ points
108
+ end
109
+
110
+ # @param x_vertices [Array<Float>]
111
+ # @param y_vertices [Array<Float>]
112
+ # @param z_vertices [Array<Float>]
113
+ # @return [Array<FFI::Pointer>]
114
+ def init_transform_pointers(x_vertices, y_vertices, z_vertices)
50
115
  x_ptr = FFI::MemoryPointer.new(:pointer, x_vertices.size)
51
116
  x_ptr.write_array_of_double(x_vertices)
52
117
  y_ptr = FFI::MemoryPointer.new(:pointer, y_vertices.size)
@@ -59,25 +124,7 @@ module OGR
59
124
  z_ptr.write_array_of_double(z_vertices)
60
125
  end
61
126
 
62
- point_count = x_vertices.size + y_vertices.size + z_vertices.size
63
-
64
- result = FFI::OGR::SRSAPI.OCTTransform(@c_pointer, point_count,
65
- x_ptr, y_ptr, z_ptr)
66
-
67
- # maybe this should raise?
68
- return false unless result
69
-
70
- x_vals = x_ptr.read_array_of_double
71
- y_vals = y_ptr.read_array_of_double
72
- z_vals = z_vertices.empty? ? nil : z_ptr.read_array_of_double
73
-
74
- points = if z_vertices.empty?
75
- NMatrix[x_vals, y_vals]
76
- else
77
- NMatrix[x_vals, y_vals, z_vals]
78
- end
79
-
80
- points.transpose.to_a
127
+ [x_ptr, y_ptr, z_ptr]
81
128
  end
82
129
  end
83
130
  end
@@ -1,13 +1,9 @@
1
1
  require 'uri'
2
2
  require 'json'
3
- require_relative '../ffi/gdal'
4
- require_relative '../ffi/ogr'
3
+ require_relative '../gdal'
4
+ require_relative '../ogr'
5
5
  require_relative 'data_source_extensions'
6
- require_relative 'exceptions'
7
- require_relative 'driver'
8
6
  require_relative 'data_source_mixins/capability_methods'
9
- require_relative 'style_table'
10
- require_relative 'layer'
11
7
  require_relative '../gdal/major_object'
12
8
 
13
9
  module OGR
@@ -23,7 +19,15 @@ module OGR
23
19
  # @param access_flag [String] 'r' for read, 'w', for write.
24
20
  # @return [OGR::DataSource]
25
21
  def self.open(path, access_flag = 'r')
26
- new(path, access_flag)
22
+ ds = new(path, access_flag)
23
+
24
+ if block_given?
25
+ result = yield ds
26
+ ds.close
27
+ result
28
+ else
29
+ ds
30
+ end
27
31
  end
28
32
 
29
33
  # @return [FFI::Pointer]
@@ -34,7 +38,7 @@ module OGR
34
38
  # @param access_flag [String] 'r' for read, 'w', for write.
35
39
  def initialize(path_or_pointer, access_flag)
36
40
  @c_pointer =
37
- if path_or_pointer.is_a? String
41
+ if path_or_pointer.is_a?(String)
38
42
  uri = URI.parse(path_or_pointer)
39
43
  file_path = uri.scheme.nil? ? ::File.expand_path(path_or_pointer) : path_or_pointer
40
44
  FFI::OGR::API.OGROpen(file_path, OGR._boolean_access_flag(access_flag), nil)
@@ -42,10 +46,9 @@ module OGR
42
46
  path_or_pointer
43
47
  end
44
48
 
45
- fail OGR::OpenFailure, file_path if @c_pointer.null?
49
+ raise OGR::OpenFailure, file_path if @c_pointer.null?
46
50
 
47
51
  @layers = []
48
- ObjectSpace.define_finalizer self, -> { destroy! }
49
52
  end
50
53
 
51
54
  # Closes opened data source and releases allocated resources.
@@ -55,7 +58,7 @@ module OGR
55
58
  FFI::OGR::API.OGR_DS_Destroy(@c_pointer)
56
59
  @c_pointer = nil
57
60
  end
58
- alias_method :close, :destroy!
61
+ alias close destroy!
59
62
 
60
63
  # Name of the file represented by this object.
61
64
  #
@@ -108,7 +111,7 @@ module OGR
108
111
  # @return [OGR::Layer]
109
112
  def create_layer(name, geometry_type: :wkbUnknown, spatial_reference: nil, **options)
110
113
  unless can_create_layer?
111
- fail OGR::UnsupportedOperation, 'This data source does not support creating layers.'
114
+ raise OGR::UnsupportedOperation, 'This data source does not support creating layers.'
112
115
  end
113
116
 
114
117
  spatial_ref_ptr = GDAL._pointer(OGR::SpatialReference, spatial_reference) if spatial_reference
@@ -118,7 +121,7 @@ module OGR
118
121
  spatial_ref_ptr, geometry_type, options_obj)
119
122
 
120
123
  unless layer_ptr
121
- fail OGR::InvalidLayer, "Unable to create layer '#{name}'."
124
+ raise OGR::InvalidLayer, "Unable to create layer '#{name}'."
122
125
  end
123
126
 
124
127
  @layers << OGR::Layer.new(layer_ptr)
@@ -145,7 +148,7 @@ module OGR
145
148
  # @return +true+ if successful, otherwise raises an OGR exception.
146
149
  def delete_layer(index)
147
150
  unless can_delete_layer?
148
- fail OGR::UnsupportedOperation, 'This data source does not support deleting layers.'
151
+ raise OGR::UnsupportedOperation, 'This data source does not support deleting layers.'
149
152
  end
150
153
 
151
154
  ogr_err = FFI::OGR::API.OGR_DS_DeleteLayer(@c_pointer, index)
@@ -2,11 +2,7 @@ module OGR
2
2
  module DataSourceExtensions
3
3
  # @return [Array<OGR::Layer>]
4
4
  def layers
5
- l = layer_count.times.map do |i|
6
- layer(i)
7
- end
8
-
9
- @layers = l
5
+ @layers = Array.new(layer_count) { |i| layer(i) }
10
6
  end
11
7
 
12
8
  # @return [Hash]
data/lib/ogr/driver.rb CHANGED
@@ -1,8 +1,7 @@
1
- require_relative '../ffi/ogr'
1
+ require_relative '../ogr'
2
+ require_relative '../gdal'
2
3
  require_relative '../gdal/major_object'
3
- require_relative '../gdal/options'
4
4
  require_relative 'driver_mixins/capability_methods'
5
- require_relative 'data_source'
6
5
 
7
6
  module OGR
8
7
  # Wrapper for OGR's Driver class. In this case, to use a driver, find the
@@ -25,7 +24,7 @@ module OGR
25
24
  # @raise [OGR::DriverNotFound] if a driver with +name+ isn't found.
26
25
  def self.by_name(name)
27
26
  driver_ptr = FFI::OGR::API.OGRGetDriverByName(name)
28
- fail OGR::DriverNotFound, name if driver_ptr.null?
27
+ raise OGR::DriverNotFound, name if driver_ptr.null?
29
28
 
30
29
  new(driver_ptr)
31
30
  end
@@ -35,20 +34,18 @@ module OGR
35
34
  # @return [OGR::Driver]
36
35
  # @raise [OGR::DriverNotFound] if a driver at +index+ isn't found.
37
36
  def self.at_index(index)
38
- fail OGR::DriverNotFound, index if index > count
37
+ raise OGR::DriverNotFound, index if index > count
39
38
 
40
39
  driver_ptr = FFI::OGR::API.OGRGetDriver(index)
41
40
  return nil if driver_ptr.null?
42
- fail OGR::DriverNotFound, index if driver_ptr.null?
41
+ raise OGR::DriverNotFound, index if driver_ptr.null?
43
42
 
44
43
  new(driver_ptr)
45
44
  end
46
45
 
47
46
  # @return [Array<String>]
48
47
  def self.names
49
- count.times.map do |i|
50
- at_index(i).name
51
- end.sort
48
+ Array.new(count) { |i| at_index(i).name }.sort
52
49
  end
53
50
 
54
51
  # @return [FFI::Pointer] C pointer that represents the Driver.
@@ -76,7 +73,7 @@ module OGR
76
73
  data_source_ptr = FFI::OGR::API.OGR_Dr_Open(@c_pointer, file_name, update)
77
74
 
78
75
  if data_source_ptr.null?
79
- fail OGR::InvalidDataSource, "Unable to open data source at #{file_name}"
76
+ raise OGR::InvalidDataSource, "Unable to open data source at #{file_name}"
80
77
  end
81
78
 
82
79
  OGR::DataSource.new(data_source_ptr, nil)
@@ -91,7 +88,7 @@ module OGR
91
88
  # @return [OGR::DataSource, nil]
92
89
  def create_data_source(file_name, **options)
93
90
  unless can_create_data_source?
94
- fail OGR::UnsupportedOperation, 'This driver does not support data source creation.'
91
+ raise OGR::UnsupportedOperation, 'This driver does not support data source creation.'
95
92
  end
96
93
 
97
94
  options_ptr = GDAL::Options.pointer(options)
@@ -100,7 +97,7 @@ module OGR
100
97
  file_name, options_ptr)
101
98
  return nil if data_source_ptr.null?
102
99
 
103
- ds = OGR::DataSource.new(data_source_ptr, nil)
100
+ ds = OGR::DataSource.new(data_source_ptr, 'w')
104
101
  yield ds if block_given?
105
102
 
106
103
  ds
@@ -110,7 +107,7 @@ module OGR
110
107
  # @return +true+ if successful, otherwise raises an OGR exception.
111
108
  def delete_data_source(file_name)
112
109
  unless can_delete_data_source?
113
- fail OGR::UnsupportedOperation, 'This driver does not support deleting data sources.'
110
+ raise OGR::UnsupportedOperation, 'This driver does not support deleting data sources.'
114
111
  end
115
112
 
116
113
  ogr_err = FFI::OGR::API.OGR_Dr_DeleteDataSource(@c_pointer, file_name)
@@ -126,7 +123,7 @@ module OGR
126
123
  source_ptr = GDAL._pointer(OGR::DataSource, source_data_source)
127
124
 
128
125
  if source_ptr.nil? || source_ptr.null?
129
- fail OGR::InvalidDataSource, source_data_source
126
+ raise OGR::InvalidDataSource, source_data_source
130
127
  end
131
128
 
132
129
  options_ptr = GDAL::Options.pointer(options)
data/lib/ogr/envelope.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative '../ffi/ogr'
1
+ require_relative '../ogr'
2
2
  require_relative 'envelope_extensions'
3
3
 
4
4
  module OGR
@@ -40,11 +40,11 @@ module OGR
40
40
  # Compares min/max X and min/max Y to the other envelope. The envelopes are
41
41
  # considered equal if those values are the same.
42
42
  #
43
- # @param other_envelope [OGR::Envelope]
43
+ # @param other [OGR::Envelope]
44
44
  # @return [Boolean]
45
- def ==(other_envelope)
46
- x_min == other_envelope.x_min && y_min == other_envelope.y_min &&
47
- x_max == other_envelope.x_max && y_max == other_envelope.y_max
45
+ def ==(other)
46
+ x_min == other.x_min && y_min == other.y_min &&
47
+ x_max == other.x_max && y_max == other.y_max
48
48
  end
49
49
 
50
50
  # Stolen from http://www.gdal.org/ogr__core_8h_source.html.
@@ -85,6 +85,22 @@ module OGR
85
85
  y_max >= other_envelope.y_max
86
86
  end
87
87
 
88
+ # @return [OGR::Polygon]
89
+ def to_polygon
90
+ ring = OGR::LinearRing.new
91
+ ring.point_count = 5
92
+ ring.set_point(0, x_min, y_max)
93
+ ring.set_point(1, x_max, y_max)
94
+ ring.set_point(2, x_max, y_min)
95
+ ring.set_point(3, x_min, y_min)
96
+ ring.set_point(4, x_min, y_max)
97
+
98
+ polygon = OGR::Polygon.new
99
+ polygon.add_geometry(ring)
100
+
101
+ polygon
102
+ end
103
+
88
104
  # @return [Hash]
89
105
  def as_json(_options = nil)
90
106
  json = {
@@ -94,8 +110,9 @@ module OGR
94
110
  y_max: y_max
95
111
  }
96
112
 
97
- if @c_struct.is_a? FFI::GDAL::OGREnvelope3D
98
- json.merge!(z_min: z_min, z_max: z_max)
113
+ if @c_struct.is_a? FFI::OGR::Envelope3D
114
+ json[:z_min] = z_min
115
+ json[:z_max] = z_max
99
116
  end
100
117
 
101
118
  json
@@ -23,7 +23,7 @@ module OGR
23
23
  # @return [Proc]
24
24
  def error_class_map(error_class)
25
25
  {
26
- OGRERR_NONE: ->(_) { true },
26
+ OGRERR_NONE: proc { true },
27
27
  OGRERR_NOT_ENOUGH_DATA: ->(msg) { raise_exception(OGR::NotEnoughData, msg) },
28
28
  OGRERR_NOT_ENOUGH_MEMORY: ->(msg) { raise_exception(::NoMemoryError, msg) },
29
29
  OGRERR_UNSUPPORTED_GEOMETRY_TYPE: ->(msg) { raise_exception(OGR::UnsupportedGeometryType, msg) },
@@ -32,7 +32,7 @@ module OGR
32
32
  OGRERR_FAILURE: ->(msg) { raise_exception(OGR::Failure, msg) },
33
33
  OGRERR_UNSUPPORTED_SRS: ->(msg) { raise_exception(OGR::UnsupportedSRS, msg) },
34
34
  OGRERR_INVALID_HANDLE: ->(msg) { raise_exception(OGR::InvalidHandle, msg) }
35
- }.fetch(error_class) { fail "Unknown OGRERR type: #{self}" }
35
+ }.fetch(error_class) { raise "Unknown OGRERR type: #{self}" }
36
36
  end
37
37
 
38
38
  # Exists solely to strip off the top 4 lines of the backtrace so it doesn't
@@ -40,7 +40,7 @@ module OGR
40
40
  def raise_exception(exception, message)
41
41
  e = exception.new(message)
42
42
  e.set_backtrace(caller(4))
43
- fail(e)
43
+ raise(e)
44
44
  end
45
45
  end
46
46
  end