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
data/lib/projection.rb
DELETED
@@ -1,207 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
module Proj
|
4
|
-
# @deprecated This class is *DEPRECATED.* It will be removed when Proj 7 is released and removes the
|
5
|
-
# underlying API's this class uses. Code should be ported to use Crs and Transformation objects.
|
6
|
-
class Projection
|
7
|
-
def self.parse(value)
|
8
|
-
case value
|
9
|
-
when Array
|
10
|
-
value
|
11
|
-
when String
|
12
|
-
value.strip.split(' ')
|
13
|
-
when Hash
|
14
|
-
array = []
|
15
|
-
value.each_pair do |key, value|
|
16
|
-
key = "+#{key}"
|
17
|
-
array << (value.nil? ? key : "#{key}=#{value}")
|
18
|
-
end
|
19
|
-
array
|
20
|
-
when Projection
|
21
|
-
value.getDef.split(' ')
|
22
|
-
else
|
23
|
-
raise ArgumentError, "Unknown type #{value.class} for projection definition"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.finalize(pointer)
|
28
|
-
proc do
|
29
|
-
Api.pj_free(pointer)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Projection classes are created using Proj4 strings which consist of a number of parameters.
|
34
|
-
# For more information please see the +opt arguments section at https://proj.org/apps/proj.html.
|
35
|
-
#
|
36
|
-
# @param value [string, array, hash] Parameters can be specified as strings, arrays or hashes.
|
37
|
-
#
|
38
|
-
# @example
|
39
|
-
# proj = Projection.new("+proj=utm +zone=21 +units=m")
|
40
|
-
# proj = Projection.new ["+proj=utm", "+zone=21", "+units=m"]
|
41
|
-
# proj = Projection.new("proj" => "utm", "zone" => "21", "units" => "m")
|
42
|
-
#
|
43
|
-
# With all variants the plus sign in front of the keys is optional.
|
44
|
-
def initialize(value)
|
45
|
-
params = self.class.parse(value)
|
46
|
-
p_params = FFI::MemoryPointer.new(:pointer, params.length)
|
47
|
-
params.each_with_index do |param, i|
|
48
|
-
p_param = FFI::MemoryPointer.from_string(param)
|
49
|
-
p_params[i].write_pointer(p_param)
|
50
|
-
end
|
51
|
-
|
52
|
-
@pointer = Api.pj_init(params.count, p_params)
|
53
|
-
self.check_error
|
54
|
-
|
55
|
-
ObjectSpace.define_finalizer(self, self.class.finalize(@pointer))
|
56
|
-
end
|
57
|
-
|
58
|
-
def check_error
|
59
|
-
ptr = Api.pj_get_errno_ref
|
60
|
-
errno = ptr.read_int
|
61
|
-
if errno != 0
|
62
|
-
# If we don't reset the error code it hangs around. This doesn't seem documented anyplace?
|
63
|
-
ptr.write_int(0)
|
64
|
-
Error.check(errno)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
def to_ptr
|
70
|
-
@pointer
|
71
|
-
end
|
72
|
-
|
73
|
-
# Returns projection definitions
|
74
|
-
#
|
75
|
-
# @return [String]
|
76
|
-
def getDef
|
77
|
-
Api.pj_get_def(self, 0)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Returns if this is a geocentric projection
|
81
|
-
#
|
82
|
-
# @return [Boolean]
|
83
|
-
def isGeocent?
|
84
|
-
Api::pj_is_geocent(self)
|
85
|
-
end
|
86
|
-
alias :isGeocentric? :isGeocent?
|
87
|
-
|
88
|
-
# Returns if this is a lat/long projection
|
89
|
-
#
|
90
|
-
# @return [Boolean]
|
91
|
-
def isLatLong?
|
92
|
-
Api::pj_is_latlong(self)
|
93
|
-
end
|
94
|
-
|
95
|
-
# Get the ID of this projection.
|
96
|
-
#
|
97
|
-
# @return [String]
|
98
|
-
def projection
|
99
|
-
getDef =~ /\+proj=(.+?) / ? $1 : nil
|
100
|
-
end
|
101
|
-
|
102
|
-
# Get the ID of the datum used in this projection.
|
103
|
-
#
|
104
|
-
# @return [String]
|
105
|
-
def datum
|
106
|
-
getDef =~ /\+datum=(.+?) / ? $1 : nil
|
107
|
-
end
|
108
|
-
|
109
|
-
# Get definition of projection in typical inspect format (#<Proj::Projection +init=... +proj=... ...>).
|
110
|
-
#
|
111
|
-
# @return [String]
|
112
|
-
def to_s
|
113
|
-
"#<#{self.class.name}#{getDef}>"
|
114
|
-
end
|
115
|
-
|
116
|
-
# Forward projection of a point. Returns a copy of the point object with coordinates projected.
|
117
|
-
#
|
118
|
-
# @param point [Point] in radians
|
119
|
-
# @return [Point] in cartesian coordinates
|
120
|
-
def forward(point)
|
121
|
-
struct = Api.pj_fwd(point, self)
|
122
|
-
self.check_error
|
123
|
-
Point.from_pointer(struct)
|
124
|
-
end
|
125
|
-
|
126
|
-
# Convenience function for calculating a forward projection with degrees instead of radians.
|
127
|
-
#
|
128
|
-
# @param point [Point] in degrees
|
129
|
-
# @return [Point] in cartesian coordinates
|
130
|
-
def forwardDeg(point)
|
131
|
-
forward(point.to_radians)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Projects all points in a collection.
|
135
|
-
#
|
136
|
-
# @param collection [Enumerable<Point>] Points specified in radians
|
137
|
-
# @return [Enumerable<Point>] Points specified in cartesian coordinates
|
138
|
-
def forward_all(collection)
|
139
|
-
collection.map do |point|
|
140
|
-
forward(point)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Inverse projection of a point. Returns a copy of the point object with coordinates projected.
|
145
|
-
#
|
146
|
-
# @param point [Point] in cartesian coordinates
|
147
|
-
# @return [Point] in radians
|
148
|
-
def inverse(point)
|
149
|
-
struct = Api.pj_inv(point, self)
|
150
|
-
self.check_error
|
151
|
-
Point.from_pointer(struct)
|
152
|
-
end
|
153
|
-
|
154
|
-
# Convenience function for calculating an inverse projection with the result in degrees instead of radians.
|
155
|
-
#
|
156
|
-
# @param point [Point] in cartesian coordinates
|
157
|
-
# @return [Point] in degrees
|
158
|
-
def inverseDeg(point)
|
159
|
-
result = inverse(point)
|
160
|
-
result.to_degrees
|
161
|
-
end
|
162
|
-
|
163
|
-
# Inverse projection of all points in a collection.
|
164
|
-
#
|
165
|
-
# @param collection [Enumerable<Point>] Points specified in cartesian coordinates
|
166
|
-
# @return [Enumerable<Point>] Points specified in radians
|
167
|
-
def inverse_all(collection)
|
168
|
-
collection.map do |point|
|
169
|
-
inverse(point)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# Transforms a point from one projection to another.
|
174
|
-
#
|
175
|
-
# @param other [Projection]
|
176
|
-
# @param point [Point]
|
177
|
-
# @return [Point]
|
178
|
-
def transform(other, point)
|
179
|
-
p_x = FFI::MemoryPointer.new(:double, 1)
|
180
|
-
p_x.write_double(point.x)
|
181
|
-
|
182
|
-
p_y = FFI::MemoryPointer.new(:double, 1)
|
183
|
-
p_y.write_double(point.y)
|
184
|
-
|
185
|
-
p_z = FFI::MemoryPointer.new(:double, 1)
|
186
|
-
p_z.write_double(0)
|
187
|
-
|
188
|
-
Api.pj_transform(self, other, 1, 1, p_x, p_y, p_z)
|
189
|
-
self.check_error
|
190
|
-
|
191
|
-
Point.new(p_x.read_double, p_y.read_double)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Transforms all points in a collection from one projection to
|
195
|
-
# another. The +collection+ object must implement the +each+,
|
196
|
-
# +clear+, and << methods (just like an Array) for this to work.
|
197
|
-
#
|
198
|
-
# @param other [Projection]
|
199
|
-
# @param collection [Enumerable, Point]
|
200
|
-
# @return [Enumerable, Point]
|
201
|
-
def transform_all(other, collection)
|
202
|
-
collection.map do |point|
|
203
|
-
transform(other, point)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
data/lib/transformation.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
module Proj
|
2
|
-
# Transformation objects convert {Coordinate Coordinates} from one {Crs} to another.
|
3
|
-
class Transformation < PjObject
|
4
|
-
# Transforms a {Coordinate} from the source {Crs} to the target {Crs}. Coordinates should be expressed in
|
5
|
-
# the units and axis order of the definition of the source CRS. The returned transformed coordinate will
|
6
|
-
# be in the units and axis order of the definition of the target CRS.
|
7
|
-
#
|
8
|
-
# For most geographic Crses, the units will be in degrees. For geographic CRS defined by the EPSG authority,
|
9
|
-
# the order of coordinates is latitude first, longitude second. When using a PROJ initialization string,
|
10
|
-
# on contrary, the order will be longitude first, latitude second.
|
11
|
-
#
|
12
|
-
# For projected CRS, the units may vary (metre, us-foot, etc..).
|
13
|
-
#
|
14
|
-
# For projected CRS defined by the EPSG authority, and with EAST / NORTH directions, the axis order might be
|
15
|
-
# easting first, northing second, or the reverse. When using a PROJ string, the order will be
|
16
|
-
# easting first, northing second, except if the +axis parameter modifies it.
|
17
|
-
#
|
18
|
-
# @param source [Crs | String] - The source Crs. See the Crs documentation for the string format
|
19
|
-
# @param target [Crs | String] - The target Crs. See the Crs documentation for the string format
|
20
|
-
# @param context [Context]
|
21
|
-
def initialize(source, target, context=nil)
|
22
|
-
pointer = if source.is_a?(Crs) && target.is_a?(Crs)
|
23
|
-
if Api.method_defined?(:proj_create_crs_to_crs_from_pj)
|
24
|
-
Api.proj_create_crs_to_crs_from_pj(context, source, target, nil, nil)
|
25
|
-
else
|
26
|
-
Api.proj_create_crs_to_crs(context, source.definition, target.definition, nil)
|
27
|
-
end
|
28
|
-
else
|
29
|
-
Api.proj_create_crs_to_crs(context, source, target, nil)
|
30
|
-
end
|
31
|
-
|
32
|
-
if pointer.null?
|
33
|
-
Error.check
|
34
|
-
end
|
35
|
-
|
36
|
-
super(pointer, context)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Transforms a {Coordinate} from the source {Crs} to the target {Crs}. Coordinates should be expressed in
|
40
|
-
# the units and axis order of the definition of the source CRS. The returned transformed coordinate will
|
41
|
-
# be in the units and axis order of the definition of the target CRS.
|
42
|
-
#
|
43
|
-
# @param coord [Coordinate]
|
44
|
-
# @return [Coordinate]
|
45
|
-
def forward(coord)
|
46
|
-
struct = Api.proj_trans(self, :PJ_FWD, coord)
|
47
|
-
Coordinate.from_coord(struct)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Transforms a {Coordinate} from the target {Crs} to the source {Crs}. Coordinates should be expressed in
|
51
|
-
# the units and axis order of the definition of the source CRS. The returned transformed coordinate will
|
52
|
-
# be in the units and axis order of the definition of the target CRS.
|
53
|
-
#
|
54
|
-
# @param coord [Coordinate]
|
55
|
-
# @return [Coordinate]
|
56
|
-
def inverse(coord)
|
57
|
-
struct = Api.proj_trans(self, :PJ_INV, coord)
|
58
|
-
Coordinate.from_coord(struct)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
data/lib/unit.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
module Proj
|
2
|
-
class Unit
|
3
|
-
attr_reader :id, :to_meter, :factor, :name
|
4
|
-
|
5
|
-
def self.list
|
6
|
-
# First get linear units
|
7
|
-
pointer_to_array = FFI::Pointer.new(Api::PJ_UNITS, Api.proj_list_units)
|
8
|
-
result = Array.new
|
9
|
-
0.step do |i|
|
10
|
-
ellipse_info = Api::PJ_UNITS.new(pointer_to_array[i])
|
11
|
-
break if ellipse_info[:id].nil?
|
12
|
-
result << self.new(ellipse_info[:id], ellipse_info[:to_meter], ellipse_info[:factor], ellipse_info[:name])
|
13
|
-
end
|
14
|
-
|
15
|
-
# Now get angular linear units
|
16
|
-
if Api.method_defined?(:proj_list_angular_units)
|
17
|
-
pointer_to_array = FFI::Pointer.new(Api::PJ_UNITS, Api.proj_list_angular_units)
|
18
|
-
0.step do |i|
|
19
|
-
ellipse_info = Api::PJ_UNITS.new(pointer_to_array[i])
|
20
|
-
break result if ellipse_info[:id].nil?
|
21
|
-
result << self.new(ellipse_info[:id], ellipse_info[:to_meter], ellipse_info[:factor], ellipse_info[:name])
|
22
|
-
end
|
23
|
-
end
|
24
|
-
result
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.get(id)
|
28
|
-
self.list.find {|ellipsoid| ellipsoid.id == id}
|
29
|
-
end
|
30
|
-
|
31
|
-
def initialize(id, to_meter, factor, name)
|
32
|
-
@id = id
|
33
|
-
@to_meter = to_meter
|
34
|
-
@factor = factor
|
35
|
-
@name = name
|
36
|
-
end
|
37
|
-
|
38
|
-
def <=>(other)
|
39
|
-
self.id <=> other.id
|
40
|
-
end
|
41
|
-
|
42
|
-
def ==(other)
|
43
|
-
self.id == other.id
|
44
|
-
end
|
45
|
-
|
46
|
-
def to_s
|
47
|
-
self.id
|
48
|
-
end
|
49
|
-
|
50
|
-
def inspect
|
51
|
-
"#<#{self.class} id=\"#{id}\", to_meter=\"#{to_meter}\", factor=\"#{factor}\", name=\"#{name}\">"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require_relative './abstract_test'
|
4
|
-
|
5
|
-
class PrimeMeridiansTest < AbstractTest
|
6
|
-
def test_get_all
|
7
|
-
prime_meridians = Proj::PrimeMeridian.list.sort.collect {|prime_meridian| prime_meridian.id}
|
8
|
-
assert prime_meridians.index('greenwich')
|
9
|
-
assert prime_meridians.index('athens')
|
10
|
-
assert prime_meridians.index('lisbon')
|
11
|
-
assert prime_meridians.index('rome')
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_one
|
15
|
-
prime_meridian = Proj::PrimeMeridian.get('lisbon')
|
16
|
-
assert_kind_of(Proj::PrimeMeridian, prime_meridian)
|
17
|
-
assert_equal('lisbon', prime_meridian.id)
|
18
|
-
assert_equal('9d07\'54.862"W', prime_meridian.defn)
|
19
|
-
assert_equal('#<Proj::PrimeMeridian id="lisbon", defn="9d07\'54.862"W">', prime_meridian.inspect)
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_compare
|
23
|
-
u1 = Proj::PrimeMeridian.get('lisbon')
|
24
|
-
u2 = Proj::PrimeMeridian.get('lisbon')
|
25
|
-
assert u1 == u2
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_failed_get
|
29
|
-
prime_meridian = Proj::PrimeMeridian.get('foo')
|
30
|
-
assert_nil prime_meridian
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|