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,381 @@
1
+ # encoding: UTF-8
2
+ require 'stringio'
3
+
4
+ module Proj
5
+ Param = Struct.new(:name, :auth_name, :code, :value, :value_string,
6
+ :unit_conv_factor, :unit_name, :unit_auth_name, :unit_code, :unit_category,
7
+ keyword_init: true)
8
+
9
+ # Coordinate Operations convert {Coordinate coordintates} to a new value. In Proj they are
10
+ # can either by {Conversion conversions} that do not exert a change in reference frame
11
+ # or {Transformation transformations} which do.
12
+ module CoordinateOperationMixin
13
+ # Return whether a coordinate operation can be instantiated as a PROJ pipeline, checking in particular that referenced grids are available.
14
+ #
15
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_is_instantiable
16
+ #
17
+ # @return [Boolean]
18
+ def instantiable?
19
+ result = Api.proj_coordoperation_is_instantiable(self.context, self)
20
+ result == 1 ? true : false
21
+ end
22
+
23
+ # Returns a coordinate operation that represents the inverse operation of this operation
24
+ #
25
+ # @return [Conversion, Transformation] Returns nil on error
26
+ def create_inverse
27
+ ptr = Api.proj_coordoperation_create_inverse(self.context, self)
28
+ self.class.create_object(ptr, self.context)
29
+ end
30
+
31
+ # @!visibility private
32
+ def method_info
33
+ out_method_name = FFI::MemoryPointer.new(:string)
34
+ out_method_auth_name = FFI::MemoryPointer.new(:string)
35
+ out_method_code = FFI::MemoryPointer.new(:string)
36
+
37
+ result = Api.proj_coordoperation_get_method_info(self.context, self, out_method_name, out_method_auth_name, out_method_code)
38
+
39
+ if result != 1
40
+ Error.check_object(self)
41
+ end
42
+
43
+ {:method_name => out_method_name.read_pointer.read_string_to_null,
44
+ :method_auth_name => out_method_auth_name.read_pointer.read_string_to_null,
45
+ :method_code => out_method_code.read_pointer.read_string_to_null}
46
+ end
47
+
48
+ # Returns the operation name
49
+ #
50
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_method_info
51
+ #
52
+ # @return [String]
53
+ def method_name
54
+ method_info[:method_name]
55
+ end
56
+
57
+ # Returns the operation authority name
58
+ #
59
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_method_info
60
+ #
61
+ # @return [String]
62
+ def method_auth_name
63
+ method_info[:method_auth_name]
64
+ end
65
+
66
+ # Returns the operation code
67
+ #
68
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_method_info
69
+ #
70
+ # @return [String]
71
+ def method_code
72
+ method_info[:method_code]
73
+ end
74
+
75
+ # Returns the number of parameters of a SingleOperation
76
+ #
77
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_param_count
78
+ #
79
+ # @return [Integer]
80
+ def param_count
81
+ Api.proj_coordoperation_get_param_count(self.context, self)
82
+ end
83
+
84
+ # Returns the index of a parameter of a SingleOperation
85
+ #
86
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_param_index
87
+ #
88
+ # @param name [String] Name of the parameter. Must not be nil
89
+ #
90
+ # @return [Integer] Index of the parameter or -1 in case of error.
91
+ def param_index(name)
92
+ Api.proj_coordoperation_get_param_index(self.context, self, name)
93
+ end
94
+
95
+ # Returns a parameter of a SingleOperation
96
+ #
97
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_param
98
+ #
99
+ # @param index [Integer] Parameter index
100
+ #
101
+ # @return [Param]
102
+ def param(index)
103
+ out_name = FFI::MemoryPointer.new(:string)
104
+ out_auth_name = FFI::MemoryPointer.new(:string)
105
+ out_code = FFI::MemoryPointer.new(:string)
106
+ out_value = FFI::MemoryPointer.new(:double)
107
+ out_value_string = FFI::MemoryPointer.new(:string)
108
+ out_unit_conv_factor = FFI::MemoryPointer.new(:double)
109
+ out_unit_name = FFI::MemoryPointer.new(:string)
110
+ out_unit_auth_name = FFI::MemoryPointer.new(:string)
111
+ out_unit_code = FFI::MemoryPointer.new(:string)
112
+ out_unit_category = FFI::MemoryPointer.new(:string)
113
+
114
+ result = Api.proj_coordoperation_get_param(self.context, self, index,
115
+ out_name, out_auth_name, out_code,
116
+ out_value, out_value_string,
117
+ out_unit_conv_factor,
118
+ out_unit_name, out_unit_auth_name,out_unit_code,
119
+ out_unit_category)
120
+ if result != 1
121
+ Error.check_object(self)
122
+ end
123
+
124
+ name_ptr = out_name.read_pointer
125
+ auth_name_ptr = out_auth_name.read_pointer
126
+ code_ptr = out_code.read_pointer
127
+ value_string_ptr = out_value_string.read_pointer
128
+ unit_name_ptr = out_unit_name.read_pointer
129
+ unit_auth_name_ptr = out_unit_auth_name.read_pointer
130
+ unit_code_ptr = out_unit_code.read_pointer
131
+ unit_category_ptr = out_unit_category.read_pointer
132
+
133
+ Param.new(name: name_ptr.null? ? nil : name_ptr.read_string_to_null,
134
+ auth_name: auth_name_ptr.null? ? nil : auth_name_ptr.read_string_to_null,
135
+ code: code_ptr.null? ? nil : code_ptr.read_string_to_null,
136
+ value: out_value.null? ? nil : out_value.read_double,
137
+ value_string: value_string_ptr.null? ? nil : value_string_ptr.read_string_to_null,
138
+ unit_conv_factor: out_unit_conv_factor.null? ? nil : out_unit_conv_factor.read_double,
139
+ unit_name: unit_name_ptr.null? ? nil : unit_name_ptr.read_string_to_null,
140
+ unit_auth_name: unit_auth_name_ptr.null? ? nil : unit_auth_name_ptr.read_string_to_null,
141
+ unit_code: unit_code_ptr.null? ? nil : unit_code_ptr.read_string_to_null,
142
+ unit_category: unit_category_ptr.null? ? nil : unit_category_ptr.read_string_to_null)
143
+ end
144
+
145
+ # Transforms a {Coordinate} from the source {Crs} to the target {Crs}. Coordinates should be expressed in
146
+ # the units and axis order of the definition of the source CRS. The returned transformed coordinate will
147
+ # be in the units and axis order of the definition of the target CRS.
148
+ #
149
+ # @see https://proj.org/development/reference/functions.html#c.proj_trans
150
+ #
151
+ # @param coord [Coordinate]
152
+ #
153
+ # @return [Coordinate]
154
+ def forward(coord)
155
+ self.transform(coord, :PJ_FWD)
156
+ end
157
+
158
+ # Transforms a {Coordinate} from the target {Crs} to the source {Crs}. Coordinates should be expressed in
159
+ # the units and axis order of the definition of the source CRS. The returned transformed coordinate will
160
+ # be in the units and axis order of the definition of the target CRS.
161
+ #
162
+ # @see https://proj.org/development/reference/functions.html#c.proj_trans
163
+ #
164
+ # @param coord [Coordinate]
165
+ #
166
+ # @return [Coordinate]
167
+ def inverse(coord)
168
+ self.transform(coord, :PJ_INV)
169
+ end
170
+
171
+ # Transforms a {Coordinate} in the specified direction. See {CoordinateOperation#forward forward} and
172
+ # {CoordinateOperation#inverse inverse}
173
+ #
174
+ # @see https://proj.org/development/reference/functions.html#c.proj_trans
175
+ #
176
+ # @param direction [PJ_DIRECTION] Direction of transformation (:PJ_FWD or :PJ_INV)
177
+ # @param coord [Coordinate]
178
+ #
179
+ # @return [Coordinate]
180
+ def transform(coord, direction)
181
+ struct = Api.proj_trans(self, direction, coord)
182
+ Coordinate.from_coord(struct)
183
+ end
184
+
185
+ # Transform boundary densifying the edges to account for nonlinear transformations along these edges
186
+ # and extracting the outermost bounds.
187
+ #
188
+ # @see https://proj.org/development/reference/functions.html#c.proj_trans_bounds
189
+ #
190
+ # @param bounds [Area] Bounding box in source CRS (target CRS if direction is inverse).
191
+ # @param direction [PJ_DIRECTION] The direction of the transformation.
192
+ # @param densify_points [Integer] Recommended to use 21. This is the number of points to use to densify the bounding polygon in the transformation.
193
+ #
194
+ # @return [Area] Bounding box in target CRS (target CRS if direction is inverse).
195
+ def transform_bounds(bounds, direction, densify_points = 21)
196
+ out_xmin = FFI::MemoryPointer.new(:double)
197
+ out_ymin = FFI::MemoryPointer.new(:double)
198
+ out_xmax = FFI::MemoryPointer.new(:double)
199
+ out_ymax = FFI::MemoryPointer.new(:double)
200
+
201
+ result = Api.proj_trans_bounds(self.context, self, direction,
202
+ bounds.xmin, bounds.ymin, bounds.xmax, bounds.ymax,
203
+ out_xmin, out_ymin, out_xmax, out_ymax, densify_points)
204
+
205
+ unless result == 0
206
+ Error.check_object(self)
207
+ end
208
+
209
+ Bounds.new(out_xmin.read_double, out_ymin.read_double, out_xmax.read_double, out_ymax.read_double)
210
+ end
211
+
212
+ # Transforms an array of {Coordinate coordinates}. Individual points that fail to transform
213
+ # will have their components set to Infinity.
214
+ #
215
+ # @param array [Array<Coordinate>] Coordinates to transform
216
+ # @param direction [PJ_DIRECTION] The direction of the transformation
217
+ #
218
+ # @return [Array<Coordinate>] Array of transformed coordinates
219
+ def transform_array(coordinates, direction)
220
+ coords_ptr = FFI::MemoryPointer.new(Api::PJ_COORD, coordinates.size)
221
+ coordinates.each_with_index do |coordinate, i|
222
+ pj_coord = Api::PJ_COORD.new(coords_ptr[i])
223
+ pj_coord.to_ptr.__copy_from__(coordinate.to_ptr, Api::PJ_COORD.size)
224
+ end
225
+
226
+ int = Api.proj_trans_array(self, direction, coordinates.size, coords_ptr)
227
+ unless int == 0
228
+ Error.check_object(self)
229
+ end
230
+
231
+ result = Array.new(coordinates.size)
232
+ 0.upto(coordinates.size) do |i|
233
+ pj_coord = Api::PJ_COORD.new(coords_ptr[i])
234
+ result[i] = Coordinate.from_coord(pj_coord)
235
+ end
236
+ result
237
+ end
238
+
239
+ # Measure the internal consistency of a given transformation. The function performs n round trip
240
+ # transformations starting in either the forward or reverse direction.
241
+ #
242
+ # @see https://proj.org/development/reference/functions.html#c.proj_roundtrip
243
+ #
244
+ # @param direction [PJ_DIRECTION] The starting direction of transformation
245
+ # @param iterations [Integer] The number of roundtrip transformations
246
+ # @param coordinate [Coordinate] The input coordinate
247
+ #
248
+ # @return [Double] The euclidean distance of the starting point coordinate and the last coordinate after n iterations back and forth.
249
+ def roundtrip(direction, iterations, coordinate)
250
+ Api.proj_roundtrip(self, direction, iterations, coordinate.pj_coord)
251
+ end
252
+
253
+ # Returns a new PJ object whose axis order is the one expected for visualization purposes
254
+ #
255
+ # @see https://proj.org/development/reference/functions.html#c.proj_normalize_for_visualization
256
+ #
257
+ # @return [CoordinateOperation] A new CoordinateOperation or nil in case of error
258
+ def normalize_for_visualization
259
+ ptr = Api.proj_normalize_for_visualization(self.context, self)
260
+ self.class.create_object(ptr, self.context)
261
+ end
262
+
263
+ # Return the operation used during the last invocation of Transformation#forward or Transformation#inverse
264
+ #
265
+ # @see }https://proj.org/development/reference/functions.html#c.proj_trans_get_last_used_operation proj_trans_get_last_used_operation
266
+ #
267
+ # @return [CoordinateOperation] The last used operation
268
+ def last_used_operation
269
+ ptr = Api.proj_trans_get_last_used_operation(self)
270
+ self.class.create_object(ptr, self.context)
271
+ end
272
+
273
+ # Return whether a coordinate operation has a "ballpark" transformation
274
+ #
275
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_has_ballpark_transformation
276
+ #
277
+ # @return [Boolean]
278
+ def ballpark_transformation?
279
+ result = Api.proj_coordoperation_has_ballpark_transformation(Context.current, self)
280
+ result == 1 ? true : false
281
+ end
282
+
283
+ # Returns the accuracy (in meters) of a coordinate operation.
284
+ #
285
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_accuracy
286
+ #
287
+ # @return [Double] The accuracy, or a negative value if unknown or in case of error.
288
+ def accuracy
289
+ Api.proj_coordoperation_get_accuracy(self.context, self)
290
+ end
291
+
292
+ # Returns the number of grids used by a CoordinateOperation
293
+ #
294
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_grid_used_count
295
+ #
296
+ # @return [Integer]
297
+ def grid_count
298
+ Api.proj_coordoperation_get_grid_used_count(self.context, self)
299
+ end
300
+
301
+ # Returns information about a Grid
302
+ #
303
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_grid_used
304
+ #
305
+ # @param index [Integer] Grid index
306
+ #
307
+ # @return [Integer]
308
+ def grid(index)
309
+ out_short_name = FFI::MemoryPointer.new(:string)
310
+ out_full_name = FFI::MemoryPointer.new(:string)
311
+ out_package_name = FFI::MemoryPointer.new(:string)
312
+ out_url = FFI::MemoryPointer.new(:string)
313
+ out_direct_download = FFI::MemoryPointer.new(:int)
314
+ out_open_license = FFI::MemoryPointer.new(:int)
315
+ out_available = FFI::MemoryPointer.new(:int)
316
+
317
+ result = Api.proj_coordoperation_get_grid_used(self.context, self, index,
318
+ out_short_name, out_full_name, out_package_name,
319
+ out_url, out_direct_download ,
320
+ out_open_license, out_available)
321
+
322
+ if result != 1
323
+ Error.check_object(self)
324
+ end
325
+
326
+ name_ptr = out_short_name.read_pointer
327
+ full_name_ptr = out_full_name.read_pointer
328
+ package_name_ptr = out_package_name.read_pointer
329
+ url_ptr = out_url.read_pointer
330
+ downloadable_ptr = out_direct_download
331
+ open_license_ptr = out_open_license
332
+ available_ptr = out_available
333
+
334
+ unless name_ptr.null?
335
+ Grid.new(name_ptr.read_string_to_null, self.context,
336
+ full_name: full_name_ptr.null? ? nil : full_name_ptr.read_string_to_null,
337
+ package_name: package_name_ptr.null? ? nil : package_name_ptr.read_string_to_null,
338
+ url: url_ptr.null? ? nil : url_ptr.read_string_to_null,
339
+ downloadable: downloadable_ptr.null? ? nil : downloadable_ptr.read_int == 1 ? true : false,
340
+ open_license: open_license_ptr.null? ? nil : open_license_ptr.read_int == 1 ? true : false,
341
+ available: available_ptr.null? ? nil : available_ptr.read_int == 1 ? true : false)
342
+ end
343
+ end
344
+
345
+ # Return the parameters of a Helmert transformation as WKT1 TOWGS84 values
346
+ #
347
+ # @see https://proj.org/development/reference/functions.html#c.proj_coordoperation_get_towgs84_values
348
+ #
349
+ # @param error_if_incompatible [Boolean] If true an exception is thrown if the coordinate operation is not compatible with a WKT1 TOWGS84 representation
350
+ #
351
+ # @return [Array<Double>] Array of 7 numbers that represent translation, rotation and scale parameters.
352
+ # Rotation and scale difference terms might be zero if the transformation only includes translation parameters
353
+ def to_wgs84(error_if_incompatible = false)
354
+ parameter_count = 7
355
+ out_values = FFI::MemoryPointer.new(:double, parameter_count)
356
+ Api.proj_coordoperation_get_towgs84_values(self.context, self, out_values, parameter_count, error_if_incompatible ? 1 : 0)
357
+ out_values.read_array_of_double(parameter_count)
358
+ end
359
+
360
+ # Returns the number of steps in a concatenated operation
361
+ #
362
+ # @see https://proj.org/development/reference/functions.html#c.proj_concatoperation_get_step_count
363
+ #
364
+ # @return [Integer] The number of steps
365
+ def step_count
366
+ Api.proj_concatoperation_get_step_count(self.context, self)
367
+ end
368
+
369
+ # Returns a step of a concatenated operation
370
+ #
371
+ # @see https://proj.org/development/reference/functions.html#c.proj_concatoperation_get_step
372
+ #
373
+ # @param index [Integer] Index of the step
374
+ #
375
+ # @return [PjObject]
376
+ def step(index)
377
+ ptr = Api.proj_concatoperation_get_step(self.context, self, index)
378
+ self.class.create_object(ptr, self.context)
379
+ end
380
+ end
381
+ end
@@ -0,0 +1,137 @@
1
+ # encoding: UTF-8
2
+
3
+ module Proj
4
+ # Represents a coordinate system for a {Crs CRS}
5
+ class CoordinateSystem < PjObject
6
+ # Create a CoordinateSystem
7
+ #
8
+ # @param context [Context] The context associated with the CoordinateSystem
9
+ # @param type [PJ_COORDINATE_SYSTEM_TYPE] Coordinate system type
10
+ # @param axes [Array<PJ_AXIS_DESCRIPTION>] Array of Axes
11
+ #
12
+ # @return [CoordinateSystem]
13
+ def self.create(type, axes, context)
14
+ axes_ptr = FFI::MemoryPointer.new(Api::PJ_AXIS_DESCRIPTION, axes.size)
15
+ axes.each_with_index do |axis, i|
16
+ axis_description_target = Api::PJ_AXIS_DESCRIPTION.new(axes_ptr[i])
17
+ axis_description_source = axis.to_description
18
+ axis_description_target.to_ptr.__copy_from__(axis_description_source.to_ptr, Api::PJ_AXIS_DESCRIPTION.size)
19
+ end
20
+
21
+ pointer = Api.proj_create_cs(context, type, axes.count, axes_ptr)
22
+ Error.check_context(context)
23
+ self.create_object(pointer, context)
24
+ end
25
+
26
+ # Create an Ellipsoidal 2D CoordinateSystem
27
+ #
28
+ # @param context [Context] The context associated with the CoordinateSystem
29
+ # @param type [PJ_COORDINATE_SYSTEM_TYPE] Coordinate system type
30
+ # @param unit_name [String] Name of the angular units. Or nil for degree
31
+ # @param unit_conv_factor [Double] Conversion factor from the angular unit to radian. Set to 0 if unit name is degree
32
+ #
33
+ # @return [CoordinateSystem]
34
+ def self.create_ellipsoidal_2d(type, context, unit_name: nil, unit_conv_factor: 0)
35
+ pointer = Api.proj_create_ellipsoidal_2D_cs(context, type, unit_name, unit_conv_factor)
36
+ Error.check_context(context)
37
+ self.create_object(pointer, context)
38
+ end
39
+
40
+ # Create an Ellipsoidal 3D CoordinateSystem
41
+ #
42
+ # @param context [Context] The context associated with the CoordinateSystem
43
+ # @param type [PJ_COORDINATE_SYSTEM_TYPE] Coordinate system type
44
+ # @param horizontal_angular_unit_name [String] Name of the angular units. Or nil for degree
45
+ # @param horizontal_angular_unit_conv_factor [Double] Conversion factor from the angular unit to radian. Set to 0 if horizontal_angular_unit_name name is degree
46
+ # @param vertical_linear_unit_name [String] Name of the angular units. Or nil for meter
47
+ # @param vertical_linear_unit_conv_factor [Double] Conversion factor from the linear unit to meter. Set to 0 if vertical_linear_unit_name name is meter
48
+ #
49
+ # @return [CoordinateSystem]
50
+ def self.create_ellipsoidal_3d(type, context, horizontal_angular_unit_name: nil, horizontal_angular_unit_conv_factor: 0, vertical_linear_unit_name: nil, vertical_linear_unit_conv_factor: 0)
51
+ pointer = Api.proj_create_ellipsoidal_3D_cs(context, type, horizontal_angular_unit_name, horizontal_angular_unit_conv_factor, vertical_linear_unit_name, vertical_linear_unit_conv_factor)
52
+ Error.check_context(context)
53
+ self.create_object(pointer, context)
54
+ end
55
+
56
+ # Create a CartesiansCS 2D coordinate system
57
+ #
58
+ # @param context [Context] The context associated with the CoordinateSystem
59
+ # @param type [PJ_COORDINATE_SYSTEM_TYPE] Coordinate system type
60
+ # @param unit_name [String] Name of the unit. Default is nil.
61
+ # @param unit_conv_factor [Double] Unit conversion factor to SI. Default is 0.
62
+ #
63
+ # @return [CoordinateSystem]
64
+ def self.create_cartesian_2d(context, type, unit_name: nil, unit_conv_factor: 0)
65
+ pointer = Api.proj_create_cartesian_2D_cs(context, type, unit_name, unit_conv_factor)
66
+ Error.check_context(context)
67
+ self.create_object(pointer, context)
68
+ end
69
+
70
+ # Returns the type of the coordinate system
71
+ #
72
+ # @see https://proj.org/development/reference/functions.html#c.proj_cs_get_type
73
+ #
74
+ # @return [PJ_COORDINATE_SYSTEM_TYPE]
75
+ def type
76
+ result = Api.proj_cs_get_type(self.context, self)
77
+ if result == :PJ_CS_TYPE_UNKNOWN
78
+ Error.check_object(self)
79
+ end
80
+ result
81
+ end
82
+
83
+ # Returns the number of axes in the coordinate system
84
+ #
85
+ # @see https://proj.org/development/reference/functions.html#c.proj_cs_get_axis_count
86
+ #
87
+ # @return [Integer]
88
+ def axis_count
89
+ result = Api.proj_cs_get_axis_count(self.context, self)
90
+ if result == -1
91
+ Error.check_object(self)
92
+ end
93
+ result
94
+ end
95
+
96
+ # Returns information about a single axis
97
+ #
98
+ # @see https://proj.org/development/reference/functions.html#c.proj_cs_get_axis_info
99
+ #
100
+ # @param index [Integer] Index of the axis
101
+ #
102
+ # @return [AxisInfo]
103
+ def axis_info(index)
104
+ p_name = FFI::MemoryPointer.new(:pointer)
105
+ p_abbreviation = FFI::MemoryPointer.new(:pointer)
106
+ p_direction = FFI::MemoryPointer.new(:pointer)
107
+ p_unit_conv_factor = FFI::MemoryPointer.new(:double)
108
+ p_unit_name = FFI::MemoryPointer.new(:pointer)
109
+ p_unit_auth_name = FFI::MemoryPointer.new(:pointer)
110
+ p_unit_code = FFI::MemoryPointer.new(:pointer)
111
+
112
+ result = Api.proj_cs_get_axis_info(self.context, self, index,
113
+ p_name, p_abbreviation, p_direction, p_unit_conv_factor, p_unit_name, p_unit_auth_name, p_unit_code)
114
+
115
+ unless result
116
+ Error.check_object(self)
117
+ end
118
+
119
+ AxisInfo.new(name: p_name.read_pointer.read_string,
120
+ abbreviation: p_abbreviation.read_pointer.read_string_to_null,
121
+ direction: p_direction.read_pointer.read_string_to_null,
122
+ unit_conv_factor: p_unit_conv_factor.read_double,
123
+ unit_name: p_unit_name.read_pointer.read_string_to_null,
124
+ unit_auth_name: p_unit_auth_name.read_pointer.read_string_to_null,
125
+ unit_code: p_unit_code.read_pointer.read_string_to_null)
126
+ end
127
+
128
+ # Returns information about all axes
129
+ #
130
+ # @return [Array<AxisInfo>]
131
+ def axes
132
+ self.axis_count.times.map do |index|
133
+ self.axis_info(index)
134
+ end
135
+ end
136
+ end
137
+ end