ffi-gdal 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +40 -5
- data/Gemfile +4 -2
- data/README.md +35 -0
- 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/layer/extensions.rb +1 -1
- data/lib/ogr/extensions/spatial_reference/extensions.rb +4 -4
- data/lib/ogr/geometry.rb +1 -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)
|
@@ -11,8 +11,8 @@ module OGR
|
|
11
11
|
# @raise [NameError] If the +unit_label+ isn't of a known type.
|
12
12
|
def angular_units=(unit_label)
|
13
13
|
unit_name = unit_label.to_s.upcase
|
14
|
-
unit_label = self.class.const_get("#{unit_name}_LABEL"
|
15
|
-
unit_value = self.class.const_get("RADIAN_TO_#{unit_name}"
|
14
|
+
unit_label = self.class.const_get(:"#{unit_name}_LABEL")
|
15
|
+
unit_value = self.class.const_get(:"RADIAN_TO_#{unit_name}")
|
16
16
|
|
17
17
|
set_angular_units(unit_label, unit_value)
|
18
18
|
rescue NameError
|
@@ -24,8 +24,8 @@ module OGR
|
|
24
24
|
# @raise [NameError] If the +unit_label+ isn't of a known type.
|
25
25
|
def linear_units=(unit_label)
|
26
26
|
unit_name = unit_label.to_s.upcase
|
27
|
-
unit_label = self.class.const_get("#{unit_name}_LABEL"
|
28
|
-
unit_value = self.class.const_get("METER_TO_#{unit_name}"
|
27
|
+
unit_label = self.class.const_get(:"#{unit_name}_LABEL")
|
28
|
+
unit_value = self.class.const_get(:"METER_TO_#{unit_name}")
|
29
29
|
|
30
30
|
set_linear_units(unit_label, unit_value)
|
31
31
|
rescue NameError
|