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
data/test/context_test.rb CHANGED
@@ -1,172 +1,210 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './abstract_test'
4
-
5
- class ContextTest < AbstractTest
6
- def test_create
7
- context = Proj::Context.new
8
- assert(context.to_ptr)
9
- end
10
-
11
- def test_finalize
12
- 100.times do
13
- context = Proj::Context.new
14
- assert(context.to_ptr)
15
- GC.start
16
- end
17
- assert(true)
18
- end
19
-
20
- def test_clone
21
- context = Proj::Context.new
22
- refute(context.use_proj4_init_rules)
23
- context.use_proj4_init_rules = true
24
- assert(context.use_proj4_init_rules)
25
-
26
- clone = context.clone
27
- assert(clone.use_proj4_init_rules)
28
- end
29
-
30
- def test_dup
31
- context = Proj::Context.new
32
- refute(context.use_proj4_init_rules)
33
- context.use_proj4_init_rules = true
34
- assert(context.use_proj4_init_rules)
35
-
36
- clone = context.clone
37
- assert(clone.use_proj4_init_rules)
38
- end
39
-
40
- def test_one_per_thread
41
- context_1 = Proj::Context.current
42
- context_2 = Proj::Context.current
43
- assert_same(context_1, context_2)
44
- end
45
-
46
- def test_search_paths
47
- context = Proj::Context.new
48
- path = File.join(Dir.tmpdir, "temp_proj_dic2")
49
-
50
- begin
51
- File.open(path, 'wb') do |file|
52
- file << "<MY_PIPELINE> +proj=pipeline +step +proj=utm +zone=31 +ellps=GRS80"
53
- end
54
-
55
- # Try to use the pipeline, an error will occur since it is not on the path
56
- error = assert_raises(Proj::Error) do
57
- Proj::Conversion.new("+init=temp_proj_dic2:MY_PIPELINE")
58
- end
59
- assert_equal("Invalid value for an argument", error.to_s)
60
-
61
- # Set the path and try again
62
- context.search_paths = [File.dirname(path)]
63
- conversion = Proj::Conversion.new("+init=temp_proj_dic2:MY_PIPELINE", context)
64
- ensure
65
- File.delete(path)
66
- end
67
- end
68
-
69
- def test_database_path
70
- refute_nil(Proj::Context.current.database_path)
71
- end
72
-
73
- def test_log_level
74
- assert_equal(:PJ_LOG_ERROR, Proj::Context.current.log_level)
75
- end
76
-
77
- def test_set_log_level
78
- context = Proj::Context.new
79
- context.log_level = :PJ_LOG_ERROR
80
- assert_equal(:PJ_LOG_ERROR, context.log_level)
81
- end
82
-
83
- def test_invalid_database_path
84
- context = Proj::Context.new
85
- path = '/wrong'
86
- error = assert_raises(Proj::Error) do
87
- context.database.path = path
88
- end
89
- # TODO - if you run this test on its own you get a useful error message, if you run all tests
90
- # at once you get a useless error message. Not sure what is causing the difference
91
- #assert_match(/No such file or directory|generic error of unknown origin|File not found or invalid/, error.to_s)
92
- assert_equal("Unknown error (code 4096)", error.to_s)
93
- end
94
-
95
- def test_set_log_function
96
- context = Proj::Context.new
97
- called = false
98
-
99
- data = FFI::MemoryPointer.new(:int)
100
- data.write_int(5)
101
-
102
- context.set_log_function(data) do |pointer, int, message|
103
- called = true
104
- refute(pointer.null?)
105
- assert_equal(5, pointer.read_int)
106
- assert_equal(1, int)
107
- assert_equal('proj_context_set_database_path: Open of /wrong failed', message)
108
- end
109
-
110
- begin
111
- context.database.path = '/wrong'
112
- rescue
113
- end
114
-
115
- assert(called)
116
- end
117
-
118
- def test_use_proj4_init_rules
119
- context = Proj::Context.new
120
- refute(context.use_proj4_init_rules)
121
-
122
- context.use_proj4_init_rules = true
123
- assert(context.use_proj4_init_rules)
124
-
125
- context.use_proj4_init_rules = false
126
- refute(context.use_proj4_init_rules)
127
- end
128
-
129
- def test_network_enabled
130
- context = Proj::Context.new
131
- refute(context.network_enabled?)
132
- end
133
-
134
- def test_network_enabled_set
135
- context = Proj::Context.new
136
- refute(context.network_enabled?)
137
-
138
- context.network_enabled = true
139
- assert(context.network_enabled?)
140
-
141
- context.network_enabled = false
142
- refute(context.network_enabled?)
143
- end
144
-
145
- def test_url
146
- context = Proj::Context.new
147
- assert_equal("https://cdn.proj.org", context.url)
148
- end
149
-
150
- def test_url_set
151
- context = Proj::Context.new
152
- assert_equal("https://cdn.proj.org", context.url)
153
-
154
- context.url = "https://cdn.proj.org/changed"
155
- assert_equal("https://cdn.proj.org/changed", context.url)
156
-
157
- context.url = "https://cdn.proj.org"
158
- assert_equal("https://cdn.proj.org", context.url)
159
- end
160
-
161
- def test_user_directory
162
- context = Proj::Context.new
163
- assert_match(/proj$/, context.user_directory)
164
- end
165
-
166
- def test_wkt_dialect
167
- context = Proj::Context.new
168
-
169
- wkt = 'LOCAL_CS["foo"]'
170
- assert_equal(:PJ_GUESSED_WKT2_2015, context.wkt_dialect(wkt))
171
- end
172
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class ContextTest < AbstractTest
6
+ def test_create
7
+ context = Proj::Context.new
8
+ assert(context.to_ptr)
9
+ end
10
+
11
+ def test_finalize
12
+ 100.times do
13
+ context = Proj::Context.new
14
+ assert(context.to_ptr)
15
+ GC.start
16
+ end
17
+ assert(true)
18
+ end
19
+
20
+ def test_clone
21
+ context = Proj::Context.new
22
+ refute(context.use_proj4_init_rules)
23
+ context.use_proj4_init_rules = true
24
+ assert(context.use_proj4_init_rules)
25
+
26
+ clone = context.clone
27
+ assert(clone.use_proj4_init_rules)
28
+ end
29
+
30
+ def test_dup
31
+ context = Proj::Context.new
32
+ refute(context.use_proj4_init_rules)
33
+ context.use_proj4_init_rules = true
34
+ assert(context.use_proj4_init_rules)
35
+
36
+ clone = context.clone
37
+ assert(clone.use_proj4_init_rules)
38
+ end
39
+
40
+ def test_one_per_thread
41
+ context_1 = Proj::Context.current
42
+ context_2 = Proj::Context.current
43
+ assert_same(context_1, context_2)
44
+ end
45
+
46
+ def test_search_paths
47
+ context = Proj::Context.new
48
+ path = File.join(Dir.tmpdir, "temp_proj_dic2")
49
+
50
+ begin
51
+ File.open(path, 'wb') do |file|
52
+ file << "<MY_PIPELINE> +proj=pipeline +step +proj=utm +zone=31 +ellps=GRS80"
53
+ end
54
+
55
+ # Try to use the pipeline, an error will occur since it is not on the path
56
+ error = assert_raises(Proj::Error) do
57
+ Proj::Conversion.new("+init=temp_proj_dic2:MY_PIPELINE", context)
58
+ end
59
+ assert_equal("Invalid value for an argument", error.to_s)
60
+
61
+ # Set the path and try again
62
+ context.search_paths = [File.dirname(path)]
63
+ conversion = Proj::Conversion.new("+init=temp_proj_dic2:MY_PIPELINE", context)
64
+ assert(conversion)
65
+ ensure
66
+ File.delete(path)
67
+ end
68
+ end
69
+
70
+ def test_database_path
71
+ refute_nil(Proj::Context.current.database.path)
72
+ end
73
+
74
+ def test_log_level
75
+ assert_equal(:PJ_LOG_ERROR, Proj::Context.current.log_level)
76
+ end
77
+
78
+ def test_set_log_level
79
+ context = Proj::Context.new
80
+ context.log_level = :PJ_LOG_ERROR
81
+ assert_equal(:PJ_LOG_ERROR, context.log_level)
82
+ end
83
+
84
+ def test_invalid_database_path
85
+ context = Proj::Context.new
86
+ path = '/wrong'
87
+ error = assert_raises(Proj::Error) do
88
+ context.database.path = path
89
+ end
90
+ # TODO - if you run this test on its own you get a useful error message, if you run all tests
91
+ # at once you get a useless error message. Not sure what is causing the difference
92
+ #assert_match(/No such file or directory|generic error of unknown origin|File not found or invalid/, error.to_s)
93
+ assert_equal("Unknown error (code 4096)", error.to_s)
94
+ end
95
+
96
+ def test_set_log_function
97
+ context = Proj::Context.new
98
+ called = false
99
+
100
+ data = FFI::MemoryPointer.new(:int)
101
+ data.write_int(5)
102
+
103
+ context.set_log_function(data) do |pointer, int, message|
104
+ called = true
105
+ refute(pointer.null?)
106
+ assert_equal(5, pointer.read_int)
107
+ assert_equal(1, int)
108
+ assert_equal('proj_context_set_database_path: Open of /wrong failed', message)
109
+ end
110
+
111
+ begin
112
+ context.database.path = '/wrong'
113
+ rescue
114
+ end
115
+
116
+ assert(called)
117
+ end
118
+
119
+ def test_set_log_function_retains_callback_and_data_pointer
120
+ context = Proj::Context.new
121
+ data = FFI::MemoryPointer.new(:int)
122
+ callback = proc { |_pointer, _int, _message| }
123
+
124
+ context.set_log_function(data, &callback)
125
+
126
+ assert_same(callback, context.instance_variable_get(:@log_function))
127
+ assert_same(data, context.instance_variable_get(:@log_data_pointer))
128
+ end
129
+
130
+ def test_use_proj4_init_rules
131
+ context = Proj::Context.new
132
+ refute(context.use_proj4_init_rules)
133
+
134
+ context.use_proj4_init_rules = true
135
+ assert(context.use_proj4_init_rules)
136
+
137
+ context.use_proj4_init_rules = false
138
+ refute(context.use_proj4_init_rules)
139
+ end
140
+
141
+ def test_network_enabled
142
+ context = Proj::Context.new
143
+ refute(context.network_enabled?)
144
+ end
145
+
146
+ def test_network_enabled_set
147
+ context = Proj::Context.new
148
+ refute(context.network_enabled?)
149
+
150
+ context.network_enabled = true
151
+ assert(context.network_enabled?)
152
+
153
+ context.network_enabled = false
154
+ refute(context.network_enabled?)
155
+ end
156
+
157
+ def test_url
158
+ context = Proj::Context.new
159
+ assert_equal("https://cdn.proj.org", context.url)
160
+ end
161
+
162
+ def test_url_set
163
+ context = Proj::Context.new
164
+ assert_equal("https://cdn.proj.org", context.url)
165
+
166
+ context.url = "https://cdn.proj.org/changed"
167
+ assert_equal("https://cdn.proj.org/changed", context.url)
168
+
169
+ context.url = "https://cdn.proj.org"
170
+ assert_equal("https://cdn.proj.org", context.url)
171
+ end
172
+
173
+ def test_ca_bundle_path
174
+ context = Proj::Context.new
175
+ context.ca_bundle_path = "/some/path/to/ca-bundle.crt"
176
+ end
177
+
178
+ def test_user_directory
179
+ context = Proj::Context.new
180
+ assert_match(/proj$/, context.user_directory)
181
+ end
182
+
183
+ if Proj::Api::PROJ_VERSION >= Gem::Version.new('9.5.0')
184
+ def test_set_user_writable_directory
185
+ context = Proj::Context.new
186
+ dir = File.join(Dir.tmpdir, "proj4rb-test-#{$$}")
187
+ begin
188
+ context.set_user_writable_directory(dir, create: true)
189
+ assert(Dir.exist?(dir))
190
+ ensure
191
+ Dir.rmdir(dir) if Dir.exist?(dir)
192
+ end
193
+ end
194
+ end
195
+
196
+ def test_wkt_dialect
197
+ context = Proj::Context.new
198
+
199
+ wkt = 'LOCAL_CS["foo"]'
200
+ assert_includes([:PJ_GUESSED_WKT2_2015, :PJ_GUESSED_WKT1_GDAL], context.wkt_dialect(wkt))
201
+ end
202
+
203
+ def test_destroy
204
+ context = Proj::Context.new
205
+ refute(context.to_ptr.null?)
206
+
207
+ context.destroy
208
+ assert(context.to_ptr.null?)
209
+ end
210
+ end
@@ -0,0 +1,11 @@
1
+ require_relative './abstract_test'
2
+
3
+ class ContextValidationTest < AbstractTest
4
+ def test_create_engineering_requires_proj_context
5
+ error = assert_raises(TypeError) do
6
+ Proj::Crs.create_engineering("EPSG", name: "4807")
7
+ end
8
+
9
+ assert_equal("expected Proj::Context, got String", error.message)
10
+ end
11
+ end