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.
- checksums.yaml +4 -4
- data/ChangeLog +26 -15
- data/README.rdoc +82 -44
- data/Rakefile +27 -27
- data/lib/api/api.rb +96 -118
- data/lib/api/api_5_0.rb +331 -300
- data/lib/api/api_5_1.rb +6 -6
- data/lib/api/api_5_2.rb +4 -4
- data/lib/api/api_6_0.rb +116 -14
- data/lib/api/api_6_1.rb +4 -4
- data/lib/api/api_6_2.rb +9 -6
- data/lib/api/api_6_3.rb +6 -0
- data/lib/api/api_7_0.rb +68 -0
- data/lib/api/api_7_1.rb +73 -0
- data/lib/api/api_7_2.rb +14 -0
- data/lib/api/api_8_0.rb +6 -0
- data/lib/api/api_8_1.rb +24 -0
- data/lib/api/api_8_2.rb +6 -0
- data/lib/api/api_9_1.rb +7 -0
- data/lib/api/api_9_2.rb +9 -0
- data/lib/api/api_experimental.rb +196 -0
- data/lib/proj/area.rb +73 -32
- data/lib/proj/axis_info.rb +44 -0
- data/lib/proj/bounds.rb +13 -0
- data/lib/proj/context.rb +174 -28
- data/lib/proj/conversion.rb +92 -0
- data/lib/proj/coordinate.rb +281 -197
- data/lib/proj/coordinate_operation_mixin.rb +381 -0
- data/lib/proj/coordinate_system.rb +137 -0
- data/lib/proj/crs.rb +672 -204
- data/lib/proj/crs_info.rb +47 -0
- data/lib/proj/database.rb +305 -0
- data/lib/proj/datum.rb +32 -0
- data/lib/proj/datum_ensemble.rb +34 -0
- data/lib/proj/ellipsoid.rb +77 -41
- data/lib/proj/error.rb +62 -9
- data/lib/proj/file_api.rb +166 -0
- data/lib/proj/grid.rb +121 -0
- data/lib/proj/grid_cache.rb +64 -0
- data/lib/proj/grid_info.rb +19 -0
- data/lib/proj/network_api.rb +92 -0
- data/lib/proj/operation.rb +42 -42
- data/lib/proj/operation_factory_context.rb +136 -0
- data/lib/proj/parameter.rb +38 -0
- data/lib/proj/parameters.rb +106 -0
- data/lib/proj/pj_object.rb +670 -80
- data/lib/proj/pj_objects.rb +44 -0
- data/lib/proj/prime_meridian.rb +65 -39
- data/lib/proj/projection.rb +698 -207
- data/lib/proj/session.rb +46 -0
- data/lib/proj/strings.rb +32 -0
- data/lib/proj/transformation.rb +101 -60
- data/lib/proj/unit.rb +108 -53
- data/lib/proj.rb +110 -9
- data/proj4rb.gemspec +5 -5
- data/test/abstract_test.rb +23 -1
- data/test/context_test.rb +172 -82
- data/test/conversion_test.rb +368 -0
- data/test/coordinate_system_test.rb +144 -0
- data/test/crs_test.rb +770 -71
- data/test/database_test.rb +360 -0
- data/test/datum_ensemble_test.rb +65 -0
- data/test/datum_test.rb +55 -0
- data/test/ellipsoid_test.rb +64 -18
- data/test/file_api_test.rb +66 -0
- data/test/grid_cache_test.rb +72 -0
- data/test/grid_test.rb +141 -0
- data/test/network_api_test.rb +45 -0
- data/test/operation_factory_context_test.rb +201 -0
- data/test/parameters_test.rb +40 -0
- data/test/pj_object_test.rb +179 -0
- data/test/prime_meridian_test.rb +76 -0
- data/test/proj_test.rb +46 -4
- data/test/projection_test.rb +646 -222
- data/test/session_test.rb +78 -0
- data/test/transformation_test.rb +149 -7
- data/test/unit_test.rb +57 -28
- metadata +51 -13
- data/lib/api/api_4_9.rb +0 -31
- data/lib/proj/config.rb +0 -70
- data/lib/proj/point.rb +0 -72
- 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
|