ffi-gdal 1.0.3 → 1.1.0
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.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +9 -0
- data/.devcontainer/devcontainer.json +98 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/workflows/codacy.yml +3 -3
- data/.github/workflows/codeql.yml +4 -4
- data/.github/workflows/continuous-integration.yml +30 -19
- data/.github/workflows/dependency-review.yml +2 -2
- data/.github/workflows/specs-in-docker.yml +12 -6
- data/.gitignore +4 -1
- data/Changelog.md +45 -4
- data/Gemfile +4 -2
- data/README.md +35 -0
- data/bin/rake +1 -1
- data/bin/rspec +1 -1
- data/bin/rubocop +1 -1
- data/lib/ext/numeric_as_data_type.rb +1 -1
- data/lib/ffi/cpl/vsi.rb +10 -0
- data/lib/ffi/gdal/gdal.rb +9 -2
- data/lib/ffi/gdal/grid_data_metrics_options.rb +27 -5
- data/lib/ffi/gdal/grid_inverse_distance_to_a_power_options.rb +30 -10
- data/lib/ffi/gdal/grid_moving_average_options.rb +30 -5
- data/lib/ffi/gdal/grid_nearest_neighbor_options.rb +24 -4
- data/lib/ffi/gdal/internal_helpers/gdal_version.rb +15 -0
- data/lib/ffi/gdal/internal_helpers/layout_version.rb +9 -0
- data/lib/ffi/gdal/internal_helpers/layout_version_resolver.rb +24 -0
- data/lib/ffi/gdal/internal_helpers.rb +11 -0
- data/lib/ffi/gdal/utils.rb +984 -0
- data/lib/ffi/gdal/version.rb +1 -1
- data/lib/ffi/gdal.rb +3 -1
- data/lib/ffi/ogr/core.rb +1 -1
- data/lib/ffi/ogr/srs_api.rb +17 -0
- data/lib/gdal/cpl_error_handler.rb +30 -15
- data/lib/gdal/exceptions.rb +35 -16
- data/lib/gdal/extensions/color_table/extensions.rb +1 -1
- data/lib/gdal/extensions/gridder.rb +4 -0
- data/lib/gdal/geo_transform.rb +13 -0
- data/lib/gdal/grid_algorithms/algorithm_base.rb +35 -0
- data/lib/gdal/grid_algorithms/inverse_distance_to_a_power.rb +3 -7
- data/lib/gdal/grid_algorithms/metric_average_distance.rb +5 -4
- data/lib/gdal/grid_algorithms/metric_average_distance_pts.rb +5 -4
- data/lib/gdal/grid_algorithms/metric_count.rb +5 -4
- data/lib/gdal/grid_algorithms/metric_maximum.rb +5 -4
- data/lib/gdal/grid_algorithms/metric_minimum.rb +5 -4
- data/lib/gdal/grid_algorithms/metric_range.rb +5 -4
- data/lib/gdal/grid_algorithms/moving_average.rb +3 -7
- data/lib/gdal/grid_algorithms/nearest_neighbor.rb +3 -7
- data/lib/gdal/grid_algorithms.rb +2 -0
- data/lib/gdal/internal_helpers.rb +8 -5
- data/lib/gdal/major_object.rb +6 -0
- data/lib/gdal/raster_band.rb +16 -12
- data/lib/gdal/utils/dem/options.rb +52 -0
- data/lib/gdal/utils/dem.rb +108 -0
- data/lib/gdal/utils/grid/options.rb +52 -0
- data/lib/gdal/utils/grid.rb +72 -0
- data/lib/gdal/utils/helpers/dataset_list.rb +43 -0
- data/lib/gdal/utils/helpers/string_list.rb +47 -0
- data/lib/gdal/utils/helpers.rb +11 -0
- data/lib/gdal/utils/info/options.rb +52 -0
- data/lib/gdal/utils/info.rb +40 -0
- data/lib/gdal/utils/nearblack/options.rb +52 -0
- data/lib/gdal/utils/nearblack.rb +119 -0
- data/lib/gdal/utils/rasterize/options.rb +52 -0
- data/lib/gdal/utils/rasterize.rb +108 -0
- data/lib/gdal/utils/translate/options.rb +52 -0
- data/lib/gdal/utils/translate.rb +72 -0
- data/lib/gdal/utils/vector_translate/options.rb +52 -0
- data/lib/gdal/utils/vector_translate.rb +132 -0
- data/lib/gdal/utils/warp/options.rb +52 -0
- data/lib/gdal/utils/warp.rb +118 -0
- data/lib/gdal/utils.rb +22 -0
- data/lib/gdal/warp_options.rb +11 -2
- data/lib/gdal.rb +1 -0
- data/lib/ogr/extensions/geometry/extensions.rb +0 -8
- data/lib/ogr/extensions/layer/extensions.rb +1 -1
- data/lib/ogr/extensions/spatial_reference/extensions.rb +4 -4
- data/lib/ogr/geometry.rb +9 -6
- data/lib/ogr/layer.rb +1 -1
- data/lib/ogr/spatial_reference.rb +27 -2
- metadata +32 -5
- data/.ruby-version +0 -1
- data/lib/gdal/grid_algorithms/data_metrics_base.rb +0 -14
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "rasterize/options"
|
4
|
+
|
5
|
+
module GDAL
|
6
|
+
module Utils
|
7
|
+
# Wrapper for gdal_rasterize using GDALRasterize C API.
|
8
|
+
#
|
9
|
+
# @see https://gdal.org/programs/gdal_rasterize.html gdal_rasterize utility documentation.
|
10
|
+
# @see https://gdal.org/api/gdal_utils.html#_CPPv413GDALRasterizePKc12GDALDatasetH12GDALDatasetHPK20GDALRasterizeOptionsPi
|
11
|
+
# GDALRasterize C API.
|
12
|
+
class Rasterize
|
13
|
+
# Perform the gdal_rasterize (GDALRasterize) operation.
|
14
|
+
#
|
15
|
+
# @example Rasterize a dataset with options (for dst_dataset_path).
|
16
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
17
|
+
# options = GDAL::Utils::Rasterize::Options.new(options: ["-ts", "10", "10"])
|
18
|
+
#
|
19
|
+
# dataset = GDAL::Utils::Rasterize.perform(
|
20
|
+
# dst_dataset_path: "destination.tif",
|
21
|
+
# src_dataset: src_dataset,
|
22
|
+
# options: options
|
23
|
+
# )
|
24
|
+
#
|
25
|
+
# # Do something with the dataset.
|
26
|
+
# puts dataset.raster_x_size
|
27
|
+
#
|
28
|
+
# # You must close the dataset when you are done with it.
|
29
|
+
# dataset.close
|
30
|
+
# src_dataset.close
|
31
|
+
#
|
32
|
+
# @example Rasterize a dataset (for dst_dataset_path) using block syntax.
|
33
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
34
|
+
# options = GDAL::Utils::Rasterize::Options.new(options: ["-ts", "10", "10"])
|
35
|
+
#
|
36
|
+
# GDAL::Utils::Rasterize.perform(
|
37
|
+
# dst_dataset_path: "destination.tif",
|
38
|
+
# src_dataset: src_dataset,
|
39
|
+
# options: options
|
40
|
+
# ) do |dataset|
|
41
|
+
# # Do something with the dataset.
|
42
|
+
# puts dataset.raster_x_size
|
43
|
+
#
|
44
|
+
# # Dataset will be closed automatically.
|
45
|
+
# end
|
46
|
+
# src_dataset.close
|
47
|
+
#
|
48
|
+
# @example Rasterize a dataset (for dst_dataset).
|
49
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
50
|
+
# dst_dataset = GDAL::Dataset.open("destination.tif", "w")
|
51
|
+
# options = GDAL::Utils::Rasterize::Options.new(options: ["-ts", "10", "10"])
|
52
|
+
#
|
53
|
+
# GDAL::Utils::Rasterize.perform(dst_dataset: dst_dataset, src_dataset: src_dataset, options: options)
|
54
|
+
#
|
55
|
+
# # You must close the dataset when you are done with it.
|
56
|
+
# dst_dataset.close
|
57
|
+
# src_dataset.close
|
58
|
+
#
|
59
|
+
# @param dst_dataset_path [String] The path to the destination dataset.
|
60
|
+
# @param dst_dataset [GDAL::Dataset] The destination dataset.
|
61
|
+
# @param src_dataset [OGR::DataSource] The source dataset.
|
62
|
+
# @param options [GDAL::Utils::Rasterize::Options] Options.
|
63
|
+
# @yield [GDAL::Dataset] The destination dataset.
|
64
|
+
# @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
|
65
|
+
def self.perform(src_dataset:, dst_dataset: nil, dst_dataset_path: nil, options: Options.new, &block)
|
66
|
+
if dst_dataset
|
67
|
+
for_dataset(dst_dataset: dst_dataset, src_dataset: src_dataset, options: options)
|
68
|
+
else
|
69
|
+
for_dataset_path(dst_dataset_path: dst_dataset_path, src_dataset: src_dataset, options: options, &block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.for_dataset(dst_dataset:, src_dataset:, options: Options.new)
|
74
|
+
result_dataset_ptr(dst_dataset: dst_dataset, src_dataset: src_dataset, options: options)
|
75
|
+
|
76
|
+
# Return the input dataset as the output dataset (dataset is modified in place).
|
77
|
+
dst_dataset
|
78
|
+
end
|
79
|
+
private_class_method :for_dataset
|
80
|
+
|
81
|
+
def self.for_dataset_path(dst_dataset_path:, src_dataset:, options: Options.new, &block)
|
82
|
+
dst_dataset_ptr = result_dataset_ptr(
|
83
|
+
dst_dataset_path: dst_dataset_path, src_dataset: src_dataset, options: options
|
84
|
+
)
|
85
|
+
|
86
|
+
::GDAL::Dataset.open(dst_dataset_ptr, "w", &block)
|
87
|
+
end
|
88
|
+
private_class_method :for_dataset_path
|
89
|
+
|
90
|
+
def self.result_dataset_ptr(src_dataset:, dst_dataset_path: nil, dst_dataset: nil, options: Options.new)
|
91
|
+
result_code_ptr = ::FFI::MemoryPointer.new(:int)
|
92
|
+
dst_dataset_ptr = ::FFI::GDAL::Utils.GDALRasterize(
|
93
|
+
dst_dataset_path,
|
94
|
+
dst_dataset&.c_pointer,
|
95
|
+
src_dataset.c_pointer,
|
96
|
+
options.c_pointer,
|
97
|
+
result_code_ptr
|
98
|
+
)
|
99
|
+
success = result_code_ptr.read_int.zero?
|
100
|
+
|
101
|
+
raise ::GDAL::Error, "GDALRasterize failed." if dst_dataset_ptr.null? || !success
|
102
|
+
|
103
|
+
dst_dataset_ptr
|
104
|
+
end
|
105
|
+
private_class_method :result_dataset_ptr
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GDAL
|
4
|
+
module Utils
|
5
|
+
class Translate
|
6
|
+
# Ruby wrapper for GDALTranslateOptions C API (options for gdal_translate utility).
|
7
|
+
#
|
8
|
+
# @see GDAL::Utils::Translate
|
9
|
+
# @see https://gdal.org/programs/gdal_translate.html gdal_translate utility documentation.
|
10
|
+
class Options
|
11
|
+
# @private
|
12
|
+
class AutoPointer < ::FFI::AutoPointer
|
13
|
+
# @param pointer [FFI::Pointer]
|
14
|
+
def self.release(pointer)
|
15
|
+
return unless pointer && !pointer.null?
|
16
|
+
|
17
|
+
::FFI::GDAL::Utils.GDALTranslateOptionsFree(pointer)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [AutoPointer] C pointer to the GDALTranslateOptions.
|
22
|
+
attr_reader :c_pointer
|
23
|
+
|
24
|
+
# @return [Array<String>] The options.
|
25
|
+
attr_reader :options
|
26
|
+
|
27
|
+
# Create a new instance.
|
28
|
+
#
|
29
|
+
# @see https://gdal.org/programs/gdal_translate.html
|
30
|
+
# List of available options could be found in gdal_translate utility documentation.
|
31
|
+
#
|
32
|
+
# @example Create a new instance.
|
33
|
+
# options = GDAL::Utils::Translate::Options.new(options: ["-of", "GTiff", "-co", "COMPRESS=DEFLATE"])
|
34
|
+
#
|
35
|
+
# @param options [Array<String>] The options list.
|
36
|
+
def initialize(options: [])
|
37
|
+
@options = options
|
38
|
+
@string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
|
39
|
+
@c_pointer = AutoPointer.new(options_pointer)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :string_list
|
45
|
+
|
46
|
+
def options_pointer
|
47
|
+
::FFI::GDAL::Utils.GDALTranslateOptionsNew(string_list.c_pointer, nil)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "translate/options"
|
4
|
+
|
5
|
+
module GDAL
|
6
|
+
module Utils
|
7
|
+
# Wrapper for gdal_translate using GDALTranslate C API.
|
8
|
+
#
|
9
|
+
# @see https://gdal.org/programs/gdal_translate.html gdal_translate utility documentation.
|
10
|
+
# @see https://gdal.org/api/gdal_utils.html#gdal__utils_8h_1a1cf5b30de14ccaf847ae7a77bb546b28 GDALTranslate C API.
|
11
|
+
class Translate
|
12
|
+
# Perform the gdal_translate (GDALTranslate) operation.
|
13
|
+
#
|
14
|
+
# @example Translate a dataset.
|
15
|
+
# src_dataset = GDAL::Dataset.open("source.tif", "r")
|
16
|
+
# dataset = GDAL::Utils::Translate.perform(dst_dataset_path: "destination.tif", src_dataset: src_dataset)
|
17
|
+
#
|
18
|
+
# # Do something with the dataset.
|
19
|
+
# puts dataset.raster_x_size
|
20
|
+
#
|
21
|
+
# # You must close the dataset when you are done with it.
|
22
|
+
# dataset.close
|
23
|
+
# src_dataset.close
|
24
|
+
#
|
25
|
+
# @example Translate a dataset with options.
|
26
|
+
# src_dataset = GDAL::Dataset.open("source.tif", "r")
|
27
|
+
# dataset = GDAL::Utils::Translate.perform(
|
28
|
+
# dst_dataset_path: "destination.tif",
|
29
|
+
# src_dataset: src_dataset,
|
30
|
+
# options: GDAL::Utils::Translate::Options.new(options: ["-of", "GTiff", "-co", "COMPRESS=DEFLATE"])
|
31
|
+
# )
|
32
|
+
#
|
33
|
+
# # Do something with the dataset.
|
34
|
+
# puts dataset.raster_x_size
|
35
|
+
#
|
36
|
+
# # You must close the dataset when you are done with it.
|
37
|
+
# dataset.close
|
38
|
+
# src_dataset.close
|
39
|
+
#
|
40
|
+
# @example Translate a dataset using block syntax.
|
41
|
+
# src_dataset = GDAL::Dataset.open("source.tif", "r")
|
42
|
+
# GDAL::Utils::Translate.perform(dst_dataset_path: "destination.tif", src_dataset: src_dataset) do |dataset|
|
43
|
+
# # Do something with the dataset.
|
44
|
+
# puts dataset.raster_x_size
|
45
|
+
#
|
46
|
+
# # Dataset will be closed automatically.
|
47
|
+
# end
|
48
|
+
# src_dataset.close
|
49
|
+
#
|
50
|
+
# @param dst_dataset_path [String] The path to the destination dataset.
|
51
|
+
# @param src_dataset [GDAL::Dataset] The source dataset.
|
52
|
+
# @param options [GDAL::Utils::Translate::Options] Options.
|
53
|
+
# @yield [GDAL::Dataset] The destination dataset.
|
54
|
+
# @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
|
55
|
+
# @raise [GDAL::Error] If the operation fails.
|
56
|
+
def self.perform(dst_dataset_path:, src_dataset:, options: Options.new, &block)
|
57
|
+
result_code_ptr = ::FFI::MemoryPointer.new(:int)
|
58
|
+
dst_dataset_ptr = ::FFI::GDAL::Utils.GDALTranslate(
|
59
|
+
dst_dataset_path,
|
60
|
+
src_dataset.c_pointer,
|
61
|
+
options.c_pointer,
|
62
|
+
result_code_ptr
|
63
|
+
)
|
64
|
+
success = result_code_ptr.read_int.zero?
|
65
|
+
|
66
|
+
raise ::GDAL::Error, "GDALTranslate failed." if dst_dataset_ptr.null? || !success
|
67
|
+
|
68
|
+
::GDAL::Dataset.open(dst_dataset_ptr, "w", &block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GDAL
|
4
|
+
module Utils
|
5
|
+
class VectorTranslate
|
6
|
+
# Ruby wrapper for GDALVectorTranslateOptions C API (options for ogr2ogr utility).
|
7
|
+
#
|
8
|
+
# @see GDAL::Utils::VectorTranslate
|
9
|
+
# @see https://gdal.org/programs/ogr2ogr.html ogr2ogr utility documentation.
|
10
|
+
class Options
|
11
|
+
# @private
|
12
|
+
class AutoPointer < ::FFI::AutoPointer
|
13
|
+
# @param pointer [FFI::Pointer]
|
14
|
+
def self.release(pointer)
|
15
|
+
return unless pointer && !pointer.null?
|
16
|
+
|
17
|
+
::FFI::GDAL::Utils.GDALVectorTranslateOptionsFree(pointer)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [AutoPointer] C pointer to the GDALVectorTranslateOptions.
|
22
|
+
attr_reader :c_pointer
|
23
|
+
|
24
|
+
# @return [Array<String>] The options.
|
25
|
+
attr_reader :options
|
26
|
+
|
27
|
+
# Create a new instance.
|
28
|
+
#
|
29
|
+
# @see https://gdal.org/programs/ogr2ogr.html
|
30
|
+
# List of available options could be found in ogr2ogr utility documentation.
|
31
|
+
#
|
32
|
+
# @example Create a new instance.
|
33
|
+
# options = GDAL::Utils::VectorTranslate::Options.new(options: ["-overwrite", "-nlt", "MULTIPOLYGON"])
|
34
|
+
#
|
35
|
+
# @param options [Array<String>] The options list.
|
36
|
+
def initialize(options: [])
|
37
|
+
@options = options
|
38
|
+
@string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
|
39
|
+
@c_pointer = AutoPointer.new(options_pointer)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :string_list
|
45
|
+
|
46
|
+
def options_pointer
|
47
|
+
::FFI::GDAL::Utils.GDALVectorTranslateOptionsNew(string_list.c_pointer, nil)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "vector_translate/options"
|
4
|
+
|
5
|
+
module GDAL
|
6
|
+
module Utils
|
7
|
+
# Wrapper for ogr2ogr using GDALVectorTranslate C API.
|
8
|
+
#
|
9
|
+
# @see https://gdal.org/programs/ogr2ogr.html ogr2ogr utility documentation.
|
10
|
+
# @see https://gdal.org/api/gdal_utils.html#_CPPv419GDALVectorTranslatePKc12GDALDatasetHiP12GDALDatasetHPK26GDALVectorTranslateOptionsPi
|
11
|
+
# GDALVectorTranslate C API.
|
12
|
+
class VectorTranslate
|
13
|
+
# Perform the ogr2ogr (GDALVectorTranslate) operation.
|
14
|
+
#
|
15
|
+
# @example Translate a vector dataset (for dst_dataset_path).
|
16
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
17
|
+
# dataset = GDAL::Utils::VectorTranslate.perform(
|
18
|
+
# dst_dataset_path: "destination.geojson",
|
19
|
+
# src_datasets: [src_dataset]
|
20
|
+
# )
|
21
|
+
#
|
22
|
+
# # Do something with the dataset.
|
23
|
+
# puts dataset.layer(0).name
|
24
|
+
#
|
25
|
+
# # You must close the dataset when you are done with it.
|
26
|
+
# dataset.close
|
27
|
+
# src_dataset.close
|
28
|
+
#
|
29
|
+
# @example Translate a vector dataset with options (for dst_dataset_path).
|
30
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
31
|
+
# dataset = GDAL::Utils::VectorTranslate.perform(
|
32
|
+
# dst_dataset_path: "destination.geojson",
|
33
|
+
# src_datasets: [src_dataset],
|
34
|
+
# options: GDAL::Utils::VectorTranslate::Options.new(options: ["-nlt", "MULTIPOLYGON"])
|
35
|
+
# )
|
36
|
+
#
|
37
|
+
# # Do something with the dataset.
|
38
|
+
# puts dataset.layer(0).name
|
39
|
+
#
|
40
|
+
# # You must close the dataset when you are done with it.
|
41
|
+
# dataset.close
|
42
|
+
# src_dataset.close
|
43
|
+
#
|
44
|
+
# @example Translate a vector dataset using block syntax (for dst_dataset_path).
|
45
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
46
|
+
# GDAL::Utils::VectorTranslate.perform(
|
47
|
+
# dst_dataset_path: "destination.geojson",
|
48
|
+
# src_datasets: [src_dataset]
|
49
|
+
# ) do |dataset|
|
50
|
+
# # Do something with the dataset.
|
51
|
+
# puts dataset.layer(0).name
|
52
|
+
#
|
53
|
+
# # Dataset will be closed automatically.
|
54
|
+
# end
|
55
|
+
# src_dataset.close
|
56
|
+
#
|
57
|
+
# @example Translate a vector dataset (for dst_dataset).
|
58
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
59
|
+
# dst_dataset = OGR::DataSource.open("destination.geojson", "w")
|
60
|
+
#
|
61
|
+
# GDAL::Utils::VectorTranslate.perform(dst_dataset: dst_dataset, src_datasets: [src_dataset])
|
62
|
+
#
|
63
|
+
# # You must close the dataset when you are done with it.
|
64
|
+
# dst_dataset.close
|
65
|
+
# src_dataset.close
|
66
|
+
#
|
67
|
+
# @example Translate a vector dataset with options (for dst_dataset).
|
68
|
+
# src_dataset = OGR::DataSource.open("source.shp", "r")
|
69
|
+
# dst_dataset = OGR::DataSource.open("destination.geojson", "w")
|
70
|
+
#
|
71
|
+
# GDAL::Utils::VectorTranslate.perform(
|
72
|
+
# dst_dataset: dst_dataset,
|
73
|
+
# src_datasets: [src_dataset],
|
74
|
+
# options: GDAL::Utils::VectorTranslate::Options.new(options: ["-nlt", "MULTIPOLYGON"])
|
75
|
+
# )
|
76
|
+
#
|
77
|
+
# # You must close the dataset when you are done with it.
|
78
|
+
# dst_dataset.close
|
79
|
+
# src_dataset.close
|
80
|
+
#
|
81
|
+
# @param dst_dataset_path [String] The path to the destination dataset.
|
82
|
+
# @param dst_dataset [OGR::DataSource] The destination dataset.
|
83
|
+
# @param src_datasets [Array<OGR::DataSource>] The source datasets.
|
84
|
+
# @param options [GDAL::Utils::VectorTranslate::Options] Options.
|
85
|
+
# @yield [OGR::DataSource] The destination dataset.
|
86
|
+
# @return [OGR::DataSource] The destination dataset (only if block is not specified; dataset must be closed).
|
87
|
+
def self.perform(dst_dataset: nil, dst_dataset_path: nil, src_datasets: [], options: Options.new, &block)
|
88
|
+
if dst_dataset
|
89
|
+
for_dataset(dst_dataset: dst_dataset, src_datasets: src_datasets, options: options)
|
90
|
+
else
|
91
|
+
for_dataset_path(dst_dataset_path: dst_dataset_path, src_datasets: src_datasets, options: options, &block)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.for_dataset(dst_dataset:, src_datasets: [], options: Options.new)
|
96
|
+
result_dataset_ptr(dst_dataset: dst_dataset, src_datasets: src_datasets, options: options)
|
97
|
+
|
98
|
+
# Return the input dataset as the output dataset (dataset is modified in place).
|
99
|
+
dst_dataset
|
100
|
+
end
|
101
|
+
private_class_method :for_dataset
|
102
|
+
|
103
|
+
def self.for_dataset_path(dst_dataset_path:, src_datasets: [], options: Options.new, &block)
|
104
|
+
dst_dataset_ptr = result_dataset_ptr(
|
105
|
+
dst_dataset_path: dst_dataset_path, src_datasets: src_datasets, options: options
|
106
|
+
)
|
107
|
+
|
108
|
+
::OGR::DataSource.open(dst_dataset_ptr, "w", &block)
|
109
|
+
end
|
110
|
+
private_class_method :for_dataset_path
|
111
|
+
|
112
|
+
def self.result_dataset_ptr(dst_dataset_path: nil, dst_dataset: nil, src_datasets: [], options: Options.new)
|
113
|
+
src_dataset_list = ::GDAL::Utils::Helpers::DatasetList.new(datasets: src_datasets)
|
114
|
+
result_code_ptr = ::FFI::MemoryPointer.new(:int)
|
115
|
+
dst_dataset_ptr = ::FFI::GDAL::Utils.GDALVectorTranslate(
|
116
|
+
dst_dataset_path,
|
117
|
+
dst_dataset&.c_pointer,
|
118
|
+
src_dataset_list.count,
|
119
|
+
src_dataset_list.c_pointer,
|
120
|
+
options.c_pointer,
|
121
|
+
result_code_ptr
|
122
|
+
)
|
123
|
+
success = result_code_ptr.read_int.zero?
|
124
|
+
|
125
|
+
raise ::GDAL::Error, "GDALVectorTranslate failed." if dst_dataset_ptr.null? || !success
|
126
|
+
|
127
|
+
dst_dataset_ptr
|
128
|
+
end
|
129
|
+
private_class_method :result_dataset_ptr
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GDAL
|
4
|
+
module Utils
|
5
|
+
class Warp
|
6
|
+
# Ruby wrapper for GDALWarpAppOptions C API (options for ogr2ogr utility).
|
7
|
+
#
|
8
|
+
# @see GDAL::Utils::Warp
|
9
|
+
# @see https://gdal.org/programs/gdalwarp.html gdalwarp utility documentation.
|
10
|
+
class Options
|
11
|
+
# @private
|
12
|
+
class AutoPointer < ::FFI::AutoPointer
|
13
|
+
# @param pointer [FFI::Pointer]
|
14
|
+
def self.release(pointer)
|
15
|
+
return unless pointer && !pointer.null?
|
16
|
+
|
17
|
+
::FFI::GDAL::Utils.GDALWarpAppOptionsFree(pointer)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [AutoPointer] C pointer to the GDALWarpAppOptions.
|
22
|
+
attr_reader :c_pointer
|
23
|
+
|
24
|
+
# @return [Array<String>] The options.
|
25
|
+
attr_reader :options
|
26
|
+
|
27
|
+
# Create a new instance.
|
28
|
+
#
|
29
|
+
# @see https://gdal.org/programs/gdalwarp.html
|
30
|
+
# List of available options could be found in gdalwarp utility documentation.
|
31
|
+
#
|
32
|
+
# @example Create a new instance.
|
33
|
+
# options = GDAL::Utils::Warp::Options.new(options: ["-multi", "-wo", "CUTLINE_ALL_TOUCHED=TRUE"])
|
34
|
+
#
|
35
|
+
# @param options [Array<String>] The options list.
|
36
|
+
def initialize(options: [])
|
37
|
+
@options = options
|
38
|
+
@string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
|
39
|
+
@c_pointer = AutoPointer.new(options_pointer)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :string_list
|
45
|
+
|
46
|
+
def options_pointer
|
47
|
+
::FFI::GDAL::Utils.GDALWarpAppOptionsNew(string_list.c_pointer, nil)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "warp/options"
|
4
|
+
|
5
|
+
module GDAL
|
6
|
+
module Utils
|
7
|
+
# Wrapper for gdalwarp using GDALWarp C API.
|
8
|
+
#
|
9
|
+
# @see https://gdal.org/programs/gdalwarp.html gdalwarp utility documentation.
|
10
|
+
# @see https://gdal.org/api/gdal_utils.html#_CPPv48GDALWarpPKc12GDALDatasetHiP12GDALDatasetHPK18GDALWarpAppOptionsPi
|
11
|
+
# GDALWarp C API.
|
12
|
+
class Warp
|
13
|
+
# Perform the gdalwarp (GDALWarp) operation.
|
14
|
+
#
|
15
|
+
# @example Warp a dataset (for dst_dataset_path).
|
16
|
+
# src_dataset = GDAL::Dataset.open("source.tif", "r")
|
17
|
+
# options = GDAL::Utils::Warp::Options.new(options: ["-t_srs", "EPSG:3857"])
|
18
|
+
#
|
19
|
+
# dataset = GDAL::Utils::Warp.perform(
|
20
|
+
# dst_dataset_path: "destination.tif",
|
21
|
+
# src_datasets: [src_dataset],
|
22
|
+
# options: options
|
23
|
+
# )
|
24
|
+
#
|
25
|
+
# # Do something with the dataset.
|
26
|
+
# puts dataset.raster_x_size
|
27
|
+
#
|
28
|
+
# # You must close the dataset when you are done with it.
|
29
|
+
# dataset.close
|
30
|
+
# src_dataset.close
|
31
|
+
#
|
32
|
+
# @example Warp a dataset (for dst_dataset_path) using block syntax.
|
33
|
+
# src_dataset = GDAL::Dataset.open("source.tif", "r")
|
34
|
+
# options = GDAL::Utils::Warp::Options.new(options: ["-t_srs", "EPSG:3857"])
|
35
|
+
#
|
36
|
+
# GDAL::Utils::Warp.perform(
|
37
|
+
# dst_dataset_path: "destination.tif",
|
38
|
+
# src_datasets: src_dataset,
|
39
|
+
# options: options
|
40
|
+
# ) do |dataset|
|
41
|
+
# # Do something with the dataset.
|
42
|
+
# puts dataset.raster_x_size
|
43
|
+
#
|
44
|
+
# # Dataset will be closed automatically.
|
45
|
+
# end
|
46
|
+
# src_dataset.close
|
47
|
+
#
|
48
|
+
# @example Warp a dataset (for dst_dataset).
|
49
|
+
# src_dataset = GDAL::Dataset.open("source.tif", "r")
|
50
|
+
# dst_dataset = GDAL::Dataset.open("destination.tif", "w") # Dataset with other projection.
|
51
|
+
#
|
52
|
+
# GDAL::Utils::Warp.perform(dst_dataset: dst_dataset, src_datasets: [src_dataset])
|
53
|
+
#
|
54
|
+
# # You must close the dataset when you are done with it.
|
55
|
+
# dst_dataset.close
|
56
|
+
# src_dataset.close
|
57
|
+
#
|
58
|
+
# @param dst_dataset_path [String] The path to the destination dataset.
|
59
|
+
# @param dst_dataset [GDAL::Dataset] The destination dataset.
|
60
|
+
# @param src_datasets [Array<GDAL::Dataset>] The source datasets.
|
61
|
+
# @param options [GDAL::Utils::Warp::Options] Options.
|
62
|
+
# @yield [GDAL::Dataset] The destination dataset.
|
63
|
+
# @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
|
64
|
+
def self.perform(dst_dataset: nil, dst_dataset_path: nil, src_datasets: [], options: Options.new, &block)
|
65
|
+
if dst_dataset
|
66
|
+
for_dataset(dst_dataset: dst_dataset, src_datasets: src_datasets, options: options)
|
67
|
+
else
|
68
|
+
for_dataset_path(dst_dataset_path: dst_dataset_path, src_datasets: src_datasets, options: options, &block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param dst_dataset [GDAL::Dataset] The destination dataset.
|
73
|
+
# @param src_datasets [Array<GDAL::Dataset>] The source datasets.
|
74
|
+
# @param options [GDAL::Utils::Warp::Options] Options.
|
75
|
+
# @return [GDAL::Dataset] The destination dataset (it's the same object as dst_dataset).
|
76
|
+
def self.for_dataset(dst_dataset:, src_datasets: [], options: Options.new)
|
77
|
+
result_dataset_ptr(dst_dataset: dst_dataset, src_datasets: src_datasets, options: options)
|
78
|
+
|
79
|
+
# Return the input dataset as the output dataset (dataset is modified in place).
|
80
|
+
dst_dataset
|
81
|
+
end
|
82
|
+
private_class_method :for_dataset
|
83
|
+
|
84
|
+
# @param dst_dataset_path [String] The path to the destination dataset.
|
85
|
+
# @param src_datasets [Array<GDAL::Dataset>] The source datasets.
|
86
|
+
# @param options [GDAL::Utils::Warp::Options] Options.
|
87
|
+
# @yield [GDAL::Dataset] The destination dataset.
|
88
|
+
# @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
|
89
|
+
def self.for_dataset_path(dst_dataset_path:, src_datasets: [], options: Options.new, &block)
|
90
|
+
dst_dataset_ptr = result_dataset_ptr(
|
91
|
+
dst_dataset_path: dst_dataset_path, src_datasets: src_datasets, options: options
|
92
|
+
)
|
93
|
+
|
94
|
+
::GDAL::Dataset.open(dst_dataset_ptr, "w", &block)
|
95
|
+
end
|
96
|
+
private_class_method :for_dataset_path
|
97
|
+
|
98
|
+
def self.result_dataset_ptr(dst_dataset_path: nil, dst_dataset: nil, src_datasets: [], options: Options.new)
|
99
|
+
src_dataset_list = ::GDAL::Utils::Helpers::DatasetList.new(datasets: src_datasets)
|
100
|
+
result_code_ptr = ::FFI::MemoryPointer.new(:int)
|
101
|
+
dst_dataset_ptr = ::FFI::GDAL::Utils.GDALWarp(
|
102
|
+
dst_dataset_path,
|
103
|
+
dst_dataset&.c_pointer,
|
104
|
+
src_dataset_list.count,
|
105
|
+
src_dataset_list.c_pointer,
|
106
|
+
options.c_pointer,
|
107
|
+
result_code_ptr
|
108
|
+
)
|
109
|
+
success = result_code_ptr.read_int.zero?
|
110
|
+
|
111
|
+
raise ::GDAL::Error, "GDALWarp failed." if dst_dataset_ptr.null? || !success
|
112
|
+
|
113
|
+
dst_dataset_ptr
|
114
|
+
end
|
115
|
+
private_class_method :result_dataset_ptr
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/gdal/utils.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GDAL
|
4
|
+
# Wrappers for the GDAL utilities.
|
5
|
+
#
|
6
|
+
# @see https://gdal.org/programs/index.html GDAL Utils documentation (gdalwarp, gdal_translate, ...).
|
7
|
+
# @see https://gdal.org/api/gdal_utils.html GDAL Utils C API.
|
8
|
+
module Utils
|
9
|
+
# Internal helpers
|
10
|
+
autoload :Helpers, File.expand_path("utils/helpers", __dir__)
|
11
|
+
|
12
|
+
# GDAL Utils
|
13
|
+
autoload :DEM, File.expand_path("utils/dem", __dir__)
|
14
|
+
autoload :Grid, File.expand_path("utils/grid", __dir__)
|
15
|
+
autoload :Nearblack, File.expand_path("utils/nearblack", __dir__)
|
16
|
+
autoload :Rasterize, File.expand_path("utils/rasterize", __dir__)
|
17
|
+
autoload :Info, File.expand_path("utils/info", __dir__)
|
18
|
+
autoload :Translate, File.expand_path("utils/translate", __dir__)
|
19
|
+
autoload :VectorTranslate, File.expand_path("utils/vector_translate", __dir__)
|
20
|
+
autoload :Warp, File.expand_path("utils/warp", __dir__)
|
21
|
+
end
|
22
|
+
end
|
data/lib/gdal/warp_options.rb
CHANGED
@@ -12,7 +12,7 @@ module GDAL
|
|
12
12
|
@destination_dataset = nil
|
13
13
|
|
14
14
|
options.each_key do |k|
|
15
|
-
assign_meth = "#{k}="
|
15
|
+
assign_meth = :"#{k}="
|
16
16
|
|
17
17
|
begin
|
18
18
|
if respond_to?(assign_meth)
|
@@ -175,8 +175,17 @@ module GDAL
|
|
175
175
|
def source_per_band_validity_mask_function=(band_procs)
|
176
176
|
mask_func = FFI::GDAL::Warper::MaskFunc
|
177
177
|
|
178
|
+
mask_func_return_type =
|
179
|
+
if mask_func.respond_to?(:return_type)
|
180
|
+
# `.return_type` is for FFI 1.16.0+;
|
181
|
+
mask_func.return_type
|
182
|
+
else
|
183
|
+
# `.result_type` is for older FFI versions.
|
184
|
+
mask_func.result_type
|
185
|
+
end
|
186
|
+
|
178
187
|
funcs = band_procs.map do |band_proc|
|
179
|
-
FFI::Function.new(
|
188
|
+
FFI::Function.new(mask_func_return_type, mask_func.param_types, band_proc, blocking: true)
|
180
189
|
end
|
181
190
|
|
182
191
|
pointer = FFI::MemoryPointer.new(:pointer, band_procs.length)
|
data/lib/gdal.rb
CHANGED
@@ -37,6 +37,7 @@ module GDAL
|
|
37
37
|
autoload :Options, gdal_require("gdal/options")
|
38
38
|
autoload :RasterAttributeTable, gdal_require("gdal/raster_attribute_table")
|
39
39
|
autoload :RasterBand, gdal_require("gdal/raster_band")
|
40
|
+
autoload :Utils, gdal_require("gdal/utils")
|
40
41
|
end
|
41
42
|
|
42
43
|
require_relative "gdal/exceptions"
|
@@ -130,7 +130,7 @@ module OGR
|
|
130
130
|
# least at this point), it needs to be as fast as possible.
|
131
131
|
each_feature_pointer do |feature_ptr| # rubocop:todo Metrics/BlockLength
|
132
132
|
field_values = field_indices.map.with_index do |j, attribute_index|
|
133
|
-
FFI::OGR::API.send("OGR_F_GetFieldAs#{with_attributes.values[attribute_index].capitalize}", feature_ptr, j)
|
133
|
+
FFI::OGR::API.send(:"OGR_F_GetFieldAs#{with_attributes.values[attribute_index].capitalize}", feature_ptr, j)
|
134
134
|
end
|
135
135
|
|
136
136
|
geom_ptr = FFI::OGR::API.OGR_F_GetGeometryRef(feature_ptr)
|