proj4rb 2.2.2 → 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 +82 -66
- data/Gemfile +4 -4
- data/README.rdoc +82 -45
- data/lib/api/api.rb +96 -111
- 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 -0
- data/lib/proj/axis_info.rb +44 -0
- data/lib/proj/bounds.rb +13 -0
- data/lib/proj/context.rb +249 -0
- data/lib/proj/conversion.rb +92 -0
- data/lib/{coordinate.rb → 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 -0
- 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 +78 -0
- data/lib/proj/error.rb +71 -0
- 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/{operation.rb → 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 -0
- data/lib/proj/pj_objects.rb +44 -0
- data/lib/proj/prime_meridian.rb +66 -0
- data/lib/proj/projection.rb +698 -0
- data/lib/proj/session.rb +46 -0
- data/lib/proj/strings.rb +32 -0
- data/lib/proj/transformation.rb +102 -0
- data/lib/proj/unit.rb +109 -0
- data/lib/proj.rb +118 -17
- data/proj4rb.gemspec +32 -32
- data/test/abstract_test.rb +29 -7
- data/test/context_test.rb +172 -82
- data/test/conversion_test.rb +368 -0
- data/test/coordinate_system_test.rb +144 -0
- data/test/coordinate_test.rb +34 -34
- data/test/crs_test.rb +1071 -372
- 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 +80 -34
- 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/operation_test.rb +29 -29
- 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 +58 -16
- data/test/projection_test.rb +650 -224
- data/test/session_test.rb +78 -0
- data/test/transformation_test.rb +209 -67
- data/test/unit_test.rb +76 -47
- metadata +67 -29
- data/lib/api/api_4_9.rb +0 -31
- data/lib/area.rb +0 -32
- data/lib/config.rb +0 -70
- data/lib/context.rb +0 -103
- data/lib/crs.rb +0 -204
- data/lib/ellipsoid.rb +0 -42
- data/lib/error.rb +0 -18
- data/lib/pj_object.rb +0 -80
- data/lib/point.rb +0 -72
- data/lib/prime_meridian.rb +0 -40
- data/lib/projection.rb +0 -207
- data/lib/transformation.rb +0 -61
- data/lib/unit.rb +0 -54
- data/test/prime_meridians_test.rb +0 -33
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Proj
|
3
|
+
class CrsInfo
|
4
|
+
attr_reader :auth_name, :code, :name, :type, :deprecated, :bbox_valid,
|
5
|
+
:west_lon_degree, :south_lat_degree, :east_lon_degree, :north_lat_degree,
|
6
|
+
:area_name, :projection_method_name, :celestial_body_name
|
7
|
+
|
8
|
+
def self.from_proj_crs_info(proj_crs_info)
|
9
|
+
data = {auth_name: proj_crs_info[:auth_name],
|
10
|
+
code: proj_crs_info[:code],
|
11
|
+
name: proj_crs_info[:name],
|
12
|
+
type: proj_crs_info[:type],
|
13
|
+
deprecated: proj_crs_info[:deprecated] == 1 ? true : false,
|
14
|
+
bbox_valid: proj_crs_info[:bbox_valid] == 1 ? true : false,
|
15
|
+
west_lon_degree: proj_crs_info[:west_lon_degree],
|
16
|
+
south_lat_degree: proj_crs_info[:south_lat_degree],
|
17
|
+
east_lon_degree: proj_crs_info[:east_lon_degree],
|
18
|
+
north_lat_degree: proj_crs_info[:north_lat_degree],
|
19
|
+
area_name: proj_crs_info[:area_name],
|
20
|
+
projection_method_name: proj_crs_info[:projection_method_name]}
|
21
|
+
|
22
|
+
if Api::PROJ_VERSION >= Gem::Version.new('8.1.0')
|
23
|
+
data[:celestial_body_name] = proj_crs_info[:celestial_body_name]
|
24
|
+
end
|
25
|
+
|
26
|
+
new(**data)
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(auth_name:, code:, name:, type:, deprecated:, bbox_valid:,
|
30
|
+
west_lon_degree:, south_lat_degree:, east_lon_degree:, north_lat_degree:,
|
31
|
+
area_name:, projection_method_name:, celestial_body_name: nil)
|
32
|
+
@auth_name = auth_name
|
33
|
+
@code = code
|
34
|
+
@name = name
|
35
|
+
@type = type
|
36
|
+
@deprecated = deprecated
|
37
|
+
@bbox_valid = bbox_valid
|
38
|
+
@west_lon_degree = west_lon_degree
|
39
|
+
@south_lat_degree = south_lat_degree
|
40
|
+
@east_lon_degree = east_lon_degree
|
41
|
+
@north_lat_degree = north_lat_degree
|
42
|
+
@area_name = area_name
|
43
|
+
@projection_method_name = projection_method_name
|
44
|
+
@celestial_body_name = celestial_body_name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,305 @@
|
|
1
|
+
module Proj
|
2
|
+
CelestialBody = Struct.new(:auth_name, :name)
|
3
|
+
|
4
|
+
# This class provides access the Proj SQLite database called proj.db. The database
|
5
|
+
# stores transformation information that must be accessible for the library to work properly.
|
6
|
+
#
|
7
|
+
# @see https://proj.org/resource_files.html#proj-db
|
8
|
+
class Database
|
9
|
+
attr_reader :context
|
10
|
+
|
11
|
+
# Create a new database instance to query the Proj database
|
12
|
+
#
|
13
|
+
# @param context [Context] A proj Context
|
14
|
+
#
|
15
|
+
# @return [Database]
|
16
|
+
def initialize(context)
|
17
|
+
@context = context
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the path the Proj database
|
21
|
+
#
|
22
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_context_get_database_path
|
23
|
+
#
|
24
|
+
# return [String]
|
25
|
+
def path
|
26
|
+
if Api.method_defined?(:proj_context_get_database_path)
|
27
|
+
Api.proj_context_get_database_path(self.context)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets the path to the Proj database
|
32
|
+
#
|
33
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_context_set_database_path
|
34
|
+
#
|
35
|
+
# @param value [String] Path to the proj database
|
36
|
+
#
|
37
|
+
# @return [Database] Returns reference to the current database instance
|
38
|
+
def path=(value)
|
39
|
+
result = Api.proj_context_set_database_path(self.context, value, nil, nil)
|
40
|
+
unless result == 1
|
41
|
+
Error.check_context(self.context)
|
42
|
+
end
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns SQL statements to run to initiate a new valid auxiliary empty database.
|
47
|
+
#
|
48
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_context_get_database_structure
|
49
|
+
#
|
50
|
+
# @return [Array<Strings>] List of sql statements
|
51
|
+
def structure
|
52
|
+
ptr = Api.proj_context_get_database_structure(self.context, nil)
|
53
|
+
Strings.new(ptr)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return a metadata from the database.
|
57
|
+
#
|
58
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_context_get_database_metadata
|
59
|
+
#
|
60
|
+
# @param key [String] The name of the metadata item. Must not be nil
|
61
|
+
# Available keys:
|
62
|
+
# DATABASE.LAYOUT.VERSION.MAJOR
|
63
|
+
# DATABASE.LAYOUT.VERSION.MINOR
|
64
|
+
# EPSG.VERSION
|
65
|
+
# EPSG.DATE
|
66
|
+
# ESRI.VERSION
|
67
|
+
# ESRI.DATE
|
68
|
+
# IGNF.SOURCE
|
69
|
+
# IGNF.VERSION
|
70
|
+
# IGNF.DATE
|
71
|
+
# NKG.SOURCE
|
72
|
+
# NKG.VERSION
|
73
|
+
# NKG.DATE
|
74
|
+
# PROJ.VERSION
|
75
|
+
# PROJ_DATA.VERSION
|
76
|
+
#
|
77
|
+
# @return [String] Returned metadata
|
78
|
+
def metadata(key)
|
79
|
+
Api.proj_context_get_database_metadata(self.context, key)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the set of authority codes of the given object type.
|
83
|
+
#
|
84
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_codes_from_database
|
85
|
+
#
|
86
|
+
# @param auth_name [String] Authority name. Must not be nil.
|
87
|
+
# @param type [PJ_TYPE] Object type.
|
88
|
+
# @param allow_deprecated [Boolean] Specifies if deprecated objects should be returned. Default is false.
|
89
|
+
#
|
90
|
+
# @return [Strings] Returned authority codes
|
91
|
+
def codes(auth_name, type, allow_deprecated = false)
|
92
|
+
ptr = Api.proj_get_codes_from_database(self.context, auth_name, type, allow_deprecated ? 1 : 0)
|
93
|
+
Strings.new(ptr)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Return a list of authorities used in the database
|
97
|
+
#
|
98
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_authorities_from_database
|
99
|
+
#
|
100
|
+
# @return [Array<Strings>] List of authorities
|
101
|
+
def authorities
|
102
|
+
ptr = Api.proj_get_authorities_from_database(self.context)
|
103
|
+
Strings.new(ptr)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Enumerate CRS infos from the database, taking into account various criteria.
|
107
|
+
#
|
108
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_crs_info_list_from_database
|
109
|
+
#
|
110
|
+
# @param auth_name [String] Authority name. Use nil to specify all authorities
|
111
|
+
# @param parameters [Parameters] Parameters to specify search criteria. May be nil
|
112
|
+
#
|
113
|
+
# @return [Array<CrsInfo>] Returned crs infos
|
114
|
+
def crs_info(auth_name = nil, parameters = nil)
|
115
|
+
out_result_count = FFI::MemoryPointer.new(:int)
|
116
|
+
ptr = Api.proj_get_crs_info_list_from_database(self.context, auth_name, parameters, out_result_count)
|
117
|
+
|
118
|
+
result = out_result_count.read_int.times.map do |index|
|
119
|
+
index_ptr = ptr + (index * FFI::Pointer::SIZE)
|
120
|
+
struct = Api::PROJ_CRS_INFO.new(index_ptr.read_pointer)
|
121
|
+
CrsInfo.from_proj_crs_info(struct)
|
122
|
+
end
|
123
|
+
|
124
|
+
Api.proj_crs_info_list_destroy(ptr)
|
125
|
+
result
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns information about a Grid from the database
|
129
|
+
#
|
130
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_grid_get_info_from_database
|
131
|
+
#
|
132
|
+
# @param name [String] The name of the grid
|
133
|
+
#
|
134
|
+
# @return [Grid]
|
135
|
+
def grid(name)
|
136
|
+
out_full_name = FFI::MemoryPointer.new(:string)
|
137
|
+
out_package_name = FFI::MemoryPointer.new(:string)
|
138
|
+
out_url = FFI::MemoryPointer.new(:string)
|
139
|
+
out_downloadable = FFI::MemoryPointer.new(:int)
|
140
|
+
out_open_license = FFI::MemoryPointer.new(:int)
|
141
|
+
out_available = FFI::MemoryPointer.new(:int)
|
142
|
+
|
143
|
+
result = Api.proj_grid_get_info_from_database(self.context, name,
|
144
|
+
out_full_name, out_package_name, out_url,
|
145
|
+
out_downloadable, out_open_license, out_available)
|
146
|
+
|
147
|
+
if result == 1
|
148
|
+
full_name_ptr = out_full_name.read_pointer
|
149
|
+
package_name_ptr = out_package_name.read_pointer
|
150
|
+
url_ptr = out_url.read_pointer
|
151
|
+
|
152
|
+
downloadable_ptr = out_downloadable
|
153
|
+
open_license_ptr = out_open_license
|
154
|
+
available_ptr = out_available
|
155
|
+
|
156
|
+
full_name = full_name_ptr.read_string_to_null
|
157
|
+
package_name = package_name_ptr.read_string_to_null
|
158
|
+
url = url_ptr.read_string_to_null
|
159
|
+
|
160
|
+
downloadable = downloadable_ptr.read_int == 1 ? true : false
|
161
|
+
open_license = open_license_ptr.read_int == 1 ? true : false
|
162
|
+
available = available_ptr.read_int == 1 ? true : false
|
163
|
+
|
164
|
+
Grid.new(name, self.context,
|
165
|
+
full_name: full_name, package_name: package_name,
|
166
|
+
url: url ? URI(url) : nil,
|
167
|
+
downloadable: downloadable, open_license: open_license, available: available)
|
168
|
+
else
|
169
|
+
Error.check_context(self.context)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns a list of geoid models available
|
174
|
+
#
|
175
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_geoid_models_from_database
|
176
|
+
#
|
177
|
+
# @param authority [String] Authority name into which the object will be inserted. Must not be nil
|
178
|
+
# @param code [Integer] Code with which the object will be inserted.Must not be nil
|
179
|
+
#
|
180
|
+
# @return [Strings] List of insert statements
|
181
|
+
def geoid_models(authority, code)
|
182
|
+
ptr = Api.proj_get_geoid_models_from_database(self.context, authority, code, nil)
|
183
|
+
Strings.new(ptr)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Returns a list of celestial bodies from the database
|
187
|
+
#
|
188
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_celestial_body_list_from_database
|
189
|
+
#
|
190
|
+
# @param authority [String] Authority name, used to restrict the search. Set to nil for all authorities.
|
191
|
+
#
|
192
|
+
# @return [Array<CelestialBody>] List of insert statements
|
193
|
+
def celestial_bodies(authority = nil)
|
194
|
+
out_result_count = FFI::MemoryPointer.new(:int)
|
195
|
+
ptr = Api.proj_get_celestial_body_list_from_database(self.context, authority, out_result_count)
|
196
|
+
|
197
|
+
body_ptrs = ptr.read_array_of_pointer(out_result_count.read_int)
|
198
|
+
result = body_ptrs.map do |body_ptr|
|
199
|
+
# First read the pointer to a structure
|
200
|
+
struct = Api::ProjCelestialBodyInfo.new(body_ptr)
|
201
|
+
|
202
|
+
# Now map this to a Ruby Struct
|
203
|
+
CelestialBody.new(struct[:auth_name], struct[:name])
|
204
|
+
end
|
205
|
+
|
206
|
+
Api.proj_celestial_body_list_destroy(ptr)
|
207
|
+
|
208
|
+
result
|
209
|
+
end
|
210
|
+
|
211
|
+
# Return the name of the celestial body of the specified object.
|
212
|
+
#
|
213
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_celestial_body_name
|
214
|
+
#
|
215
|
+
# @param object [PjObject] Object of type CRS, Datum or Ellipsoid. Must not be nil.
|
216
|
+
#
|
217
|
+
# @return [String] The name of the celestial body or nil
|
218
|
+
def celestial_body_name(object)
|
219
|
+
Api.proj_get_celestial_body_name(self.context, object)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Suggests a database code for the specified object.
|
223
|
+
#
|
224
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_suggests_code_for
|
225
|
+
#
|
226
|
+
# @param object [PjObject] Object for which to suggest a code.
|
227
|
+
# @param authority [String] Authority name into which the object will be inserted.
|
228
|
+
# @param numeric_code [Boolean] Whether the code should be numeric, or derived from the object name.
|
229
|
+
#
|
230
|
+
# @return [String] The suggested code
|
231
|
+
def suggest_code_for(object, authority, numeric_code)
|
232
|
+
ptr = Api.proj_suggests_code_for(self.context, object, authority, numeric_code ? 1 : 0, nil)
|
233
|
+
result = ptr.read_string_to_null
|
234
|
+
Api.proj_string_destroy(ptr)
|
235
|
+
result
|
236
|
+
end
|
237
|
+
|
238
|
+
# Returns a list of units from the database
|
239
|
+
#
|
240
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_units_from_database
|
241
|
+
#
|
242
|
+
# @param auth_name [String] Authority name, used to restrict the search. Or nil for all authorities.
|
243
|
+
# @param category [String] Filter by category, if this parameter is not nil. Category is one of "linear", "linear_per_time", "angular", "angular_per_time", "scale", "scale_per_time" or "time
|
244
|
+
# @param allow_deprecated [Boolean] Whether deprecated units should also be returned. Default false.
|
245
|
+
#
|
246
|
+
# @return [Array<Unit>] Array of units
|
247
|
+
def units(auth_name: nil, category: nil, allow_deprecated: false)
|
248
|
+
# Create pointer to read the count output parameter
|
249
|
+
out_result_count = FFI::MemoryPointer.new(:int)
|
250
|
+
|
251
|
+
# Result is an array of pointers to structures
|
252
|
+
pp_units = Api.proj_get_units_from_database(Context.current, auth_name, category, allow_deprecated ? 1 : 0, out_result_count)
|
253
|
+
count = out_result_count.read(:int)
|
254
|
+
array_p_units = pp_units.read_array_of_pointer(count)
|
255
|
+
|
256
|
+
result = Array.new(count)
|
257
|
+
count.times do |i|
|
258
|
+
unit_info = Api::PROJ_UNIT_INFO.new(array_p_units[i])
|
259
|
+
|
260
|
+
result[i] = Unit.new(unit_info[:auth_name],
|
261
|
+
unit_info[:code],
|
262
|
+
unit_info[:name],
|
263
|
+
unit_info[:category],
|
264
|
+
unit_info[:conv_factor],
|
265
|
+
unit_info[:proj_short_name],
|
266
|
+
unit_info[:deprecated])
|
267
|
+
end
|
268
|
+
|
269
|
+
Api.proj_unit_list_destroy(pp_units)
|
270
|
+
|
271
|
+
result
|
272
|
+
end
|
273
|
+
|
274
|
+
# Returns information for a unit of measure from a database lookup
|
275
|
+
#
|
276
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_uom_get_info_from_database
|
277
|
+
#
|
278
|
+
# @param auth_name [String] Authority name
|
279
|
+
# @param code [String] Unit of measure code
|
280
|
+
#
|
281
|
+
# @return [Unit] Unit
|
282
|
+
def unit(auth_name, code)
|
283
|
+
out_name = FFI::MemoryPointer.new(:string)
|
284
|
+
out_conv_factor = FFI::MemoryPointer.new(:double)
|
285
|
+
out_category = FFI::MemoryPointer.new(:string)
|
286
|
+
|
287
|
+
result = Api.proj_uom_get_info_from_database(self.context, auth_name, code,
|
288
|
+
out_name, out_conv_factor , out_category)
|
289
|
+
|
290
|
+
if result == 1
|
291
|
+
name_ptr = out_name.read_pointer
|
292
|
+
conv_factor_ptr = out_conv_factor
|
293
|
+
category_ptr = out_category.read_pointer
|
294
|
+
|
295
|
+
name = name_ptr.read_string_to_null
|
296
|
+
conv_factor = conv_factor_ptr.read_double
|
297
|
+
category = category_ptr.read_string_to_null
|
298
|
+
|
299
|
+
Unit.new(auth_name, code, name, category, conv_factor, nil, false)
|
300
|
+
else
|
301
|
+
Error.check_context(self.context)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
data/lib/proj/datum.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Proj
|
2
|
+
class Datum < PjObject
|
3
|
+
# Returns the frame reference epoch of a dynamic geodetic or vertical reference frame
|
4
|
+
#
|
5
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_dynamic_datum_get_frame_reference_epoch
|
6
|
+
#
|
7
|
+
# @return [Double] The frame reference epoch as decimal year, or -1 in case of error.
|
8
|
+
def frame_reference_epoch
|
9
|
+
Api.proj_dynamic_datum_get_frame_reference_epoch(self.context, self)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Return the ellipsoid
|
13
|
+
#
|
14
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_ellipsoid
|
15
|
+
#
|
16
|
+
# @return [PjObject]
|
17
|
+
def ellipsoid
|
18
|
+
ptr = Api.proj_get_ellipsoid(self.context, self)
|
19
|
+
self.class.create_object(ptr, self.context)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the prime meridian
|
23
|
+
#
|
24
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_get_prime_meridian
|
25
|
+
#
|
26
|
+
# @return [PjObject]
|
27
|
+
def prime_meridian
|
28
|
+
ptr = Api.proj_get_prime_meridian(self.context, self)
|
29
|
+
self.class.create_object(ptr, self.context)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Proj
|
2
|
+
class DatumEnsemble < PjObject
|
3
|
+
|
4
|
+
# Returns the number of members of a datum ensemble
|
5
|
+
#
|
6
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_datum_ensemble_get_member_count
|
7
|
+
#
|
8
|
+
# @return [Integer]
|
9
|
+
def count
|
10
|
+
Api.proj_datum_ensemble_get_member_count(self.context, self)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns a member from a datum ensemble.
|
14
|
+
#
|
15
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_datum_ensemble_get_member
|
16
|
+
#
|
17
|
+
# @param index [Integer] Index of the datum member to extract. Should be between 0 and DatumEnsembel#count - 1.
|
18
|
+
#
|
19
|
+
# @return [Integer]
|
20
|
+
def [](index)
|
21
|
+
ptr = Api.proj_datum_ensemble_get_member(self.context, self, index)
|
22
|
+
self.class.create_object(ptr, self.context)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the positional accuracy of the datum ensemble
|
26
|
+
#
|
27
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_datum_ensemble_get_accuracy
|
28
|
+
#
|
29
|
+
# @return [Float] The data ensemble accuracy or -1 in case of error
|
30
|
+
def accuracy
|
31
|
+
Api.proj_datum_ensemble_get_accuracy(self.context, self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Proj
|
2
|
+
class Ellipsoid < PjObject
|
3
|
+
# Returns a list of ellipsoids that are built into Proj. A more comprehensive
|
4
|
+
# list is stored in the Proj database and can be queried via PjObject#create_from_database
|
5
|
+
def self.built_in
|
6
|
+
pointer_to_array = FFI::Pointer.new(Api::PJ_ELLPS, Api.proj_list_ellps)
|
7
|
+
|
8
|
+
result = Array.new
|
9
|
+
0.step do |i|
|
10
|
+
pj_ellps = Api::PJ_ELLPS.new(pointer_to_array[i])
|
11
|
+
break result if pj_ellps[:id].nil?
|
12
|
+
result << pj_ellps
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns ellipsoid parameters
|
18
|
+
#
|
19
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_ellipsoid_get_parameters
|
20
|
+
#
|
21
|
+
# @return [Hash] Hash of ellipsoid parameters. Axes are in meters
|
22
|
+
def parameters
|
23
|
+
@parameters ||= begin
|
24
|
+
out_semi_major_metre = FFI::MemoryPointer.new(:double)
|
25
|
+
out_semi_minor_metre = FFI::MemoryPointer.new(:double)
|
26
|
+
out_is_semi_minor_computed = FFI::MemoryPointer.new(:int)
|
27
|
+
out_inv_flattening = FFI::MemoryPointer.new(:double)
|
28
|
+
|
29
|
+
result = Api.proj_ellipsoid_get_parameters(self.context, self, out_semi_major_metre, out_semi_minor_metre, out_is_semi_minor_computed, out_inv_flattening)
|
30
|
+
|
31
|
+
if result != 1
|
32
|
+
Error.check_object(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
{semi_major_axis: out_semi_major_metre.read_double,
|
36
|
+
semi_minor_axis: out_semi_minor_metre.read_double,
|
37
|
+
semi_minor_axis_computed: out_is_semi_minor_computed.read_int == 1 ? true : false,
|
38
|
+
inverse_flattening: out_inv_flattening.null? ? nil : out_inv_flattening.read_double}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the semi-major axis in meters
|
43
|
+
#
|
44
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_ellipsoid_get_parameters
|
45
|
+
#
|
46
|
+
# @return [Double]
|
47
|
+
def semi_major_axis
|
48
|
+
self.parameters[:semi_major_axis]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the semi-minor axis in meters
|
52
|
+
#
|
53
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_ellipsoid_get_parameters
|
54
|
+
#
|
55
|
+
# @return [Double]
|
56
|
+
def semi_minor_axis
|
57
|
+
self.parameters[:semi_minor_axis]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns whether the semi-minor axis is computed
|
61
|
+
#
|
62
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_ellipsoid_get_parameters
|
63
|
+
#
|
64
|
+
# @return [Boolean]
|
65
|
+
def semi_minor_axis_computed
|
66
|
+
self.parameters[:semi_minor_axis_computed]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the inverse flattening value
|
70
|
+
#
|
71
|
+
# @see https://proj.org/development/reference/functions.html#c.proj_ellipsoid_get_parameters
|
72
|
+
#
|
73
|
+
# @return [Double]
|
74
|
+
def inverse_flattening
|
75
|
+
self.parameters[:inverse_flattening]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/proj/error.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Proj
|
2
|
+
# Represents error thrown by Proj
|
3
|
+
#
|
4
|
+
# @see https://proj.org/development/errorhandling.html
|
5
|
+
class Error < StandardError
|
6
|
+
# Error codes typically related to coordinate operation initialization
|
7
|
+
PROJ_ERR_INVALID_OP = 1024 # Other/unspecified error related to coordinate operation initialization
|
8
|
+
PROJ_ERR_INVALID_OP_WRONG_SYNTAX = PROJ_ERR_INVALID_OP + 1 # Invalid pipeline structure, missing +proj argument, etc
|
9
|
+
PROJ_ERR_INVALID_OP_MISSING_ARG = PROJ_ERR_INVALID_OP + 2 # Missing required operation parameter
|
10
|
+
PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE = PROJ_ERR_INVALID_OP + 3 # One of the operation parameter has an illegal value
|
11
|
+
PROJ_ERR_INVALID_OP_MUTUALLY_EXCLUSIVE_ARGS = PROJ_ERR_INVALID_OP + 4 # Mutually exclusive arguments
|
12
|
+
PROJ_ERR_INVALID_OP_FILE_NOT_FOUND_OR_INVALID = PROJ_ERR_INVALID_OP + 5 # File not found (particular case of PROJ_ERR_INVALID_OP_ILLEGAL_ARG_VALUE)
|
13
|
+
|
14
|
+
# Error codes related to transformation on a specific coordinate
|
15
|
+
PROJ_ERR_COORD_TRANSFM = 2048 # Other error related to coordinate transformation
|
16
|
+
PROJ_ERR_COORD_TRANSFM_INVALID_COORD = PROJ_ERR_COORD_TRANSFM + 1 # For e.g lat > 90deg
|
17
|
+
PROJ_ERR_COORD_TRANSFM_OUTSIDE_PROJECTION_DOMAIN = PROJ_ERR_COORD_TRANSFM + 2 # Coordinate is outside of the projection domain. e.g approximate mercator with |longitude - lon_0| > 90deg, or iterative convergence method failed
|
18
|
+
PROJ_ERR_COORD_TRANSFM_NO_OPERATION = PROJ_ERR_COORD_TRANSFM + 3 # No operation found, e.g if no match the required accuracy, or if ballpark transformations were asked to not be used and they would be only such candidate
|
19
|
+
PROJ_ERR_COORD_TRANSFM_OUTSIDE_GRID = PROJ_ERR_COORD_TRANSFM + 4 # Point to transform falls outside grid or subgrid
|
20
|
+
PROJ_ERR_COORD_TRANSFM_GRID_AT_NODATA = PROJ_ERR_COORD_TRANSFM + 5 # Point to transform falls in a grid cell that evaluates to nodata
|
21
|
+
|
22
|
+
# Other type of errors
|
23
|
+
PROJ_ERR_OTHER = 4096
|
24
|
+
PROJ_ERR_OTHER_API_MISUSE = PROJ_ERR_OTHER + 1 # Error related to a misuse of PROJ API
|
25
|
+
PROJ_ERR_OTHER_NO_INVERSE_OP = PROJ_ERR_OTHER + 2 # No inverse method available
|
26
|
+
PROJ_ERR_OTHER_NETWORK_ERROR = PROJ_ERR_OTHER + 3 # Failure when accessing a network resource
|
27
|
+
|
28
|
+
# Check the context to see if an error occurred. If an error has happened will
|
29
|
+
# raise an exception.
|
30
|
+
def self.check_context(context)
|
31
|
+
unless context.errno == 0
|
32
|
+
# raise(self, "#{self.category(context.errno)}: #{self.message(context)}")
|
33
|
+
raise(self, self.message(context, context.errno))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.check_object(pj_object)
|
38
|
+
# It would be nice if Proj exposed the proj_context_errno_set method so
|
39
|
+
# we don't need a pj_object
|
40
|
+
context = pj_object.context
|
41
|
+
unless context.errno == 0
|
42
|
+
message = self.message(context, context.errno)
|
43
|
+
Api.proj_errno_reset(pj_object)
|
44
|
+
raise(self, message)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the current error-state of the context. An non-zero error codes indicates an error.
|
49
|
+
#
|
50
|
+
# See https://proj.org/development/reference/functions.html#c.proj_errno_string proj_errno_string
|
51
|
+
#
|
52
|
+
# @param context [Context] The context the error occurred in
|
53
|
+
# @param errno [Integer] The error number
|
54
|
+
#
|
55
|
+
# return [String]
|
56
|
+
def self.message(context, errno)
|
57
|
+
if Api.method_defined?(:proj_context_errno_string)
|
58
|
+
Api.proj_context_errno_string(context, errno)
|
59
|
+
elsif Api.method_defined?(:proj_errno_string)
|
60
|
+
Api.proj_errno_string(errno)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Converts an errno to a error category
|
65
|
+
def self.category(errno)
|
66
|
+
self.constants.find do |constant|
|
67
|
+
self.const_get(constant) == errno
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|