proj4rb 4.1.0 → 5.0.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -0
  3. data/Gemfile +4 -4
  4. data/README.md +53 -0
  5. data/lib/api/proj.rb +750 -0
  6. data/lib/api/proj_experimental.rb +7 -0
  7. data/lib/api/proj_ffi.rb +47 -0
  8. data/lib/api/proj_version.rb +26 -0
  9. data/lib/examples/axis_order_normalization.rb +13 -0
  10. data/lib/examples/batch_transformation.rb +25 -0
  11. data/lib/examples/context_logging.rb +26 -0
  12. data/lib/examples/crs_identification.rb +18 -0
  13. data/lib/examples/database_query.rb +27 -0
  14. data/lib/examples/geodetic_distance.rb +38 -0
  15. data/lib/examples/geodetic_to_projected.rb +18 -0
  16. data/lib/examples/operation_factory_context.rb +19 -0
  17. data/lib/examples/pipeline_operator.rb +21 -0
  18. data/lib/examples/promote_demote_3d.rb +23 -0
  19. data/lib/examples/serialization_formats.rb +17 -0
  20. data/lib/examples/transform_bounds.rb +18 -0
  21. data/lib/examples/transformation_with_area.rb +18 -0
  22. data/lib/proj/area.rb +74 -74
  23. data/lib/proj/axis_info.rb +44 -44
  24. data/lib/proj/bounds.rb +22 -0
  25. data/lib/proj/bounds3d.rb +45 -0
  26. data/lib/proj/context.rb +57 -23
  27. data/lib/proj/conversion.rb +94 -91
  28. data/lib/proj/coordinate.rb +304 -281
  29. data/lib/proj/coordinate_metadata.rb +38 -0
  30. data/lib/proj/coordinate_operation_mixin.rb +464 -381
  31. data/lib/proj/coordinate_system.rb +143 -137
  32. data/lib/proj/crs.rb +688 -672
  33. data/lib/proj/crs_info.rb +47 -47
  34. data/lib/proj/database.rb +310 -305
  35. data/lib/proj/datum.rb +32 -32
  36. data/lib/proj/datum_ensemble.rb +34 -34
  37. data/lib/proj/domain.rb +82 -0
  38. data/lib/proj/ellipsoid.rb +77 -77
  39. data/lib/proj/error.rb +7 -8
  40. data/lib/proj/file_api_callbacks.rb +165 -0
  41. data/lib/proj/grid.rb +121 -121
  42. data/lib/proj/grid_cache.rb +65 -64
  43. data/lib/proj/grid_info.rb +19 -19
  44. data/lib/proj/life_span.rb +21 -0
  45. data/lib/proj/network_api_callbacks.rb +86 -0
  46. data/lib/proj/operation.rb +66 -42
  47. data/lib/proj/operation_factory_context.rb +4 -2
  48. data/lib/proj/options.rb +41 -0
  49. data/lib/proj/parameter.rb +37 -37
  50. data/lib/proj/parameters.rb +106 -107
  51. data/lib/proj/pj_axis_description.rb +26 -0
  52. data/lib/proj/pj_object.rb +602 -670
  53. data/lib/proj/pj_objects.rb +45 -45
  54. data/lib/proj/pj_param_description.rb +28 -0
  55. data/lib/proj/prime_meridian.rb +65 -65
  56. data/lib/proj/projection.rb +1771 -698
  57. data/lib/proj/session.rb +2 -0
  58. data/lib/proj/transformation.rb +102 -102
  59. data/lib/proj/unit.rb +81 -108
  60. data/lib/proj.rb +10 -3
  61. data/lib/proj4.rb +5 -5
  62. data/proj4rb.gemspec +10 -5
  63. data/test/abstract_test.rb +7 -28
  64. data/test/context_test.rb +210 -172
  65. data/test/context_validation_test.rb +11 -0
  66. data/test/conversion_test.rb +376 -368
  67. data/test/coordinate_metadata_test.rb +34 -0
  68. data/test/coordinate_system_test.rb +162 -144
  69. data/test/coordinate_test.rb +289 -34
  70. data/test/crs_test.rb +1112 -1072
  71. data/test/database_test.rb +407 -359
  72. data/test/datum_ensemble_test.rb +64 -64
  73. data/test/datum_test.rb +61 -54
  74. data/test/domain_test.rb +72 -0
  75. data/test/ellipsoid_test.rb +80 -80
  76. data/test/examples_test.rb +149 -0
  77. data/test/file_api_example.rb +58 -0
  78. data/test/file_api_test.rb +74 -66
  79. data/test/grid_cache_test.rb +72 -72
  80. data/test/grid_test.rb +126 -141
  81. data/test/network_api_example.rb +48 -0
  82. data/test/network_api_test.rb +33 -45
  83. data/test/operation_factory_context_test.rb +225 -201
  84. data/test/operation_test.rb +40 -29
  85. data/test/options_test.rb +17 -0
  86. data/test/parameters_test.rb +86 -40
  87. data/test/pj_object_test.rb +221 -179
  88. data/test/prime_meridian_test.rb +75 -75
  89. data/test/proj_test.rb +58 -58
  90. data/test/projection_test.rb +680 -650
  91. data/test/session_test.rb +78 -77
  92. data/test/transformation_test.rb +238 -210
  93. data/test/unit_test.rb +114 -76
  94. metadata +45 -31
  95. data/ChangeLog +0 -89
  96. data/README.rdoc +0 -207
  97. data/lib/api/api.rb +0 -117
  98. data/lib/api/api_5_0.rb +0 -338
  99. data/lib/api/api_5_1.rb +0 -7
  100. data/lib/api/api_5_2.rb +0 -5
  101. data/lib/api/api_6_0.rb +0 -146
  102. data/lib/api/api_6_1.rb +0 -5
  103. data/lib/api/api_6_2.rb +0 -10
  104. data/lib/api/api_6_3.rb +0 -6
  105. data/lib/api/api_7_0.rb +0 -69
  106. data/lib/api/api_7_1.rb +0 -73
  107. data/lib/api/api_7_2.rb +0 -14
  108. data/lib/api/api_8_0.rb +0 -6
  109. data/lib/api/api_8_1.rb +0 -24
  110. data/lib/api/api_8_2.rb +0 -6
  111. data/lib/api/api_9_1.rb +0 -7
  112. data/lib/api/api_9_2.rb +0 -9
  113. data/lib/api/api_experimental.rb +0 -201
  114. data/lib/proj/file_api.rb +0 -166
  115. data/lib/proj/network_api.rb +0 -92
@@ -0,0 +1,58 @@
1
+ module Proj
2
+ # The FileApiExample class is a simple file api implementation that delegates
3
+ # to Ruby's built-in File operations.
4
+ class FileApiExample
5
+ include FileApiCallbacks
6
+
7
+ def initialize(context)
8
+ install_callbacks(context)
9
+ end
10
+
11
+ def open(path, access_mode)
12
+ case access_mode
13
+ when :PROJ_OPEN_ACCESS_READ_ONLY
14
+ File.open(path, mode: 'rb') if File.exist?(path)
15
+ when :PROJ_OPEN_ACCESS_READ_UPDATE
16
+ File.exist?(path) ? File.open(path, mode: 'r+b') : File.open(path, mode: 'w+b')
17
+ when :PROJ_OPEN_ACCESS_CREATE
18
+ File.open(path, mode: 'w+b')
19
+ end
20
+ end
21
+
22
+ def read(file, size_bytes)
23
+ file.read(size_bytes)
24
+ end
25
+
26
+ def write(file, data)
27
+ file.write(data)
28
+ end
29
+
30
+ def seek(file, offset, whence)
31
+ file.seek(offset, whence)
32
+ end
33
+
34
+ def tell(file)
35
+ file.tell
36
+ end
37
+
38
+ def close(file)
39
+ file.close
40
+ end
41
+
42
+ def exists(path)
43
+ File.exist?(path)
44
+ end
45
+
46
+ def mkdir(path)
47
+ Dir.mkdir(path)
48
+ end
49
+
50
+ def unlink(path)
51
+ File.unlink(path) if File.exist?(path)
52
+ end
53
+
54
+ def rename(original_path, new_path)
55
+ File.rename(original_path, new_path)
56
+ end
57
+ end
58
+ end
@@ -1,66 +1,74 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './abstract_test'
4
-
5
- class FileApiTest < AbstractTest
6
- def setup
7
- super
8
- # Make sure FileAPI callbacks are not GCed
9
- #GC.stress = true
10
- end
11
-
12
- def teardown
13
- super
14
- GC.stress = false
15
- end
16
-
17
-
18
- def test_read
19
- skip "This test causes a segfault due to the way Proj cleans up on shutdown"
20
- context = Proj::Context.new
21
- # Network needs to be on for grid delete to work
22
- context.network_enabled = true
23
-
24
- # Create a grid
25
- grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
26
- grid.delete
27
-
28
- grid.download
29
- assert(grid.downloaded?)
30
- context.network_enabled = false
31
-
32
- # Hook up a custom FileApiImpl
33
- context.set_file_api(Proj::FileApiImpl)
34
-
35
- conversion = Proj::Conversion.new(<<~EOS, context)
36
- +proj=pipeline
37
- +step +proj=unitconvert +xy_in=deg +xy_out=rad
38
- +step +proj=vgridshift +grids=dk_sdfe_dvr90.tif +multiplier=1
39
- +step +proj=unitconvert +xy_in=rad +xy_out=deg
40
- EOS
41
-
42
- coord = Proj::Coordinate.new(lon: 12, lat: 56, z: 0)
43
- new_coord = conversion.forward(coord)
44
- assert_in_delta(12, new_coord.lon)
45
- assert_in_delta(56, new_coord.lat)
46
- assert_in_delta(36.5909996032715, new_coord.z, 1e-10)
47
-
48
- context.destroy
49
- end
50
-
51
- def test_write
52
- skip "This test causes a segfault due to the way Proj cleans up on shutdown"
53
-
54
- context = Proj::Context.new
55
- context.network_enabled = true
56
-
57
- # Create a grid
58
- grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
59
- grid.delete
60
-
61
- context.set_file_api(Proj::FileApiImpl)
62
- grid.download
63
-
64
- assert(grid.downloaded?)
65
- end
66
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+ require_relative './file_api_example'
5
+
6
+ class FileApiTest < AbstractTest
7
+ def setup
8
+ super
9
+ # Make sure FileAPI callbacks are not GCed
10
+ GC.stress = true
11
+ end
12
+
13
+ def teardown
14
+ # Clean up downloaded grid so other tests aren't affected
15
+ context = Proj::Context.new
16
+ context.network_enabled = true
17
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
18
+ grid.delete
19
+ super
20
+ GC.stress = false
21
+ end
22
+
23
+
24
+ def test_read
25
+ context = Proj::Context.new
26
+ # Network needs to be on for grid delete to work
27
+ context.network_enabled = true
28
+
29
+ # Create a grid
30
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
31
+ grid.delete
32
+
33
+ grid.download
34
+ assert(grid.downloaded?)
35
+ context.network_enabled = false
36
+
37
+ # Hook up a custom FileApiImpl
38
+ context.set_file_api(Proj::FileApiExample)
39
+
40
+ conversion = Proj::Conversion.new(<<~EOS, context)
41
+ +proj=pipeline
42
+ +step +proj=unitconvert +xy_in=deg +xy_out=rad
43
+ +step +proj=vgridshift +grids=dk_sdfe_dvr90.tif +multiplier=1
44
+ +step +proj=unitconvert +xy_in=rad +xy_out=deg
45
+ EOS
46
+
47
+ coord = Proj::Coordinate.new(lon: 12, lat: 56, z: 0)
48
+ new_coord = conversion.forward(coord)
49
+ assert_in_delta(12, new_coord.lon)
50
+ assert_in_delta(56, new_coord.lat)
51
+ assert_in_delta(36.5909996032715, new_coord.z, 1e-10)
52
+
53
+ # Release the grid file handle so teardown can delete the file (Windows)
54
+ conversion.destroy
55
+ context.destroy
56
+ end
57
+
58
+ def test_write
59
+ context = Proj::Context.new
60
+ context.network_enabled = true
61
+
62
+ # Create a grid
63
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
64
+ grid.delete
65
+
66
+ context.set_file_api(Proj::FileApiExample)
67
+ grid.download
68
+
69
+ assert(grid.downloaded?)
70
+
71
+ # Release the grid file handle so teardown can delete the file (Windows)
72
+ context.destroy
73
+ end
74
+ end
@@ -1,72 +1,72 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './abstract_test'
4
-
5
- class GridCacheTest < AbstractTest
6
- def download(grid)
7
- begin
8
- grid.download
9
- ensure
10
- grid.delete
11
- end
12
- end
13
-
14
- def test_clear
15
- context = Proj::Context.new
16
- context.network_enabled = true
17
- context.cache.enabled = true
18
-
19
- cache_path = File.join(context.user_directory, "cache.db")
20
- context.cache.clear
21
- refute(File.exist?(cache_path))
22
- end
23
-
24
- def test_disable
25
- context = Proj::Context.new
26
- cache_path = File.join(context.user_directory, "cache.db")
27
-
28
- context.network_enabled = true
29
- context.cache.clear
30
- context.cache.enabled = false
31
- refute(File.exist?(cache_path))
32
-
33
- database = Proj::Database.new(context)
34
- grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
35
-
36
- # Download the file to create the cache
37
- download(grid)
38
-
39
- refute(File.exist?(cache_path))
40
- end
41
-
42
- def test_set_path
43
- context = Proj::Context.new
44
- context.network_enabled = true
45
- database = Proj::Database.new(context)
46
- grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
47
-
48
- # Custom path
49
- cache_path = context.cache.path = File.join(Dir.tmpdir, "proj_cache_test.db")
50
- refute(File.exist?(cache_path))
51
-
52
- # Download the file to create the cache
53
- download(grid)
54
-
55
- assert(File.exist?(cache_path))
56
-
57
- context.cache.clear
58
- refute(File.exist?(cache_path))
59
- end
60
-
61
- def test_ttl
62
- context = Proj::Context.new
63
- context.cache.ttl = 60
64
- assert(true)
65
- end
66
-
67
- def test_max_size
68
- context = Proj::Context.new
69
- context.cache.max_size = 100
70
- assert(true)
71
- end
72
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class GridCacheTest < AbstractTest
6
+ def download(grid)
7
+ begin
8
+ grid.download
9
+ ensure
10
+ grid.delete
11
+ end
12
+ end
13
+
14
+ def test_clear
15
+ context = Proj::Context.new
16
+ context.network_enabled = true
17
+ context.cache.enabled = true
18
+
19
+ cache_path = File.join(context.user_directory, "cache.db")
20
+ context.cache.clear
21
+ refute(File.exist?(cache_path))
22
+ end
23
+
24
+ def test_disable
25
+ context = Proj::Context.new
26
+ cache_path = File.join(context.user_directory, "cache.db")
27
+
28
+ context.network_enabled = true
29
+ context.cache.clear
30
+ context.cache.enabled = false
31
+ refute(File.exist?(cache_path))
32
+
33
+ database = Proj::Database.new(context)
34
+ grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
35
+
36
+ # Download the file to create the cache
37
+ download(grid)
38
+
39
+ refute(File.exist?(cache_path))
40
+ end
41
+
42
+ def test_set_path
43
+ context = Proj::Context.new
44
+ context.network_enabled = true
45
+ database = Proj::Database.new(context)
46
+ grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
47
+
48
+ # Custom path
49
+ cache_path = context.cache.path = File.join(Dir.tmpdir, "proj_cache_test.db")
50
+ refute(File.exist?(cache_path))
51
+
52
+ # Download the file to create the cache
53
+ download(grid)
54
+
55
+ assert(File.exist?(cache_path))
56
+
57
+ context.cache.clear
58
+ refute(File.exist?(cache_path))
59
+ end
60
+
61
+ def test_ttl
62
+ context = Proj::Context.new
63
+ context.cache.ttl = 60
64
+ assert(true)
65
+ end
66
+
67
+ def test_max_size
68
+ context = Proj::Context.new
69
+ context.cache.max_size = 100
70
+ assert(true)
71
+ end
72
+ end
data/test/grid_test.rb CHANGED
@@ -1,141 +1,126 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './abstract_test'
4
-
5
- class GridTest < AbstractTest
6
- def test_grid
7
- database = Proj::Database.new(Proj::Context.current)
8
- grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
9
-
10
- assert_equal("au_icsm_GDA94_GDA2020_conformal.tif", grid.name)
11
- assert(grid.full_name.empty?)
12
- assert(grid.package_name.empty?)
13
- assert_equal("https://cdn.proj.org/au_icsm_GDA94_GDA2020_conformal.tif", grid.url.to_s)
14
- assert(grid.downloadable?)
15
- assert(grid.open_license?)
16
- refute(grid.available?)
17
- end
18
-
19
- def test_grid_proj6_name
20
- database = Proj::Database.new(Proj::Context.current)
21
- grid = database.grid("GDA94_GDA2020_conformal.gsb")
22
-
23
- assert_equal("GDA94_GDA2020_conformal.gsb", grid.name)
24
- assert(grid.full_name.empty?)
25
- assert(grid.package_name.empty?)
26
- assert_instance_of(URI::HTTPS, grid.url)
27
- assert_equal("https://cdn.proj.org/au_icsm_GDA94_GDA2020_conformal.tif", grid.url.to_s)
28
- assert(grid.downloadable?)
29
- assert(grid.open_license?)
30
- refute(grid.available?)
31
- end
32
-
33
- def test_downloaded_network_disabled
34
- context = Proj::Context.new
35
- context.network_enabled = false
36
-
37
- grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
38
- refute(grid.downloaded?)
39
- end
40
-
41
- def test_downloaded_network_enabled
42
- context = Proj::Context.new
43
- context.network_enabled = true
44
-
45
- grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
46
- refute(grid.downloaded?)
47
- end
48
-
49
- def test_download
50
- context = Proj::Context.new
51
- context.network_enabled = true
52
-
53
- grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
54
- refute(grid.path)
55
-
56
- begin
57
- grid.download
58
- assert(grid.path)
59
- assert(grid.downloaded?)
60
- ensure
61
- grid.delete
62
- end
63
- end
64
-
65
- def test_download_with_progress
66
- context = Proj::Context.new
67
- context.network_enabled = true
68
-
69
- database = Proj::Database.new(context)
70
- grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
71
-
72
- progress_values = Array.new
73
- begin
74
- downloaded = grid.download do |progress|
75
- progress_values << progress
76
- end
77
- assert(downloaded)
78
- ensure
79
- grid.delete
80
- end
81
-
82
- assert(progress_values.count > 1)
83
- assert(progress_values.include?(1.0))
84
- end
85
-
86
- def test_download_with_progress_cancel
87
- context = Proj::Context.new
88
- context.network_enabled = true
89
-
90
- database = Proj::Database.new(context)
91
- grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
92
-
93
- progress_values = Array.new
94
- begin
95
- downloaded = grid.download do |progress|
96
- progress_values << progress
97
- # Cancel download
98
- false
99
- end
100
- refute(downloaded)
101
- ensure
102
- grid.delete
103
- end
104
-
105
- assert_equal(1, progress_values.count)
106
- refute(progress_values.include?(1.0))
107
- end
108
-
109
- def test_grid_info
110
- context = Proj::Context.new
111
- context.network_enabled = true
112
- grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
113
-
114
- begin
115
- assert(grid.info.filename.empty?)
116
- #assert_equal("dk_sdfe_dvr90.tif", grid.info.gridname)
117
- # assert_equal("gtiff", grid.info.format)
118
- # assert_in_delta(0, grid.info.lower_left[:lam])
119
- # assert_in_delta(0, grid.info.lower_left[:phi])
120
- # assert_in_delta(0, grid.info.upper_right[:lam])
121
- # assert_in_delta(0, grid.info.upper_right[:phi])
122
- # assert_in_delta(0, grid.info.size_lon)
123
- # assert_in_delta(0, grid.info.size_lat)
124
- # assert_in_delta(0, grid.info.cell_size_lon)
125
- # assert_in_delta(0, grid.info.cell_size_lat)
126
- ensure
127
- grid.delete
128
- end
129
- end
130
-
131
- def test_grid_invalid
132
- skip "This test sometimes raises an error and sometimes doesn't."
133
- database = Proj::Database.new(Proj::Context.current)
134
- grid = database.grid("invalid")
135
-
136
- error = assert_raises(Proj::Error) do
137
- grid = database.grid("invalid")
138
- end
139
- assert_equal("Unknown error (code 4096)", error.to_s)
140
- end
141
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class GridTest < AbstractTest
6
+ def test_grid
7
+ database = Proj::Database.new(Proj::Context.current)
8
+ grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
9
+
10
+ assert_equal("au_icsm_GDA94_GDA2020_conformal.tif", grid.name)
11
+ assert(grid.package_name.empty?)
12
+ assert_equal("https://cdn.proj.org/au_icsm_GDA94_GDA2020_conformal.tif", grid.url.to_s)
13
+ assert(grid.downloadable?)
14
+ assert(grid.open_license?)
15
+ end
16
+
17
+ def test_grid_proj6_name
18
+ database = Proj::Database.new(Proj::Context.current)
19
+ grid = database.grid("GDA94_GDA2020_conformal.gsb")
20
+
21
+ assert_equal("GDA94_GDA2020_conformal.gsb", grid.name)
22
+ assert(grid.package_name.empty?)
23
+ assert_instance_of(URI::HTTPS, grid.url)
24
+ assert_equal("https://cdn.proj.org/au_icsm_GDA94_GDA2020_conformal.tif", grid.url.to_s)
25
+ assert(grid.downloadable?)
26
+ assert(grid.open_license?)
27
+ end
28
+
29
+ def test_downloaded_network_disabled
30
+ context = Proj::Context.new
31
+ context.network_enabled = false
32
+
33
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
34
+ refute(grid.downloaded?)
35
+ end
36
+
37
+ def test_downloaded_network_enabled
38
+ context = Proj::Context.new
39
+ context.network_enabled = true
40
+
41
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
42
+ refute(grid.downloaded?)
43
+ end
44
+
45
+ def test_download
46
+ context = Proj::Context.new
47
+ context.network_enabled = true
48
+
49
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
50
+ refute(grid.path)
51
+
52
+ begin
53
+ grid.download
54
+ assert(grid.path)
55
+ assert(grid.downloaded?)
56
+ ensure
57
+ grid.delete
58
+ end
59
+ end
60
+
61
+ def test_download_with_progress
62
+ context = Proj::Context.new
63
+ context.network_enabled = true
64
+
65
+ database = Proj::Database.new(context)
66
+ grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
67
+
68
+ progress_values = Array.new
69
+ begin
70
+ downloaded = grid.download do |progress|
71
+ progress_values << progress
72
+ end
73
+ assert(downloaded)
74
+ ensure
75
+ grid.delete
76
+ end
77
+
78
+ assert(progress_values.count > 1)
79
+ assert(progress_values.include?(1.0))
80
+ end
81
+
82
+ def test_download_with_progress_cancel
83
+ context = Proj::Context.new
84
+ context.network_enabled = true
85
+
86
+ database = Proj::Database.new(context)
87
+ grid = database.grid("au_icsm_GDA94_GDA2020_conformal.tif")
88
+
89
+ progress_values = Array.new
90
+ begin
91
+ downloaded = grid.download do |progress|
92
+ progress_values << progress
93
+ # Cancel download
94
+ false
95
+ end
96
+ refute(downloaded)
97
+ ensure
98
+ grid.delete
99
+ end
100
+
101
+ assert_equal(1, progress_values.count)
102
+ refute(progress_values.include?(1.0))
103
+ end
104
+
105
+ def test_grid_info
106
+ context = Proj::Context.new
107
+ context.network_enabled = true
108
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
109
+
110
+ begin
111
+ assert(grid.info.filename.empty?)
112
+ #assert_equal("dk_sdfe_dvr90.tif", grid.info.gridname)
113
+ # assert_equal("gtiff", grid.info.format)
114
+ # assert_in_delta(0, grid.info.lower_left[:lam])
115
+ # assert_in_delta(0, grid.info.lower_left[:phi])
116
+ # assert_in_delta(0, grid.info.upper_right[:lam])
117
+ # assert_in_delta(0, grid.info.upper_right[:phi])
118
+ # assert_in_delta(0, grid.info.size_lon)
119
+ # assert_in_delta(0, grid.info.size_lat)
120
+ # assert_in_delta(0, grid.info.cell_size_lon)
121
+ # assert_in_delta(0, grid.info.cell_size_lat)
122
+ ensure
123
+ grid.delete
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,48 @@
1
+ require 'net/http'
2
+
3
+ module Proj
4
+ # The NetworkApiExample class is a simple network api implementation that
5
+ # delegates to Ruby's built-in Net::HTTP.
6
+ class NetworkApiExample
7
+ include NetworkApiCallbacks
8
+
9
+ def initialize(context)
10
+ install_callbacks(context)
11
+ end
12
+
13
+ def open(uri, offset, size_to_read)
14
+ http = Net::HTTP.new(uri.host, uri.port)
15
+ if uri.scheme == "https"
16
+ http.use_ssl = true
17
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
18
+ end
19
+ http.start
20
+
21
+ data, response = read_data(http, uri, offset, size_to_read)
22
+ { http: http, uri: uri, response: response, data: data }
23
+ end
24
+
25
+ def close(connection)
26
+ connection[:http].finish
27
+ end
28
+
29
+ def header_value(connection, name)
30
+ connection[:response][name]
31
+ end
32
+
33
+ def read_range(connection, offset, size_to_read)
34
+ data, response = read_data(connection[:http], connection[:uri], offset, size_to_read)
35
+ connection[:response] = response
36
+ data
37
+ end
38
+
39
+ private
40
+
41
+ def read_data(http, uri, offset, size_to_read)
42
+ headers = {"Range": "bytes=#{offset}-#{offset + size_to_read - 1}"}
43
+ request = Net::HTTP::Get.new(uri.request_uri, headers)
44
+ response = http.request(request)
45
+ [response.body.force_encoding("ASCII-8BIT"), response]
46
+ end
47
+ end
48
+ end