rgeo 0.2.1 → 0.2.2
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.
- data/History.rdoc +9 -0
- data/README.rdoc +8 -4
- data/Version +1 -1
- data/ext/geos_c_impl/extconf.rb +4 -0
- data/ext/proj4_c_impl/extconf.rb +6 -0
- data/lib/rgeo/cartesian/factory.rb +5 -1
- data/lib/rgeo/coord_sys.rb +25 -6
- data/lib/rgeo/coord_sys/cs/entities.rb +805 -0
- data/lib/rgeo/coord_sys/cs/factories.rb +138 -0
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +307 -0
- data/lib/rgeo/coord_sys/proj4.rb +3 -0
- data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +112 -0
- data/lib/rgeo/coord_sys/srs_database/interface.rb +112 -0
- data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +143 -0
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +88 -0
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +90 -0
- data/lib/rgeo/feature/types.rb +11 -7
- data/lib/rgeo/geos/factory.rb +6 -1
- data/lib/rgeo/geos/impl_additions.rb +1 -1
- data/lib/rgeo/geos/zm_impl.rb +1 -1
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -1
- data/test/coord_sys/tc_active_record_table.rb +97 -0
- data/test/coord_sys/tc_ogc_cs.rb +356 -0
- data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
- data/test/coord_sys/tc_sr_org.rb +70 -0
- data/test/coord_sys/tc_url_reader.rb +82 -0
- data/test/geos/tc_polygon.rb +24 -0
- metadata +21 -3
@@ -0,0 +1,138 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# OGC CS factory for RGeo
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
module CoordSys
|
40
|
+
|
41
|
+
|
42
|
+
# This module contains an implementation of the CS (coordinate
|
43
|
+
# systems) package of the OGC Coordinate Transform spec. It contains
|
44
|
+
# classes for representing ellipsoids, datums, coordinate systems,
|
45
|
+
# and other related concepts, as well as a parser for the WKT format
|
46
|
+
# for specifying coordinate systems.
|
47
|
+
#
|
48
|
+
# Generally, the easiest way to create coordinate system objects is
|
49
|
+
# to use RGeo::CoordSys::CS.create_from_wkt, which parses the WKT
|
50
|
+
# format. This and other methods of the FactoryMethods module are all
|
51
|
+
# available as convenient module functions on the CS module.
|
52
|
+
#
|
53
|
+
# Almost the entire spec is implemented here. Currently missing are:
|
54
|
+
#
|
55
|
+
# * XML format is not implemented. We're assuming that WKT is the
|
56
|
+
# preferred format.
|
57
|
+
# * The PT and CT packages are not implemented.
|
58
|
+
# * FittedCoordinateSystem is not implemented.
|
59
|
+
|
60
|
+
module CS
|
61
|
+
|
62
|
+
|
63
|
+
module FactoryMethods
|
64
|
+
|
65
|
+
def create_compound_coordinate_system(name_, head_, tail_)
|
66
|
+
CompoundCoordinateSystem.create(name_, head_, tail_)
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_ellipsoid(name_, semi_major_axis_, semi_minor_axis_, linear_unit_)
|
70
|
+
Ellipsoid.create_ellipsoid(name_, semi_major_axis_, semi_minor_axis_, linear_unit_)
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_flattened_sphere(name_, semi_major_axis_, inverse_flattening_, linear_unit_)
|
74
|
+
Ellipsoid.create_flattened_sphere(name_, semi_major_axis_, inverse_flattening_, linear_unit_)
|
75
|
+
end
|
76
|
+
|
77
|
+
def create_from_wkt(str_)
|
78
|
+
WKTParser.new(str_).parse
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_geographic_coordinate_system(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_)
|
82
|
+
GeographicCoordinateSystem.create(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_)
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_horizontal_datum(name_, horizontal_datum_type_, ellipsoid_, to_wgs84_)
|
86
|
+
HorizontalDatum.create(name_, horizontal_datum_type_, ellipsoid_, to_wgs84_)
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_local_coordinate_system(name_, datum_, unit_, axes_)
|
90
|
+
LocalCoordinateSystem.create(name_, datum_, unit_, axes_)
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_local_datum(name_, local_datum_type_)
|
94
|
+
LocalDatum.create(name, local_datum_type_)
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_prime_meridian(name_, angular_unit_, longitude_)
|
98
|
+
PrimeMeridian.create(name, angular_unit_, longitude_)
|
99
|
+
end
|
100
|
+
|
101
|
+
def create_projected_coordinate_system(name_, gcs_, projection_, linear_unit_, axis0_, axis1_)
|
102
|
+
ProjectedCoordinateSystem.create(name_, gcs_, projection_, linear_unit_, axis0_, axis1_)
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_projection(name_, wkt_projection_class_, parameters_)
|
106
|
+
Projection.create(name_, wkt_projection_class_, parameters_)
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_vertical_coordinate_system(name_, vertical_datum_, vertical_unit_, axis_)
|
110
|
+
VerticalCoordinateSystem.create(name_, vertical_datum_, vertical_unit_, axis_)
|
111
|
+
end
|
112
|
+
|
113
|
+
def create_vertical_datum(name_, vertical_datum_type_)
|
114
|
+
VerticalDatum.create(name_, vertical_datum_type_)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
class CoordinateSystemFactory
|
121
|
+
|
122
|
+
include FactoryMethods
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
class << self
|
128
|
+
|
129
|
+
include FactoryMethods
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# OGC CS wkt parser for RGeo
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module RGeo
|
38
|
+
|
39
|
+
module CoordSys
|
40
|
+
|
41
|
+
|
42
|
+
module CS
|
43
|
+
|
44
|
+
|
45
|
+
class WKTParser # :nodoc:
|
46
|
+
|
47
|
+
def initialize(str_)
|
48
|
+
@scanner = ::StringScanner.new(str_)
|
49
|
+
next_token
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def parse(containing_type_=nil)
|
54
|
+
if @cur_token.kind_of?(QuotedString) ||
|
55
|
+
@cur_token.kind_of?(::Numeric) ||
|
56
|
+
(containing_type_ == 'AXIS' && @cur_token.kind_of?(TypeString))
|
57
|
+
value_ = @cur_token
|
58
|
+
next_token
|
59
|
+
return value_
|
60
|
+
end
|
61
|
+
unless @cur_token.kind_of?(TypeString)
|
62
|
+
raise Error::ParseError("Found token #{@cur_token} when we expected a value")
|
63
|
+
end
|
64
|
+
type_ = @cur_token
|
65
|
+
next_token
|
66
|
+
consume_token_type(:begin)
|
67
|
+
args_ = ArgumentList.new
|
68
|
+
args_ << parse(type_)
|
69
|
+
loop do
|
70
|
+
break unless @cur_token == :comma
|
71
|
+
next_token
|
72
|
+
args_ << parse(type_)
|
73
|
+
end
|
74
|
+
consume_token_type(:end)
|
75
|
+
obj_ = nil
|
76
|
+
case type_
|
77
|
+
when 'AUTHORITY'
|
78
|
+
obj_ = AuthorityClause.new(args_.shift(QuotedString), args_.shift(QuotedString))
|
79
|
+
when 'AXIS'
|
80
|
+
obj_ = AxisInfo.create(args_.shift(QuotedString), args_.shift(TypeString))
|
81
|
+
when 'TOWGS84'
|
82
|
+
bursa_wolf_params_ = args_.find_all(::Numeric)
|
83
|
+
unless bursa_wolf_params_.size == 7
|
84
|
+
raise Error::ParseError("Expected 7 Bursa Wolf parameters but found #{bursa_wolf_params_.size}")
|
85
|
+
end
|
86
|
+
obj_ = WGS84ConversionInfo.create(*bursa_wolf_params_)
|
87
|
+
when 'UNIT'
|
88
|
+
case containing_type_
|
89
|
+
when 'GEOCCS', 'VERT_CS', 'PROJCS', 'SPHEROID'
|
90
|
+
klass_ = LinearUnit
|
91
|
+
when 'GEOGCS'
|
92
|
+
klass_ = AngularUnit
|
93
|
+
else
|
94
|
+
klass_ = Unit
|
95
|
+
end
|
96
|
+
obj_ = klass_.create(args_.shift(QuotedString), args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
|
97
|
+
when 'PARAMETER'
|
98
|
+
obj_ = ProjectionParameter.create(args_.shift(QuotedString), args_.shift(::Numeric))
|
99
|
+
when 'PRIMEM'
|
100
|
+
obj_ = PrimeMeridian.create(args_.shift(QuotedString), nil, args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
|
101
|
+
when 'SPHEROID'
|
102
|
+
obj_ = Ellipsoid.create_flattened_sphere(args_.shift(QuotedString), args_.shift(::Numeric), args_.shift(::Numeric), args_.find_first(LinearUnit), *args_.find_first(AuthorityClause).to_a)
|
103
|
+
when 'PROJECTION'
|
104
|
+
name_ = args_.shift(QuotedString)
|
105
|
+
obj_ = Projection.create(name_, name_, args_.find_all(ProjectionParameter), *args_.find_first(AuthorityClause).to_a)
|
106
|
+
when 'DATUM'
|
107
|
+
name_ = args_.shift(QuotedString)
|
108
|
+
ellipsoid_ = args_.find_first(Ellipsoid)
|
109
|
+
to_wgs84_ = args_.find_first(WGS84ConversionInfo)
|
110
|
+
obj_ = HorizontalDatum.create(name_, HD_GEOCENTRIC, ellipsoid_, to_wgs84_, *args_.find_first(AuthorityClause).to_a)
|
111
|
+
when 'VERT_DATUM'
|
112
|
+
obj_ = VerticalDatum.create(args_.shift(QuotedString), args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
|
113
|
+
when 'LOCAL_DATUM'
|
114
|
+
obj_ = LocalDatum.create(args_.shift(QuotedString), args_.shift(::Numeric), *args_.find_first(AuthorityClause).to_a)
|
115
|
+
when 'COMPD_CS'
|
116
|
+
obj_ = CompoundCoordinateSystem.create(args_.shift(QuotedString), args_.shift(CoordinateSystem), args_.shift(CoordinateSystem), *args_.find_first(AuthorityClause).to_a)
|
117
|
+
when 'LOCAL_CS'
|
118
|
+
name_ = args_.shift(QuotedString)
|
119
|
+
local_datum_ = args_.find_first(LocalDatum)
|
120
|
+
unit_ = args_.find_first(Unit)
|
121
|
+
axes_ = args_.find_all(AxisInfo)
|
122
|
+
unless axes_.size > 0
|
123
|
+
raise Error::ParseError("Expected at least one AXIS in a LOCAL_CS")
|
124
|
+
end
|
125
|
+
obj_ = LocalCoordinateSystem.create(name_, local_datum_, unit_, axes_, *args_.find_first(AuthorityClause).to_a)
|
126
|
+
when 'GEOCCS'
|
127
|
+
name_ = args_.shift(QuotedString)
|
128
|
+
horizontal_datum_ = args_.find_first(HorizontalDatum)
|
129
|
+
prime_meridian_ = args_.find_first(PrimeMeridian)
|
130
|
+
linear_unit_ = args_.find_first(LinearUnit)
|
131
|
+
axes_ = args_.find_all(AxisInfo)
|
132
|
+
unless axes_.size == 0 || axes_.size == 3
|
133
|
+
raise Error::ParseError("GEOCCS must contain either 0 or 3 AXIS parameters")
|
134
|
+
end
|
135
|
+
obj_ = GeocentricCoordinateSystem.create(name_, horizontal_datum_, prime_meridian_, linear_unit_, axes_[0], axes_[1], axes_[2], *args_.find_first(AuthorityClause).to_a)
|
136
|
+
when 'VERT_CS'
|
137
|
+
name_ = args_.shift(QuotedString)
|
138
|
+
vertical_datum_ = args_.find_first(VerticalDatum)
|
139
|
+
linear_unit_ = args_.find_first(LinearUnit)
|
140
|
+
axis_ = args_.find_first(AxisInfo)
|
141
|
+
obj_ = VerticalCoordinateSystem.create(name_, vertical_datum_, linear_unit_, axis_, *args_.find_first(AuthorityClause).to_a)
|
142
|
+
when 'GEOGCS'
|
143
|
+
name_ = args_.shift(QuotedString)
|
144
|
+
horizontal_datum_ = args_.find_first(HorizontalDatum)
|
145
|
+
prime_meridian_ = args_.find_first(PrimeMeridian)
|
146
|
+
angular_unit_ = args_.find_first(AngularUnit)
|
147
|
+
axes_ = args_.find_all(AxisInfo)
|
148
|
+
unless axes_.size == 0 || axes_.size == 2
|
149
|
+
raise Error::ParseError("GEOGCS must contain either 0 or 2 AXIS parameters")
|
150
|
+
end
|
151
|
+
obj_ = GeographicCoordinateSystem.create(name_, angular_unit_, horizontal_datum_, prime_meridian_, axes_[0], axes_[1], *args_.find_first(AuthorityClause).to_a)
|
152
|
+
when 'PROJCS'
|
153
|
+
name_ = args_.shift(QuotedString)
|
154
|
+
geographic_coordinate_system_ = args_.find_first(GeographicCoordinateSystem)
|
155
|
+
projection_ = args_.find_first(Projection)
|
156
|
+
parameters_ = args_.find_all(ProjectionParameter)
|
157
|
+
projection_.instance_variable_get(:@parameters).concat(parameters_)
|
158
|
+
linear_unit_ = args_.find_first(LinearUnit)
|
159
|
+
axes_ = args_.find_all(AxisInfo)
|
160
|
+
unless axes_.size == 0 || axes_.size == 2
|
161
|
+
raise Error::ParseError("PROJCS must contain either 0 or 2 AXIS parameters")
|
162
|
+
end
|
163
|
+
obj_ = ProjectedCoordinateSystem.create(name_, geographic_coordinate_system_, projection_, linear_unit_, axes_[0], axes_[1], *args_.find_first(AuthorityClause).to_a)
|
164
|
+
else
|
165
|
+
raise Error::ParseError, "Unrecognized type: #{type_}"
|
166
|
+
end
|
167
|
+
args_.assert_empty
|
168
|
+
obj_
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def consume_token_type(type_) # :nodoc:
|
173
|
+
expect_token_type(type_)
|
174
|
+
tok_ = @cur_token
|
175
|
+
next_token
|
176
|
+
tok_
|
177
|
+
end
|
178
|
+
|
179
|
+
def expect_token_type(type_) # :nodoc:
|
180
|
+
unless type_ === @cur_token
|
181
|
+
raise Error::ParseError, "#{type_.inspect} expected but #{@cur_token.inspect} found."
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def next_token # :nodoc:
|
186
|
+
@scanner.skip(/\s+/)
|
187
|
+
case @scanner.peek(1)
|
188
|
+
when '"'
|
189
|
+
@scanner.getch
|
190
|
+
@cur_token = QuotedString.new(@scanner.scan(/[^"]*/))
|
191
|
+
@scanner.getch
|
192
|
+
when ','
|
193
|
+
@scanner.getch
|
194
|
+
@cur_token = :comma
|
195
|
+
when '(','['
|
196
|
+
@scanner.getch
|
197
|
+
@cur_token = :begin
|
198
|
+
when ']',')'
|
199
|
+
@scanner.getch
|
200
|
+
@cur_token = :end
|
201
|
+
when /[a-zA-Z]/
|
202
|
+
@cur_token = TypeString.new(@scanner.scan(/[a-zA-Z]\w*/))
|
203
|
+
when '', nil
|
204
|
+
@cur_token = nil
|
205
|
+
else
|
206
|
+
@scanner.scan_until(/[^\s\(\)\[\],"]+/)
|
207
|
+
token_ = @scanner.matched
|
208
|
+
if token_ =~ /^[-+]?(\d+(\.\d*)?|\.\d+)(e[-+]?\d+)?$/
|
209
|
+
@cur_token = token_.to_f
|
210
|
+
else
|
211
|
+
raise Error::ParseError, "Bad token: #{token_.inspect}"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
@cur_token
|
215
|
+
end
|
216
|
+
|
217
|
+
def cur_token # :nodoc:
|
218
|
+
@cur_token
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
class QuotedString < ::String # :nodoc:
|
223
|
+
end
|
224
|
+
|
225
|
+
class TypeString < ::String # :nodoc:
|
226
|
+
end
|
227
|
+
|
228
|
+
class AuthorityClause # :nodoc:
|
229
|
+
|
230
|
+
def initialize(name_, code_)
|
231
|
+
@name = name_
|
232
|
+
@code = code_
|
233
|
+
end
|
234
|
+
|
235
|
+
def to_a
|
236
|
+
[@name, @code]
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
class ArgumentList # :nodoc:
|
243
|
+
|
244
|
+
def initialize
|
245
|
+
@values = []
|
246
|
+
end
|
247
|
+
|
248
|
+
def <<(value_)
|
249
|
+
@values << value_
|
250
|
+
end
|
251
|
+
|
252
|
+
def assert_empty
|
253
|
+
if @values.size > 0
|
254
|
+
names_ = @values.map do |val_|
|
255
|
+
val_.kind_of?(Base) ? val_._wkt_typename : val_.inspect
|
256
|
+
end
|
257
|
+
raise Error::ParseError, "#{@remaining} unexpected arguments: #{names_.join(', ')}"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def find_first(klass_)
|
262
|
+
@values.each_with_index do |val_, index_|
|
263
|
+
if val_.kind_of?(klass_)
|
264
|
+
@values.slice!(index_)
|
265
|
+
return val_
|
266
|
+
end
|
267
|
+
end
|
268
|
+
nil
|
269
|
+
end
|
270
|
+
|
271
|
+
def find_all(klass_)
|
272
|
+
results_ = []
|
273
|
+
nvalues_ = []
|
274
|
+
@values.each do |val_|
|
275
|
+
if val_.kind_of?(klass_)
|
276
|
+
results_ << val_
|
277
|
+
else
|
278
|
+
nvalues_ << val_
|
279
|
+
end
|
280
|
+
end
|
281
|
+
@values = nvalues_
|
282
|
+
results_
|
283
|
+
end
|
284
|
+
|
285
|
+
def shift(klass_=nil)
|
286
|
+
val_ = @values.shift
|
287
|
+
unless val_
|
288
|
+
raise Error::ParseError, "No arguments left... expected #{klass_}"
|
289
|
+
end
|
290
|
+
if klass_ && !val_.kind_of?(klass_)
|
291
|
+
raise Error::ParseError, "Expected #{klass_} but got #{val_.class}"
|
292
|
+
end
|
293
|
+
val_
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
data/lib/rgeo/coord_sys/proj4.rb
CHANGED
@@ -168,6 +168,9 @@ module RGeo
|
|
168
168
|
if defn_.kind_of?(::Hash)
|
169
169
|
defn_ = defn_.map{ |k_, v_| v_ ? "+#{k_}=#{v_}" : "+#{k_}" }.join(' ')
|
170
170
|
end
|
171
|
+
unless defn_ =~ /^\s*\+/
|
172
|
+
defn_ = defn_.sub(/^(\s*)/, '\1+').gsub(/(\s+)([^+\s])/, '\1+\2')
|
173
|
+
end
|
171
174
|
result_ = _create(defn_)
|
172
175
|
result_ = nil unless result_._valid?
|
173
176
|
end
|