proj4rb 3.0.0 → 4.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +26 -15
  3. data/README.rdoc +82 -44
  4. data/Rakefile +27 -27
  5. data/lib/api/api.rb +96 -118
  6. data/lib/api/api_5_0.rb +331 -300
  7. data/lib/api/api_5_1.rb +6 -6
  8. data/lib/api/api_5_2.rb +4 -4
  9. data/lib/api/api_6_0.rb +116 -14
  10. data/lib/api/api_6_1.rb +4 -4
  11. data/lib/api/api_6_2.rb +9 -6
  12. data/lib/api/api_6_3.rb +6 -0
  13. data/lib/api/api_7_0.rb +68 -0
  14. data/lib/api/api_7_1.rb +73 -0
  15. data/lib/api/api_7_2.rb +14 -0
  16. data/lib/api/api_8_0.rb +6 -0
  17. data/lib/api/api_8_1.rb +24 -0
  18. data/lib/api/api_8_2.rb +6 -0
  19. data/lib/api/api_9_1.rb +7 -0
  20. data/lib/api/api_9_2.rb +9 -0
  21. data/lib/api/api_experimental.rb +196 -0
  22. data/lib/proj/area.rb +73 -32
  23. data/lib/proj/axis_info.rb +44 -0
  24. data/lib/proj/bounds.rb +13 -0
  25. data/lib/proj/context.rb +174 -28
  26. data/lib/proj/conversion.rb +92 -0
  27. data/lib/proj/coordinate.rb +281 -197
  28. data/lib/proj/coordinate_operation_mixin.rb +381 -0
  29. data/lib/proj/coordinate_system.rb +137 -0
  30. data/lib/proj/crs.rb +672 -204
  31. data/lib/proj/crs_info.rb +47 -0
  32. data/lib/proj/database.rb +305 -0
  33. data/lib/proj/datum.rb +32 -0
  34. data/lib/proj/datum_ensemble.rb +34 -0
  35. data/lib/proj/ellipsoid.rb +77 -41
  36. data/lib/proj/error.rb +62 -9
  37. data/lib/proj/file_api.rb +166 -0
  38. data/lib/proj/grid.rb +121 -0
  39. data/lib/proj/grid_cache.rb +64 -0
  40. data/lib/proj/grid_info.rb +19 -0
  41. data/lib/proj/network_api.rb +92 -0
  42. data/lib/proj/operation.rb +42 -42
  43. data/lib/proj/operation_factory_context.rb +136 -0
  44. data/lib/proj/parameter.rb +38 -0
  45. data/lib/proj/parameters.rb +106 -0
  46. data/lib/proj/pj_object.rb +670 -80
  47. data/lib/proj/pj_objects.rb +44 -0
  48. data/lib/proj/prime_meridian.rb +65 -39
  49. data/lib/proj/projection.rb +698 -207
  50. data/lib/proj/session.rb +46 -0
  51. data/lib/proj/strings.rb +32 -0
  52. data/lib/proj/transformation.rb +101 -60
  53. data/lib/proj/unit.rb +108 -53
  54. data/lib/proj.rb +110 -9
  55. data/proj4rb.gemspec +5 -5
  56. data/test/abstract_test.rb +23 -1
  57. data/test/context_test.rb +172 -82
  58. data/test/conversion_test.rb +368 -0
  59. data/test/coordinate_system_test.rb +144 -0
  60. data/test/crs_test.rb +770 -71
  61. data/test/database_test.rb +360 -0
  62. data/test/datum_ensemble_test.rb +65 -0
  63. data/test/datum_test.rb +55 -0
  64. data/test/ellipsoid_test.rb +64 -18
  65. data/test/file_api_test.rb +66 -0
  66. data/test/grid_cache_test.rb +72 -0
  67. data/test/grid_test.rb +141 -0
  68. data/test/network_api_test.rb +45 -0
  69. data/test/operation_factory_context_test.rb +201 -0
  70. data/test/parameters_test.rb +40 -0
  71. data/test/pj_object_test.rb +179 -0
  72. data/test/prime_meridian_test.rb +76 -0
  73. data/test/proj_test.rb +46 -4
  74. data/test/projection_test.rb +646 -222
  75. data/test/session_test.rb +78 -0
  76. data/test/transformation_test.rb +149 -7
  77. data/test/unit_test.rb +57 -28
  78. metadata +51 -13
  79. data/lib/api/api_4_9.rb +0 -31
  80. data/lib/proj/config.rb +0 -70
  81. data/lib/proj/point.rb +0 -72
  82. data/test/prime_meridians_test.rb +0 -33
@@ -0,0 +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
data/test/grid_test.rb ADDED
@@ -0,0 +1,141 @@
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
@@ -0,0 +1,45 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class NetworkApiTest < AbstractTest
6
+ def setup
7
+ super
8
+ # Make sure downloader callbacks are not GCed
9
+ #GC.stress = true
10
+ end
11
+
12
+ def teardown
13
+ super
14
+ GC.stress = false
15
+ end
16
+
17
+ def test_download
18
+ skip "This test causes a segfault due to the way Proj cleans up on shutdown"
19
+
20
+ context = Proj::Context.new
21
+ context.network_enabled = true
22
+
23
+ # Create a grid
24
+ grid = Proj::Grid.new("dk_sdfe_dvr90.tif", context)
25
+ grid.delete
26
+
27
+ context.cache.clear
28
+
29
+ # Install custom network api
30
+ context.set_network_api(Proj::NetworkApiImpl)
31
+
32
+ conversion = Proj::Conversion.new(<<~EOS, context)
33
+ +proj=pipeline
34
+ +step +proj=unitconvert +xy_in=deg +xy_out=rad
35
+ +step +proj=vgridshift +grids=dk_sdfe_dvr90.tif +multiplier=1
36
+ +step +proj=unitconvert +xy_in=rad +xy_out=deg
37
+ EOS
38
+
39
+ coord = Proj::Coordinate.new(lon: 12, lat: 56, z: 0)
40
+ new_coord = conversion.forward(coord)
41
+ assert_in_delta(12, new_coord.lon)
42
+ assert_in_delta(56, new_coord.lat)
43
+ assert_in_delta(36.5909996032715, new_coord.z, 1e-10)
44
+ end
45
+ end
@@ -0,0 +1,201 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class OperationFactoryContextTest < AbstractTest
6
+ def test_create
7
+ context = Proj::Context.new
8
+ factory_context = Proj::OperationFactoryContext.new(context)
9
+ assert(context.to_ptr)
10
+ end
11
+
12
+ def test_finalize
13
+ 100.times do
14
+ context = Proj::Context.new
15
+ factory_context = Proj::OperationFactoryContext.new(context)
16
+ assert(context.to_ptr)
17
+ GC.start
18
+ end
19
+ assert(true)
20
+ end
21
+
22
+ def test_create_operations
23
+ context = Proj::Context.new
24
+ source = Proj::Crs.create_from_database("EPSG", "4267", :PJ_CATEGORY_CRS)
25
+ target = Proj::Crs.create_from_database("EPSG", "4269", :PJ_CATEGORY_CRS)
26
+
27
+ factory_context = Proj::OperationFactoryContext.new(context)
28
+ factory_context.spatial_criterion = :PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION
29
+ factory_context.grid_availability = :PROJ_GRID_AVAILABILITY_IGNORED
30
+
31
+ operations = factory_context.create_operations(source, target)
32
+ assert_equal(10, operations.count)
33
+
34
+ operation = operations[0]
35
+ assert_equal("NAD27 to NAD83 (4)", operation.name)
36
+ refute(operation.ballpark_transformation?)
37
+ end
38
+
39
+ def test_suggested_operation
40
+ context = Proj::Context.new
41
+ source = Proj::Crs.create_from_database("EPSG", "4267", :PJ_CATEGORY_CRS)
42
+ target = Proj::Crs.create_from_database("EPSG", "4269", :PJ_CATEGORY_CRS)
43
+
44
+ factory_context = Proj::OperationFactoryContext.new(context)
45
+ factory_context.spatial_criterion = :PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION
46
+ factory_context.grid_availability = :PROJ_GRID_AVAILABILITY_IGNORED
47
+
48
+ operations = factory_context.create_operations(source, target)
49
+
50
+ coord = Proj::Coordinate.new(x: 40, y: -100)
51
+ index = operations.suggested_operation(:PJ_FWD, coord)
52
+
53
+ expected = case
54
+ when proj9?
55
+ 2
56
+ else
57
+ 7
58
+ end
59
+ assert_equal(expected, index)
60
+
61
+ operation = operations[index]
62
+
63
+ expected = case
64
+ when proj9?
65
+ "NAD27 to NAD83 (1)"
66
+ else
67
+ "Ballpark geographic offset from NAD27 to NAD83"
68
+ end
69
+
70
+ assert_equal(expected, operation.name)
71
+ end
72
+
73
+ def test_ballpark_transformations
74
+ context = Proj::Context.new
75
+ source = Proj::Crs.create_from_database("EPSG", "4267", :PJ_CATEGORY_CRS)
76
+ target = Proj::Crs.create_from_database("EPSG", "4258", :PJ_CATEGORY_CRS)
77
+
78
+ factory_context = Proj::OperationFactoryContext.new(context)
79
+ factory_context.spatial_criterion = :PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION
80
+ factory_context.grid_availability = :PROJ_GRID_AVAILABILITY_IGNORED
81
+
82
+ # Allowed implicitly
83
+ operations = factory_context.create_operations(source, target)
84
+ assert_equal(1, operations.count)
85
+
86
+ # Allow explicitly
87
+ factory_context.ballpark_transformations = true
88
+ operations = factory_context.create_operations(source, target)
89
+ assert_equal(1, operations.count)
90
+
91
+ # Disallow
92
+ factory_context.ballpark_transformations = false
93
+ operations = factory_context.create_operations(source, target)
94
+ assert_equal(0, operations.count)
95
+ end
96
+
97
+ def test_desired_accuracy
98
+ context = Proj::Context.new
99
+ factory_context = Proj::OperationFactoryContext.new(context)
100
+ factory_context.desired_accuracy = 5
101
+ end
102
+
103
+ def test_set_area_of_interest
104
+ context = Proj::Context.new
105
+ factory_context = Proj::OperationFactoryContext.new(context)
106
+ factory_context.set_area_of_interest(10, 10, 10, 10)
107
+ end
108
+
109
+ def test_crs_extent_use
110
+ context = Proj::Context.new
111
+ factory_context = Proj::OperationFactoryContext.new(context)
112
+ factory_context.crs_extent_use = :PJ_CRS_EXTENT_SMALLEST
113
+ end
114
+
115
+ def test_spatial_criterion
116
+ context = Proj::Context.new
117
+ factory_context = Proj::OperationFactoryContext.new(context)
118
+ factory_context.spatial_criterion = :PROJ_SPATIAL_CRITERION_STRICT_CONTAINMENT
119
+ end
120
+
121
+ def test_grid_availability
122
+ context = Proj::Context.new
123
+ factory_context = Proj::OperationFactoryContext.new(context)
124
+ factory_context.grid_availability = :PROJ_GRID_AVAILABILITY_USE
125
+ end
126
+
127
+ def test_use_proj_alternative_grid_names
128
+ context = Proj::Context.new
129
+ factory_context = Proj::OperationFactoryContext.new(context)
130
+ factory_context.use_proj_alternative_grid_names = true
131
+ end
132
+
133
+ def test_allow_use_intermediate_crs
134
+ context = Proj::Context.new
135
+ # There is no direct transformations between both
136
+ source = Proj::Crs.create_from_database("EPSG", "4230", :PJ_CATEGORY_CRS)
137
+ target = Proj::Crs.create_from_database("EPSG", "4171", :PJ_CATEGORY_CRS)
138
+
139
+ # Default behavior: allow any pivot
140
+ factory_context = Proj::OperationFactoryContext.new(context)
141
+ operations = factory_context.create_operations(source, target)
142
+ assert_equal(1, operations.count)
143
+
144
+ operation = operations[0]
145
+ assert_equal("ED50 to ETRS89 (10) + Inverse of RGF93 v1 to ETRS89 (1)", operation.name)
146
+ refute(operation.ballpark_transformation?)
147
+
148
+ # Disallow pivots
149
+ factory_context.allow_use_intermediate_crs = :PROJ_INTERMEDIATE_CRS_USE_NEVER
150
+ operations = factory_context.create_operations(source, target)
151
+ assert_equal(1, operations.count)
152
+
153
+ operation = operations[0]
154
+ assert_equal("Ballpark geographic offset from ED50 to RGF93 v1", operation.name)
155
+ assert(operation.ballpark_transformation?)
156
+ end
157
+
158
+ def test_allowed_intermediate_crs
159
+ context = Proj::Context.new
160
+
161
+ # There is no direct transformations between both
162
+ source = Proj::Crs.create_from_database("EPSG", "4230", :PJ_CATEGORY_CRS)
163
+ target = Proj::Crs.create_from_database("EPSG", "4171", :PJ_CATEGORY_CRS)
164
+
165
+ # Restrict pivot to ETRS89
166
+ factory_context = Proj::OperationFactoryContext.new(context, authority: "EPSG")
167
+ factory_context.allowed_intermediate_crs = ["EPSG", "4258"]
168
+
169
+ operations = factory_context.create_operations(source, target)
170
+ assert_equal(1, operations.count)
171
+
172
+ operation = operations[0]
173
+ assert_equal("ED50 to ETRS89 (10) + Inverse of RGF93 v1 to ETRS89 (1)", operation.name)
174
+ end
175
+
176
+ def test_discard_superseded
177
+ context = Proj::Context.new
178
+ source = Proj::Crs.create_from_database("EPSG", "4203", :PJ_CATEGORY_CRS)
179
+ target = Proj::Crs.create_from_database("EPSG", "4326", :PJ_CATEGORY_CRS)
180
+
181
+ factory_context = Proj::OperationFactoryContext.new(context)
182
+ factory_context.spatial_criterion = :PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION
183
+ factory_context.grid_availability = :PROJ_GRID_AVAILABILITY_IGNORED
184
+
185
+ factory_context.discard_superseded = true
186
+ operations = factory_context.create_operations(source, target)
187
+ assert_equal(4, operations.count)
188
+
189
+ factory_context.discard_superseded = false
190
+ operations = factory_context.create_operations(source, target)
191
+ assert_equal(5, operations.count)
192
+ end
193
+
194
+ if proj9?
195
+ def test_set_area_of_interest_name
196
+ context = Proj::Context.new
197
+ factory_context = Proj::OperationFactoryContext.new(context)
198
+ factory_context.area_of_interest_name = 'test'
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class ParametersTest < AbstractTest
6
+ def test_types_nil
7
+ params = Proj::Parameters.new
8
+ assert(params.types.empty?)
9
+ end
10
+
11
+ def test_types_one
12
+ types = [:PJ_TYPE_GEODETIC_CRS]
13
+ params = Proj::Parameters.new
14
+ params.types = types
15
+ assert_equal(types, params.types)
16
+ end
17
+
18
+ def test_types_many
19
+ types = [:PJ_TYPE_GEODETIC_CRS, :PJ_TYPE_GEOCENTRIC_CRS, :PJ_TYPE_GEOGRAPHIC_CRS]
20
+ params = Proj::Parameters.new
21
+ params.types = types
22
+ assert_equal(types, params.types)
23
+ end
24
+
25
+ def test_bbox_valid
26
+ params = Proj::Parameters.new
27
+ refute(params.bbox_valid)
28
+
29
+ params.bbox_valid = true
30
+ assert(params.bbox_valid)
31
+ end
32
+
33
+ def test_allow_deprecated
34
+ params = Proj::Parameters.new
35
+ refute(params.allow_deprecated)
36
+
37
+ params.allow_deprecated = true
38
+ assert(params.allow_deprecated)
39
+ end
40
+ end
@@ -0,0 +1,179 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+ class PjObjectTest < AbstractTest
5
+ def test_clone
6
+ object = Proj::PjObject.create("+proj=longlat")
7
+ clone = object.clone
8
+ assert(object.equivalent_to?(clone, :PJ_COMP_STRICT))
9
+ assert(object.context.equal?(clone.context))
10
+ end
11
+
12
+ def test_dup
13
+ object = Proj::PjObject.create("+proj=longlat")
14
+ clone = object.dup
15
+ assert(object.equivalent_to?(clone, :PJ_COMP_STRICT))
16
+ assert(object.context.equal?(clone.context))
17
+ end
18
+
19
+ def test_equivalent
20
+ from_epsg = Proj::PjObject.create_from_database("EPSG", "7844", :PJ_CATEGORY_CRS)
21
+ from_wkt = Proj::PjObject.create_from_wkt(<<~EOS)
22
+ GEOGCRS["GDA2020",
23
+ DATUM["GDA2020",
24
+ ELLIPSOID["GRS_1980",6378137,298.257222101,
25
+ LENGTHUNIT["metre",1]]],
26
+ PRIMEM["Greenwich",0,
27
+ ANGLEUNIT["Degree",0.0174532925199433]],
28
+ CS[ellipsoidal,2],
29
+ AXIS["geodetic latitude (Lat)",north,
30
+ ORDER[1],
31
+ ANGLEUNIT["degree",0.0174532925199433]],
32
+ AXIS["geodetic longitude (Lon)",east,
33
+ ORDER[2],
34
+ ANGLEUNIT["degree",0.0174532925199433]]]"
35
+ EOS
36
+
37
+ assert(from_epsg.equivalent_to?(from_wkt, :PJ_COMP_EQUIVALENT))
38
+ end
39
+
40
+ def test_accuracy_crs
41
+ object = Proj::PjObject.create_from_database("EPSG", "4326", :PJ_CATEGORY_CRS)
42
+ assert_equal(-1, object.accuracy)
43
+ end
44
+
45
+ def test_accuracy_coordinate_operation
46
+ object = Proj::PjObject.create_from_database("EPSG", "1170", :PJ_CATEGORY_COORDINATE_OPERATION)
47
+ assert_equal(16.0, object.accuracy)
48
+ end
49
+
50
+ def test_accuracy_projection
51
+ object = Proj::Conversion.new("+proj=helmert")
52
+ assert_equal(-1.0, object.accuracy)
53
+ end
54
+
55
+ def test_id_code
56
+ crs = Proj::Crs.new('EPSG:4326')
57
+ assert_equal("4326", crs.id_code)
58
+ refute(crs.id_code(1))
59
+ end
60
+
61
+ def test_remarks_transformation
62
+ transformation = Proj::PjObject.create_from_database("EPSG", "8048", :PJ_CATEGORY_COORDINATE_OPERATION)
63
+
64
+ expected = "Scale difference in ppb where 1/billion = 1E-9. See CT codes 8444-46 for NTv2 method giving equivalent results for Christmas Island, Cocos Islands and Australia respectively. See CT code 8447 for alternative including distortion model for Australia only."
65
+ assert_equal(expected, transformation.remarks)
66
+ end
67
+
68
+ def test_remarks_conversion
69
+ operation = Proj::PjObject.create_from_database("EPSG", "3811", :PJ_CATEGORY_COORDINATE_OPERATION)
70
+
71
+ expected = "Replaces Lambert 2005."
72
+ assert_equal(expected, operation.remarks)
73
+ end
74
+
75
+ def test_scope_transformation
76
+ transformation = Proj::PjObject.create_from_database("EPSG", "8048", :PJ_CATEGORY_COORDINATE_OPERATION)
77
+
78
+ expected = "Transformation of GDA94 coordinates that have been derived through GNSS CORS."
79
+ assert_equal(expected, transformation.scope)
80
+ end
81
+
82
+ def test_scope_conversion
83
+ operation = Proj::PjObject.create_from_database("EPSG", "3811", :PJ_CATEGORY_COORDINATE_OPERATION)
84
+
85
+ expected = "Engineering survey, topographic mapping."
86
+ assert_equal(expected, operation.scope)
87
+ end
88
+
89
+ def test_scope_invalid
90
+ operation = Proj::Conversion.new("+proj=noop")
91
+ refute(operation.scope)
92
+ end
93
+
94
+ def test_factors
95
+ conversion = Proj::Conversion.new("+proj=merc +ellps=WGS84")
96
+ coord = Proj::Coordinate.new(lon: Proj.degrees_to_radians(12), lat: Proj.degrees_to_radians(55))
97
+ factors = conversion.factors(coord)
98
+
99
+ assert_in_delta(1.739526610076288, factors[:meridional_scale], 1e-7)
100
+ assert_in_delta(1.739526609938368, factors[:parallel_scale], 1e-7)
101
+ assert_in_delta(3.0259528269235867, factors[:areal_scale], 1e-7)
102
+
103
+ assert_in_delta(0.0, factors[:angular_distortion], 1e-7)
104
+ assert_in_delta(1.5707963267948966, factors[:meridian_parallel_angle], 1e-7)
105
+ assert_in_delta(0.0, factors[:meridian_convergence], 1e-7)
106
+
107
+ assert_in_delta(1.7395266100073281, factors[:tissot_semimajor], 1e-7)
108
+ assert_in_delta(1.7395266100073281, factors[:tissot_semiminor], 1e-7)
109
+
110
+ assert_in_delta(0.9999999999996122, factors[:dx_dlam], 1e-7)
111
+ assert_in_delta(0.0, factors[:dx_dphi], 1e-7)
112
+ assert_in_delta(0.0, factors[:dy_dlam], 1e-7)
113
+ assert_in_delta(1.7395897312200146, factors[:dy_dphi], 1e-7)
114
+ end
115
+
116
+ def test_create_from_name
117
+ context = Proj::Context.new
118
+ objects = Proj::PjObject.create_from_name("WGS 84", context)
119
+ assert_equal(5, objects.size)
120
+ end
121
+
122
+ def test_create_from_name_with_auth_name
123
+ context = Proj::Context.new
124
+ objects = Proj::PjObject.create_from_name("WGS 84", context, auth_name: "xx")
125
+ assert_equal(0, objects.size)
126
+ end
127
+
128
+ def test_create_from_name_with_types
129
+ context = Proj::Context.new
130
+ objects = Proj::PjObject.create_from_name("WGS 84", context, types: [:PJ_TYPE_GEODETIC_CRS, :PJ_TYPE_PROJECTED_CRS])
131
+ assert_equal(3, objects.size)
132
+ end
133
+
134
+ def test_create_from_name_with_types_and_approximate_match
135
+ context = Proj::Context.new
136
+ objects = Proj::PjObject.create_from_name("WGS 84", context, approximate_match: true,
137
+ types: [:PJ_TYPE_GEODETIC_CRS, :PJ_TYPE_PROJECTED_CRS])
138
+
139
+ expected = proj9? ? 442 : 440
140
+ assert_equal(expected, objects.size)
141
+ end
142
+
143
+ def test_create_from_name_with_types_and_approximate_match_and_limit
144
+ context = Proj::Context.new
145
+ objects = Proj::PjObject.create_from_name("WGS 84", context, approximate_match: true, limit: 25,
146
+ types: [:PJ_TYPE_GEODETIC_CRS, :PJ_TYPE_PROJECTED_CRS])
147
+ assert_equal(25, objects.size)
148
+ end
149
+
150
+ def test_deprecated_true
151
+ wkt = <<~EOS
152
+ GEOGCRS["SAD69 (deprecated)",
153
+ DATUM["South_American_Datum_1969",
154
+ ELLIPSOID["GRS 1967",6378160,298.247167427,
155
+ LENGTHUNIT["metre",1,
156
+ ID["EPSG",9001]]]],
157
+ PRIMEM["Greenwich",0,
158
+ ANGLEUNIT["degree",0.0174532925199433,
159
+ ID["EPSG",9122]]],
160
+ CS[ellipsoidal,2],
161
+ AXIS["latitude",north,
162
+ ORDER[1],
163
+ ANGLEUNIT["degree",0.0174532925199433,
164
+ ID["EPSG",9122]]],
165
+ AXIS["longitude",east,
166
+ ORDER[2],
167
+ ANGLEUNIT["degree",0.0174532925199433,
168
+ ID["EPSG",9122]]]]
169
+ EOS
170
+
171
+ crs = Proj::Crs.create(wkt)
172
+ assert(crs.deprecated?)
173
+ end
174
+
175
+ def test_deprecated_false
176
+ crs = Proj::Crs.create_from_database("EPSG", "4326", :PJ_CATEGORY_CRS)
177
+ refute(crs.deprecated?)
178
+ end
179
+ end