ffi-gdal 1.0.0.beta3 → 1.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +62 -0
  4. data/Gemfile +1 -1
  5. data/History.md +53 -28
  6. data/README.md +6 -0
  7. data/Rakefile +23 -1
  8. data/examples/extract_and_colorize.rb +21 -22
  9. data/examples/geometries.rb +2 -2
  10. data/examples/gridding.rb +106 -0
  11. data/examples/ogr_layer_to_layer.rb +1 -1
  12. data/examples/points.txt +127 -0
  13. data/examples/testing_gdal.rb +3 -4
  14. data/ffi-gdal.gemspec +3 -2
  15. data/lib/ext/error_symbols.rb +2 -57
  16. data/lib/ext/ffi_library_function_checks.rb +26 -0
  17. data/lib/ext/float_ext.rb +2 -2
  18. data/lib/ext/narray_ext.rb +2 -0
  19. data/lib/ext/numeric_as_data_type.rb +19 -0
  20. data/lib/ext/to_bool.rb +4 -4
  21. data/lib/ffi/cpl/conv.rb +132 -0
  22. data/lib/ffi/cpl/error.rb +67 -0
  23. data/lib/ffi/cpl/hash_set.rb +39 -0
  24. data/lib/ffi/cpl/http.rb +25 -0
  25. data/lib/ffi/cpl/http_result.rb +18 -0
  26. data/lib/ffi/cpl/list.rb +38 -0
  27. data/lib/ffi/cpl/mime_part.rb +11 -0
  28. data/lib/ffi/cpl/minixml.rb +47 -0
  29. data/lib/ffi/cpl/port.rb +23 -0
  30. data/lib/ffi/cpl/quad_tree.rb +51 -0
  31. data/lib/ffi/{ogr/ogr_envelope.rb → cpl/rect_obj.rb} +3 -3
  32. data/lib/ffi/cpl/string.rb +95 -0
  33. data/lib/ffi/cpl/vsi.rb +115 -0
  34. data/lib/ffi/cpl/xml_node.rb +6 -6
  35. data/lib/ffi/gdal/alg.rb +385 -0
  36. data/lib/ffi/gdal/{gdal_color_entry.rb → color_entry.rb} +1 -2
  37. data/lib/ffi/gdal/exceptions.rb +6 -0
  38. data/lib/ffi/gdal/{gdal_gcp.rb → gcp.rb} +1 -3
  39. data/lib/ffi/gdal/{gdal_h.rb → gdal.rb} +253 -252
  40. data/lib/ffi/gdal/grid.rb +58 -0
  41. data/lib/ffi/gdal/{gdal_grid_data_metrics_options.rb → grid_data_metrics_options.rb} +1 -2
  42. data/lib/ffi/gdal/{gdal_grid_inverse_distance_to_a_power_options.rb → grid_inverse_distance_to_a_power_options.rb} +1 -2
  43. data/lib/ffi/gdal/{gdal_grid_moving_average_options.rb → grid_moving_average_options.rb} +1 -2
  44. data/lib/ffi/gdal/{gdal_grid_nearest_neighbor_options.rb → grid_nearest_neighbor_options.rb} +1 -2
  45. data/lib/ffi/gdal/matching.rb +20 -0
  46. data/lib/ffi/gdal/{gdal_rpc_info.rb → rpc_info.rb} +1 -2
  47. data/lib/ffi/gdal/{gdal_transformer_info.rb → transformer_info.rb} +1 -2
  48. data/lib/ffi/gdal/version.rb +1 -1
  49. data/lib/ffi/gdal/vrt.rb +92 -0
  50. data/lib/ffi/gdal/{gdal_warp_options.rb → warp_options.rb} +8 -4
  51. data/lib/ffi/gdal/warper.rb +70 -0
  52. data/lib/ffi/gdal.rb +56 -69
  53. data/lib/ffi/ogr/api.rb +567 -0
  54. data/lib/ffi/ogr/{ogr_contour_writer_info.rb → contour_writer_info.rb} +2 -3
  55. data/lib/ffi/ogr/core.rb +181 -0
  56. data/lib/ffi/ogr/envelope.rb +12 -0
  57. data/lib/ffi/ogr/{ogr_envelope_3d.rb → envelope_3d.rb} +2 -2
  58. data/lib/ffi/ogr/featurestyle.rb +29 -0
  59. data/lib/ffi/ogr/field.rb +63 -0
  60. data/lib/ffi/ogr/geocoding.rb +30 -0
  61. data/lib/ffi/ogr/srs_api.rb +407 -0
  62. data/lib/ffi/ogr/style_param.rb +13 -0
  63. data/lib/ffi/ogr/{ogr_style_value.rb → style_value.rb} +4 -3
  64. data/lib/ffi/ogr.rb +7 -7
  65. data/lib/ffi-gdal.rb +7 -145
  66. data/lib/gdal/color_entry.rb +18 -14
  67. data/lib/gdal/color_entry_mixins/extensions.rb +32 -0
  68. data/lib/gdal/color_interpretation.rb +2 -2
  69. data/lib/gdal/color_table.rb +37 -32
  70. data/lib/gdal/color_table_mixins/extensions.rb +48 -0
  71. data/lib/gdal/cpl_error_handler.rb +119 -0
  72. data/lib/gdal/data_type.rb +7 -7
  73. data/lib/gdal/dataset.rb +131 -238
  74. data/lib/gdal/dataset_mixins/algorithm_methods.rb +182 -0
  75. data/lib/gdal/dataset_mixins/extensions.rb +542 -0
  76. data/lib/gdal/dataset_mixins/matching.rb +26 -0
  77. data/lib/gdal/driver.rb +68 -92
  78. data/lib/gdal/driver_mixins/extensions.rb +93 -0
  79. data/lib/gdal/exceptions.rb +32 -4
  80. data/lib/gdal/geo_transform.rb +63 -43
  81. data/lib/gdal/geo_transform_mixins/extensions.rb +57 -0
  82. data/lib/gdal/grid.rb +144 -0
  83. data/lib/gdal/grid_types/data_metrics_base.rb +14 -0
  84. data/lib/gdal/grid_types/inverse_distance_to_a_power.rb +19 -0
  85. data/lib/gdal/grid_types/metric_average_distance.rb +12 -0
  86. data/lib/gdal/grid_types/metric_average_distance_pts.rb +12 -0
  87. data/lib/gdal/grid_types/metric_count.rb +12 -0
  88. data/lib/gdal/grid_types/metric_maximum.rb +12 -0
  89. data/lib/gdal/grid_types/metric_minimum.rb +12 -0
  90. data/lib/gdal/grid_types/metric_range.rb +12 -0
  91. data/lib/gdal/grid_types/moving_average.rb +19 -0
  92. data/lib/gdal/grid_types/nearest_neighbor.rb +19 -0
  93. data/lib/gdal/grid_types.rb +22 -0
  94. data/lib/gdal/internal_helpers.rb +94 -0
  95. data/lib/gdal/major_object.rb +4 -7
  96. data/lib/gdal/options.rb +14 -7
  97. data/lib/gdal/raster_attribute_table.rb +38 -47
  98. data/lib/gdal/raster_attribute_table_mixins/extensions.rb +41 -0
  99. data/lib/gdal/raster_band.rb +193 -227
  100. data/lib/gdal/raster_band_classifier.rb +107 -0
  101. data/lib/gdal/raster_band_mixins/algorithm_methods.rb +292 -0
  102. data/lib/gdal/raster_band_mixins/extensions.rb +238 -0
  103. data/lib/gdal/rpc_info.rb +35 -0
  104. data/lib/gdal/transformer.rb +15 -0
  105. data/lib/gdal/transformers/approximate_transformer.rb +48 -0
  106. data/lib/gdal/transformers/base_general_image_projection_transformer.rb +45 -0
  107. data/lib/gdal/transformers/gcp_transformer.rb +55 -0
  108. data/lib/gdal/transformers/general_image_projection_transformer.rb +31 -0
  109. data/lib/gdal/transformers/general_image_projection_transformer2.rb +52 -0
  110. data/lib/gdal/transformers/general_image_projection_transformer3.rb +25 -0
  111. data/lib/gdal/transformers/geolocation_transformer.rb +42 -0
  112. data/lib/gdal/transformers/reprojection_transformer.rb +39 -0
  113. data/lib/gdal/transformers/rpc_transformer.rb +56 -0
  114. data/lib/gdal/transformers/tps_transformer.rb +40 -0
  115. data/lib/gdal/virtual_dataset.rb +96 -0
  116. data/lib/gdal/warp_operation.rb +20 -23
  117. data/lib/gdal.rb +17 -0
  118. data/lib/ogr/coordinate_transformation.rb +16 -41
  119. data/lib/ogr/data_source.rb +103 -58
  120. data/lib/ogr/data_source_extensions.rb +5 -6
  121. data/lib/ogr/data_source_mixins/capability_methods.rb +27 -0
  122. data/lib/ogr/driver.rb +61 -33
  123. data/lib/ogr/driver_mixins/capability_methods.rb +16 -0
  124. data/lib/ogr/envelope.rb +29 -18
  125. data/lib/ogr/envelope_extensions.rb +70 -49
  126. data/lib/ogr/error_handling.rb +46 -0
  127. data/lib/ogr/exceptions.rb +58 -12
  128. data/lib/ogr/feature.rb +334 -86
  129. data/lib/ogr/feature_definition.rb +94 -51
  130. data/lib/ogr/feature_definition_extensions.rb +36 -13
  131. data/lib/ogr/feature_extensions.rb +62 -11
  132. data/lib/ogr/field.rb +175 -54
  133. data/lib/ogr/field_definition.rb +110 -0
  134. data/lib/ogr/{field_extensions.rb → field_definition_extensions.rb} +4 -5
  135. data/lib/ogr/{geocoding_session.rb → geocoder.rb} +14 -13
  136. data/lib/ogr/geometries/geometry_collection.rb +13 -0
  137. data/lib/ogr/geometries/line_string.rb +35 -0
  138. data/lib/ogr/geometries/linear_ring.rb +11 -0
  139. data/lib/ogr/geometries/multi_line_string.rb +16 -0
  140. data/lib/ogr/geometries/multi_point.rb +14 -0
  141. data/lib/ogr/geometries/multi_polygon.rb +21 -0
  142. data/lib/ogr/geometries/none_geometry.rb +13 -0
  143. data/lib/ogr/geometries/point.rb +65 -0
  144. data/lib/ogr/geometries/point_extensions.rb +32 -0
  145. data/lib/ogr/geometries/polygon.rb +14 -0
  146. data/lib/ogr/geometries/unknown_geometry.rb +10 -0
  147. data/lib/ogr/geometry.rb +270 -242
  148. data/lib/ogr/geometry_extensions.rb +8 -9
  149. data/lib/ogr/geometry_field_definition.rb +99 -0
  150. data/lib/ogr/geometry_field_definition_extensions.rb +19 -0
  151. data/lib/ogr/geometry_types/container.rb +75 -0
  152. data/lib/ogr/geometry_types/curve.rb +25 -28
  153. data/lib/ogr/geometry_types/surface.rb +13 -4
  154. data/lib/ogr/internal_helpers.rb +57 -0
  155. data/lib/ogr/layer.rb +60 -181
  156. data/lib/ogr/layer_mixins/capability_methods.rb +102 -0
  157. data/lib/ogr/layer_mixins/extensions.rb +59 -0
  158. data/lib/ogr/layer_mixins/ogr_feature_methods.rb +127 -0
  159. data/lib/ogr/layer_mixins/ogr_field_methods.rb +143 -0
  160. data/lib/ogr/layer_mixins/ogr_layer_method_methods.rb +163 -0
  161. data/lib/ogr/layer_mixins/ogr_query_filter_methods.rb +89 -0
  162. data/lib/ogr/layer_mixins/ogr_sql_methods.rb +48 -0
  163. data/lib/ogr/spatial_reference.rb +108 -589
  164. data/lib/ogr/spatial_reference_extensions.rb +29 -3
  165. data/lib/ogr/spatial_reference_mixins/coordinate_system_getter_setters.rb +494 -0
  166. data/lib/ogr/spatial_reference_mixins/exporters.rb +134 -0
  167. data/lib/ogr/spatial_reference_mixins/importers.rb +243 -0
  168. data/lib/ogr/spatial_reference_mixins/morphers.rb +25 -0
  169. data/lib/ogr/spatial_reference_mixins/parameter_getter_setters.rb +122 -0
  170. data/lib/ogr/spatial_reference_mixins/type_checks.rb +62 -0
  171. data/lib/ogr/style_table.rb +53 -5
  172. data/lib/ogr/style_table_extensions.rb +21 -5
  173. data/lib/ogr/style_tool.rb +118 -0
  174. data/lib/ogr.rb +8 -0
  175. data/spec/ffi-gdal_spec.rb +1 -2
  176. data/spec/integration/{color_table_info_spec.rb → gdal/color_table_info_spec.rb} +12 -12
  177. data/spec/integration/{dataset_info_spec.rb → gdal/dataset_info_spec.rb} +2 -6
  178. data/spec/integration/{driver_info_spec.rb → gdal/driver_info_spec.rb} +5 -5
  179. data/spec/integration/{geo_transform_info_spec.rb → gdal/geo_transform_info_spec.rb} +1 -14
  180. data/spec/integration/{raster_attribute_table_info_spec.rb → gdal/raster_attribute_table_info_spec.rb} +1 -2
  181. data/spec/integration/{raster_band_info_spec.rb → gdal/raster_band_info_spec.rb} +30 -42
  182. data/spec/integration/ogr/layer_spec.rb +97 -0
  183. data/spec/spec_helper.rb +94 -5
  184. data/spec/support/integration_help.rb +1 -0
  185. data/spec/support/shared_contexts.rb +26 -0
  186. data/spec/support/shared_examples/{major_object_examples.rb → gdal/major_object_examples.rb} +5 -5
  187. data/spec/support/shared_examples/ogr/a_25D_geometry.rb +7 -0
  188. data/spec/support/shared_examples/ogr/a_container_geometry.rb +47 -0
  189. data/spec/support/shared_examples/ogr/a_geometry.rb +404 -0
  190. data/spec/support/shared_examples/ogr/a_line_string.rb +16 -0
  191. data/spec/support/test_style_table.txt +3 -0
  192. data/spec/unit/ext/error_symbols_spec.rb +41 -53
  193. data/spec/unit/ext/numeric_as_data_type_spec.rb +113 -0
  194. data/spec/unit/ffi/gdal_spec.rb +70 -0
  195. data/spec/unit/gdal/color_entry_spec.rb +5 -0
  196. data/spec/unit/gdal/color_interpretation_spec.rb +5 -0
  197. data/spec/unit/gdal/{color_table_extensions_spec.rb → color_table_mixins/extensions_spec.rb} +3 -3
  198. data/spec/unit/gdal/color_table_spec.rb +14 -16
  199. data/spec/unit/gdal/data_type_spec.rb +10 -17
  200. data/spec/unit/gdal/dataset_spec.rb +4 -7
  201. data/spec/unit/gdal/driver_mixins/extensions_spec.rb +22 -0
  202. data/spec/unit/gdal/driver_spec.rb +49 -0
  203. data/spec/unit/gdal/environment_methods_spec.rb +6 -0
  204. data/spec/unit/gdal/geo_transform_spec.rb +276 -0
  205. data/spec/unit/gdal/grid_spec.rb +5 -0
  206. data/spec/unit/gdal/internal_helpers_spec.rb +112 -0
  207. data/spec/unit/gdal/major_object_spec.rb +6 -0
  208. data/spec/unit/gdal/options_spec.rb +5 -0
  209. data/spec/unit/gdal/raster_attribute_table_spec.rb +5 -0
  210. data/spec/unit/gdal/raster_band_classifier_spec.rb +134 -0
  211. data/spec/unit/gdal/raster_band_spec.rb +5 -0
  212. data/spec/unit/gdal/rpc_info_spec.rb +5 -0
  213. data/spec/unit/gdal/version_info_spec.rb +6 -0
  214. data/spec/unit/gdal/virtual_dataset_spec.rb +32 -0
  215. data/spec/unit/gdal/warp_operation_spec.rb +5 -0
  216. data/spec/unit/ogr/data_source_mixins/capability_methods_spec.rb +30 -0
  217. data/spec/unit/ogr/data_source_spec.rb +209 -0
  218. data/spec/unit/ogr/driver_mixins/capability_methods_spec.rb +18 -0
  219. data/spec/unit/ogr/driver_spec.rb +150 -0
  220. data/spec/unit/ogr/envelope_spec.rb +322 -0
  221. data/spec/unit/ogr/feature_definition_spec.rb +313 -0
  222. data/spec/unit/ogr/feature_spec.rb +379 -0
  223. data/spec/unit/ogr/field_definition_spec.rb +135 -0
  224. data/spec/unit/ogr/field_spec.rb +193 -0
  225. data/spec/unit/ogr/geometries/geometry_collection_spec.rb +186 -0
  226. data/spec/unit/ogr/geometries/line_string_spec.rb +105 -0
  227. data/spec/unit/ogr/{linear_ring_spec.rb → geometries/linear_ring_spec.rb} +10 -31
  228. data/spec/unit/ogr/geometries/multi_line_string_spec.rb +14 -0
  229. data/spec/unit/ogr/geometries/multi_point_spec.rb +14 -0
  230. data/spec/unit/ogr/geometries/multi_polygon_spec.rb +41 -0
  231. data/spec/unit/ogr/geometries/none_geometry_spec.rb +12 -0
  232. data/spec/unit/ogr/{point_spec.rb → geometries/point_spec.rb} +19 -25
  233. data/spec/unit/ogr/geometries/polygon_spec.rb +17 -0
  234. data/spec/unit/ogr/geometries/unknown_geometry_spec.rb +10 -0
  235. data/spec/unit/ogr/geometry_field_definition_spec.rb +87 -0
  236. data/spec/unit/ogr/geometry_spec.rb +542 -0
  237. data/spec/unit/ogr/internal_helpers_spec.rb +57 -0
  238. data/spec/unit/ogr/layer_mixins/capability_methods_spec.rb +88 -0
  239. data/spec/unit/ogr/layer_mixins/ogr_feature_methods_spec.rb +145 -0
  240. data/spec/unit/ogr/layer_mixins/ogr_field_methods_spec.rb +432 -0
  241. data/spec/unit/ogr/layer_mixins/ogr_layer_method_methods_spec.rb +20 -0
  242. data/spec/unit/ogr/layer_mixins/ogr_query_filter_methods_spec.rb +42 -0
  243. data/spec/unit/ogr/layer_mixins/ogr_sql_methods_spec.rb +12 -0
  244. data/spec/unit/ogr/layer_spec.rb +66 -67
  245. data/spec/unit/ogr/spatial_reference_mixins/coordinate_system_getter_setters_spec.rb +46 -0
  246. data/spec/unit/ogr/spatial_reference_mixins/exporters_spec.rb +139 -0
  247. data/spec/unit/ogr/spatial_reference_mixins/importers_spec.rb +38 -0
  248. data/spec/unit/ogr/spatial_reference_mixins/morphers_spec.rb +36 -0
  249. data/spec/unit/ogr/spatial_reference_mixins/parameter_getter_setters_spec.rb +102 -0
  250. data/spec/unit/ogr/spatial_reference_mixins/type_checks_spec.rb +157 -0
  251. data/spec/unit/ogr/spatial_reference_spec.rb +42 -0
  252. data/spec/unit/ogr/style_table_spec.rb +132 -0
  253. data/spec/unit/ogr/style_tool_spec.rb +157 -0
  254. data/spec/unit/version_info_spec.rb +1 -1
  255. metadata +285 -75
  256. data/lib/ffi/cpl/conv_h.rb +0 -143
  257. data/lib/ffi/cpl/error_h.rb +0 -63
  258. data/lib/ffi/cpl/minixml_h.rb +0 -14
  259. data/lib/ffi/cpl/string_h.rb +0 -81
  260. data/lib/ffi/cpl/vsi_h.rb +0 -112
  261. data/lib/ffi/gdal/alg_h.rb +0 -127
  262. data/lib/ffi/gdal/grid_h.rb +0 -51
  263. data/lib/ffi/gdal/warper_h.rb +0 -48
  264. data/lib/ffi/ogr/api_h.rb +0 -553
  265. data/lib/ffi/ogr/core_h.rb +0 -148
  266. data/lib/ffi/ogr/featurestyle_h.rb +0 -22
  267. data/lib/ffi/ogr/geocoding_h.rb +0 -21
  268. data/lib/ffi/ogr/ogr_field.rb +0 -50
  269. data/lib/ffi/ogr/ogr_style_param.rb +0 -12
  270. data/lib/ffi/ogr/srs_api_h.rb +0 -325
  271. data/lib/gdal/color_entry_extensions.rb +0 -30
  272. data/lib/gdal/color_table_extensions.rb +0 -47
  273. data/lib/gdal/dataset_extensions.rb +0 -496
  274. data/lib/gdal/driver_extensions.rb +0 -56
  275. data/lib/gdal/geo_transform_extensions.rb +0 -90
  276. data/lib/gdal/raster_attribute_table_extensions.rb +0 -40
  277. data/lib/gdal/raster_band_extensions.rb +0 -198
  278. data/lib/ogr/geometry_types/collection.rb +0 -45
  279. data/lib/ogr/layer_extensions.rb +0 -55
  280. data/lib/ogr/line_string.rb +0 -7
  281. data/lib/ogr/linear_ring.rb +0 -6
  282. data/lib/ogr/multi_line_string.rb +0 -9
  283. data/lib/ogr/multi_point.rb +0 -7
  284. data/lib/ogr/multi_polygon.rb +0 -14
  285. data/lib/ogr/point.rb +0 -89
  286. data/lib/ogr/polygon.rb +0 -9
@@ -1,496 +0,0 @@
1
- require 'json'
2
-
3
- module GDAL
4
- # Methods not originally supplied with GDAL, but enhance it.
5
- module DatasetExtensions
6
-
7
- # Computes NDVI from the red and near-infrared bands in the dataset. Raises
8
- # a GDAL::RequiredBandNotFound if one of those band types isn't found.
9
- #
10
- # @param destination [String] Path to output the new dataset to.
11
- # @param driver_name [String] The type of dataset to create.
12
- # @param band_order [Array<String>] The list of band types, i.e. ['red',
13
- # 'green', 'blue'].
14
- def extract_ndvi(destination, driver_name: 'GTiff', band_order: nil,
15
- data_type: :GDT_Float32, remove_negatives: false, no_data_value: -9999.0,
16
- **options)
17
- original_bands = if band_order
18
- bands_with_labels(band_order)
19
- else
20
- {
21
- red: red_band,
22
- green: green_band,
23
- blue: blue_band,
24
- nir: undefined_band
25
- }
26
- end
27
-
28
- red = original_bands[:red]
29
- nir = original_bands[:nir]
30
-
31
- if red.nil?
32
- fail RequiredBandNotFound, 'Red band not found.'
33
- elsif nir.nil?
34
- fail RequiredBandNotFound, 'Near-infrared'
35
- end
36
-
37
- the_array = calculate_ndvi(red.to_na(data_type), nir.to_na(data_type),
38
- no_data_value, remove_negatives, data_type)
39
- driver = GDAL::Driver.by_name(driver_name)
40
-
41
- driver.create_dataset(destination, raster_x_size, raster_y_size, data_type: data_type, **options) do |ndvi_dataset|
42
-
43
- ndvi_dataset.geo_transform = geo_transform
44
- ndvi_dataset.projection = projection
45
-
46
- ndvi_band = ndvi_dataset.raster_band(1)
47
- ndvi_band.write_array(the_array, data_type: data_type)
48
- ndvi_band.no_data_value = no_data_value
49
- end
50
- end
51
-
52
- # Computes GNDVI from the green and near-infrared bands in the dataset.
53
- # Raises a GDAL::RequiredBandNotFound if one of those band types isn't
54
- # found.
55
- #
56
- # @param destination [String] Path to output the new dataset to.
57
- # @param driver_name [String] The type of dataset to create.
58
- # @param band_order [Array<String>] The list of band types, i.e. ['red',
59
- # 'green', 'blue'].
60
- def extract_gndvi(destination, driver_name: 'GTiff', band_order: nil,
61
- data_type: :GDT_Float32, remove_negatives: false, no_data_value: -9999.0,
62
- **options)
63
- original_bands = if band_order
64
- bands_with_labels(band_order)
65
- else
66
- {
67
- red: red_band,
68
- green: green_band,
69
- blue: blue_band,
70
- nir: undefined_band
71
- }
72
- end
73
-
74
- green = original_bands[:green]
75
- nir = original_bands[:nir]
76
-
77
- if green.nil?
78
- fail RequiredBandNotFound, 'Green band not found.'
79
- elsif nir.nil?
80
- fail RequiredBandNotFound, 'Near-infrared'
81
- end
82
-
83
- the_array = calculate_ndvi(green.to_na(data_type), nir.to_na(data_type),
84
- no_data_value, remove_negatives, data_type)
85
- driver = GDAL::Driver.by_name(driver_name)
86
-
87
- driver.create_dataset(destination, raster_x_size, raster_y_size, data_type: data_type, **options) do |gndvi_dataset|
88
- gndvi_dataset.geo_transform = geo_transform
89
- gndvi_dataset.projection = projection
90
-
91
- gndvi_band = gndvi_dataset.raster_band(1)
92
- gndvi_band.write_array(the_array, data_type: data_type)
93
- gndvi_band.no_data_value = no_data_value
94
- end
95
- end
96
-
97
- # Extracts the NIR band and writes to a new file. NOTE: be sure to close
98
- # the dataset object that gets returned or your data will not get written
99
- # to the file.
100
- #
101
- # @param destination [String] The destination file path.
102
- # @param band_number [Fixnum] The number of the band that is the NIR band.
103
- # Remember that raster bands are 1-indexed, not 0-indexed.
104
- # @param driver_name [String] the GDAL::Driver short name to use for the
105
- # new dataset.
106
- # @return [GDAL::Dataset]
107
- def extract_nir(destination, band_number, driver_name: 'GTiff', data_type: :GDT_Byte)
108
- driver = GDAL::Driver.by_name(driver_name)
109
- original_nir_band = raster_band(band_number)
110
-
111
- driver.create_dataset(destination, raster_x_size, raster_y_size, data_type: data_type) do |nir_dataset|
112
- nir_dataset.geo_transform = geo_transform
113
- nir_dataset.projection = projection
114
-
115
- nir_band = nir_dataset.raster_band(1)
116
- original_nir_band.copy_whole_raster(nir_band)
117
- end
118
- end
119
-
120
- # Extracts the RGB bands and writes to a new file. NOTE: be sure to close
121
- # the dataset object that gets returned or your data will not get written
122
- # to the file.
123
- #
124
- # @param destination [String] The destination file path.
125
- # @param driver_name [String] the GDAL::Driver short name to use for the
126
- # new dataset.
127
- # @param band_order [Array<String>] The list of band types, i.e. ['red',
128
- # 'green', 'blue'].
129
- # @return [GDAL::Dataset]
130
- def extract_natural_color(destination, driver_name: 'GTiff', band_order: nil)
131
- rows = raster_y_size
132
- columns = raster_x_size
133
- driver = GDAL::Driver.by_name(driver_name)
134
-
135
- original_bands = if band_order
136
- bands_with_labels(band_order)
137
- else
138
- {
139
- red: red_band,
140
- green: green_band,
141
- blue: blue_band
142
- }
143
- end
144
-
145
- driver.create_dataset(destination, columns, rows, bands: 3) do |new_dataset|
146
- new_dataset.geo_transform = geo_transform
147
- new_dataset.projection = projection
148
-
149
- new_red_band = new_dataset.raster_band(1)
150
- original_bands[:red].copy_whole_raster(new_red_band)
151
-
152
- new_green_band = new_dataset.raster_band(2)
153
- original_bands[:green].copy_whole_raster(new_green_band)
154
-
155
- new_blue_band = new_dataset.raster_band(3)
156
- original_bands[:blue].copy_whole_raster(new_blue_band)
157
- end
158
- end
159
-
160
- # @param red_band_array [NArray]
161
- # @param nir_band_array [NArray]
162
- # @param remove_negatives [Fixnum] Value to replace negative values with.
163
- # @return [NArray]
164
- def calculate_ndvi(red_band_array, nir_band_array, no_data_value,
165
- remove_negatives=false, data_type=nil)
166
-
167
- # convert based on data type
168
- if data_type != :GDT_Float32
169
- nir_band_array = nir_band_array.to_type(NArray::DFLOAT)
170
- red_band_array = red_band_array.to_type(NArray::DFLOAT)
171
- end
172
-
173
- numerator = nir_band_array - red_band_array
174
- denominator = (nir_band_array + red_band_array)
175
- ndvi = numerator / denominator
176
-
177
- # Remove NaNs
178
- 0.upto(ndvi.size - 1) do |i|
179
- ndvi[i] = no_data_value if ndvi[i].is_a?(Float) && ndvi[i].nan?
180
- end
181
-
182
- final_array = case data_type
183
- when :GDT_Byte
184
- calculate_ndvi_byte(ndvi)
185
- when :GDT_UInt16
186
- calculate_ndvi_uint16(ndvi)
187
- else
188
- ndvi
189
- end
190
-
191
- remove_negatives ? remove_negatives_from(final_array) : final_array
192
- end
193
-
194
- # Map raster bands to a label, as a hash. Useful for when bands don't match
195
- # the color_interpretation that's returned from GDAL. This simply maps the
196
- # list of labels you pass in to the raster bands.
197
- #
198
- # Valid labels:
199
- # * Near-infrared: 'N', :nir
200
- # * Red: 'R', :red
201
- # * Green: 'G', :green
202
- # * Blue: 'B', :blue
203
- # * Alpha: 'A', :alpha
204
- #
205
- # @param order [Array<Object>]
206
- # @return [Hash{<Object> => GDAL::RasterBand}]
207
- def bands_with_labels(order)
208
- order.each_with_object({}).each_with_index do |(band_label, obj), i|
209
- label = case band_label.to_s
210
- when 'N', 'nir' then :nir
211
- when 'R', 'red' then :red
212
- when 'G', 'green' then :green
213
- when 'B', 'blue' then :blue
214
- else
215
- band_label
216
- end
217
-
218
- obj[label] = raster_band(i + 1)
219
- end
220
- end
221
-
222
- # @return [Array<GDAL::RasterBand>]
223
- def raster_bands
224
- 1.upto(raster_count).map do |i|
225
- raster_band(i)
226
- end
227
- end
228
-
229
- # Iterates raster bands from 1 to #raster_count and yields them to the given
230
- # block.
231
- def each_band
232
- 1.upto(raster_count) do |i|
233
- yield(raster_band(i))
234
- end
235
- end
236
-
237
- # Returns the first raster band for which the block returns true. Ex.
238
- #
239
- # dataset.find_band do |band|
240
- # band.color_interpretation == :GCI_RedBand
241
- # end
242
- #
243
- # @return [GDAL::RasterBand]
244
- def find_band
245
- each_band do |band|
246
- result = yield(band)
247
- return band if result
248
- end
249
- end
250
-
251
- # @return [GDAL::RasterBand]
252
- def red_band
253
- band = find_band do |band|
254
- band.color_interpretation == :GCI_RedBand
255
- end
256
-
257
- band.is_a?(GDAL::RasterBand) ? band : nil
258
- end
259
-
260
- # @return [GDAL::RasterBand]
261
- def green_band
262
- band = find_band do |band|
263
- band.color_interpretation == :GCI_GreenBand
264
- end
265
-
266
- band.is_a?(GDAL::RasterBand) ? band : nil
267
- end
268
-
269
- # @return [GDAL::RasterBand]
270
- def blue_band
271
- band = find_band do |band|
272
- band.color_interpretation == :GCI_BlueBand
273
- end
274
-
275
- band.is_a?(GDAL::RasterBand) ? band : nil
276
- end
277
-
278
- # @return [GDAL::RasterBand]
279
- def undefined_band
280
- band = find_band do |band|
281
- band.color_interpretation == :GCI_Undefined
282
- end
283
-
284
- band.is_a?(GDAL::RasterBand) ? band : nil
285
- end
286
-
287
- # Creates a OGR::SpatialReference object from the dataset's projection.
288
- #
289
- # @return [OGR::SpatialReference]
290
- def spatial_reference
291
- return @spatial_reference if @spatial_reference
292
-
293
- return nil if projection.empty?
294
-
295
- @spatial_reference = OGR::SpatialReference.new(projection)
296
- end
297
-
298
- # Converts raster band number +band_number+ to the vector format
299
- # +vector_driver_name+. Similar to gdal_polygonize.py. If block format is
300
- # used, the new DataSource will be closed/flushed when the block returns. If
301
- # the non-block format is used, you need to call #close on the DataSource.
302
- #
303
- # @param file_name [String] Path to write the vector file to.
304
- # @param vector_driver_name [String] One of OGR::Driver.names.
305
- # @param geometry_type [FFI::GDAL::OGRwkbGeometryType] The type of geometry
306
- # to use when turning the raster into a vector image.
307
- # @param layer_name_prefix [String] Prefix of the name to give the new
308
- # vector layer.
309
- # @param band_numbers [Array<Fixnum>,Fixnum] Number of the raster band or
310
- # bands from this dataset to vectorize. Can be a single Fixnum or array
311
- # of Fixnums.
312
- # @return [OGR::DataSource]
313
- def to_vector(file_name, vector_driver_name, geometry_type: :wkbPolygon,
314
- layer_name_prefix: 'band_number', band_numbers: [1],
315
- field_name_prefix: 'field')
316
- band_numbers = band_numbers.is_a?(Array) ? band_numbers : [band_numbers]
317
-
318
- ogr_driver = OGR::Driver.by_name(vector_driver_name)
319
- spatial_ref = OGR::SpatialReference.new(projection)
320
- spatial_ref.auto_identify_epsg!
321
-
322
- data_source = ogr_driver.create_data_source(file_name)
323
- band_numbers.each_with_index do |band_number, i|
324
- log "Starting to polygonize raster band #{band_number}..."
325
-
326
- layer_name = "#{layer_name_prefix}-#{band_number}"
327
- layer = data_source.create_layer(layer_name, geometry_type: geometry_type,
328
- spatial_reference: spatial_ref)
329
-
330
- unless layer
331
- raise OGR::InvalidLayer, "Unable to create layer '#{layer_name}'."
332
- end
333
-
334
- field_name = "#{field_name_prefix}#{i}"
335
- layer.create_field(field_name, :OFTInteger)
336
-
337
- band = raster_band(band_number)
338
- band.no_data_value = -9999
339
-
340
- unless band
341
- raise GDAL::InvalidBandNumber, "Unknown band number: #{band_number}"
342
- end
343
-
344
- pixel_value_field = layer.feature_definition.field_index(field_name)
345
- band.polygonize(layer, pixel_value_field: pixel_value_field)
346
- end
347
-
348
- if block_given?
349
- yield data_source
350
- data_source.close
351
- end
352
-
353
- data_source
354
- end
355
-
356
- # Converts the dataset to an in-memory vector, then creates a OGR::Geometry
357
- # from its extent (i.e. from the boundary of the image).
358
- #
359
- # @return [OGR::Geometry] A convex hull geometry.
360
- def to_geometry
361
- raster_data_source = to_vector('memory', 'Memory', geometry_type: :wkbLinearRing)
362
-
363
- raster_data_source.layer(0).geometry_from_extent
364
- end
365
-
366
- # @param wkt_geometry_string [String]
367
- # @param wkt_srid [Fixnum]
368
- # @return [Boolean]
369
- def contains_geometry?(wkt_geometry_string, wkt_srid=4326)
370
- source_srs = OGR::SpatialReference.new_from_epsg(wkt_srid)
371
- source_geometry = OGR::Geometry.create_from_wkt(wkt_geometry_string, source_srs)
372
- @raster_geometry ||= to_geometry
373
-
374
- coordinate_transformation = OGR::CoordinateTransformation.create(source_srs,
375
- @raster_geometry.spatial_reference)
376
- source_geometry.transform!(coordinate_transformation)
377
-
378
- @raster_geometry.contains? source_geometry
379
- end
380
-
381
- def image_warp(destination_file, driver, band_numbers, **warp_options)
382
- raise NotImplementedError, '#image_warp not yet implemented.'
383
-
384
- options_ptr = GDAL::Options.pointer(warp_options)
385
- driver = GDAL::Driver.by_name(driver)
386
- destination_dataset = driver.create_dataset(destination_file, raster_x_size, raster_y_size)
387
-
388
- band_numbers = band_numbers.is_a?(Array) ? band_numbers : [band_numbers]
389
- log "band numbers: #{band_numbers}"
390
-
391
- bands_ptr = FFI::MemoryPointer.new(:pointer, band_numbers.size)
392
- bands_ptr.write_array_of_int(band_numbers)
393
- log "band numbers ptr null? #{bands_ptr.null?}"
394
-
395
- warp_options_struct = FFI::GDAL::GDALWarpOptions.new
396
-
397
- warp_options.each do |k, _|
398
- warp_options_struct[k] = warp_options[k]
399
- end
400
-
401
- warp_options[:source_dataset] = c_pointer
402
- warp_options[:destination_dataset] = destination_dataset.c_pointer
403
- warp_options[:band_count] = band_numbers.size
404
- warp_options[:source_bands] = bands_ptr
405
- warp_options[:transformer] = transformer
406
- warp_options[:transformer_arg] = transformer_arg
407
-
408
- log "transformer: #{transformer}"
409
- error_threshold = 0.0
410
- order = 0
411
-
412
- transformer_ptr = FFI::GDAL.GDALCreateGenImgProjTransformer(@dataset_pointer,
413
- projection,
414
- destination_dataset.c_pointer,
415
- destination.projection,
416
- false,
417
- error_threshold,
418
- order)
419
-
420
- warp_operation = GDAL::WarpOperation.new(warp_options)
421
- warp_operation.chunk_and_warp_image(0, 0, raster_x_size, raster_y_size)
422
- transformer.destroy!
423
- warp_operation.destroy!
424
-
425
- destination = GDAL::Dataset.new(destination_dataset_ptr)
426
- destination.close
427
-
428
- destination
429
- end
430
-
431
- # Retrieves pixels from each raster band and converts this to an array of
432
- # points per pixel. For example:
433
- #
434
- # # If the arrays for each band look like:
435
- # red_band_array = [0, 0, 0]
436
- # green_band_array = [10, 10, 10]
437
- # blue_band_array = [99, 99, 99]
438
- # alpha_band_array = [250, 150, 2]
439
- #
440
- # # This array would look like:
441
- # [[0, 10, 99, 2], [0, 10, 99, 150], [0, 10, 99, 250]]
442
- # @return NArray
443
- def to_na
444
- na = NMatrix.to_na(raster_bands.map { |raster_band| raster_band.to_na })
445
-
446
- NArray[*na.transpose]
447
- end
448
-
449
- def as_json
450
- {
451
- dataset: {
452
- driver: driver.long_name,
453
- file_list: file_list,
454
- gcp_count: gcp_count,
455
- gcp_projection: gcp_projection,
456
- geo_transform: geo_transform.as_json,
457
- projection: projection,
458
- raster_count: raster_count,
459
- raster_bands: raster_bands.map(&:as_json),
460
- spatial_reference: spatial_reference.as_json
461
- },
462
- metadata: all_metadata
463
- }
464
- end
465
-
466
- def to_json
467
- as_json.to_json
468
- end
469
-
470
- private
471
-
472
- # @param ndvi [NArray]
473
- # @return [NArray]
474
- def calculate_ndvi_byte(ndvi)
475
- (ndvi + 1) * (255.0 / 2)
476
- end
477
-
478
- # @param ndvi [NArray]
479
- # @return [NArray]
480
- def calculate_ndvi_uint16(ndvi)
481
- (ndvi + 1) * (65535.0 / 2)
482
- end
483
-
484
- # Sets any negative values in the NArray to 0.
485
- #
486
- # @param narray [NArray]
487
- # @return [NArray]
488
- def remove_negatives_from(narray, replace_with=0)
489
- 0.upto(narray.size - 1) do |i|
490
- narray[i] = replace_with if narray[i] < 0
491
- end
492
-
493
- narray
494
- end
495
- end
496
- end
@@ -1,56 +0,0 @@
1
- module GDAL
2
- module DriverExtensions
3
-
4
- # The things that this driver can do, as reported by its metadata.
5
- # Possibilities include:
6
- # * :open
7
- # * :create
8
- # * :copy
9
- # * :virtual_io
10
- # * :rasters
11
- # * :vectors
12
- #
13
- # @return [Array<Symbol>]
14
- def capabilities
15
- caps = []
16
- caps << :open if can_open_datasets?
17
- caps << :create if can_create_datasets?
18
- caps << :copy if can_copy_datasets?
19
- caps << :virtual_io if can_do_virtual_io?
20
- caps << :rasters if can_do_rasters?
21
- caps << :vectors if can_do_vectors?
22
-
23
- caps
24
- end
25
-
26
- # @return [Boolean]
27
- def can_open_datasets?
28
- metadata_item('DCAP_OPEN') == 'YES'
29
- end
30
-
31
- # @return [Boolean]
32
- def can_create_datasets?
33
- metadata_item('DCAP_CREATE') == 'YES'
34
- end
35
-
36
- # @return [Boolean]
37
- def can_copy_datasets?
38
- metadata_item('DCAP_CREATECOPY') == 'YES'
39
- end
40
-
41
- # @return [Boolean]
42
- def can_do_virtual_io?
43
- metadata_item('DCAP_VIRTUALIO') == 'YES'
44
- end
45
-
46
- # @return [Boolean]
47
- def can_do_rasters?
48
- metadata_item('DCAP_RASTER') == 'YES'
49
- end
50
-
51
- # @return [Boolean]
52
- def can_do_vectors?
53
- metadata_item('DCAP_VECTOR') == 'YES'
54
- end
55
- end
56
- end
@@ -1,90 +0,0 @@
1
- require 'json'
2
-
3
- module GDAL
4
- module GeoTransformExtensions
5
-
6
- # The calculated UTM easting of the pixel on the map.
7
- #
8
- # @return [Float]
9
- def x_projection(x_pixel, y_pixel)
10
- return nil if null?
11
-
12
- apply_geo_transform(x_pixel, y_pixel)[:x_location]
13
- end
14
-
15
- # The calculated UTM northing of the pixel on the map.
16
- #
17
- # @return [Float]
18
- def y_projection(x_pixel, y_pixel)
19
- return nil if null?
20
-
21
- apply_geo_transform(x_pixel, y_pixel)[:y_location]
22
- end
23
-
24
- # The algorithm per http://www.gdal.org/gdal_datamodel.html.
25
- def pixel_to_world(pixel, line)
26
- x_geo = x_origin + (pixel * pixel_width) + (line * x_rotation)
27
- y_geo = y_origin + (pixel * pixel_height) + (line * y_rotation)
28
-
29
- { longitude: y_geo, latitude: x_geo }
30
- end
31
-
32
- # Adapted from "Advanced Geospatial Python Modeling". Calculates the
33
- # pixel location of a geospatial coordinate.
34
- #
35
- # @param lon [Fixnum]
36
- # @param lat [Fixnum]
37
- # @param value_type [Symbol] Data type to return: :float or :integer.
38
- # @return [Hash<x, y>] [pixel, line]
39
- def world_to_pixel(lon, lat, value_type=:float)
40
- pixel = (lon - x_origin) / pixel_width
41
- line = (y_origin - lat) / pixel_height
42
-
43
- case value_type
44
- when :float
45
- { x: pixel.to_f, y: line.to_f }
46
- when :integer
47
- { x: pixel.to_i, y: line.to_i }
48
- else
49
- { x: pixel, y: line }
50
- end
51
- end
52
-
53
- # All attributes as an Array, in the order:
54
- # * x_origin
55
- # * pixel_width
56
- # * x_rotation
57
- # * y_origin
58
- # * y_rotation
59
- # * pixel_height
60
- #
61
- # @return [Array]
62
- def to_a
63
- [
64
- x_origin,
65
- pixel_width,
66
- x_rotation,
67
- y_origin,
68
- y_rotation,
69
- pixel_height
70
- ]
71
- end
72
-
73
- # @return [Hash]
74
- def as_json
75
- {
76
- x_origin: x_origin,
77
- x_rotation: x_rotation,
78
- pixel_width: pixel_width,
79
- y_origin: y_origin,
80
- y_rotation: y_rotation,
81
- pixel_height: pixel_height
82
- }
83
- end
84
-
85
- # @return [String]
86
- def to_json
87
- as_json.to_json
88
- end
89
- end
90
- end
@@ -1,40 +0,0 @@
1
- require 'json'
2
-
3
- module GDAL
4
- module RasterAttributeTableExtensions
5
-
6
- # Get +column_name+, +column_usage+, +column_type+ as a Hash.
7
- #
8
- # @param index [Fixnum]
9
- # @return [Hash]
10
- def column(index)
11
- {
12
- name: column_name(index),
13
- usage: column_usage(index),
14
- type: column_type(index)
15
- }
16
- end
17
-
18
- # @return [Array<Hash>]
19
- def columns
20
- 0.upto(column_count - 1).map do |i|
21
- column(i)
22
- end
23
- end
24
-
25
- # @return [Hash]
26
- def as_json
27
- {
28
- column_count: column_count,
29
- columns: columns,
30
- linear_binning: linear_binning,
31
- row_count: row_count
32
- }
33
- end
34
-
35
- # @return [String]
36
- def to_json
37
- as_json.to_json
38
- end
39
- end
40
- end