schleyfox-rgeo 0.2.5
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 +199 -0
- data/README.rdoc +172 -0
- data/Spatial_Programming_With_RGeo.rdoc +440 -0
- data/Version +1 -0
- data/ext/geos_c_impl/extconf.rb +84 -0
- data/ext/geos_c_impl/factory.c +468 -0
- data/ext/geos_c_impl/factory.h +224 -0
- data/ext/geos_c_impl/geometry.c +705 -0
- data/ext/geos_c_impl/geometry.h +55 -0
- data/ext/geos_c_impl/geometry_collection.c +482 -0
- data/ext/geos_c_impl/geometry_collection.h +69 -0
- data/ext/geos_c_impl/line_string.c +509 -0
- data/ext/geos_c_impl/line_string.h +64 -0
- data/ext/geos_c_impl/main.c +70 -0
- data/ext/geos_c_impl/point.c +193 -0
- data/ext/geos_c_impl/point.h +62 -0
- data/ext/geos_c_impl/polygon.c +265 -0
- data/ext/geos_c_impl/polygon.h +66 -0
- data/ext/geos_c_impl/preface.h +50 -0
- data/ext/proj4_c_impl/extconf.rb +88 -0
- data/ext/proj4_c_impl/main.c +271 -0
- data/lib/rgeo.rb +124 -0
- data/lib/rgeo/cartesian.rb +60 -0
- data/lib/rgeo/cartesian/analysis.rb +118 -0
- data/lib/rgeo/cartesian/bounding_box.rb +337 -0
- data/lib/rgeo/cartesian/calculations.rb +161 -0
- data/lib/rgeo/cartesian/factory.rb +209 -0
- data/lib/rgeo/cartesian/feature_classes.rb +173 -0
- data/lib/rgeo/cartesian/feature_methods.rb +106 -0
- data/lib/rgeo/cartesian/interface.rb +150 -0
- data/lib/rgeo/coord_sys.rb +79 -0
- data/lib/rgeo/coord_sys/cs/entities.rb +1524 -0
- data/lib/rgeo/coord_sys/cs/factories.rb +208 -0
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +308 -0
- data/lib/rgeo/coord_sys/proj4.rb +312 -0
- data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +194 -0
- data/lib/rgeo/coord_sys/srs_database/interface.rb +165 -0
- data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +188 -0
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +108 -0
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +108 -0
- data/lib/rgeo/error.rb +63 -0
- data/lib/rgeo/feature.rb +88 -0
- data/lib/rgeo/feature/curve.rb +156 -0
- data/lib/rgeo/feature/factory.rb +332 -0
- data/lib/rgeo/feature/factory_generator.rb +138 -0
- data/lib/rgeo/feature/geometry.rb +614 -0
- data/lib/rgeo/feature/geometry_collection.rb +129 -0
- data/lib/rgeo/feature/line.rb +66 -0
- data/lib/rgeo/feature/line_string.rb +102 -0
- data/lib/rgeo/feature/linear_ring.rb +66 -0
- data/lib/rgeo/feature/multi_curve.rb +113 -0
- data/lib/rgeo/feature/multi_line_string.rb +66 -0
- data/lib/rgeo/feature/multi_point.rb +73 -0
- data/lib/rgeo/feature/multi_polygon.rb +97 -0
- data/lib/rgeo/feature/multi_surface.rb +116 -0
- data/lib/rgeo/feature/point.rb +120 -0
- data/lib/rgeo/feature/polygon.rb +141 -0
- data/lib/rgeo/feature/surface.rb +122 -0
- data/lib/rgeo/feature/types.rb +305 -0
- data/lib/rgeo/geographic.rb +75 -0
- data/lib/rgeo/geographic/factory.rb +287 -0
- data/lib/rgeo/geographic/interface.rb +410 -0
- data/lib/rgeo/geographic/proj4_projector.rb +98 -0
- data/lib/rgeo/geographic/projected_feature_classes.rb +213 -0
- data/lib/rgeo/geographic/projected_feature_methods.rb +228 -0
- data/lib/rgeo/geographic/projected_window.rb +467 -0
- data/lib/rgeo/geographic/simple_mercator_projector.rb +157 -0
- data/lib/rgeo/geographic/spherical_feature_classes.rb +212 -0
- data/lib/rgeo/geographic/spherical_feature_methods.rb +97 -0
- data/lib/rgeo/geographic/spherical_math.rb +206 -0
- data/lib/rgeo/geos.rb +72 -0
- data/lib/rgeo/geos/factory.rb +301 -0
- data/lib/rgeo/geos/impl_additions.rb +76 -0
- data/lib/rgeo/geos/interface.rb +139 -0
- data/lib/rgeo/geos/zm_factory.rb +275 -0
- data/lib/rgeo/geos/zm_impl.rb +432 -0
- data/lib/rgeo/impl_helper.rb +53 -0
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +235 -0
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +85 -0
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +197 -0
- data/lib/rgeo/impl_helper/basic_point_methods.rb +138 -0
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +121 -0
- data/lib/rgeo/impl_helper/math.rb +50 -0
- data/lib/rgeo/version.rb +52 -0
- data/lib/rgeo/wkrep.rb +72 -0
- data/lib/rgeo/wkrep/wkb_generator.rb +267 -0
- data/lib/rgeo/wkrep/wkb_parser.rb +315 -0
- data/lib/rgeo/wkrep/wkt_generator.rb +275 -0
- data/lib/rgeo/wkrep/wkt_parser.rb +496 -0
- data/test/common/geometry_collection_tests.rb +238 -0
- data/test/common/line_string_tests.rb +324 -0
- data/test/common/multi_line_string_tests.rb +209 -0
- data/test/common/multi_point_tests.rb +201 -0
- data/test/common/multi_polygon_tests.rb +208 -0
- data/test/common/point_tests.rb +331 -0
- data/test/common/polygon_tests.rb +232 -0
- data/test/coord_sys/tc_active_record_table.rb +102 -0
- data/test/coord_sys/tc_ogc_cs.rb +356 -0
- data/test/coord_sys/tc_proj4.rb +138 -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_factory.rb +91 -0
- data/test/geos/tc_geometry_collection.rb +62 -0
- data/test/geos/tc_line_string.rb +62 -0
- data/test/geos/tc_misc.rb +72 -0
- data/test/geos/tc_multi_line_string.rb +62 -0
- data/test/geos/tc_multi_point.rb +62 -0
- data/test/geos/tc_multi_polygon.rb +63 -0
- data/test/geos/tc_point.rb +86 -0
- data/test/geos/tc_polygon.rb +86 -0
- data/test/geos/tc_zmfactory.rb +85 -0
- data/test/projected_geographic/tc_geometry_collection.rb +62 -0
- data/test/projected_geographic/tc_line_string.rb +62 -0
- data/test/projected_geographic/tc_multi_line_string.rb +62 -0
- data/test/projected_geographic/tc_multi_point.rb +62 -0
- data/test/projected_geographic/tc_multi_polygon.rb +63 -0
- data/test/projected_geographic/tc_point.rb +93 -0
- data/test/projected_geographic/tc_polygon.rb +62 -0
- data/test/simple_cartesian/tc_calculations.rb +145 -0
- data/test/simple_cartesian/tc_geometry_collection.rb +69 -0
- data/test/simple_cartesian/tc_line_string.rb +70 -0
- data/test/simple_cartesian/tc_multi_line_string.rb +67 -0
- data/test/simple_cartesian/tc_multi_point.rb +67 -0
- data/test/simple_cartesian/tc_multi_polygon.rb +70 -0
- data/test/simple_cartesian/tc_point.rb +91 -0
- data/test/simple_cartesian/tc_polygon.rb +67 -0
- data/test/simple_mercator/tc_geometry_collection.rb +62 -0
- data/test/simple_mercator/tc_line_string.rb +62 -0
- data/test/simple_mercator/tc_multi_line_string.rb +62 -0
- data/test/simple_mercator/tc_multi_point.rb +62 -0
- data/test/simple_mercator/tc_multi_polygon.rb +63 -0
- data/test/simple_mercator/tc_point.rb +93 -0
- data/test/simple_mercator/tc_polygon.rb +62 -0
- data/test/simple_mercator/tc_window.rb +219 -0
- data/test/spherical_geographic/tc_calculations.rb +203 -0
- data/test/spherical_geographic/tc_geometry_collection.rb +70 -0
- data/test/spherical_geographic/tc_line_string.rb +70 -0
- data/test/spherical_geographic/tc_multi_line_string.rb +67 -0
- data/test/spherical_geographic/tc_multi_point.rb +67 -0
- data/test/spherical_geographic/tc_multi_polygon.rb +70 -0
- data/test/spherical_geographic/tc_point.rb +100 -0
- data/test/spherical_geographic/tc_polygon.rb +67 -0
- data/test/tc_cartesian_analysis.rb +107 -0
- data/test/tc_oneoff.rb +63 -0
- data/test/wkrep/tc_wkb_generator.rb +249 -0
- data/test/wkrep/tc_wkb_parser.rb +353 -0
- data/test/wkrep/tc_wkt_generator.rb +362 -0
- data/test/wkrep/tc_wkt_parser.rb +480 -0
- metadata +267 -0
@@ -0,0 +1,496 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Well-known text 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
|
+
require 'strscan'
|
38
|
+
|
39
|
+
|
40
|
+
module RGeo
|
41
|
+
|
42
|
+
module WKRep
|
43
|
+
|
44
|
+
|
45
|
+
# This class provides the functionality of parsing a geometry from
|
46
|
+
# WKT (well-known text) format. You may also customize the parser
|
47
|
+
# to recognize PostGIS EWKT extensions to the input, or Simple
|
48
|
+
# Features Specification 1.2 extensions for Z and M coordinates.
|
49
|
+
#
|
50
|
+
# To use this class, create an instance with the desired settings and
|
51
|
+
# customizations, and call the parse method.
|
52
|
+
#
|
53
|
+
# === Configuration options
|
54
|
+
#
|
55
|
+
# You must provide each parser with an RGeo::Feature::FactoryGenerator.
|
56
|
+
# It should understand the configuration options <tt>:srid</tt>,
|
57
|
+
# <tt>:has_z_coordinate</tt>, and <tt>:has_m_coordinate</tt>.
|
58
|
+
# You may also pass a specific RGeo::Feature::Factory, or nil to
|
59
|
+
# specify the default Cartesian FactoryGenerator.
|
60
|
+
#
|
61
|
+
# The following additional options are recognized. These can be passed
|
62
|
+
# to the constructor, or set on the object afterwards.
|
63
|
+
#
|
64
|
+
# [<tt>:support_ewkt</tt>]
|
65
|
+
# Activate support for PostGIS EWKT type tags, which appends an "M"
|
66
|
+
# to tags to indicate the presence of M but not Z, and also
|
67
|
+
# recognizes the SRID prefix. Default is false.
|
68
|
+
# [<tt>:support_wkt12</tt>]
|
69
|
+
# Activate support for SFS 1.2 extensions to the type codes, which
|
70
|
+
# use a "M", "Z", or "ZM" token to signal the presence of Z and M
|
71
|
+
# values in the data. SFS 1.2 types such as triangle, tin, and
|
72
|
+
# polyhedralsurface are NOT yet supported. Default is false.
|
73
|
+
# [<tt>:strict_wkt11</tt>]
|
74
|
+
# If true, parsing will proceed in SFS 1.1 strict mode, which
|
75
|
+
# disallows any values other than X or Y. This has no effect if
|
76
|
+
# support_ewkt or support_wkt12 are active. Default is false.
|
77
|
+
# [<tt>:ignore_extra_tokens</tt>]
|
78
|
+
# If true, extra tokens at the end of the data are ignored. If
|
79
|
+
# false (the default), extra tokens will trigger a parse error.
|
80
|
+
# [<tt>:default_srid</tt>]
|
81
|
+
# A SRID to pass to the factory generator if no SRID is present in
|
82
|
+
# the input. Defaults to nil (i.e. don't specify a SRID).
|
83
|
+
|
84
|
+
class WKTParser
|
85
|
+
|
86
|
+
|
87
|
+
# Create and configure a WKT parser. See the WKTParser
|
88
|
+
# documentation for the options that can be passed.
|
89
|
+
|
90
|
+
def initialize(factory_generator_=nil, opts_={})
|
91
|
+
self.factory_generator = factory_generator_
|
92
|
+
@support_ewkt = opts_[:support_ewkt] ? true : false
|
93
|
+
@support_wkt12 = opts_[:support_wkt12] ? true : false
|
94
|
+
@strict_wkt11 = @support_ewkt || @support_wkt12 ? false : opts_[:strict_wkt11] ? true : false
|
95
|
+
@ignore_extra_tokens = opts_[:ignore_extra_tokens] ? true : false
|
96
|
+
@default_srid = opts_[:default_srid]
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# Returns the factory generator. See WKTParser for details.
|
101
|
+
def factory_generator
|
102
|
+
@factory_generator
|
103
|
+
end
|
104
|
+
|
105
|
+
# If this parser was given an exact factory, returns it; otherwise
|
106
|
+
# returns nil.
|
107
|
+
def exact_factory
|
108
|
+
@exact_factory
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sets the factory_generator. See WKTParser for details.
|
112
|
+
def factory_generator=(value_)
|
113
|
+
if value_.kind_of?(Feature::Factory::Instance)
|
114
|
+
@factory_generator = Feature::FactoryGenerator.single(value_)
|
115
|
+
@exact_factory = value_
|
116
|
+
elsif value_.respond_to?(:call)
|
117
|
+
@factory_generator = value_
|
118
|
+
@exact_factory = nil
|
119
|
+
else
|
120
|
+
@factory_generator = Cartesian.method(:preferred_factory)
|
121
|
+
@exact_factory = nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Sets the factory_generator to the given block.
|
126
|
+
# See WKTParser for details.
|
127
|
+
def to_generate_factory(&block_)
|
128
|
+
self.factory_generator = block_
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns true if this parser supports EWKT.
|
132
|
+
# See WKTParser for details.
|
133
|
+
def support_ewkt?
|
134
|
+
@support_ewkt
|
135
|
+
end
|
136
|
+
|
137
|
+
# Sets the the support_ewkt flag. See WKTParser for details.
|
138
|
+
def support_ewkt=(value_)
|
139
|
+
@support_ewkt = value_ ? true : false
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns true if this parser supports SFS 1.2 extensions.
|
143
|
+
# See WKTParser for details.
|
144
|
+
def support_wkt12?
|
145
|
+
@support_wkt12
|
146
|
+
end
|
147
|
+
|
148
|
+
# Sets the the support_wkt12 flag. See WKTParser for details.
|
149
|
+
def support_wkt12=(value_)
|
150
|
+
@support_wkt12 = value_ ? true : false
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns true if this parser strictly adheres to WKT 1.1.
|
154
|
+
# See WKTParser for details.
|
155
|
+
def strict_wkt11?
|
156
|
+
@strict_wkt11
|
157
|
+
end
|
158
|
+
|
159
|
+
# Sets the the strict_wkt11 flag. See WKTParser for details.
|
160
|
+
def strict_wkt11=(value_)
|
161
|
+
@strict_wkt11 = value_ ? true : false
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns true if this parser ignores extra tokens.
|
165
|
+
# See WKTParser for details.
|
166
|
+
def ignore_extra_tokens?
|
167
|
+
@ignore_extra_tokens
|
168
|
+
end
|
169
|
+
|
170
|
+
# Sets the the ignore_extra_tokens flag. See WKTParser for details.
|
171
|
+
def ignore_extra_tokens=(value_)
|
172
|
+
@ignore_extra_tokens = value_ ? true : false
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# Parse the given string, and return a geometry object.
|
177
|
+
|
178
|
+
def parse(str_)
|
179
|
+
str_ = str_.downcase
|
180
|
+
@cur_factory = @exact_factory
|
181
|
+
if @cur_factory
|
182
|
+
@cur_factory_support_z = @cur_factory.property(:has_z_coordinate) ? true : false
|
183
|
+
@cur_factory_support_m = @cur_factory.property(:has_m_coordinate) ? true : false
|
184
|
+
end
|
185
|
+
@cur_expect_z = nil
|
186
|
+
@cur_expect_m = nil
|
187
|
+
@cur_srid = @default_srid
|
188
|
+
if @support_ewkt && str_ =~ /^srid=(\d+);/i
|
189
|
+
str_ = $'
|
190
|
+
@cur_srid = $1.to_i
|
191
|
+
end
|
192
|
+
begin
|
193
|
+
_start_scanner(str_)
|
194
|
+
obj_ = _parse_type_tag(false)
|
195
|
+
if @cur_token && !@ignore_extra_tokens
|
196
|
+
raise Error::ParseError, "Extra tokens beginning with #{@cur_token.inspect}."
|
197
|
+
end
|
198
|
+
ensure
|
199
|
+
_clean_scanner
|
200
|
+
end
|
201
|
+
obj_
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
def _check_factory_support # :nodoc:
|
206
|
+
if @cur_expect_z && !@cur_factory_support_z
|
207
|
+
raise Error::ParseError, "Geometry calls for Z coordinate but factory doesn't support it."
|
208
|
+
end
|
209
|
+
if @cur_expect_m && !@cur_factory_support_m
|
210
|
+
raise Error::ParseError, "Geometry calls for M coordinate but factory doesn't support it."
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def _ensure_factory # :nodoc:
|
216
|
+
unless @cur_factory
|
217
|
+
@cur_factory = @factory_generator.call(:srid => @cur_srid, :has_z_coordinate => @cur_expect_z, :has_m_coordinate => @cur_expect_m)
|
218
|
+
@cur_factory_support_z = @cur_factory.property(:has_z_coordinate) ? true : false
|
219
|
+
@cur_factory_support_m = @cur_factory.property(:has_m_coordinate) ? true : false
|
220
|
+
_check_factory_support unless @cur_expect_z.nil?
|
221
|
+
end
|
222
|
+
@cur_factory
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
def _parse_type_tag(contained_) # :nodoc:
|
227
|
+
_expect_token_type(::String)
|
228
|
+
if @support_ewkt && @cur_token =~ /^(.+)(m)$/
|
229
|
+
type_ = $1
|
230
|
+
zm_ = $2
|
231
|
+
else
|
232
|
+
type_ = @cur_token
|
233
|
+
zm_ = ''
|
234
|
+
end
|
235
|
+
_next_token
|
236
|
+
if zm_.length == 0 && @support_wkt12 && @cur_token.kind_of?(::String) && @cur_token =~ /^z?m?$/
|
237
|
+
zm_ = @cur_token
|
238
|
+
_next_token
|
239
|
+
end
|
240
|
+
if zm_.length > 0 || @strict_wkt11
|
241
|
+
creating_expectation_ = @cur_expect_z.nil?
|
242
|
+
expect_z_ = zm_[0,1] == 'z' ? true : false
|
243
|
+
if @cur_expect_z.nil?
|
244
|
+
@cur_expect_z = expect_z_
|
245
|
+
elsif expect_z_ != @cur_expect_z
|
246
|
+
raise Error::ParseError, "Surrounding collection has Z but contained geometry doesn't."
|
247
|
+
end
|
248
|
+
expect_m_ = zm_[-1,1] == 'm' ? true : false
|
249
|
+
if @cur_expect_m.nil?
|
250
|
+
@cur_expect_m = expect_m_
|
251
|
+
else expect_m_ != @cur_expect_m
|
252
|
+
raise Error::ParseError, "Surrounding collection has M but contained geometry doesn't."
|
253
|
+
end
|
254
|
+
if creating_expectation_
|
255
|
+
if @cur_factory
|
256
|
+
_check_factory_support
|
257
|
+
else
|
258
|
+
_ensure_factory
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
case type_
|
263
|
+
when 'point'
|
264
|
+
_parse_point(true)
|
265
|
+
when 'linestring'
|
266
|
+
_parse_line_string
|
267
|
+
when 'polygon'
|
268
|
+
_parse_polygon
|
269
|
+
when 'geometrycollection'
|
270
|
+
_parse_geometry_collection
|
271
|
+
when 'multipoint'
|
272
|
+
_parse_multi_point
|
273
|
+
when 'multilinestring'
|
274
|
+
_parse_multi_line_string
|
275
|
+
when 'multipolygon'
|
276
|
+
_parse_multi_polygon
|
277
|
+
else
|
278
|
+
raise Error::ParseError, "Unknown type tag: #{type_.inspect}."
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
def _parse_coords # :nodoc:
|
284
|
+
_expect_token_type(::Numeric)
|
285
|
+
x_ = @cur_token
|
286
|
+
_next_token
|
287
|
+
_expect_token_type(::Numeric)
|
288
|
+
y_ = @cur_token
|
289
|
+
_next_token
|
290
|
+
extra_ = []
|
291
|
+
if @cur_expect_z.nil?
|
292
|
+
while ::Numeric === @cur_token
|
293
|
+
extra_ << @cur_token
|
294
|
+
_next_token
|
295
|
+
end
|
296
|
+
num_extras_ = extra_.size
|
297
|
+
@cur_expect_z = num_extras_ > 0 && (!@cur_factory || @cur_factory_support_z) ? true : false
|
298
|
+
num_extras_ -= 1 if @cur_expect_z
|
299
|
+
@cur_expect_m = num_extras_ > 0 && (!@cur_factory || @cur_factory_support_m) ? true : false
|
300
|
+
num_extras_ -= 1 if @cur_expect_m
|
301
|
+
if num_extras_ > 0
|
302
|
+
raise Error::ParseError, "Found #{extra_.size+2} coordinates, which is too many for this factory."
|
303
|
+
end
|
304
|
+
_ensure_factory
|
305
|
+
else
|
306
|
+
val_ = 0
|
307
|
+
if @cur_expect_z
|
308
|
+
_expect_token_type(::Numeric)
|
309
|
+
val_ = @cur_token
|
310
|
+
_next_token
|
311
|
+
end
|
312
|
+
if @cur_factory_support_z
|
313
|
+
extra_ << val_
|
314
|
+
end
|
315
|
+
val_ = 0
|
316
|
+
if @cur_expect_m
|
317
|
+
_expect_token_type(::Numeric)
|
318
|
+
val_ = @cur_token
|
319
|
+
_next_token
|
320
|
+
end
|
321
|
+
if @cur_factory_support_m
|
322
|
+
extra_ << val_
|
323
|
+
end
|
324
|
+
end
|
325
|
+
@cur_factory.point(x_, y_, *extra_)
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
def _parse_point(convert_empty_=false) # :nodoc:
|
330
|
+
if convert_empty_ && @cur_token == 'empty'
|
331
|
+
point_ = _ensure_factory.multi_point([])
|
332
|
+
else
|
333
|
+
_expect_token_type(:begin)
|
334
|
+
_next_token
|
335
|
+
point_ = _parse_coords
|
336
|
+
_expect_token_type(:end)
|
337
|
+
end
|
338
|
+
_next_token
|
339
|
+
point_
|
340
|
+
end
|
341
|
+
|
342
|
+
|
343
|
+
def _parse_line_string # :nodoc:
|
344
|
+
points_ = []
|
345
|
+
if @cur_token != 'empty'
|
346
|
+
_expect_token_type(:begin)
|
347
|
+
_next_token
|
348
|
+
loop do
|
349
|
+
points_ << _parse_coords
|
350
|
+
break if @cur_token == :end
|
351
|
+
_expect_token_type(:comma)
|
352
|
+
_next_token
|
353
|
+
end
|
354
|
+
end
|
355
|
+
_next_token
|
356
|
+
_ensure_factory.line_string(points_)
|
357
|
+
end
|
358
|
+
|
359
|
+
|
360
|
+
def _parse_polygon # :nodoc:
|
361
|
+
inner_rings_ = []
|
362
|
+
if @cur_token == 'empty'
|
363
|
+
outer_ring_ = _ensure_factory.linear_ring([])
|
364
|
+
else
|
365
|
+
_expect_token_type(:begin)
|
366
|
+
_next_token
|
367
|
+
outer_ring_ = _parse_line_string
|
368
|
+
loop do
|
369
|
+
break if @cur_token == :end
|
370
|
+
_expect_token_type(:comma)
|
371
|
+
_next_token
|
372
|
+
inner_rings_ << _parse_line_string
|
373
|
+
end
|
374
|
+
end
|
375
|
+
_next_token
|
376
|
+
_ensure_factory.polygon(outer_ring_, inner_rings_)
|
377
|
+
end
|
378
|
+
|
379
|
+
|
380
|
+
def _parse_geometry_collection # :nodoc:
|
381
|
+
geometries_ = []
|
382
|
+
if @cur_token != 'empty'
|
383
|
+
_expect_token_type(:begin)
|
384
|
+
_next_token
|
385
|
+
loop do
|
386
|
+
geometries_ << _parse_type_tag(true)
|
387
|
+
break if @cur_token == :end
|
388
|
+
_expect_token_type(:comma)
|
389
|
+
_next_token
|
390
|
+
end
|
391
|
+
end
|
392
|
+
_next_token
|
393
|
+
_ensure_factory.collection(geometries_)
|
394
|
+
end
|
395
|
+
|
396
|
+
|
397
|
+
def _parse_multi_point # :nodoc:
|
398
|
+
points_ = []
|
399
|
+
if @cur_token != 'empty'
|
400
|
+
_expect_token_type(:begin)
|
401
|
+
_next_token
|
402
|
+
loop do
|
403
|
+
points_ << _parse_point
|
404
|
+
break if @cur_token == :end
|
405
|
+
_expect_token_type(:comma)
|
406
|
+
_next_token
|
407
|
+
end
|
408
|
+
end
|
409
|
+
_next_token
|
410
|
+
_ensure_factory.multi_point(points_)
|
411
|
+
end
|
412
|
+
|
413
|
+
|
414
|
+
def _parse_multi_line_string # :nodoc:
|
415
|
+
line_strings_ = []
|
416
|
+
if @cur_token != 'empty'
|
417
|
+
_expect_token_type(:begin)
|
418
|
+
_next_token
|
419
|
+
loop do
|
420
|
+
line_strings_ << _parse_line_string
|
421
|
+
break if @cur_token == :end
|
422
|
+
_expect_token_type(:comma)
|
423
|
+
_next_token
|
424
|
+
end
|
425
|
+
end
|
426
|
+
_next_token
|
427
|
+
_ensure_factory.multi_line_string(line_strings_)
|
428
|
+
end
|
429
|
+
|
430
|
+
|
431
|
+
def _parse_multi_polygon # :nodoc:
|
432
|
+
polygons_ = []
|
433
|
+
if @cur_token != 'empty'
|
434
|
+
_expect_token_type(:begin)
|
435
|
+
_next_token
|
436
|
+
loop do
|
437
|
+
polygons_ << _parse_polygon
|
438
|
+
break if @cur_token == :end
|
439
|
+
_expect_token_type(:comma)
|
440
|
+
_next_token
|
441
|
+
end
|
442
|
+
end
|
443
|
+
_next_token
|
444
|
+
_ensure_factory.multi_polygon(polygons_)
|
445
|
+
end
|
446
|
+
|
447
|
+
|
448
|
+
def _start_scanner(str_) # :nodoc:
|
449
|
+
@_scanner = ::StringScanner.new(str_)
|
450
|
+
_next_token
|
451
|
+
end
|
452
|
+
|
453
|
+
|
454
|
+
def _clean_scanner # :nodoc:
|
455
|
+
@_scanner = nil
|
456
|
+
@cur_token = nil
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
def _expect_token_type(type_) # :nodoc:
|
461
|
+
unless type_ === @cur_token
|
462
|
+
raise Error::ParseError, "#{type_.inspect} expected but #{@cur_token.inspect} found."
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
|
467
|
+
def _next_token # :nodoc:
|
468
|
+
if @_scanner.scan_until(/\(|\)|\[|\]|,|[^\s\(\)\[\],]+/)
|
469
|
+
token_ = @_scanner.matched
|
470
|
+
case token_
|
471
|
+
when /^[-+]?(\d+(\.\d*)?|\.\d+)(e[-+]?\d+)?$/
|
472
|
+
@cur_token = token_.to_f
|
473
|
+
when /^[a-z]+$/
|
474
|
+
@cur_token = token_
|
475
|
+
when ','
|
476
|
+
@cur_token = :comma
|
477
|
+
when '(','['
|
478
|
+
@cur_token = :begin
|
479
|
+
when ']',')'
|
480
|
+
@cur_token = :end
|
481
|
+
else
|
482
|
+
raise Error::ParseError, "Bad token: #{token_.inspect}"
|
483
|
+
end
|
484
|
+
else
|
485
|
+
@cur_token = nil
|
486
|
+
end
|
487
|
+
@cur_token
|
488
|
+
end
|
489
|
+
|
490
|
+
|
491
|
+
end
|
492
|
+
|
493
|
+
|
494
|
+
end
|
495
|
+
|
496
|
+
end
|