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,10 +1,4 @@
1
- require 'log_switch'
2
-
3
1
  module GDAL
4
- module Logger
5
- include LogSwitch
6
- end
7
-
8
2
  # @private
9
3
  module InternalHelpers
10
4
  def self.included(base)
@@ -32,18 +26,38 @@ module GDAL
32
26
  end
33
27
  end
34
28
 
35
- # @param data_type [FFI::GDAL::DataType]
36
- # @return [Symbol] The FFI Symbol that represents a data type.
29
+ # @param data_type [FFI::GDAL::GDAL::DataType]
30
+ # @param size [Fixnum] Size of the pointer to allocate.
31
+ # @return [FFI::MemoryPointer]
37
32
  def _pointer_from_data_type(data_type, size = nil)
38
33
  pointer_type = _gdal_data_type_to_ffi(data_type)
39
34
 
35
+ size ? FFI::MemoryPointer.new(pointer_type, size) : FFI::MemoryPointer.new(pointer_type)
36
+ end
37
+
38
+ # @param data_type [FFI::GDAL::GDAL::DataType]
39
+ # @param size [Fixnum] Size of the pointer to allocate.
40
+ # @return [FFI::Buffer]
41
+ def _buffer_from_data_type(data_type, size = nil)
42
+ pointer_type = _gdal_data_type_to_ffi(data_type)
43
+
40
44
  if size
41
- FFI::MemoryPointer.new(pointer_type, size)
45
+ FFI::Buffer.alloc_inout(pointer_type, size)
42
46
  else
43
- FFI::MemoryPointer.new(pointer_type)
47
+ FFI::Buffer.alloc_inout(pointer_type)
44
48
  end
45
49
  end
46
50
 
51
+ # @param data_type [FFI::GDAL::GDAL::DataType]
52
+ # @param narray_args Args to pass to the NArray initializer.
53
+ # @return [NArray]
54
+ def _narray_from_data_type(data_type, *narray_args)
55
+ init_meth = _gdal_data_type_to_narray(data_type)
56
+ narray_args = 0 if narray_args.empty?
57
+
58
+ NArray.send(init_meth, *narray_args)
59
+ end
60
+
47
61
  # Takes an array of strings (or things that should be converted to
48
62
  # strings) and creates a char**.
49
63
  #
@@ -56,28 +70,121 @@ module GDAL
56
70
 
57
71
  string_pointers << nil
58
72
  array_pointer = FFI::MemoryPointer.new(:pointer, strings.size + 1)
73
+ i = 0
59
74
 
60
- string_pointers.each_with_index do |ptr, i|
61
- array_pointer[i].put_pointer(0, ptr)
75
+ # fast-ruby says while is faster than each_with_index
76
+ while i < string_pointers.length
77
+ array_pointer[i].put_pointer(0, string_pointers[i])
78
+ i += 1
62
79
  end
63
80
 
64
81
  array_pointer
65
82
  end
66
83
 
84
+ # @param type [Symbol] FFI type of pointer to make a pointer to.
85
+ # @return [FFI::MemoryPointer] Pointer to a pointer.
86
+ def _pointer_pointer(type)
87
+ pointer = FFI::MemoryPointer.new(type)
88
+ pointer_ptr = FFI::MemoryPointer.new(:pointer)
89
+ pointer_ptr.write_pointer(pointer)
90
+
91
+ pointer_ptr
92
+ end
93
+
94
+ # @return [String, nil]
95
+ def _read_pointer_pointer_safely(pointer_ptr, type)
96
+ return if pointer_ptr.read_pointer.null?
97
+
98
+ pointer_ptr.read_pointer.send("read_#{type}".to_sym)
99
+ end
100
+
67
101
  # Maps GDAL DataTypes to FFI types.
68
102
  #
69
- # @param data_type [FFI::GDAL::DataType]
103
+ # @param data_type [FFI::GDAL::GDAL::DataType]
104
+ # @return [Symbol]
70
105
  def _gdal_data_type_to_ffi(data_type)
71
106
  case data_type
72
- when :GDT_Byte then :uchar
73
- when :GDT_UInt16 then :uint16
74
- when :GDT_Int16 then :int16
75
- when :GDT_UInt32 then :uint32
76
- when :GDT_Int32 then :int32
77
- when :GDT_Float32 then :float
78
- when :GDT_Float64 then :double
107
+ when :GDT_Byte then :uchar
108
+ when :GDT_UInt16 then :uint16
109
+ when :GDT_Int16, :GDT_CInt16 then :int16
110
+ when :GDT_UInt32 then :uint32
111
+ when :GDT_Int32, :GDT_CInt32 then :int32
112
+ when :GDT_Float32, :GDT_CFloat32 then :float
113
+ when :GDT_Float64, :GDT_CFloat64 then :double
114
+ else
115
+ raise GDAL::InvalidDataType, "Unknown data type: #{data_type}"
116
+ end
117
+ end
118
+
119
+ # Maps GDAL DataTypes to NArray types.
120
+ #
121
+ # @param data_type [FFI::GDAL::GDAL::DataType]
122
+ # @return [Symbol]
123
+ def _gdal_data_type_to_narray(data_type)
124
+ case data_type
125
+ when :GDT_Byte then :byte
126
+ when :GDT_Int16 then :sint
127
+ when :GDT_UInt16, :GDT_Int32, :GDT_UInt32 then :int
128
+ when :GDT_Float32 then :float
129
+ when :GDT_Float64 then :dfloat
130
+ when :GDT_CInt16, :GDT_CInt32 then :scomplex
131
+ when :GDT_CFloat32 then :complex
132
+ when :GDT_CFloat64 then :dcomplex
133
+ else
134
+ raise GDAL::InvalidDataType, "Unknown data type: #{data_type}"
135
+ end
136
+ end
137
+
138
+ # Maps GDAL DataTypes to NArray type constants.
139
+ #
140
+ # @param data_type [FFI::GDAL::GDAL::DataType]
141
+ # @return [Symbol]
142
+ def _gdal_data_type_to_narray_type_constant(data_type)
143
+ case data_type
144
+ when :GDT_Byte then NArray::BYTE
145
+ when :GDT_Int16 then NArray::SINT
146
+ when :GDT_UInt16, :GDT_Int32, :GDT_UInt32 then NArray::INT
147
+ when :GDT_Float32 then NArray::FLOAT
148
+ when :GDT_Float64 then NArray::DFLOAT
149
+ when :GDT_CInt16, :GDT_CInt32 then NArray::SCOMPLEX
150
+ when :GDT_CFloat32 then NArray::COMPLEX
151
+ when :GDT_CFloat64 then NArray::DCOMPLEX
152
+ else
153
+ raise GDAL::InvalidDataType, "Unknown data type: #{data_type}"
154
+ end
155
+ end
156
+
157
+ # Helper method for reading an FFI pointer based on the GDAL DataType of
158
+ # the pointer.
159
+ #
160
+ # @param pointer [FFI::Pointer] The pointer to read from.
161
+ # @param data_type [FFI::GDAL::GDAL::DataType] The GDAL data type that
162
+ # determines what FFI type to use when reading.
163
+ # @param length [Fixnum] The amount of data to read from the pointer. If
164
+ # > 1, the "read_array_of_" method will be called.
165
+ # @return [Number, Array<Number>]
166
+ def _read_pointer(pointer, data_type, length = 1)
167
+ if length == 1
168
+ pointer.send("read_#{_gdal_data_type_to_ffi(data_type)}")
169
+ else
170
+ pointer.send("read_array_of_#{_gdal_data_type_to_ffi(data_type)}", length)
171
+ end
172
+ end
173
+
174
+ # Helper method for writing data to an FFI pointer based on the GDAL
175
+ # DataType of the pointer.
176
+ #
177
+ # @param pointer [FFI::Pointer] The pointer to write to.
178
+ # @param data_type [FFI::GDAL::GDAL::DataType] The GDAL data type that
179
+ # determines what FFI type to use when writing.
180
+ # @param data [Fixnum] The data to write to the pointer. If it's an Array
181
+ # with size > 1, the "write_array_of_" method will be called.
182
+ def _write_pointer(pointer, data_type, data)
183
+ if data.is_a?(Array) && data.size > 1
184
+ pointer.send("write_array_of_#{_gdal_data_type_to_ffi(data_type)}", data)
79
185
  else
80
- :float
186
+ data = data.first if data.is_a?(Array)
187
+ pointer.send("write_#{_gdal_data_type_to_ffi(data_type)}", data)
81
188
  end
82
189
  end
83
190
 
@@ -86,9 +193,11 @@ module GDAL
86
193
  #
87
194
  # @param function_name [Symbol]
88
195
  # @return [Boolean]
196
+ # TODO: Should the #respond_to? check all FFI::GDAL::* classes? What about
197
+ # OGR?
89
198
  def _supported?(function_name)
90
199
  !FFI::GDAL.unsupported_gdal_functions.include?(function_name) &&
91
- FFI::GDAL.respond_to?(function_name)
200
+ FFI::GDAL::GDAL.respond_to?(function_name)
92
201
  end
93
202
 
94
203
  # @param char [String] 'r' or 'w'
@@ -98,7 +207,7 @@ module GDAL
98
207
  case char
99
208
  when 'r' then :GF_Read
100
209
  when 'w' then :GF_Write
101
- else fail GDAL::InvalidAccessFlag, "Invalid access flag: #{char}"
210
+ else raise GDAL::InvalidAccessFlag, "Invalid access flag: #{char}"
102
211
  end
103
212
  end
104
213
  end
@@ -1,15 +1,16 @@
1
- require_relative '../ffi/gdal'
1
+ require_relative '../gdal'
2
+ require 'multi_xml'
2
3
 
3
4
  module GDAL
4
5
  module MajorObject
5
6
  # @return [Array<String>]
6
7
  def metadata_domain_list
7
- unless defined? FFI::GDAL.GDALGetMetadataDomainList
8
+ unless defined? FFI::GDAL::GDAL.GDALGetMetadataDomainList
8
9
  warn "GDALGetMetadataDomainList is't defined. GDAL::MajorObject#metadata_domain_list disabled."
9
10
  return []
10
11
  end
11
12
 
12
- list_pointer = FFI::GDAL.GDALGetMetadataDomainList(c_pointer)
13
+ list_pointer = FFI::GDAL::GDAL.GDALGetMetadataDomainList(@c_pointer)
13
14
  return [] if list_pointer.null?
14
15
 
15
16
  strings = list_pointer.get_array_of_string(0)
@@ -19,8 +20,10 @@ module GDAL
19
20
 
20
21
  # @param domain [String] Name of the domain to get metadata for.
21
22
  # @return [Hash]
22
- def metadata(domain = '')
23
- m = FFI::GDAL.GDALGetMetadata(c_pointer, domain)
23
+ def metadata(domain = nil)
24
+ return unless @c_pointer
25
+
26
+ m = FFI::GDAL::GDAL.GDALGetMetadata(@c_pointer, domain)
24
27
  return {} if m.null?
25
28
 
26
29
  data_array = m.get_array_of_string(0)
@@ -40,11 +43,11 @@ module GDAL
40
43
  # @param domain [String]
41
44
  # @return [String]
42
45
  def metadata_item(name, domain = '')
43
- FFI::GDAL.GDALGetMetadataItem(c_pointer, name, domain)
46
+ FFI::GDAL::GDAL.GDALGetMetadataItem(@c_pointer, name, domain)
44
47
  end
45
48
 
46
49
  def set_metadata_item(name, value, domain = '')
47
- FFI::GDAL.GDALSetMetadataItem(c_pointer, name, value.to_s, domain)
50
+ FFI::GDAL::GDAL.GDALSetMetadataItem(@c_pointer, name, value.to_s, domain)
48
51
  end
49
52
 
50
53
  # @return [Hash{domain => Array<String>}]
@@ -59,16 +62,16 @@ module GDAL
59
62
 
60
63
  # @return [String]
61
64
  def description
62
- FFI::GDAL.GDALGetDescription(c_pointer)
65
+ FFI::GDAL::GDAL.GDALGetDescription(@c_pointer)
63
66
  end
64
67
 
65
68
  # @param new_description [String]
66
69
  def description=(new_description)
67
- FFI::GDAL.GDALSetDescription(c_pointer, new_description.to_s)
70
+ FFI::GDAL::GDAL.GDALSetDescription(@c_pointer, new_description.to_s)
68
71
  end
69
72
 
70
73
  def null?
71
- c_pointer.null?
74
+ @c_pointer.null?
72
75
  end
73
76
  end
74
77
  end
@@ -0,0 +1,130 @@
1
+ require_relative 'driver'
2
+
3
+ module GDAL
4
+ # NOT YET WORKING!
5
+ #
6
+ # Port from gdal_merge.py, this lets you programmatically merge datasets.
7
+ class Merger
8
+ # @param [String] output_driver_name
9
+ # @param [String] output_file_name
10
+ # @param [Symbol] output_data_type
11
+ # @param [Array<GDAL::Dataset>] datasets
12
+ # @param [Hash] creation_options
13
+ def initialize(output_driver_name, output_file_name, output_data_type, datasets, **creation_options)
14
+ @output_driver = Driver.by_name(output_driver_name)
15
+ @output_file_name = output_file_name
16
+ @output_data_type = output_data_type
17
+ @datasets = datasets
18
+ @creation_options = creation_options
19
+ end
20
+
21
+ # @return [GDAL::Dataset]
22
+ def merge(target_align_pixels: false)
23
+ dest_geo_transform = build_geo_transform(target_align_pixels)
24
+ dest_dataset = build_empty_dataset(dest_geo_transform)
25
+ calculate_dimensions(dest_dataset)
26
+ end
27
+
28
+ private
29
+
30
+ def calculate_dimensions(dest_dataset)
31
+ @datasets.map.with_index do |d, _i|
32
+ dest_ulx = [dest_dataset.geo_transform.x_origin, d.geo_transform.x_origin].max
33
+ dest_lrx = [dest_dataset.lower_right_x, d.lower_right_x].min
34
+
35
+ uly_candidates = [dest_dataset.geo_transform.y_origin, d.geo_transform.y_origin]
36
+ lry_candidates = [dest_dataset.lower_right_y, d.lower_right_y]
37
+
38
+ if dest_dataset.geo_transform.y_origin < 0
39
+ dest_uly = uly_candidates.min
40
+ dest_lry = lry_candidates.max
41
+ else
42
+ dest_uly = uly_candidates.max
43
+ dest_lry = lry_candidates.min
44
+ end
45
+
46
+ dest_offsets = dest_dataset.geo_transform.world_to_pixel(dest_ulx, dest_uly, 0.1)
47
+ dest_sizes = dest_dataset.geo_transform.world_to_pixel(dest_lrx, dest_lry, 0.5)
48
+ dest_x_size = dest_sizes[:pixel] - dest_offsets[:pixel]
49
+ dest_y_size = dest_sizes[:line] - dest_offsets[:line]
50
+
51
+ src_offsets = d.geo_transform.world_to_pixel(dest_ulx, dest_uly)
52
+ src_sizes = d.geo_transform.world_to_pixel(dest_lrx, dest_lry, 0.5)
53
+ src_x_size = src_sizes[:pixel] - src_offsets[:pixel]
54
+ src_y_size = src_sizes[:line] - src_offsets[:line]
55
+
56
+ {
57
+ dest_x_offset: dest_offsets[:pixel],
58
+ dest_y_offset: dest_offsets[:line],
59
+ dest_x_size: dest_x_size,
60
+ dest_y_size: dest_y_size,
61
+ src_x_offset: src_offsets[:pixel],
62
+ src_y_offset: src_offsets[:line],
63
+ src_x_size: src_x_size,
64
+ src_y_size: src_y_size
65
+ }
66
+ end
67
+ end
68
+
69
+ # @return [GDAL::GeoTransform]
70
+ def build_geo_transform(target_align_pixels)
71
+ gt = GDAL::GeoTransform.new
72
+
73
+ gt.x_origin = overall_x_origin
74
+ gt.y_origin = overall_y_origin
75
+
76
+ first_transform = @datasets.first.geo_transform
77
+ gt.pixel_width = first_transform.pixel_width # psize_x
78
+ gt.pixel_height = first_transform.pixel_height # psize_y
79
+ gt.x_rotation = first_transform.x_rotation
80
+ gt.y_rotation = first_transform.y_rotation
81
+
82
+ gt.align! if target_align_pixels
83
+
84
+ gt
85
+ end
86
+
87
+ # @param [GDAL::GeoTransform] geo_transform
88
+ def build_empty_dataset(geo_transform)
89
+ x_size = x_size(geo_transform, overall_lower_x)
90
+ y_size = x_size(geo_transform, overall_lower_y)
91
+ data_type = @output_data_type
92
+
93
+ dataset = @output_driver.create_dataset(@output_file_name, x_size, y_size, data_type: data_type)
94
+ dataset.geo_transform = geo_transform
95
+ dataset.projection = @datasets.first.projection
96
+ dataset
97
+ # new_band = dataset.raster_band(1)
98
+ # new_band.write_xy_narray(raster_band.to_na)
99
+
100
+ # @datasets.each do |d|
101
+ # dataset.raster_band(1).copy_whole_raster(new_band)
102
+ # new_band.write_xy_narray(dataset.raster_band(1).to_na)
103
+ # end
104
+ end
105
+
106
+ def overall_x_origin
107
+ @datasets.map { |dataset| dataset.geo_transform.x_origin }.min
108
+ end
109
+
110
+ def overall_y_origin
111
+ @datasets.map { |dataset| dataset.geo_transform.y_origin }.max
112
+ end
113
+
114
+ def overall_lower_x
115
+ @datasets.map(&:lower_right_x).max
116
+ end
117
+
118
+ def overall_lower_y
119
+ @datasets.map(&:lower_right_y).min
120
+ end
121
+
122
+ def x_size(geo_transform, lower_right_x)
123
+ ((lower_right_x - geo_transform.x_origin) / geo_transform.pixel_width + 0.5).to_i
124
+ end
125
+
126
+ def y_size(geo_transform, lower_right_y)
127
+ ((lower_right_y - geo_transform.y_origin) / geo_transform.pixel_height + 0.5).to_i
128
+ end
129
+ end
130
+ end
data/lib/gdal/options.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'ffi'
2
- require_relative '../ffi/cpl/string'
3
2
 
4
3
  module GDAL
5
4
  # A wrapper for the way GDAL does key/value pair options for methods.
@@ -19,6 +18,8 @@ module GDAL
19
18
  end
20
19
  end
21
20
 
21
+ # @param hash [Hash] The hash of options to turn into a CPL key/value pair
22
+ # set.
22
23
  def initialize(hash = {})
23
24
  super()
24
25
  capitalize_keys!(hash)
@@ -30,7 +31,7 @@ module GDAL
30
31
  options_ptr = FFI::MemoryPointer.new(:pointer, size)
31
32
 
32
33
  each do |key, value|
33
- options_ptr = FFI::CPL::String.CSLSetNameValue(options_ptr, key, value)
34
+ options_ptr = FFI::CPL::String.CSLSetNameValue(options_ptr, key, value.to_s)
34
35
  end
35
36
 
36
37
  options_ptr
@@ -1,4 +1,4 @@
1
- require_relative '../ffi/gdal'
1
+ require_relative '../gdal'
2
2
  require_relative 'raster_attribute_table_mixins/extensions'
3
3
 
4
4
  module GDAL
@@ -11,8 +11,8 @@ module GDAL
11
11
  # @return [GDAL::RasterAttributeTable]
12
12
  def self.from_color_table(color_table)
13
13
  color_table_ptr = GDAL._pointer(GDAL::ColorTable, color_table)
14
- rat_ptr = FFI::GDAL.GDALCreateRasterAttributeTable
15
- FFI::GDAL.GDALRATInitializeFromColorTable(rat_ptr, color_table_ptr)
14
+ rat_ptr = FFI::GDAL::GDAL.GDALCreateRasterAttributeTable
15
+ FFI::GDAL::GDAL.GDALRATInitializeFromColorTable(rat_ptr, color_table_ptr)
16
16
 
17
17
  new(rat_ptr)
18
18
  end
@@ -22,13 +22,13 @@ module GDAL
22
22
 
23
23
  # @param pointer [FFI::Pointer]
24
24
  def initialize(pointer = nil)
25
- @c_pointer = pointer || FFI::GDAL.GDALCreateRasterAttributeTable
25
+ @c_pointer = pointer || FFI::GDAL::GDAL.GDALCreateRasterAttributeTable
26
26
  end
27
27
 
28
28
  def destroy!
29
29
  return unless @c_pointer
30
30
 
31
- FFI::GDAL.GDALDestroyRasterAttributeTable(@c_pointer)
31
+ FFI::GDAL::GDAL.GDALDestroyRasterAttributeTable(@c_pointer)
32
32
  @c_pointer = nil
33
33
  end
34
34
 
@@ -36,8 +36,8 @@ module GDAL
36
36
  #
37
37
  # @return [GDAL::RasterAttributeTable]
38
38
  def clone
39
- rat_ptr = FFI::GDAL.GDALRATClone(@c_pointer)
40
- return nil if rat_ptr.null?
39
+ rat_ptr = FFI::GDAL::GDAL.GDALRATClone(@c_pointer)
40
+ return nil if rat_ptr.nil? || rat_ptr.null?
41
41
 
42
42
  self.class.new(rat_ptr)
43
43
  end
@@ -47,106 +47,125 @@ module GDAL
47
47
  #
48
48
  # @return [Boolean]
49
49
  def changes_written_to_file?
50
- FFI::GDAL.GDALRATChangesAreWrittenToFile(@c_pointer)
50
+ FFI::GDAL::GDAL.GDALRATChangesAreWrittenToFile(@c_pointer)
51
51
  end
52
52
 
53
53
  # @return [Fixnum]
54
54
  def column_count
55
- FFI::GDAL.GDALRATGetColumnCount(@c_pointer)
55
+ FFI::GDAL::GDAL.GDALRATGetColumnCount(@c_pointer)
56
56
  end
57
57
 
58
58
  # @param index [Fixnum] The column number.
59
59
  # @return [String]
60
60
  def column_name(index)
61
- FFI::GDAL.GDALRATGetNameOfCol(@c_pointer, index)
61
+ FFI::GDAL::GDAL.GDALRATGetNameOfCol(@c_pointer, index)
62
62
  end
63
+ alias name_of_col column_name
63
64
 
64
65
  # @param index [Fixnum] The column number.
65
66
  # @return [GDALRATFieldUsage]
66
67
  def column_usage(index)
67
- FFI::GDAL.GDALRATGetUsageOfCol(@c_pointer, index)
68
+ FFI::GDAL::GDAL.GDALRATGetUsageOfCol(@c_pointer, index)
68
69
  end
70
+ alias usage_of_col column_usage
69
71
 
70
72
  # @param index [Fixnum] The column number.
71
73
  # @return [GDALRATFieldType]
72
74
  def column_type(index)
73
- FFI::GDAL.GDALRATGetTypeOfCol(@c_pointer, index)
75
+ FFI::GDAL::GDAL.GDALRATGetTypeOfCol(@c_pointer, index)
74
76
  end
77
+ alias type_of_col column_type
75
78
 
76
79
  # @param field_usage [GDALRATFieldUsage]
77
- # @return [Fixnum] The column number.
80
+ # @return [Fixnum] The column number or nil.
78
81
  def column_of_usage(field_usage)
79
- FFI::GDAL.GDALRATGetColOfUsage(@c_pointer, field_usage)
82
+ column_number = FFI::GDAL::GDAL.GDALRATGetColOfUsage(@c_pointer, field_usage)
83
+ return if column_number < 0
84
+
85
+ column_number
80
86
  end
81
87
 
82
88
  # @param name [String]
83
- # @param type [FFI::GDALRATFieldType]
84
- # @param usage [FFI::GDALRATFieldUsage]
89
+ # @param type [FFI::GDAL::GDALRATFieldType]
90
+ # @param usage [FFI::GDAL::GDALRATFieldUsage]
85
91
  # @return [Boolean]
86
92
  def create_column(name, type, usage)
87
- !!FFI::GDAL.GDALRATCreateColumn(@c_pointer, name, type, usage)
93
+ FFI::GDAL::GDAL.GDALRATCreateColumn(@c_pointer, name, type, usage)
88
94
  end
89
95
 
90
96
  # @return [Fixnum] The number of rows.
91
97
  def row_count
92
- FFI::GDAL.GDALRATGetRowCount(@c_pointer)
98
+ FFI::GDAL::GDAL.GDALRATGetRowCount(@c_pointer)
93
99
  end
94
100
 
95
101
  # @return [Fixnum] The number of rows.
96
102
  def row_count=(count)
97
- FFI::GDAL.GDALRATSetRowCount(@c_pointer, count)
103
+ FFI::GDAL::GDAL.GDALRATSetRowCount(@c_pointer, count)
98
104
  end
99
105
 
100
106
  # Get the row for a pixel value.
101
107
  #
102
- # @param value [Float]
103
- # @return [Fixnum]
104
- def row_of_value(value)
105
- FFI::GDAL.GDALRATGetRowOfValue(@c_pointer, value)
108
+ # @param pixel_value [Float]
109
+ # @return [Fixnum] Index of the row or nil.
110
+ def row_of_value(pixel_value)
111
+ row_index = FFI::GDAL::GDAL.GDALRATGetRowOfValue(@c_pointer, pixel_value)
112
+ return if row_index < 0
113
+
114
+ row_index
106
115
  end
107
116
 
108
117
  # @param row [Fixnum]
109
118
  # @param field [Fixnum]
110
119
  # @return [String]
111
- def value_to_s(row, field)
112
- FFI::GDAL.GDALRATGetValueAsString(@c_pointer, row, field)
120
+ def value_as_string(row, field)
121
+ FFI::GDAL::GDAL.GDALRATGetValueAsString(@c_pointer, row, field)
113
122
  end
114
123
 
115
124
  # @param row [Fixnum]
116
125
  # @param field [Fixnum]
117
126
  # @return [Fixnum]
118
- def value_to_i(row, field)
119
- FFI::GDAL.GDALRATGetValueAsInt(@c_pointer, row, field)
127
+ def value_as_integer(row, field)
128
+ FFI::GDAL::GDAL.GDALRATGetValueAsInt(@c_pointer, row, field)
120
129
  end
130
+ alias value_as_int value_as_integer
121
131
 
122
132
  # @param row [Fixnum]
123
133
  # @param field [Fixnum]
124
134
  # @return [Float]
125
- def value_to_f(row, field)
126
- FFI::GDAL.GDALRATGetValueAsDouble(@c_pointer, row, field)
135
+ def value_as_double(row, field)
136
+ FFI::GDAL::GDAL.GDALRATGetValueAsDouble(@c_pointer, row, field)
127
137
  end
138
+ alias value_as_float value_as_double
128
139
 
129
140
  # @param row [Fixnum]
130
141
  # @param field [Fixnum]
131
- # @param value [String, Float, Fixnum]
132
- def add_value(row, field, value)
133
- case value.class.name
134
- when 'String'
135
- FFI::GDAL.GDALRATSetValueAsString(@c_pointer, row, field, value)
136
- when 'Float'
137
- FFI::GDAL.GDALRATSetValueAsDouble(@c_pointer, row, field, value)
138
- when 'Fixnum'
139
- FFI::GDAL.GDALRATSetValueAsInt(@c_pointer, row, field, value)
140
- else
141
- fail "Unknown value type for value '#{value}'"
142
- end
142
+ # @param value [String]
143
+ def set_value_as_string(row, field, value)
144
+ FFI::GDAL::GDAL.GDALRATSetValueAsString(@c_pointer, row, field, value)
143
145
  end
144
146
 
147
+ # @param row [Fixnum]
148
+ # @param field [Fixnum]
149
+ # @param value [Float]
150
+ def set_value_as_double(row, field, value)
151
+ FFI::GDAL::GDAL.GDALRATSetValueAsDouble(@c_pointer, row, field, value)
152
+ end
153
+ alias set_value_as_float set_value_as_double
154
+
155
+ # @param row [Fixnum]
156
+ # @param field [Fixnum]
157
+ # @param value [Fixnum]
158
+ def set_value_as_integer(row, field, value)
159
+ FFI::GDAL::GDAL.GDALRATSetValueAsInt(@c_pointer, row, field, value)
160
+ end
161
+ alias set_value_as_int set_value_as_integer
162
+
145
163
  # @return [Hash{row_0_minimum => Float, bin_size => Float}]
146
164
  def linear_binning
147
165
  row_0_min_ptr = FFI::MemoryPointer.new(:double)
148
166
  bin_size_ptr = FFI::MemoryPointer.new(:double)
149
- FFI::GDAL.GDALRATGetLinearBinning(@c_pointer, row_0_min_ptr, bin_size_ptr)
167
+ result = FFI::GDAL::GDAL.GDALRATGetLinearBinning(@c_pointer, row_0_min_ptr, bin_size_ptr)
168
+ return unless result
150
169
 
151
170
  {
152
171
  row_0_minimum: row_0_min_ptr.read_double,
@@ -154,23 +173,27 @@ module GDAL
154
173
  }
155
174
  end
156
175
 
176
+ # @param row_0_minimum [Float]
177
+ # @param bin_size [Float]
178
+ def set_linear_binning(row_0_minimum, bin_size)
179
+ FFI::GDAL::GDAL.GDALRATSetLinearBinning(@c_pointer, row_0_minimum, bin_size)
180
+ end
181
+
157
182
  # @param entry_count [Fixnum] The number of entries to produce. The default
158
183
  # will try to auto-determine the number.
159
- # @return [GDAL::ColorTable]
184
+ # @return [GDAL::ColorTable, nil]
160
185
  def to_color_table(entry_count = -1)
161
- color_table_pointer = FFI::GDAL.GDALRATTranslateToColorTable(@c_pointer, entry_count)
186
+ color_table_pointer = FFI::GDAL::GDAL.GDALRATTranslateToColorTable(@c_pointer, entry_count)
187
+ return if color_table_pointer.nil? || color_table_pointer.null?
162
188
 
163
189
  GDAL::ColorTable.new(color_table_pointer)
164
190
  end
165
191
 
166
- # @param file_path [String]
192
+ # @param file_path [String] Without giving a +file_path+, dumps to STDOUT.
167
193
  def dump_readable(file_path = nil)
168
- file = if file_path
169
- File.open(file_path, 'r')
170
- else
171
- file_path
172
- end
173
- FFI::GDAL.GDALRATDumpReadable(@c_pointer, file)
194
+ file_ptr = file_path ? FFI::CPL::Conv.CPLOpenShared(file_path, 'w', false) : nil
195
+ FFI::GDAL::GDAL.GDALRATDumpReadable(@c_pointer, file_ptr)
196
+ FFI::CPL::Conv.CPLCloseShared(file_ptr) if file_ptr
174
197
  end
175
198
  end
176
199
  end