ffi-gdal 1.0.0.beta8 → 1.0.0.beta9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +25 -16
  3. data/.rubocop_todo.yml +13 -18
  4. data/History.md +10 -0
  5. data/ffi-gdal.gemspec +2 -2
  6. data/lib/ffi/gdal/version.rb +1 -1
  7. data/lib/ffi/gdal/warp_options.rb +0 -11
  8. data/lib/ffi/gdal.rb +1 -3
  9. data/lib/ffi/ogr/srs_api.rb +0 -2
  10. data/lib/gdal/color_table_mixins/extensions.rb +1 -3
  11. data/lib/gdal/dataset_mixins/extensions.rb +2 -4
  12. data/lib/gdal/driver.rb +3 -7
  13. data/lib/gdal/geo_transform.rb +1 -3
  14. data/lib/gdal/grid.rb +0 -2
  15. data/lib/gdal/raster_band.rb +2 -1
  16. data/lib/gdal/raster_band_classifier.rb +48 -15
  17. data/lib/gdal/raster_band_mixins/extensions.rb +4 -0
  18. data/lib/ogr/data_source.rb +3 -9
  19. data/lib/ogr/driver.rb +2 -6
  20. data/lib/ogr/envelope.rb +2 -2
  21. data/lib/ogr/error_handling.rb +1 -1
  22. data/lib/ogr/feature.rb +2 -0
  23. data/lib/ogr/field.rb +3 -1
  24. data/lib/ogr/geometries/line_string.rb +0 -3
  25. data/lib/ogr/geometry.rb +1 -3
  26. data/lib/ogr/geometry_mixins/extensions.rb +1 -3
  27. data/lib/ogr/layer_mixins/extensions.rb +2 -4
  28. data/lib/ogr/layer_mixins/ogr_feature_methods.rb +4 -12
  29. data/lib/ogr/layer_mixins/ogr_field_methods.rb +4 -12
  30. data/lib/ogr/layer_mixins/ogr_sql_methods.rb +1 -3
  31. data/spec/integration/gdal/dataset_info_spec.rb +12 -12
  32. data/spec/integration/gdal/raster_band_info_spec.rb +1 -3
  33. data/spec/spec_helper.rb +1 -1
  34. data/spec/unit/gdal/raster_band_classifier_spec.rb +38 -2
  35. data/spec/unit/ogr/feature_spec.rb +1 -1
  36. data/spec/unit/ogr/field_spec.rb +1 -1
  37. data/spec/unit/ogr/spatial_reference_mixins/exporters_spec.rb +12 -12
  38. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f3dc48a3584647ad17acba068529c648efd09a4c
4
- data.tar.gz: 1f92faa1bc794b5e35ba831d072258daf2942618
2
+ SHA256:
3
+ metadata.gz: fdaa59a5ef4022ef21872fc621c9f5ff872b07d40334dc002f4802aae99ec4ba
4
+ data.tar.gz: bcb79fc1ef548adb1b3d32cca73e0762d3b4cbee3bd068fe03fe65d9cf886807
5
5
  SHA512:
6
- metadata.gz: 5de8ff8356431d9a4d149eb9d93e64462e8eb5a0b7c138bc29dd4683b9e8f747b9e5d7a12e9281eeb405faf13bfd965cf8cae4326beef5db6e125e2cea386c9c
7
- data.tar.gz: 34dc5007a0c1f7dc27b9cb698ab244bd7324211d182d9c552d42bdc662311ce8b5b61fcb3c27c3e1f48f539171f1149ee33ecf5fc08498575f74391c5af972b3
6
+ metadata.gz: 9b20b80ea7995d46e3f9cab97f54c558d3810aea8903a27a44446d05be713b51b6e6ca9dfd57ccb72771cabd28ee560a4ac78e13fd9628c5009d5c6b650c11a6
7
+ data.tar.gz: f75a07f4a6139a59d022c59de617629d248b45ea79e3de3916f39066ae1a5e4999851d1ddfad146f80b81c35eef1e691a043315a5ac5686fa9b199a013630376
data/.rubocop.yml CHANGED
@@ -1,6 +1,12 @@
1
1
  ---
2
2
  inherit_from: .rubocop_todo.yml
3
3
 
4
+ Layout/AlignParameters:
5
+ EnforcedStyle: with_fixed_indentation
6
+
7
+ Layout/DotPosition:
8
+ EnforcedStyle: trailing
9
+
4
10
  Lint/UselessAssignment:
5
11
  Exclude:
6
12
  - examples/geometries.rb
@@ -44,30 +50,37 @@ Metrics/ParameterLists:
44
50
  - lib/gdal/warp_operation.rb
45
51
  - lib/ogr/spatial_reference_mixins/coordinate_system_getter_setters.rb
46
52
 
47
- Style/AccessorMethodName:
53
+ Naming/AccessorMethodName:
48
54
  Exclude:
49
55
  - lib/ogr/layer_mixins/ogr_field_methods.rb
50
56
  - lib/ogr/layer_mixins/ogr_query_filter_methods.rb
51
57
  - lib/ogr/spatial_reference_mixins/coordinate_system_getter_setters.rb
52
58
 
53
- Style/AlignParameters:
54
- EnforcedStyle: with_fixed_indentation
59
+ Naming/FileName:
60
+ Exclude:
61
+ - Rakefile
62
+ - lib/ffi-gdal.rb
63
+ - spec/ffi-gdal_spec.rb
64
+
65
+ Naming/PredicateName:
66
+ Exclude:
67
+ - lib/ogr/geometry_mixins/extensions.rb
68
+
69
+ Naming/UncommunicativeMethodParamName:
70
+ Exclude:
71
+ - lib/gdal/raster_band_mixins/io_extensions.rb
72
+ - lib/ogr/geometries/line_string.rb
73
+ - lib/ogr/geometries/line_string_25d.rb
74
+ - lib/ogr/geometries/point.rb
75
+ - lib/ogr/geometries/point_25d.rb
76
+ - lib/ogr/geometry_types/curve.rb
55
77
 
56
78
  Style/Documentation:
57
79
  Enabled: false
58
80
 
59
- Style/DotPosition:
60
- EnforcedStyle: trailing
61
-
62
81
  Style/DoubleNegation:
63
82
  Enabled: false
64
83
 
65
- Style/FileName:
66
- Exclude:
67
- - Rakefile
68
- - lib/ffi-gdal.rb
69
- - spec/ffi-gdal_spec.rb
70
-
71
84
  Style/FormatString:
72
85
  EnforcedStyle: percent
73
86
 
@@ -77,10 +90,6 @@ Style/PercentLiteralDelimiters:
77
90
  '%w': '[]'
78
91
  '%W': '[]'
79
92
 
80
- Style/PredicateName:
81
- Exclude:
82
- - lib/ogr/geometry_mixins/extensions.rb
83
-
84
93
  Style/SymbolArray:
85
94
  Enabled: true
86
95
 
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2017-04-21 10:44:22 -0700 using RuboCop version 0.48.1.
3
+ # on 2018-03-21 17:46:40 -0700 using RuboCop version 0.54.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -10,10 +10,10 @@
10
10
  Metrics/AbcSize:
11
11
  Max: 74
12
12
 
13
- # Offense count: 1
13
+ # Offense count: 3
14
14
  # Configuration parameters: CountComments, ExcludedMethods.
15
15
  Metrics/BlockLength:
16
- Max: 29
16
+ Max: 67
17
17
 
18
18
  # Offense count: 11
19
19
  # Configuration parameters: CountComments.
@@ -24,11 +24,16 @@ Metrics/ClassLength:
24
24
  Metrics/CyclomaticComplexity:
25
25
  Max: 21
26
26
 
27
- # Offense count: 84
27
+ # Offense count: 82
28
28
  # Configuration parameters: CountComments.
29
29
  Metrics/MethodLength:
30
30
  Max: 78
31
31
 
32
+ # Offense count: 2
33
+ # Configuration parameters: CountKeywordArgs.
34
+ Metrics/ParameterLists:
35
+ Max: 9
36
+
32
37
  # Offense count: 6
33
38
  Metrics/PerceivedComplexity:
34
39
  Max: 11
@@ -39,24 +44,14 @@ Style/GuardClause:
39
44
  Exclude:
40
45
  - 'lib/gdal/gridder/point_extracting.rb'
41
46
 
42
- # Adding to allow for targeting ruby 2.3, but the fixes for this cop aren't
43
- # compatible with ruby 2.2. (I want to keep the frozen-string stuff in)
44
- #
45
- # Offense count: 2
46
- # Cop supports --auto-correct.
47
- # Configuration parameters: EnforcedStyle, SupportedStyles.
48
- # SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
49
- Style/IndentHeredoc:
47
+ # Offense count: 1
48
+ Style/MixinUsage:
50
49
  Exclude:
51
- - 'spec/integration/gdal/dataset_info_spec.rb'
52
- - 'spec/unit/ogr/spatial_reference_mixins/exporters_spec.rb'
50
+ - 'examples/ogr_layer_to_layer.rb'
53
51
 
54
- # Adding to allow for targeting ruby 2.3, but the fixes for this cop aren't
55
- # compatible with ruby 2.2. (I want to keep the frozen-string stuff in)
56
- #
57
52
  # Offense count: 10
58
53
  # Cop supports --auto-correct.
59
- # Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
54
+ # Configuration parameters: AutoCorrect, EnforcedStyle.
60
55
  # SupportedStyles: predicate, comparison
61
56
  Style/NumericPredicate:
62
57
  Exclude:
data/History.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  Format for this file derived from [http://keepachangelog.com](http://keepachangelog.com).
4
4
 
5
+ ## 1.0.0.beta9 / 2018-03-26
6
+
7
+ ### Bug Fixes
8
+
9
+ * [AGDEV-30729] Change `OGERR_NONE` to use a lambda.
10
+
11
+ ### Improvements
12
+
13
+ * Fix some new rubocops.
14
+
5
15
  ## 1.0.0.beta8 / 2017-04-24
6
16
 
7
17
  ### Improvements
data/ffi-gdal.gemspec CHANGED
@@ -1,7 +1,6 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
5
  require 'ffi/gdal/version'
7
6
 
@@ -23,6 +22,7 @@ Gem::Specification.new do |spec|
23
22
  spec.add_dependency 'log_switch', '~> 1.0.0'
24
23
  spec.add_dependency 'multi_xml'
25
24
  spec.add_dependency 'narray', '~> 0.6.0'
25
+ spec.add_dependency 'numo-narray'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1.6'
28
28
  spec.add_development_dependency 'byebug'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module FFI
4
4
  module GDAL
5
- VERSION = '1.0.0.beta8'
5
+ VERSION = '1.0.0.beta9'
6
6
  end
7
7
  end
@@ -7,48 +7,37 @@ module FFI
7
7
  class WarpOptions < FFI::Struct
8
8
  layout :warp_operation_options, :pointer,
9
9
  :warp_memory_limit, :double,
10
-
11
10
  :resample_alg, FFI::GDAL::Warper::ResampleAlg,
12
11
  :working_data_type, FFI::GDAL::GDAL::DataType,
13
12
  :source_dataset, GDAL.find_type(:GDALDatasetH),
14
13
  :destination_dataset, GDAL.find_type(:GDALDatasetH),
15
-
16
14
  :band_count, :int,
17
15
  :source_bands, :pointer,
18
16
  :destination_bands, :pointer,
19
17
  :source_alpha_band, :int,
20
18
  :destination_alpha_band, :int,
21
-
22
19
  :source_no_data_real, :pointer,
23
20
  :source_no_data_imaginary, :pointer,
24
21
  :destination_no_data_real, :pointer,
25
22
  :destination_no_data_imaginary, :pointer,
26
-
27
23
  :progress, GDAL.find_type(:GDALProgressFunc),
28
24
  :progress_arg, :pointer,
29
25
  :transformer, Alg.find_type(:GDALTransformerFunc),
30
26
  :transformer_arg, :pointer,
31
-
32
27
  :source_per_band_validity_mask_function, :pointer,
33
28
  :source_per_band_validity_mask_function_arg, :pointer,
34
-
35
29
  :source_validity_mask_function, Warper.find_type(:GDALMaskFunc),
36
30
  :source_validity_mask_function_arg, :pointer,
37
-
38
31
  :source_density_mask_function, Warper.find_type(:GDALMaskFunc),
39
32
  :source_density_mask_function_arg, :pointer,
40
-
41
33
  :destination_density_mask_function, Warper.find_type(:GDALMaskFunc),
42
34
  :destination_density_mask_function_arg, :pointer,
43
-
44
35
  :destination_validity_mask_function, Warper.find_type(:GDALMaskFunc),
45
36
  :destination_validity_mask_function_arg, :pointer,
46
-
47
37
  :pre_warp_chunk_processor, callback(%i[pointer pointer], CPL::Error::CPLErr),
48
38
  :pre_warp_processor_arg, :pointer,
49
39
  :post_warp_chunk_processor, callback(%i[pointer pointer], CPL::Error::CPLErr),
50
40
  :post_warp_processor_arg, :pointer,
51
-
52
41
  :cutline, :pointer,
53
42
  :cutline_blend_distance, :double
54
43
 
data/lib/ffi/gdal.rb CHANGED
@@ -36,9 +36,7 @@ module FFI
36
36
  def self.find_lib(lib)
37
37
  lib_file_name = "#{lib}.#{FFI::Platform::LIBSUFFIX}*"
38
38
 
39
- if ENV['GDAL_LIBRARY_PATH']
40
- return Dir[File.join(ENV['GDAL_LIBRARY_PATH'], lib_file_name)]
41
- end
39
+ return Dir[File.join(ENV['GDAL_LIBRARY_PATH'], lib_file_name)] if ENV['GDAL_LIBRARY_PATH']
42
40
 
43
41
  search_paths.map do |search_path|
44
42
  Dir.glob(search_path).map do |path|
@@ -39,7 +39,6 @@ module FFI
39
39
  # -----------------------------------------------------------------------
40
40
  # Constants
41
41
  # -----------------------------------------------------------------------
42
- # rubocop:disable Metrics/BlockLength
43
42
  SRS_UL = FFI::ConstGenerator.new('SRS_UL') do |gen|
44
43
  gen.include FFI::GDAL._file_with_constants('ogr_srs_api.h')
45
44
  gen.const :SRS_UL_METER, '%s', nil, :METER_LABEL, &:inspect
@@ -96,7 +95,6 @@ module FFI
96
95
  gen.const :SRS_UL_INDIAN_CHAIN, '%s', nil, :INDIAN_CHAIN_LABEL, &:inspect
97
96
  gen.const :SRS_UL_INDIAN_CHAIN_CONV, '%s', nil, :METER_TO_INDIAN_CHAIN, &:to_f
98
97
  end
99
- # rubocop:enable Metrics/BlockLength
100
98
 
101
99
  SRS_UL.calculate
102
100
 
@@ -6,9 +6,7 @@ module GDAL
6
6
  module ColorTableMixins
7
7
  module Extensions
8
8
  def color_entries_for(color_number)
9
- unless (1..4).to_a.include? color_number
10
- raise "Invalid ColorEntry number 'color#{color_number}'"
11
- end
9
+ raise "Invalid ColorEntry number 'color#{color_number}'" unless (1..4).to_a.include? color_number
12
10
 
13
11
  Array.new(color_entry_count) do |i|
14
12
  color_entry(i).send("color#{color_number}".to_sym)
@@ -258,7 +258,7 @@ module GDAL
258
258
  spatial_ref = OGR::SpatialReference.new(projection)
259
259
  begin
260
260
  spatial_ref.auto_identify_epsg!
261
- rescue
261
+ rescue StandardError
262
262
  OGR::UnsupportedSRS
263
263
  end
264
264
  end
@@ -276,9 +276,7 @@ module GDAL
276
276
  layer.create_field(OGR::FieldDefinition.new(field_name, :OFTInteger))
277
277
  band = raster_band(band_number)
278
278
 
279
- unless band
280
- raise GDAL::InvalidBandNumber, "Unknown band number: #{band_number}"
281
- end
279
+ raise GDAL::InvalidBandNumber, "Unknown band number: #{band_number}" unless band
282
280
 
283
281
  pixel_value_field = layer.feature_definition.field_index(field_name)
284
282
  options = { pixel_value_field: pixel_value_field }
data/lib/gdal/driver.rb CHANGED
@@ -27,9 +27,7 @@ module GDAL
27
27
  def self.by_name(name)
28
28
  driver_ptr = FFI::GDAL::GDAL.GDALGetDriverByName(name)
29
29
 
30
- if driver_ptr.null?
31
- raise InvalidDriverName, "'#{name}' is not a valid driver name."
32
- end
30
+ raise InvalidDriverName, "'#{name}' is not a valid driver name." if driver_ptr.null?
33
31
 
34
32
  new(driver_ptr)
35
33
  end
@@ -39,9 +37,7 @@ module GDAL
39
37
  # @return [GDAL::Driver]
40
38
  # @raise [GDAL::InvalidDriverIndex] If driver at +index+ does not exist.
41
39
  def self.at_index(index)
42
- if index > count
43
- raise InvalidDriverIndex, "index must be between 0 and #{count - 1}."
44
- end
40
+ raise InvalidDriverIndex, "index must be between 0 and #{count - 1}." if index > count
45
41
 
46
42
  driver_ptr = FFI::GDAL::GDAL.GDALGetDriver(index)
47
43
 
@@ -176,7 +172,7 @@ module GDAL
176
172
  def copy_dataset(source_dataset, destination_path, progress_block = nil, progress_arg = nil, strict: true,
177
173
  **options)
178
174
  source_dataset_ptr = make_dataset_pointer(source_dataset)
179
- raise GDAL::OpenFailure, "Source dataset couldn't be read" if source_dataset_ptr && source_dataset_ptr.null?
175
+ raise GDAL::OpenFailure, "Source dataset couldn't be read" if source_dataset_ptr&.null?
180
176
 
181
177
  options_ptr = GDAL::Options.pointer(options)
182
178
 
@@ -170,9 +170,7 @@ module GDAL
170
170
  def compose(other_geo_transform)
171
171
  other_ptr = GDAL._pointer(GDAL::GeoTransform, other_geo_transform)
172
172
 
173
- unless other_ptr
174
- raise GDAL::NullObject, "Unable to access pointer for '#{other_geo_transform}'"
175
- end
173
+ raise GDAL::NullObject, "Unable to access pointer for '#{other_geo_transform}'" unless other_ptr
176
174
 
177
175
  new_gt_ptr = self.class.new_pointer
178
176
  FFI::GDAL::GDAL.GDALComposeGeoTransforms(@c_pointer, other_ptr, new_gt_ptr)
data/lib/gdal/grid.rb CHANGED
@@ -33,7 +33,6 @@ module GDAL
33
33
  # @param progress_block [Proc]
34
34
  # @param progress_arg [FFI::Pointer]
35
35
  # @return [FFI::MemoryPointer] Pointer to the grid data.
36
- # rubocop:disable Metrics/ParameterLists
37
36
  def create(points, extents, data_pointer, output_size = { x: 256, y: 256 },
38
37
  progress_block = nil, progress_arg = nil)
39
38
  points = points.to_a if points.is_a? NArray
@@ -69,7 +68,6 @@ module GDAL
69
68
  progress_arg # pProgressArg
70
69
  )
71
70
  end
72
- # rubocop:enable Metrics/ParameterLists
73
71
 
74
72
  private
75
73
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'narray'
4
+ require 'numo/narray'
4
5
  require_relative '../gdal'
5
6
  require_relative 'raster_band_mixins/algorithm_extensions'
6
7
  require_relative 'raster_band_mixins/algorithm_methods'
@@ -140,7 +141,7 @@ module GDAL
140
141
  def category_names=(names)
141
142
  names_pointer = GDAL._string_array_to_pointer(names)
142
143
 
143
- !!FFI::GDAL::GDAL.GDALSetRasterCategoryNames(@c_pointer, names_pointer)
144
+ FFI::GDAL::GDAL.GDALSetRasterCategoryNames(@c_pointer, names_pointer)
144
145
  end
145
146
 
146
147
  # The no data value for a band is generally a special marker value used to
@@ -51,20 +51,22 @@ module GDAL
51
51
  # @param range_count [Fixnum] The number of ranges to create.
52
52
  # @return [Array<Hash>, nil]
53
53
  def equal_count_ranges(range_count)
54
- sorted_pixels = @raster_band.to_na.sort
55
- no_data = @raster_band.no_data_value[:value]
56
- sorted_and_masked_pixels = no_data ? sorted_pixels[sorted_pixels.ne(no_data)] : sorted_pixels
57
- return [] if sorted_and_masked_pixels.empty?
54
+ pixels = @raster_band.to_nna
55
+ masked_pixels = masked_pixels(pixels)
56
+
57
+ return [] if masked_pixels.empty?
58
58
 
59
+ sorted_and_masked_pixels = masked_pixels.to_a.sort
59
60
  range_size = (sorted_and_masked_pixels.size / range_count).to_i
60
61
 
61
- log "Masked pixel count/total pixel count: #{sorted_and_masked_pixels.size}/#{sorted_pixels.size}"
62
+ log "Masked pixel count/total pixel count: #{sorted_and_masked_pixels.size}/#{pixels.size}"
62
63
  log "Min pixel value: #{sorted_and_masked_pixels.min}"
63
64
  log "Max pixel value: #{sorted_and_masked_pixels.max}"
64
65
  log "Range size: #{range_size}"
65
66
 
66
67
  break_values = Array.new(range_count) { |i| sorted_and_masked_pixels[range_size * i] }.uniq
67
68
  log "Break values: #{break_values}"
69
+
68
70
  return if break_values.uniq.size != range_count
69
71
 
70
72
  breakpoint_calculator = lambda do |range_number|
@@ -85,27 +87,58 @@ module GDAL
85
87
  # values, so if you don't want to overwrite the Dataset you're working with,
86
88
  # you should copy it first.
87
89
  def classify!
88
- nodata_value = @raster_band.no_data_value[:value]
89
- band_pixels = @raster_band.to_na
90
- new_band_pixels = GDAL._narray_from_data_type(@raster_band.data_type, @raster_band.x_size, @raster_band.y_size)
91
- new_band_pixels[band_pixels.eq(nodata_value)] = nodata_value if nodata_value
92
- data_pixels = nodata_value ? band_pixels.ne(nodata_value) : band_pixels
90
+ band_pixels = @raster_band.to_nna
91
+ new_band_pixels = band_pixels.clone
92
+ data_pixels = if nodata_value
93
+ nodata_is_nan? ? ~band_pixels.isnan : band_pixels.ne(nodata_value)
94
+ else
95
+ Numo::Bit.cast(band_pixels.new_ones)
96
+ end
93
97
 
94
98
  @ranges.each do |r|
95
- new_band_pixels[
96
- data_pixels.
97
- and(band_pixels.le(r[:range].max)).
98
- and(band_pixels.ge(r[:range].min))
99
- ] = r[:map_to]
99
+ new_band_pixels[data_pixels & band_pixels.le(r[:range].max) & band_pixels.ge(r[:range].min)] = r[:map_to]
100
100
  end
101
101
 
102
+ mask_nan(new_band_pixels, data_pixels) if nodata_is_nan?
102
103
  @raster_band.write_xy_narray(new_band_pixels)
103
104
  end
104
105
 
106
+ # @return [Numeric] NODATA value for the @raster_band.
107
+ def nodata_value
108
+ @raster_band.no_data_value[:value]
109
+ end
110
+
111
+ # @return [Boolean] True if NODATA is NaN.
112
+ def nodata_is_nan?
113
+ nodata_value.is_a?(Float) && nodata_value.nan?
114
+ end
115
+
105
116
  private
106
117
 
118
+ # @param pixels [Numo::NArray]
119
+ # @return [Numo::NArray]
120
+ def masked_pixels(pixels)
121
+ no_data = @raster_band.no_data_value[:value]
122
+
123
+ if no_data
124
+ mask = no_data.is_a?(Float) && no_data.nan? ? ~pixels.isnan : pixels.ne(no_data)
125
+ pixels[mask]
126
+ else
127
+ pixels
128
+ end
129
+ end
130
+
107
131
  def range_for_type(min, max)
108
132
  min.to_data_type(@raster_band.data_type)..max.to_data_type(@raster_band.data_type)
109
133
  end
134
+
135
+ # Set nodata pixels to 0 and set the nodata value to 0.
136
+ #
137
+ # @param new_band_pixels [Numo::NArray]
138
+ # @param data_pixels [Numo::Bit]
139
+ def mask_nan(new_band_pixels, data_pixels)
140
+ new_band_pixels[~data_pixels] = 0
141
+ @raster_band.no_data_value = 0
142
+ end
110
143
  end
111
144
  end
@@ -37,6 +37,10 @@ module GDAL
37
37
  narray.to_type(narray_type)
38
38
  end
39
39
 
40
+ def to_nna
41
+ Numo::NArray[to_a]
42
+ end
43
+
40
44
  # Each pixel of the raster projected using the dataset's geo_transform.
41
45
  # The output NArray is a 3D array where the inner-most array is a the
42
46
  # lat an lon, those are contained in an array per pixel line, and finally
@@ -112,9 +112,7 @@ module OGR
112
112
  # @param options [Hash] Driver-specific options.
113
113
  # @return [OGR::Layer]
114
114
  def create_layer(name, geometry_type: :wkbUnknown, spatial_reference: nil, **options)
115
- unless can_create_layer?
116
- raise OGR::UnsupportedOperation, 'This data source does not support creating layers.'
117
- end
115
+ raise OGR::UnsupportedOperation, 'This data source does not support creating layers.' unless can_create_layer?
118
116
 
119
117
  spatial_ref_ptr = GDAL._pointer(OGR::SpatialReference, spatial_reference) if spatial_reference
120
118
  options_obj = GDAL::Options.pointer(options)
@@ -122,9 +120,7 @@ module OGR
122
120
  layer_ptr = FFI::OGR::API.OGR_DS_CreateLayer(@c_pointer, name,
123
121
  spatial_ref_ptr, geometry_type, options_obj)
124
122
 
125
- unless layer_ptr
126
- raise OGR::InvalidLayer, "Unable to create layer '#{name}'."
127
- end
123
+ raise OGR::InvalidLayer, "Unable to create layer '#{name}'." unless layer_ptr
128
124
 
129
125
  @layers << OGR::Layer.new(layer_ptr)
130
126
 
@@ -149,9 +145,7 @@ module OGR
149
145
  # @param index [Fixnum]
150
146
  # @return +true+ if successful, otherwise raises an OGR exception.
151
147
  def delete_layer(index)
152
- unless can_delete_layer?
153
- raise OGR::UnsupportedOperation, 'This data source does not support deleting layers.'
154
- end
148
+ raise OGR::UnsupportedOperation, 'This data source does not support deleting layers.' unless can_delete_layer?
155
149
 
156
150
  ogr_err = FFI::OGR::API.OGR_DS_DeleteLayer(@c_pointer, index)
157
151
 
data/lib/ogr/driver.rb CHANGED
@@ -74,9 +74,7 @@ module OGR
74
74
 
75
75
  data_source_ptr = FFI::OGR::API.OGR_Dr_Open(@c_pointer, file_name, update)
76
76
 
77
- if data_source_ptr.null?
78
- raise OGR::InvalidDataSource, "Unable to open data source at #{file_name}"
79
- end
77
+ raise OGR::InvalidDataSource, "Unable to open data source at #{file_name}" if data_source_ptr.null?
80
78
 
81
79
  OGR::DataSource.new(data_source_ptr, nil)
82
80
  end
@@ -124,9 +122,7 @@ module OGR
124
122
  def copy_data_source(source_data_source, new_file_name, **options)
125
123
  source_ptr = GDAL._pointer(OGR::DataSource, source_data_source)
126
124
 
127
- if source_ptr.nil? || source_ptr.null?
128
- raise OGR::InvalidDataSource, source_data_source
129
- end
125
+ raise OGR::InvalidDataSource, source_data_source if source_ptr.nil? || source_ptr.null?
130
126
 
131
127
  options_ptr = GDAL::Options.pointer(options)
132
128
 
data/lib/ogr/envelope.rb CHANGED
@@ -71,7 +71,7 @@ module OGR
71
71
 
72
72
  # @param new_z_min [Float]
73
73
  def z_min=(new_z_min)
74
- return nil unless @c_struct.is_a? FFI::OGR::Envelope3D
74
+ return unless @c_struct.is_a? FFI::OGR::Envelope3D
75
75
 
76
76
  @c_struct[:min_z] = new_z_min
77
77
  end
@@ -85,7 +85,7 @@ module OGR
85
85
 
86
86
  # @param new_z_max [Float]
87
87
  def z_max=(new_z_max)
88
- return nil unless @c_struct.is_a? FFI::OGR::Envelope3D
88
+ return unless @c_struct.is_a? FFI::OGR::Envelope3D
89
89
 
90
90
  @c_struct[:max_z] = new_z_max
91
91
  end
@@ -25,7 +25,7 @@ module OGR
25
25
  # @return [Proc]
26
26
  def error_class_map(error_class)
27
27
  {
28
- OGRERR_NONE: proc { true },
28
+ OGRERR_NONE: ->(_msg) { true },
29
29
  OGRERR_NOT_ENOUGH_DATA: ->(msg) { raise_exception(OGR::NotEnoughData, msg) },
30
30
  OGRERR_NOT_ENOUGH_MEMORY: ->(msg) { raise_exception(::NoMemoryError, msg) },
31
31
  OGRERR_UNSUPPORTED_GEOMETRY_TYPE: ->(msg) { raise_exception(OGR::UnsupportedGeometryType, msg) },
data/lib/ogr/feature.rb CHANGED
@@ -392,6 +392,7 @@ module OGR
392
392
 
393
393
  formatted_tz = OGR._format_time_zone_for_ruby(time_zone_flag_ptr.read_int)
394
394
 
395
+ # rubocop:disable Style/DateTime
395
396
  if formatted_tz
396
397
  DateTime.new(
397
398
  year_ptr.read_int,
@@ -412,6 +413,7 @@ module OGR
412
413
  second_ptr.read_int
413
414
  )
414
415
  end
416
+ # rubocop:enable Style/DateTime
415
417
  end
416
418
 
417
419
  # @return [String]
data/lib/ogr/field.rb CHANGED
@@ -52,7 +52,7 @@ module OGR
52
52
 
53
53
  # TODO: This blows up when another value type has been set.
54
54
  def string
55
- return '' if @c_struct[:string] && @c_struct[:string].null?
55
+ return '' if @c_struct[:string]&.null?
56
56
 
57
57
  @c_struct[:string].read_string
58
58
  end
@@ -186,6 +186,7 @@ module OGR
186
186
 
187
187
  formatted_tz = OGR._format_time_zone_for_ruby(c_date[:tz_flag].to_i)
188
188
 
189
+ # rubocop:disable Style/DateTime
189
190
  DateTime.new(c_date[:year],
190
191
  c_date[:month],
191
192
  c_date[:day],
@@ -193,6 +194,7 @@ module OGR
193
194
  c_date[:minute],
194
195
  c_date[:second],
195
196
  formatted_tz)
197
+ # rubocop:enable Style/DateTime
196
198
  end
197
199
 
198
200
  # @param new_date [Date, Time, DateTime]
@@ -6,8 +6,6 @@ module OGR
6
6
  class LineString
7
7
  include OGR::Geometry
8
8
  include GeometryTypes::Curve
9
-
10
- # rubocop:disable Metrics/ParameterLists
11
9
  def self.approximate_arc_angles(center_x, center_y, z, primary_radius, secondary_radius,
12
10
  rotation, start_angle, end_angle, max_angle_step_size_degrees = 0)
13
11
  geometry_ptr = FFI::GDAL::GDAL.OGR_G_ApproximateArcAngles(
@@ -25,7 +23,6 @@ module OGR
25
23
 
26
24
  new(geometry_ptr)
27
25
  end
28
- # rubocop:enable Metrics/ParameterLists
29
26
 
30
27
  def initialize(geometry_ptr = nil, spatial_reference: nil)
31
28
  geometry_ptr ||= OGR::Geometry.create(:wkbLineString)
data/lib/ogr/geometry.rb CHANGED
@@ -619,9 +619,7 @@ module OGR
619
619
 
620
620
  linear_ring = OGR::LinearRing.new
621
621
 
622
- if line_string.spatial_reference
623
- linear_ring.spatial_reference = line_string.spatial_reference.clone
624
- end
622
+ linear_ring.spatial_reference = line_string.spatial_reference.clone if line_string.spatial_reference
625
623
 
626
624
  linear_ring.import_from_wkt(line_string.to_wkt.tr('LINESTRING', 'LINEARRING'))
627
625
  linear_ring.close_rings! if close_rings
@@ -70,9 +70,7 @@ module OGR
70
70
  # field = FieldDefinition.new('Name', :OFTString)
71
71
  # field.width = 32
72
72
 
73
- unless layer
74
- raise OGR::InvalidLayer, "Unable to create layer '#{layer_name}'."
75
- end
73
+ raise OGR::InvalidLayer, "Unable to create layer '#{layer_name}'." unless layer
76
74
 
77
75
  feature = layer.create_feature(layer_name)
78
76
  feature.geometry = self
@@ -24,7 +24,7 @@ module OGR
24
24
 
25
25
  begin
26
26
  yield feature
27
- rescue
27
+ rescue StandardError
28
28
  feature.destroy!
29
29
  raise
30
30
  end
@@ -52,7 +52,7 @@ module OGR
52
52
 
53
53
  begin
54
54
  yield feature_ptr
55
- rescue
55
+ rescue StandardError
56
56
  FFI::OGR::API.OGR_F_Destroy(feature_ptr)
57
57
  raise
58
58
  end
@@ -128,7 +128,6 @@ module OGR
128
128
  # I've tried refactoring chunks of this out to separate methods and
129
129
  # performance suffers greatly. Since this is a key part of gridding (at
130
130
  # least at this point), it needs to be as fast as possible.
131
- # rubocop:disable Metrics/BlockLength
132
131
  each_feature_pointer do |feature_ptr|
133
132
  field_values = field_indices.map.with_index do |j, attribute_index|
134
133
  FFI::OGR::API.send("OGR_F_GetFieldAs#{with_attributes.values[attribute_index].capitalize}", feature_ptr, j)
@@ -211,7 +210,6 @@ module OGR
211
210
  "Not sure how to extract point_values for a #{geom_type}"
212
211
  end
213
212
  end
214
- # rubocop:enable Metrics/BlockLength
215
213
 
216
214
  log "#point_values took #{Time.now - start}s"
217
215
 
@@ -25,9 +25,7 @@ module OGR
25
25
  # @param feature [OGR::Feature] [description]
26
26
  # @return [Boolean]
27
27
  def create_feature(feature)
28
- unless can_sequential_write?
29
- raise OGR::UnsupportedOperation, 'This layer does not support feature creation.'
30
- end
28
+ raise OGR::UnsupportedOperation, 'This layer does not support feature creation.' unless can_sequential_write?
31
29
 
32
30
  ogr_err = FFI::OGR::API.OGR_L_CreateFeature(@c_pointer, feature.c_pointer)
33
31
 
@@ -41,9 +39,7 @@ module OGR
41
39
  # @raise [OGR::Failure] When trying to delete a feature with an ID that
42
40
  # does not exist.
43
41
  def delete_feature(feature_id)
44
- unless can_delete_feature?
45
- raise OGR::UnsupportedOperation, 'This layer does not support feature deletion.'
46
- end
42
+ raise OGR::UnsupportedOperation, 'This layer does not support feature deletion.' unless can_delete_feature?
47
43
 
48
44
  ogr_err = FFI::OGR::API.OGR_L_DeleteFeature(@c_pointer, feature_id)
49
45
 
@@ -63,9 +59,7 @@ module OGR
63
59
  #
64
60
  # @param new_feature [OGR::Feature, FFI::Pointer]
65
61
  def feature=(new_feature)
66
- unless can_random_write?
67
- raise OGR::UnsupportedOperation, '#feature= not supported by this Layer'
68
- end
62
+ raise OGR::UnsupportedOperation, '#feature= not supported by this Layer' unless can_random_write?
69
63
 
70
64
  new_feature_ptr = GDAL._pointer(OGR::Feature, new_feature)
71
65
  raise OGR::InvalidFeature if new_feature_ptr.nil? || new_feature_ptr.null?
@@ -79,9 +73,7 @@ module OGR
79
73
  # be <= +feature_count+, but no checking is done to ensure.
80
74
  # @return [OGR::Feature, nil]
81
75
  def feature(index)
82
- unless can_random_read?
83
- raise OGR::UnsupportedOperation, '#feature(index) not supported by this Layer'
84
- end
76
+ raise OGR::UnsupportedOperation, '#feature(index) not supported by this Layer' unless can_random_read?
85
77
 
86
78
  feature_pointer = FFI::OGR::API.OGR_L_GetFeature(@c_pointer, index)
87
79
  return nil if feature_pointer.null?
@@ -12,9 +12,7 @@ module OGR
12
12
  # different form, depending on the limitations of the format driver.
13
13
  # @return [Boolean]
14
14
  def create_field(field_definition, approx_ok = false)
15
- unless can_create_field?
16
- raise OGR::UnsupportedOperation, 'This layer does not support field creation.'
17
- end
15
+ raise OGR::UnsupportedOperation, 'This layer does not support field creation.' unless can_create_field?
18
16
 
19
17
  field_definition_ptr = GDAL._pointer(OGR::FieldDefinition, field_definition)
20
18
  ogr_err = FFI::OGR::API.OGR_L_CreateField(@c_pointer, field_definition_ptr, approx_ok)
@@ -26,9 +24,7 @@ module OGR
26
24
  #
27
25
  # @return +true+ if successful, otherwise raises an OGR exception.
28
26
  def delete_field(field_id)
29
- unless can_delete_field?
30
- raise OGR::UnsupportedOperation, 'This driver does not support field deletion.'
31
- end
27
+ raise OGR::UnsupportedOperation, 'This driver does not support field deletion.' unless can_delete_field?
32
28
 
33
29
  ogr_err = FFI::OGR::API.OGR_L_DeleteField(@c_pointer, field_id)
34
30
 
@@ -39,9 +35,7 @@ module OGR
39
35
  # which they should be reordered. I.e. [0, 2, 3, 1, 4].
40
36
  # @return [Boolean]
41
37
  def reorder_fields(*new_order)
42
- unless can_reorder_fields?
43
- raise OGR::UnsupportedOperation, 'This driver does not support field reordering.'
44
- end
38
+ raise OGR::UnsupportedOperation, 'This driver does not support field reordering.' unless can_reorder_fields?
45
39
 
46
40
  return false if new_order.empty?
47
41
  return false if new_order.any? { |i| i > feature_definition.field_count }
@@ -58,9 +52,7 @@ module OGR
58
52
  # @param old_position [Fixnum]
59
53
  # @param new_position [Fixnum]
60
54
  def reorder_field(old_position, new_position)
61
- unless can_reorder_fields?
62
- raise OGR::UnsupportedOperation, 'This driver does not support field reordering.'
63
- end
55
+ raise OGR::UnsupportedOperation, 'This driver does not support field reordering.' unless can_reorder_fields?
64
56
 
65
57
  ogr_err = FFI::OGR::API.OGR_L_ReorderField(@c_pointer, old_position, new_position)
66
58
 
@@ -37,9 +37,7 @@ module OGR
37
37
 
38
38
  # @return [Boolean]
39
39
  def transact
40
- unless supports_transactions?
41
- raise OGR::UnsupportedOperation, 'This layer does not support transactions.'
42
- end
40
+ raise OGR::UnsupportedOperation, 'This layer does not support transactions.' unless supports_transactions?
43
41
 
44
42
  ogr_err = yield
45
43
 
@@ -79,18 +79,18 @@ RSpec.describe 'Dataset Info', type: :integration do
79
79
 
80
80
  context 'param is an valid projection string' do
81
81
  let(:wkt) do
82
- <<-WKT
83
- GEOGCS["WGS 84",
84
- DATUM["WGS_1984",
85
- SPHEROID["WGS 84",6378137,298.257223563,
86
- AUTHORITY["EPSG",7030]],
87
- TOWGS84[0,0,0,0,0,0,0],
88
- AUTHORITY["EPSG",6326]],
89
- PRIMEM["Greenwich",0,AUTHORITY["EPSG",8901]],
90
- UNIT["DMSH",0.0174532925199433,AUTHORITY["EPSG",9108]],
91
- AXIS["Lat",NORTH],
92
- AXIS["Long",EAST],
93
- AUTHORITY["EPSG",4326]]
82
+ <<~WKT
83
+ GEOGCS["WGS 84",
84
+ DATUM["WGS_1984",
85
+ SPHEROID["WGS 84",6378137,298.257223563,
86
+ AUTHORITY["EPSG",7030]],
87
+ TOWGS84[0,0,0,0,0,0,0],
88
+ AUTHORITY["EPSG",6326]],
89
+ PRIMEM["Greenwich",0,AUTHORITY["EPSG",8901]],
90
+ UNIT["DMSH",0.0174532925199433,AUTHORITY["EPSG",9108]],
91
+ AXIS["Lat",NORTH],
92
+ AXIS["Long",EAST],
93
+ AUTHORITY["EPSG",4326]]
94
94
  WKT
95
95
  end
96
96
 
@@ -58,9 +58,7 @@ RSpec.describe 'Raster Band Info', type: :integration do
58
58
 
59
59
  describe '#color_table' do
60
60
  it 'is a GDAL::ColorTable' do
61
- if subject.color_table
62
- expect(subject.color_table).to be_a GDAL::ColorTable
63
- end
61
+ expect(subject.color_table).to be_a GDAL::ColorTable if subject.color_table
64
62
  end
65
63
  end
66
64
 
data/spec/spec_helper.rb CHANGED
@@ -9,7 +9,7 @@ SimpleCov.start do
9
9
  add_group 'ext', 'lib/ext'
10
10
  end
11
11
 
12
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
12
+ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
13
13
  require 'ffi-gdal'
14
14
  require 'byebug'
15
15
 
@@ -98,8 +98,8 @@ RSpec.describe GDAL::RasterBandClassifier do
98
98
  end
99
99
 
100
100
  context 'all nodata pixels' do
101
- let(:band_narray) { NArray.byte(0) }
102
- before { allow(raster_band).to receive(:to_na).and_return(band_narray) }
101
+ let(:band_narray) { Numo::Int8.new(3, 5).fill(0) }
102
+ before { allow(raster_band).to receive(:to_nna).and_return(band_narray) }
103
103
 
104
104
  it 'returns an empty Array' do
105
105
  expect(subject.equal_count_ranges(10)).to eq([])
@@ -196,4 +196,40 @@ RSpec.describe GDAL::RasterBandClassifier do
196
196
  end
197
197
  end
198
198
  end
199
+
200
+ describe '#masked_pixels' do
201
+ let(:pixels) { dataset.raster_band(1).to_nna }
202
+ let(:raster_band) { double 'Band', no_data_value: { value: nodata_value } }
203
+
204
+ before { subject.instance_variable_set(:@raster_band, raster_band) }
205
+
206
+ context 'nodata is NaN' do
207
+ let(:nodata_value) { Float::NAN }
208
+ let(:pixels) { Numo::DFloat.cast(dataset.raster_band(1).to_nna) }
209
+
210
+ before do
211
+ pixels[pixels.eq(0)] = nodata_value
212
+ end
213
+
214
+ it 'removes all nodata values' do
215
+ expect(subject.send(:masked_pixels, pixels).isnan.count_true).to eq 0
216
+ end
217
+ end
218
+
219
+ context 'nodata is a number' do
220
+ let(:nodata_value) { 0 }
221
+
222
+ it 'removes all nodata values' do
223
+ expect(subject.send(:masked_pixels, pixels).eq(0).count_true).to eq 0
224
+ end
225
+ end
226
+
227
+ context 'nodata is nil' do
228
+ let(:nodata_value) { nil }
229
+
230
+ it 'returns the original pixels' do
231
+ expect(subject.send(:masked_pixels, pixels)).to eq pixels
232
+ end
233
+ end
234
+ end
199
235
  end
@@ -275,7 +275,7 @@ RSpec.describe OGR::Feature do
275
275
  end
276
276
 
277
277
  describe '#set_field_date_time + #field_as_date_time' do
278
- let(:date_time) { DateTime.now }
278
+ let(:date_time) { DateTime.now } # rubocop:disable Style/DateTime
279
279
 
280
280
  context 'to a valid index' do
281
281
  it 'adds the field' do
@@ -184,7 +184,7 @@ RSpec.describe OGR::Field do
184
184
 
185
185
  describe '#date= + #date' do
186
186
  context 'valid date' do
187
- let(:now) { DateTime.now }
187
+ let(:now) { DateTime.now } # rubocop:disable Style/DateTime
188
188
 
189
189
  it 'sets the date' do
190
190
  subject.date = now
@@ -109,18 +109,18 @@ RSpec.describe OGR::SpatialReference do
109
109
  subject { described_class.new_from_epsg(4322) }
110
110
 
111
111
  it 'returns a well-known text String' do
112
- expect(subject.to_pretty_wkt).to eq <<-WKT.strip
113
- GEOGCS["WGS 72",
114
- DATUM["WGS_1972",
115
- SPHEROID["WGS 72",6378135,298.26,
116
- AUTHORITY["EPSG","7043"]],
117
- TOWGS84[0,0,4.5,0,0,0.554,0.2263],
118
- AUTHORITY["EPSG","6322"]],
119
- PRIMEM["Greenwich",0,
120
- AUTHORITY["EPSG","8901"]],
121
- UNIT["degree",0.0174532925199433,
122
- AUTHORITY["EPSG","9122"]],
123
- AUTHORITY["EPSG","4322"]]
112
+ expect(subject.to_pretty_wkt).to eq <<~WKT.strip
113
+ GEOGCS["WGS 72",
114
+ DATUM["WGS_1972",
115
+ SPHEROID["WGS 72",6378135,298.26,
116
+ AUTHORITY["EPSG","7043"]],
117
+ TOWGS84[0,0,4.5,0,0,0.554,0.2263],
118
+ AUTHORITY["EPSG","6322"]],
119
+ PRIMEM["Greenwich",0,
120
+ AUTHORITY["EPSG","8901"]],
121
+ UNIT["degree",0.0174532925199433,
122
+ AUTHORITY["EPSG","9122"]],
123
+ AUTHORITY["EPSG","4322"]]
124
124
  WKT
125
125
  end
126
126
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-gdal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta8
4
+ version: 1.0.0.beta9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Loveless
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-28 00:00:00.000000000 Z
11
+ date: 2018-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.6.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: numo-narray
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -530,7 +544,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
530
544
  version: 1.3.1
531
545
  requirements: []
532
546
  rubyforge_project:
533
- rubygems_version: 2.6.11
547
+ rubygems_version: 2.7.6
534
548
  signing_key:
535
549
  specification_version: 4
536
550
  summary: FFI wrapper for GDAL/OGR.