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/session_test.rb CHANGED
@@ -1,78 +1,79 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './abstract_test'
4
-
5
- class SessionTest < AbstractTest
6
- def teardown
7
- GC.start
8
- end
9
-
10
- def create_crs
11
- Proj::Crs.new(<<~EOS, Proj::Context.new)
12
- GEOGCRS["myGDA2020",
13
- DATUM["GDA2020",
14
- ELLIPSOID["GRS_1980",6378137,298.257222101,
15
- LENGTHUNIT["metre",1]]],
16
- PRIMEM["Greenwich",0,
17
- ANGLEUNIT["Degree",0.0174532925199433]],
18
- CS[ellipsoidal,2],
19
- AXIS["geodetic latitude (Lat)",north,
20
- ORDER[1],
21
- ANGLEUNIT["degree",0.0174532925199433]],
22
- AXIS["geodetic longitude (Lon)",east,
23
- ORDER[2],
24
- ANGLEUNIT["degree",0.0174532925199433]]]
25
- EOS
26
- end
27
-
28
- def test_create_session
29
- session = Proj::Session.new
30
- assert(session)
31
- end
32
-
33
- def test_finalize
34
- 100.times do
35
- crs = Proj::Session.new(Proj::Context.new)
36
- assert(crs.to_ptr)
37
- GC.start
38
- end
39
- assert(true)
40
- end
41
-
42
- def test_insert_statements
43
- crs = create_crs
44
- session = Proj::Session.new(crs.context)
45
- statements = session.get_insert_statements(crs, "HOBU", "XXXX")
46
- assert_equal(4, statements.count)
47
-
48
- expected = "INSERT INTO geodetic_datum VALUES('HOBU','GEODETIC_DATUM_XXXX','GDA2020','','EPSG','7019','EPSG','8901',NULL,NULL,NULL,NULL,0);"
49
- assert_equal(expected, statements[0])
50
- end
51
-
52
- def test_insert_statements_empty_authorities
53
- crs = create_crs
54
-
55
- session = Proj::Session.new(crs.context)
56
- statements = session.get_insert_statements(crs, "HOBU", "XXXX", false, [])
57
- assert_equal(6, statements.count)
58
- end
59
-
60
- def test_insert_statements_authorities_proj
61
- crs = create_crs
62
-
63
- session = Proj::Session.new(crs.context)
64
- statements = session.get_insert_statements(crs, "HOBU", "XXXX", false, ['EPSG'])
65
- assert_equal(4, statements.count)
66
- end
67
-
68
- def test_insert_twice
69
- crs = create_crs
70
-
71
- session = Proj::Session.new(crs.context)
72
- statements = session.get_insert_statements(crs, "HOBU", "XXXX")
73
- assert_equal(4, statements.count)
74
-
75
- statements = session.get_insert_statements(crs, "HOBU", "XXXX")
76
- assert_equal(0, statements.count)
77
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class SessionTest < AbstractTest
6
+ def teardown
7
+ GC.start
8
+ end
9
+
10
+ def create_crs
11
+ Proj::Crs.new(<<~EOS, Proj::Context.new)
12
+ GEOGCRS["myGDA2020",
13
+ DATUM["GDA2020",
14
+ ELLIPSOID["GRS_1980",6378137,298.257222101,
15
+ LENGTHUNIT["metre",1]]],
16
+ PRIMEM["Greenwich",0,
17
+ ANGLEUNIT["Degree",0.0174532925199433]],
18
+ CS[ellipsoidal,2],
19
+ AXIS["geodetic latitude (Lat)",north,
20
+ ORDER[1],
21
+ ANGLEUNIT["degree",0.0174532925199433]],
22
+ AXIS["geodetic longitude (Lon)",east,
23
+ ORDER[2],
24
+ ANGLEUNIT["degree",0.0174532925199433]]]
25
+ EOS
26
+ end
27
+
28
+ def test_create_session
29
+ session = Proj::Session.new
30
+ assert(session)
31
+ end
32
+
33
+ def test_finalize
34
+ 100.times do
35
+ crs = Proj::Session.new(Proj::Context.new)
36
+ assert(crs.to_ptr)
37
+ GC.start
38
+ end
39
+ assert(true)
40
+ end
41
+
42
+ def test_insert_statements
43
+ crs = create_crs
44
+ session = Proj::Session.new(crs.context)
45
+ statements = session.get_insert_statements(crs, "HOBU", "XXXX")
46
+ assert_operator(statements.count, :>=, 4)
47
+
48
+ insert = statements.find { |s| s.include?("INSERT INTO geodetic_datum") }
49
+ assert(insert, "Expected an INSERT INTO geodetic_datum statement")
50
+ assert_includes(insert, "'HOBU','GEODETIC_DATUM_XXXX','GDA2020'")
51
+ end
52
+
53
+ def test_insert_statements_empty_authorities
54
+ crs = create_crs
55
+
56
+ session = Proj::Session.new(crs.context)
57
+ statements = session.get_insert_statements(crs, "HOBU", "XXXX", false, [])
58
+ assert_equal(6, statements.count)
59
+ end
60
+
61
+ def test_insert_statements_authorities_proj
62
+ crs = create_crs
63
+
64
+ session = Proj::Session.new(crs.context)
65
+ statements = session.get_insert_statements(crs, "HOBU", "XXXX", false, ['EPSG'])
66
+ assert_equal(4, statements.count)
67
+ end
68
+
69
+ def test_insert_twice
70
+ crs = create_crs
71
+
72
+ session = Proj::Session.new(crs.context)
73
+ statements = session.get_insert_statements(crs, "HOBU", "XXXX")
74
+ assert_equal(4, statements.count)
75
+
76
+ statements = session.get_insert_statements(crs, "HOBU", "XXXX")
77
+ assert_equal(0, statements.count)
78
+ end
78
79
  end
@@ -1,210 +1,238 @@
1
- # encoding: UTF-8
2
-
3
- require_relative './abstract_test'
4
-
5
- class TransformationTest < AbstractTest
6
- PRECISION = 1.5
7
-
8
- def setup
9
- @crs_wgs84 = Proj::Crs.new('EPSG:4326')
10
- @crs_gk = Proj::Crs.new('EPSG:31467')
11
- end
12
-
13
- def test_create_from_strings
14
- transform = Proj::Transformation.new('EPSG:31467', 'EPSG:4326')
15
- assert(transform.info)
16
- end
17
-
18
- def test_create_from_crs
19
- transform = Proj::Transformation.new(@crs_wgs84, @crs_gk)
20
- assert(transform.info)
21
- end
22
-
23
- def test_create
24
- context = Proj::Context.new
25
- coordinate_system = Proj::CoordinateSystem.create_ellipsoidal_2d(:PJ_ELLPS2D_LONGITUDE_LATITUDE, context)
26
- source_crs = Proj::Crs.create_geographic(context,
27
- name: "Source CRS",
28
- datum_name: "World Geodetic System 1984",
29
- ellipsoid_name: "WGS 84",
30
- semi_major_meter: 6378137,
31
- inv_flattening: 298.257223563,
32
- prime_meridian_name: "Greenwich",
33
- prime_meridian_offset: 0.0,
34
- pm_angular_units: "Degree",
35
- pm_angular_units_conv: 0.0174532925199433,
36
- coordinate_system: coordinate_system)
37
-
38
- target_crs = Proj::Crs.create_geographic(context,
39
- name: "WGS 84",
40
- datum_name: "World Geodetic System 1984",
41
- ellipsoid_name: "WGS 84",
42
- semi_major_meter: 6378137,
43
- inv_flattening: 298.257223563,
44
- prime_meridian_name: "Greenwich",
45
- prime_meridian_offset: 0.0,
46
- pm_angular_units: "Degree",
47
- pm_angular_units_conv: 0.0174532925199433,
48
- coordinate_system: coordinate_system)
49
-
50
- interp_crs = Proj::Crs.create_geographic(context,
51
- name: "Interpolation CRS",
52
- datum_name: "World Geodetic System 1984",
53
- ellipsoid_name: "WGS 84",
54
- semi_major_meter: 6378137,
55
- inv_flattening: 298.257223563,
56
- prime_meridian_name: "Greenwich",
57
- prime_meridian_offset: 0.0,
58
- pm_angular_units: "Degree",
59
- pm_angular_units_conv: 0.0174532925199433,
60
- coordinate_system: coordinate_system)
61
-
62
- param = Proj::Parameter.new(name: "param name", value: 0.99,
63
- unit_conv_factor: 1.0, unit_type: :PJ_UT_SCALE)
64
-
65
- transformation = Proj::Transformation.create(context, name: "transf", auth_name: "transf auth", code: "transf code",
66
- source_crs: source_crs, target_crs: target_crs, interpolation_crs: interp_crs,
67
- method_name: "method", method_auth_name: "method_auth", method_code: "1",
68
- params: [param], accuracy: 0)
69
-
70
- assert_equal(1, transformation.param_count)
71
-
72
- assert(source_crs.equivalent_to?(transformation.source_crs, :PJ_COMP_STRICT))
73
- assert(target_crs.equivalent_to?(transformation.target_crs, :PJ_COMP_STRICT))
74
- end
75
-
76
- # echo "3458305 5428192" | cs2cs -f '%.10f' +init=epsg:31467 +to +init=epsg:4326 -
77
- def test_gk_to_wgs84_forward
78
- transform = Proj::Transformation.new(@crs_gk, @crs_wgs84)
79
- from = Proj::Coordinate.new(x: 5428192.0, y: 3458305.0, z: -5.1790915237)
80
- to = transform.forward(from)
81
-
82
- assert_in_delta(48.98963932450735, to.x, PRECISION)
83
- assert_in_delta(8.429263044355544, to.y, PRECISION)
84
- assert_in_delta(-5.1790915237, to.z, PRECISION)
85
- assert_in_delta(0, to.t, PRECISION)
86
- end
87
-
88
- def test_gk_to_wgs84_inverse
89
- transform = Proj::Transformation.new(@crs_gk, @crs_wgs84)
90
- from = Proj::Coordinate.new(lam: 48.9906726079, phi: 8.4302123334)
91
- to = transform.inverse(from)
92
-
93
- assert_in_delta(5428306, to.x, PRECISION)
94
- assert_in_delta(3458375, to.y, PRECISION)
95
- assert_in_delta(0, to.z, PRECISION)
96
- assert_in_delta(0, to.t, PRECISION)
97
- end
98
-
99
- # echo "8.4293092923 48.9896114523" | cs2cs -f '%.10f' +init=epsg:4326 +to +init=epsg:31467 -
100
- def test_wgs84_to_gk_forward
101
- transform = Proj::Transformation.new(@crs_wgs84, @crs_gk)
102
- from = Proj::Coordinate.new(lam: 48.9906726079, phi: 8.4302123334)
103
- to = transform.forward(from)
104
-
105
- assert_in_delta(5428306, to.x, PRECISION)
106
- assert_in_delta(3458375, to.y, PRECISION)
107
- assert_in_delta(0, to.z, PRECISION)
108
- assert_in_delta(0, to.t, PRECISION)
109
- end
110
-
111
- def test_wgs84_to_gk_forward_inverse
112
- transform = Proj::Transformation.new(@crs_wgs84, @crs_gk)
113
- from = Proj::Coordinate.new(x: 5428192.0, y: 3458305.0, z: -5.1790915237)
114
- to = transform.inverse(from)
115
-
116
- assert_in_delta(48.98963932450735, to.x, PRECISION)
117
- assert_in_delta(8.429263044355544, to.y, PRECISION)
118
- assert_in_delta(-5.1790915237, to.z, PRECISION)
119
- assert_in_delta(0, to.t, PRECISION)
120
- end
121
-
122
- def test_with_area
123
- area = Proj::Area.new(west_lon_degree: -114.1324, south_lat_degree: 49.5614,
124
- east_lon_degree: 3.76488, north_lat_degree: 62.1463)
125
- transformation = Proj::Transformation.new("EPSG:4277", "EPSG:4326", area: area)
126
-
127
- coordinate1 = Proj::Coordinate.new(x: 50, y: -2, z: 0, t: Float::INFINITY)
128
- coordinate2 = transformation.forward(coordinate1)
129
-
130
- assert_in_delta(50.00065628, coordinate2.x, 1e-4)
131
- assert_in_delta(-2.00133989, coordinate2.y, 1e-4)
132
- end
133
-
134
- def test_accuracy_filter
135
- src = Proj::Crs.new("EPSG:4326")
136
- dst = Proj::Crs.new("EPSG:4258")
137
-
138
- error = assert_raises(Proj::Error) do
139
- Proj::Transformation.new(src, dst, accuracy: 0.05)
140
- end
141
- assert_equal("No operation found matching criteria", error.to_s)
142
- end
143
-
144
- def test_ballpark_filter
145
- src = Proj::Crs.new("EPSG:4267")
146
- dst = Proj::Crs.new("EPSG:4258")
147
-
148
- error = assert_raises(Proj::Error) do
149
- Proj::Transformation.new(src, dst, allow_ballpark: false)
150
- end
151
- assert_equal("No operation found matching criteria", error.to_s)
152
- end
153
-
154
- if proj8?
155
- def test_transform_bounds
156
- transform = Proj::Transformation.new("EPSG:4326",
157
- "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
158
-
159
- start_bounds = Proj::Bounds.new(40, -120, 64, -80)
160
- end_bounds = transform.transform_bounds(start_bounds, :PJ_FWD, 0)
161
-
162
- assert_equal(-1684649.4133828662, end_bounds.xmin)
163
- assert_equal(-350356.8137658477, end_bounds.ymin)
164
- assert_equal(1684649.4133828674, end_bounds.xmax)
165
- assert_equal(2234551.1855909275, end_bounds.ymax)
166
- end
167
-
168
- def test_transform_bounds_normalized
169
- transform = Proj::Transformation.new("EPSG:4326",
170
- "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
171
-
172
- normalized = transform.normalize_for_visualization
173
-
174
- start_bounds = Proj::Bounds.new(-120, 40, -80, 64)
175
- end_bounds = normalized.transform_bounds(start_bounds, :PJ_FWD, 100)
176
-
177
- assert_equal(-1684649.4133828662, end_bounds.xmin)
178
- assert_equal(-555777.7923351025, end_bounds.ymin)
179
- assert_equal(1684649.4133828674, end_bounds.xmax)
180
- assert_equal(2234551.1855909275, end_bounds.ymax)
181
- end
182
-
183
- def test_transform_bounds_densify
184
- transform = Proj::Transformation.new("EPSG:4326",
185
- "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
186
-
187
- start_bounds = Proj::Bounds.new(40, -120, 64, -80)
188
- end_bounds = transform.transform_bounds(start_bounds, :PJ_FWD, 100)
189
-
190
- assert_equal(-1684649.4133828662, end_bounds.xmin)
191
- assert_equal(-555777.7923351025, end_bounds.ymin)
192
- assert_equal(1684649.4133828674, end_bounds.xmax)
193
- assert_equal(2234551.1855909275, end_bounds.ymax)
194
- end
195
-
196
- def test_instantiable
197
- operation = Proj::Conversion.create_from_database("EPSG", "1671", :PJ_CATEGORY_COORDINATE_OPERATION)
198
- assert(operation.instantiable?)
199
- end
200
-
201
- def test_steps_not_concatenated
202
- operation = Proj::Conversion.create_from_database("EPSG", "8048", :PJ_CATEGORY_COORDINATE_OPERATION)
203
- assert_instance_of(Proj::Transformation, operation)
204
- assert_equal(:PJ_TYPE_TRANSFORMATION, operation.proj_type)
205
-
206
- assert_equal(0, operation.step_count)
207
- refute(operation.step(0))
208
- end
209
- end
210
- end
1
+ # encoding: UTF-8
2
+
3
+ require_relative './abstract_test'
4
+
5
+ class TransformationTest < AbstractTest
6
+ PRECISION = 1.5
7
+
8
+ def setup
9
+ @crs_wgs84 = Proj::Crs.new('EPSG:4326')
10
+ @crs_gk = Proj::Crs.new('EPSG:31467')
11
+ end
12
+
13
+ def test_create_from_strings
14
+ transform = Proj::Transformation.new('EPSG:31467', 'EPSG:4326')
15
+ assert(transform.info)
16
+ end
17
+
18
+ def test_create_from_crs
19
+ transform = Proj::Transformation.new(@crs_wgs84, @crs_gk)
20
+ assert(transform.info)
21
+ end
22
+
23
+ def test_create
24
+ context = Proj::Context.new
25
+ coordinate_system = Proj::CoordinateSystem.create_ellipsoidal_2d(:PJ_ELLPS2D_LONGITUDE_LATITUDE, context)
26
+ source_crs = Proj::Crs.create_geographic(context,
27
+ name: "Source CRS",
28
+ datum_name: "World Geodetic System 1984",
29
+ ellipsoid_name: "WGS 84",
30
+ semi_major_meter: 6378137,
31
+ inv_flattening: 298.257223563,
32
+ prime_meridian_name: "Greenwich",
33
+ prime_meridian_offset: 0.0,
34
+ pm_angular_units: "Degree",
35
+ pm_angular_units_conv: 0.0174532925199433,
36
+ coordinate_system: coordinate_system)
37
+
38
+ target_crs = Proj::Crs.create_geographic(context,
39
+ name: "WGS 84",
40
+ datum_name: "World Geodetic System 1984",
41
+ ellipsoid_name: "WGS 84",
42
+ semi_major_meter: 6378137,
43
+ inv_flattening: 298.257223563,
44
+ prime_meridian_name: "Greenwich",
45
+ prime_meridian_offset: 0.0,
46
+ pm_angular_units: "Degree",
47
+ pm_angular_units_conv: 0.0174532925199433,
48
+ coordinate_system: coordinate_system)
49
+
50
+ interp_crs = Proj::Crs.create_geographic(context,
51
+ name: "Interpolation CRS",
52
+ datum_name: "World Geodetic System 1984",
53
+ ellipsoid_name: "WGS 84",
54
+ semi_major_meter: 6378137,
55
+ inv_flattening: 298.257223563,
56
+ prime_meridian_name: "Greenwich",
57
+ prime_meridian_offset: 0.0,
58
+ pm_angular_units: "Degree",
59
+ pm_angular_units_conv: 0.0174532925199433,
60
+ coordinate_system: coordinate_system)
61
+
62
+ param = Proj::Parameter.new(name: "param name", value: 0.99,
63
+ unit_conv_factor: 1.0, unit_type: :PJ_UT_SCALE)
64
+
65
+ transformation = Proj::Transformation.create(context, name: "transf", auth_name: "transf auth", code: "transf code",
66
+ source_crs: source_crs, target_crs: target_crs, interpolation_crs: interp_crs,
67
+ method_name: "method", method_auth_name: "method_auth", method_code: "1",
68
+ params: [param], accuracy: 0)
69
+
70
+ assert_equal(1, transformation.param_count)
71
+
72
+ assert(source_crs.equivalent_to?(transformation.source_crs, :PJ_COMP_STRICT))
73
+ assert(target_crs.equivalent_to?(transformation.target_crs, :PJ_COMP_STRICT))
74
+ end
75
+
76
+ # echo "3458305 5428192" | cs2cs -f '%.10f' +init=epsg:31467 +to +init=epsg:4326 -
77
+ def test_gk_to_wgs84_forward
78
+ transform = Proj::Transformation.new(@crs_gk, @crs_wgs84)
79
+ from = Proj::Coordinate.new(x: 5428192.0, y: 3458305.0, z: -5.1790915237)
80
+ to = transform.forward(from)
81
+
82
+ assert_in_delta(48.98963932450735, to.x, PRECISION)
83
+ assert_in_delta(8.429263044355544, to.y, PRECISION)
84
+ assert_in_delta(-5.1790915237, to.z, PRECISION)
85
+ assert_in_delta(0, to.t, PRECISION)
86
+ end
87
+
88
+ def test_gk_to_wgs84_inverse
89
+ transform = Proj::Transformation.new(@crs_gk, @crs_wgs84)
90
+ from = Proj::Coordinate.new(lam: 48.9906726079, phi: 8.4302123334)
91
+ to = transform.inverse(from)
92
+
93
+ assert_in_delta(5428306, to.x, PRECISION)
94
+ assert_in_delta(3458375, to.y, PRECISION)
95
+ assert_in_delta(0, to.z, PRECISION)
96
+ assert_in_delta(0, to.t, PRECISION)
97
+ end
98
+
99
+ # echo "8.4293092923 48.9896114523" | cs2cs -f '%.10f' +init=epsg:4326 +to +init=epsg:31467 -
100
+ def test_wgs84_to_gk_forward
101
+ transform = Proj::Transformation.new(@crs_wgs84, @crs_gk)
102
+ from = Proj::Coordinate.new(lam: 48.9906726079, phi: 8.4302123334)
103
+ to = transform.forward(from)
104
+
105
+ assert_in_delta(5428306, to.x, PRECISION)
106
+ assert_in_delta(3458375, to.y, PRECISION)
107
+ assert_in_delta(0, to.z, PRECISION)
108
+ assert_in_delta(0, to.t, PRECISION)
109
+ end
110
+
111
+ def test_wgs84_to_gk_forward_inverse
112
+ transform = Proj::Transformation.new(@crs_wgs84, @crs_gk)
113
+ from = Proj::Coordinate.new(x: 5428192.0, y: 3458305.0, z: -5.1790915237)
114
+ to = transform.inverse(from)
115
+
116
+ assert_in_delta(48.98963932450735, to.x, PRECISION)
117
+ assert_in_delta(8.429263044355544, to.y, PRECISION)
118
+ assert_in_delta(-5.1790915237, to.z, PRECISION)
119
+ assert_in_delta(0, to.t, PRECISION)
120
+ end
121
+
122
+ def test_with_area
123
+ area = Proj::Area.new(west_lon_degree: -114.1324, south_lat_degree: 49.5614,
124
+ east_lon_degree: 3.76488, north_lat_degree: 62.1463)
125
+ transformation = Proj::Transformation.new("EPSG:4277", "EPSG:4326", area: area)
126
+
127
+ coordinate1 = Proj::Coordinate.new(x: 50, y: -2, z: 0, t: Float::INFINITY)
128
+ coordinate2 = transformation.forward(coordinate1)
129
+
130
+ assert_in_delta(50.00065628, coordinate2.x, 1e-4)
131
+ assert_in_delta(-2.00133989, coordinate2.y, 1e-4)
132
+ end
133
+
134
+ def test_accuracy_filter
135
+ src = Proj::Crs.new("EPSG:4326")
136
+ dst = Proj::Crs.new("EPSG:4258")
137
+
138
+ error = assert_raises(Proj::Error) do
139
+ Proj::Transformation.new(src, dst, accuracy: 0.05)
140
+ end
141
+ assert_includes(["No operation found matching criteria", "Unknown error (code 4096)"], error.to_s)
142
+ end
143
+
144
+ def test_ballpark_filter
145
+ src = Proj::Crs.new("EPSG:4267")
146
+ dst = Proj::Crs.new("EPSG:4258")
147
+
148
+ error = assert_raises(Proj::Error) do
149
+ Proj::Transformation.new(src, dst, allow_ballpark: false)
150
+ end
151
+ assert_includes(["No operation found matching criteria", "Unknown error (code 4096)"], error.to_s)
152
+ end
153
+
154
+ if Proj::Api::PROJ_VERSION >= '8.0.0'
155
+ def test_transform_bounds
156
+ transform = Proj::Transformation.new("EPSG:4326",
157
+ "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
158
+
159
+ start_bounds = Proj::Bounds.new(40, -120, 64, -80)
160
+ end_bounds = transform.transform_bounds(start_bounds, :PJ_FWD, 0)
161
+
162
+ assert_in_delta(-1684649.4133828662, end_bounds.xmin, 1e-3)
163
+ assert_in_delta(-350356.8137658477, end_bounds.ymin, 1e-3)
164
+ assert_in_delta(1684649.4133828674, end_bounds.xmax, 1e-3)
165
+ assert_in_delta(2234551.1855909275, end_bounds.ymax, 1e-3)
166
+ end
167
+
168
+ def test_transform_bounds_normalized
169
+ transform = Proj::Transformation.new("EPSG:4326",
170
+ "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
171
+
172
+ normalized = transform.normalize_for_visualization
173
+
174
+ start_bounds = Proj::Bounds.new(-120, 40, -80, 64)
175
+ end_bounds = normalized.transform_bounds(start_bounds, :PJ_FWD, 100)
176
+
177
+ assert_in_delta(-1684649.4133828662, end_bounds.xmin, 1e-3)
178
+ assert_in_delta(-555777.7923351025, end_bounds.ymin, 1e-3)
179
+ assert_in_delta(1684649.4133828674, end_bounds.xmax, 1e-3)
180
+ assert_in_delta(2234551.1855909275, end_bounds.ymax, 1e-3)
181
+ end
182
+
183
+ def test_transform_bounds_densify
184
+ transform = Proj::Transformation.new("EPSG:4326",
185
+ "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
186
+
187
+ start_bounds = Proj::Bounds.new(40, -120, 64, -80)
188
+ end_bounds = transform.transform_bounds(start_bounds, :PJ_FWD, 100)
189
+
190
+ assert_in_delta(-1684649.4133828662, end_bounds.xmin, 1e-3)
191
+ assert_in_delta(-555777.7923351025, end_bounds.ymin, 1e-3)
192
+ assert_in_delta(1684649.4133828674, end_bounds.xmax, 1e-3)
193
+ assert_in_delta(2234551.1855909275, end_bounds.ymax, 1e-3)
194
+ end
195
+
196
+ def test_instantiable
197
+ operation = Proj::Conversion.create_from_database("EPSG", "1671", :PJ_CATEGORY_COORDINATE_OPERATION)
198
+ assert(operation.instantiable?)
199
+ end
200
+
201
+ def test_steps_not_concatenated
202
+ operation = Proj::Conversion.create_from_database("EPSG", "8048", :PJ_CATEGORY_COORDINATE_OPERATION)
203
+ assert_instance_of(Proj::Transformation, operation)
204
+ assert_equal(:PJ_TYPE_TRANSFORMATION, operation.proj_type)
205
+
206
+ assert_equal(0, operation.step_count)
207
+ refute(operation.step(0))
208
+ end
209
+ end
210
+
211
+ if Proj::Api::PROJ_VERSION >= Gem::Version.new('9.6.0')
212
+ def test_transform_bounds_3d
213
+ transform = Proj::Transformation.new("EPSG:4326",
214
+ "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs")
215
+
216
+ start_bounds = Proj::Bounds3d.new(40, -120, 100, 64, -80, 500)
217
+ end_bounds = transform.transform_bounds_3d(start_bounds, :PJ_FWD, 21)
218
+
219
+ assert_in_delta(-1684649.4133828662, end_bounds.xmin, 1e-3)
220
+ assert_in_delta(-555797.9720927872, end_bounds.ymin, 1e-3)
221
+ assert_in_delta(100.0, end_bounds.zmin, 1e-3)
222
+ assert_in_delta(1684649.4133828674, end_bounds.xmax, 1e-3)
223
+ assert_in_delta(2234551.1855909275, end_bounds.ymax, 1e-3)
224
+ assert_in_delta(500.0, end_bounds.zmax, 1e-3)
225
+ end
226
+
227
+ def test_transform_bounds_3d_error
228
+ context = Proj::Context.new
229
+ conv = Proj::Conversion.new("+proj=cart +ellps=GRS80", context)
230
+ bounds = Proj::Bounds3d.new(40, -120, 100, 64, -80, 500)
231
+
232
+ error = assert_raises(Proj::Error) do
233
+ conv.transform_bounds_3d(bounds, :PJ_FWD, 0)
234
+ end
235
+ assert_equal("Invalid coordinate", error.message)
236
+ end
237
+ end
238
+ end