proj4rb 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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