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