rgeo 1.1.2 → 2.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/ext/geos_c_impl/extconf.rb +5 -3
- data/ext/geos_c_impl/factory.c +4 -4
- data/ext/geos_c_impl/geometry.c +1 -1
- data/lib/rgeo.rb +2 -4
- data/lib/rgeo/cartesian.rb +6 -16
- data/lib/rgeo/cartesian/analysis.rb +22 -20
- data/lib/rgeo/cartesian/bounding_box.rb +83 -79
- data/lib/rgeo/cartesian/calculations.rb +40 -38
- data/lib/rgeo/cartesian/factory.rb +134 -169
- data/lib/rgeo/cartesian/feature_classes.rb +2 -18
- data/lib/rgeo/cartesian/feature_methods.rb +37 -39
- data/lib/rgeo/cartesian/interface.rb +11 -9
- data/lib/rgeo/coord_sys.rb +9 -8
- data/lib/rgeo/coord_sys/cs/entities.rb +345 -303
- data/lib/rgeo/coord_sys/cs/factories.rb +30 -28
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +128 -126
- data/lib/rgeo/coord_sys/srs_database/{interface.rb → entry.rb} +26 -32
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +19 -17
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +21 -19
- data/lib/rgeo/error.rb +3 -1
- data/lib/rgeo/feature.rb +23 -34
- data/lib/rgeo/feature/curve.rb +2 -0
- data/lib/rgeo/feature/factory.rb +15 -13
- data/lib/rgeo/feature/factory_generator.rb +7 -5
- data/lib/rgeo/feature/geometry.rb +31 -29
- data/lib/rgeo/feature/geometry_collection.rb +6 -4
- data/lib/rgeo/feature/line.rb +2 -0
- data/lib/rgeo/feature/line_string.rb +3 -1
- data/lib/rgeo/feature/linear_ring.rb +2 -0
- data/lib/rgeo/feature/multi_curve.rb +2 -0
- data/lib/rgeo/feature/multi_line_string.rb +2 -0
- data/lib/rgeo/feature/multi_point.rb +2 -0
- data/lib/rgeo/feature/multi_polygon.rb +2 -0
- data/lib/rgeo/feature/multi_surface.rb +2 -0
- data/lib/rgeo/feature/point.rb +2 -0
- data/lib/rgeo/feature/polygon.rb +3 -1
- data/lib/rgeo/feature/surface.rb +2 -0
- data/lib/rgeo/feature/types.rb +107 -103
- data/lib/rgeo/geographic.rb +17 -27
- data/lib/rgeo/geographic/factory.rb +154 -199
- data/lib/rgeo/geographic/interface.rb +141 -137
- data/lib/rgeo/geographic/proj4_projector.rb +28 -23
- data/lib/rgeo/geographic/projected_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/projected_feature_methods.rb +59 -49
- data/lib/rgeo/geographic/projected_window.rb +4 -2
- data/lib/rgeo/geographic/simple_mercator_projector.rb +41 -39
- data/lib/rgeo/geographic/spherical_feature_classes.rb +2 -18
- data/lib/rgeo/geographic/spherical_feature_methods.rb +67 -67
- data/lib/rgeo/geographic/spherical_math.rb +81 -87
- data/lib/rgeo/geos.rb +23 -34
- data/lib/rgeo/geos/capi_factory.rb +106 -135
- data/lib/rgeo/geos/capi_feature_classes.rb +19 -37
- data/lib/rgeo/geos/ffi_factory.rb +276 -297
- data/lib/rgeo/geos/ffi_feature_classes.rb +2 -20
- data/lib/rgeo/geos/ffi_feature_methods.rb +170 -166
- data/lib/rgeo/geos/interface.rb +25 -23
- data/lib/rgeo/geos/utils.rb +47 -39
- data/lib/rgeo/geos/zm_factory.rb +171 -185
- data/lib/rgeo/geos/zm_feature_classes.rb +2 -20
- data/lib/rgeo/geos/zm_feature_methods.rb +76 -72
- data/lib/rgeo/impl_helper.rb +1 -11
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +72 -75
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +21 -23
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +57 -49
- data/lib/rgeo/impl_helper/basic_point_methods.rb +29 -25
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +31 -27
- data/lib/rgeo/impl_helper/math.rb +2 -0
- data/lib/rgeo/impl_helper/utils.rb +9 -15
- data/lib/rgeo/version.rb +3 -1
- data/lib/rgeo/wkrep.rb +20 -30
- data/lib/rgeo/wkrep/wkb_generator.rb +87 -84
- data/lib/rgeo/wkrep/wkb_parser.rb +93 -93
- data/lib/rgeo/wkrep/wkt_generator.rb +67 -63
- data/lib/rgeo/wkrep/wkt_parser.rb +172 -168
- metadata +17 -32
- data/lib/rgeo/feature/mixins.rb +0 -143
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# Well-known text generator for RGeo
|
@@ -48,12 +50,12 @@ module RGeo
|
|
48
50
|
# Create and configure a WKT generator. See the WKTGenerator
|
49
51
|
# documentation for the options that can be passed.
|
50
52
|
|
51
|
-
def initialize(
|
52
|
-
@tag_format =
|
53
|
+
def initialize(opts = {})
|
54
|
+
@tag_format = opts[:tag_format] || opts[:type_format] || :wkt11
|
53
55
|
@emit_ewkt_srid = @tag_format == :ewkt ?
|
54
|
-
(
|
55
|
-
@square_brackets =
|
56
|
-
@convert_case =
|
56
|
+
(opts[:emit_ewkt_srid] ? true : false) : nil
|
57
|
+
@square_brackets = opts[:square_brackets] ? true : false
|
58
|
+
@convert_case = opts[:convert_case]
|
57
59
|
end
|
58
60
|
|
59
61
|
# Returns the format for type tags. See WKTGenerator for details.
|
@@ -74,7 +76,7 @@ module RGeo
|
|
74
76
|
# Returns the case for output. See WKTGenerator for details.
|
75
77
|
attr_reader :convert_case
|
76
78
|
|
77
|
-
def
|
79
|
+
def properties
|
78
80
|
{
|
79
81
|
"tag_format" => @tag_format.to_s,
|
80
82
|
"emit_ewkt_srid" => @emit_ewkt_srid,
|
@@ -86,120 +88,122 @@ module RGeo
|
|
86
88
|
# Generate and return the WKT format for the given geometry object,
|
87
89
|
# according to the current settings.
|
88
90
|
|
89
|
-
def generate(
|
91
|
+
def generate(obj)
|
90
92
|
@begin_bracket = @square_brackets ? "[" : "("
|
91
93
|
@end_bracket = @square_brackets ? "]" : ")"
|
92
|
-
|
94
|
+
factory = obj.factory
|
93
95
|
if @tag_format == :wkt11_strict
|
94
96
|
@cur_support_z = nil
|
95
97
|
@cur_support_m = nil
|
96
98
|
else
|
97
|
-
@cur_support_z =
|
98
|
-
@cur_support_m =
|
99
|
+
@cur_support_z = factory.property(:has_z_coordinate)
|
100
|
+
@cur_support_m = factory.property(:has_m_coordinate)
|
99
101
|
end
|
100
|
-
|
102
|
+
str = generate_feature(obj, true)
|
101
103
|
if @convert_case == :upper
|
102
|
-
|
104
|
+
str.upcase
|
103
105
|
elsif @convert_case == :lower
|
104
|
-
|
106
|
+
str.downcase
|
105
107
|
else
|
106
|
-
|
108
|
+
str
|
107
109
|
end
|
108
110
|
end
|
109
111
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
112
|
+
private
|
113
|
+
|
114
|
+
def generate_feature(obj, toplevel = false)
|
115
|
+
type = obj.geometry_type
|
116
|
+
type = Feature::LineString if type.subtype_of?(Feature::LineString)
|
117
|
+
tag = type.type_name.dup
|
114
118
|
if @tag_format == :ewkt
|
115
|
-
|
116
|
-
|
119
|
+
tag << "M" if @cur_support_m && !@cur_support_z
|
120
|
+
tag = "SRID=#{obj.srid};#{tag}" if toplevel && @emit_ewkt_srid
|
117
121
|
elsif @tag_format == :wkt12
|
118
122
|
if @cur_support_z
|
119
123
|
if @cur_support_m
|
120
|
-
|
124
|
+
tag << " ZM"
|
121
125
|
else
|
122
|
-
|
126
|
+
tag << " Z"
|
123
127
|
end
|
124
128
|
elsif @cur_support_m
|
125
|
-
|
129
|
+
tag << " M"
|
126
130
|
end
|
127
131
|
end
|
128
|
-
if
|
129
|
-
"#{
|
130
|
-
elsif
|
131
|
-
"#{
|
132
|
-
elsif
|
133
|
-
"#{
|
134
|
-
elsif
|
135
|
-
"#{
|
136
|
-
elsif
|
137
|
-
"#{
|
138
|
-
elsif
|
139
|
-
"#{
|
140
|
-
elsif
|
141
|
-
"#{
|
132
|
+
if type == Feature::Point
|
133
|
+
"#{tag} #{generate_point(obj)}"
|
134
|
+
elsif type == Feature::LineString
|
135
|
+
"#{tag} #{generate_line_string(obj)}"
|
136
|
+
elsif type == Feature::Polygon
|
137
|
+
"#{tag} #{generate_polygon(obj)}"
|
138
|
+
elsif type == Feature::GeometryCollection
|
139
|
+
"#{tag} #{generate_geometry_collection(obj)}"
|
140
|
+
elsif type == Feature::MultiPoint
|
141
|
+
"#{tag} #{generate_multi_point(obj)}"
|
142
|
+
elsif type == Feature::MultiLineString
|
143
|
+
"#{tag} #{generate_multi_line_string(obj)}"
|
144
|
+
elsif type == Feature::MultiPolygon
|
145
|
+
"#{tag} #{generate_multi_polygon(obj)}"
|
142
146
|
else
|
143
|
-
raise Error::ParseError, "Unrecognized geometry type: #{
|
147
|
+
raise Error::ParseError, "Unrecognized geometry type: #{type}"
|
144
148
|
end
|
145
149
|
end
|
146
150
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
151
|
+
def generate_coords(obj)
|
152
|
+
str = +"#{obj.x} #{obj.y}"
|
153
|
+
str << " #{obj.z}" if @cur_support_z
|
154
|
+
str << " #{obj.m}" if @cur_support_m
|
155
|
+
str
|
152
156
|
end
|
153
157
|
|
154
|
-
def
|
155
|
-
"#{@begin_bracket}#{
|
158
|
+
def generate_point(obj)
|
159
|
+
"#{@begin_bracket}#{generate_coords(obj)}#{@end_bracket}"
|
156
160
|
end
|
157
161
|
|
158
|
-
def
|
159
|
-
if
|
162
|
+
def generate_line_string(obj)
|
163
|
+
if obj.is_empty?
|
160
164
|
"EMPTY"
|
161
165
|
else
|
162
|
-
"#{@begin_bracket}#{
|
166
|
+
"#{@begin_bracket}#{obj.points.map { |p| generate_coords(p) }.join(', ')}#{@end_bracket}"
|
163
167
|
end
|
164
168
|
end
|
165
169
|
|
166
|
-
def
|
167
|
-
if
|
170
|
+
def generate_polygon(obj)
|
171
|
+
if obj.is_empty?
|
168
172
|
"EMPTY"
|
169
173
|
else
|
170
|
-
"#{@begin_bracket}#{([
|
174
|
+
"#{@begin_bracket}#{([generate_line_string(obj.exterior_ring)] + obj.interior_rings.map { |r| generate_line_string(r) }).join(', ')}#{@end_bracket}"
|
171
175
|
end
|
172
176
|
end
|
173
177
|
|
174
|
-
def
|
175
|
-
if
|
178
|
+
def generate_geometry_collection(obj)
|
179
|
+
if obj.is_empty?
|
176
180
|
"EMPTY"
|
177
181
|
else
|
178
|
-
"#{@begin_bracket}#{
|
182
|
+
"#{@begin_bracket}#{obj.map { |f| generate_feature(f) }.join(', ')}#{@end_bracket}"
|
179
183
|
end
|
180
184
|
end
|
181
185
|
|
182
|
-
def
|
183
|
-
if
|
186
|
+
def generate_multi_point(obj)
|
187
|
+
if obj.is_empty?
|
184
188
|
"EMPTY"
|
185
189
|
else
|
186
|
-
"#{@begin_bracket}#{
|
190
|
+
"#{@begin_bracket}#{obj.map { |f| generate_point(f) }.join(', ')}#{@end_bracket}"
|
187
191
|
end
|
188
192
|
end
|
189
193
|
|
190
|
-
def
|
191
|
-
if
|
194
|
+
def generate_multi_line_string(obj)
|
195
|
+
if obj.is_empty?
|
192
196
|
"EMPTY"
|
193
197
|
else
|
194
|
-
"#{@begin_bracket}#{
|
198
|
+
"#{@begin_bracket}#{obj.map { |f| generate_line_string(f) }.join(', ')}#{@end_bracket}"
|
195
199
|
end
|
196
200
|
end
|
197
201
|
|
198
|
-
def
|
199
|
-
if
|
202
|
+
def generate_multi_polygon(obj)
|
203
|
+
if obj.is_empty?
|
200
204
|
"EMPTY"
|
201
205
|
else
|
202
|
-
"#{@begin_bracket}#{
|
206
|
+
"#{@begin_bracket}#{obj.map { |f| generate_polygon(f) }.join(', ')}#{@end_bracket}"
|
203
207
|
end
|
204
208
|
end
|
205
209
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# Well-known text parser for RGeo
|
@@ -51,22 +53,22 @@ module RGeo
|
|
51
53
|
# Create and configure a WKT parser. See the WKTParser
|
52
54
|
# documentation for the options that can be passed.
|
53
55
|
|
54
|
-
def initialize(
|
55
|
-
if
|
56
|
-
@factory_generator = Feature::FactoryGenerator.single(
|
57
|
-
@exact_factory =
|
58
|
-
elsif
|
59
|
-
@factory_generator =
|
56
|
+
def initialize(factory_generator = nil, opts = {})
|
57
|
+
if factory_generator.is_a?(Feature::Factory::Instance)
|
58
|
+
@factory_generator = Feature::FactoryGenerator.single(factory_generator)
|
59
|
+
@exact_factory = factory_generator
|
60
|
+
elsif factory_generator.respond_to?(:call)
|
61
|
+
@factory_generator = factory_generator
|
60
62
|
@exact_factory = nil
|
61
63
|
else
|
62
64
|
@factory_generator = Cartesian.method(:preferred_factory)
|
63
65
|
@exact_factory = nil
|
64
66
|
end
|
65
|
-
@support_ewkt =
|
66
|
-
@support_wkt12 =
|
67
|
-
@strict_wkt11 = @support_ewkt || @support_wkt12 ? false :
|
68
|
-
@ignore_extra_tokens =
|
69
|
-
@default_srid =
|
67
|
+
@support_ewkt = opts[:support_ewkt] ? true : false
|
68
|
+
@support_wkt12 = opts[:support_wkt12] ? true : false
|
69
|
+
@strict_wkt11 = @support_ewkt || @support_wkt12 ? false : opts[:strict_wkt11] ? true : false
|
70
|
+
@ignore_extra_tokens = opts[:ignore_extra_tokens] ? true : false
|
71
|
+
@default_srid = opts[:default_srid]
|
70
72
|
end
|
71
73
|
|
72
74
|
# Returns the factory generator. See WKTParser for details.
|
@@ -100,7 +102,7 @@ module RGeo
|
|
100
102
|
@ignore_extra_tokens
|
101
103
|
end
|
102
104
|
|
103
|
-
def
|
105
|
+
def properties
|
104
106
|
{
|
105
107
|
"support_ewkt" => @support_ewkt,
|
106
108
|
"support_wkt12" => @support_wkt12,
|
@@ -112,8 +114,8 @@ module RGeo
|
|
112
114
|
|
113
115
|
# Parse the given string, and return a geometry object.
|
114
116
|
|
115
|
-
def parse(
|
116
|
-
|
117
|
+
def parse(str)
|
118
|
+
str = str.downcase
|
117
119
|
@cur_factory = @exact_factory
|
118
120
|
if @cur_factory
|
119
121
|
@cur_factory_support_z = @cur_factory.property(:has_z_coordinate) ? true : false
|
@@ -122,23 +124,25 @@ module RGeo
|
|
122
124
|
@cur_expect_z = nil
|
123
125
|
@cur_expect_m = nil
|
124
126
|
@cur_srid = @default_srid
|
125
|
-
if @support_ewkt &&
|
126
|
-
|
127
|
+
if @support_ewkt && str =~ /^srid=(\d+);/i
|
128
|
+
str = $'
|
127
129
|
@cur_srid = Regexp.last_match(1).to_i
|
128
130
|
end
|
129
131
|
begin
|
130
|
-
|
131
|
-
|
132
|
+
start_scanner(str)
|
133
|
+
obj = parse_type_tag
|
132
134
|
if @cur_token && !@ignore_extra_tokens
|
133
135
|
raise Error::ParseError, "Extra tokens beginning with #{@cur_token.inspect}."
|
134
136
|
end
|
135
137
|
ensure
|
136
|
-
|
138
|
+
clean_scanner
|
137
139
|
end
|
138
|
-
|
140
|
+
obj
|
139
141
|
end
|
140
142
|
|
141
|
-
|
143
|
+
private
|
144
|
+
|
145
|
+
def check_factory_support
|
142
146
|
if @cur_expect_z && !@cur_factory_support_z
|
143
147
|
raise Error::ParseError, "Geometry calls for Z coordinate but factory doesn't support it."
|
144
148
|
end
|
@@ -147,255 +151,255 @@ module RGeo
|
|
147
151
|
end
|
148
152
|
end
|
149
153
|
|
150
|
-
def
|
154
|
+
def ensure_factory
|
151
155
|
unless @cur_factory
|
152
156
|
@cur_factory = @factory_generator.call(srid: @cur_srid, has_z_coordinate: @cur_expect_z, has_m_coordinate: @cur_expect_m)
|
153
157
|
@cur_factory_support_z = @cur_factory.property(:has_z_coordinate) ? true : false
|
154
158
|
@cur_factory_support_m = @cur_factory.property(:has_m_coordinate) ? true : false
|
155
|
-
|
159
|
+
check_factory_support unless @cur_expect_z.nil?
|
156
160
|
end
|
157
161
|
@cur_factory
|
158
162
|
end
|
159
163
|
|
160
|
-
def
|
161
|
-
|
164
|
+
def parse_type_tag
|
165
|
+
expect_token_type(String)
|
162
166
|
if @support_ewkt && @cur_token =~ /^(.+)(m)$/
|
163
|
-
|
164
|
-
|
167
|
+
type = Regexp.last_match(1)
|
168
|
+
zm = Regexp.last_match(2)
|
165
169
|
else
|
166
|
-
|
167
|
-
|
170
|
+
type = @cur_token
|
171
|
+
zm = ""
|
168
172
|
end
|
169
|
-
|
170
|
-
if
|
171
|
-
|
172
|
-
|
173
|
+
next_token
|
174
|
+
if zm.length == 0 && @support_wkt12 && @cur_token.is_a?(String) && @cur_token =~ /^z?m?$/
|
175
|
+
zm = @cur_token
|
176
|
+
next_token
|
173
177
|
end
|
174
|
-
if
|
175
|
-
|
176
|
-
|
178
|
+
if zm.length > 0 || @strict_wkt11
|
179
|
+
creating_expectation = @cur_expect_z.nil?
|
180
|
+
expect_z = zm[0, 1] == "z" ? true : false
|
177
181
|
if @cur_expect_z.nil?
|
178
|
-
@cur_expect_z =
|
179
|
-
elsif
|
182
|
+
@cur_expect_z = expect_z
|
183
|
+
elsif expect_z != @cur_expect_z
|
180
184
|
raise Error::ParseError, "Surrounding collection has Z but contained geometry doesn't."
|
181
185
|
end
|
182
|
-
|
186
|
+
expect_m = zm[-1, 1] == "m" ? true : false
|
183
187
|
if @cur_expect_m.nil?
|
184
|
-
@cur_expect_m =
|
185
|
-
elsif
|
188
|
+
@cur_expect_m = expect_m
|
189
|
+
elsif expect_m != @cur_expect_m
|
186
190
|
raise Error::ParseError, "Surrounding collection has M but contained geometry doesn't."
|
187
191
|
end
|
188
|
-
if
|
192
|
+
if creating_expectation
|
189
193
|
if @cur_factory
|
190
|
-
|
194
|
+
check_factory_support
|
191
195
|
else
|
192
|
-
|
196
|
+
ensure_factory
|
193
197
|
end
|
194
198
|
end
|
195
199
|
end
|
196
|
-
case
|
200
|
+
case type
|
197
201
|
when "point"
|
198
|
-
|
202
|
+
parse_point(true)
|
199
203
|
when "linestring"
|
200
|
-
|
204
|
+
parse_line_string
|
201
205
|
when "polygon"
|
202
|
-
|
206
|
+
parse_polygon
|
203
207
|
when "geometrycollection"
|
204
|
-
|
208
|
+
parse_geometry_collection
|
205
209
|
when "multipoint"
|
206
|
-
|
210
|
+
parse_multi_point
|
207
211
|
when "multilinestring"
|
208
|
-
|
212
|
+
parse_multi_line_string
|
209
213
|
when "multipolygon"
|
210
|
-
|
214
|
+
parse_multi_polygon
|
211
215
|
else
|
212
|
-
raise Error::ParseError, "Unknown type tag: #{
|
216
|
+
raise Error::ParseError, "Unknown type tag: #{type.inspect}."
|
213
217
|
end
|
214
218
|
end
|
215
219
|
|
216
|
-
def
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
220
|
+
def parse_coords
|
221
|
+
expect_token_type(Numeric)
|
222
|
+
x = @cur_token
|
223
|
+
next_token
|
224
|
+
expect_token_type(Numeric)
|
225
|
+
y = @cur_token
|
226
|
+
next_token
|
227
|
+
extra = []
|
224
228
|
if @cur_expect_z.nil?
|
225
|
-
while
|
226
|
-
|
227
|
-
|
229
|
+
while Numeric === @cur_token
|
230
|
+
extra << @cur_token
|
231
|
+
next_token
|
228
232
|
end
|
229
|
-
|
230
|
-
@cur_expect_z =
|
231
|
-
|
232
|
-
@cur_expect_m =
|
233
|
-
|
234
|
-
if
|
235
|
-
raise Error::ParseError, "Found #{
|
233
|
+
num_extras = extra.size
|
234
|
+
@cur_expect_z = num_extras > 0 && (!@cur_factory || @cur_factory_support_z) ? true : false
|
235
|
+
num_extras -= 1 if @cur_expect_z
|
236
|
+
@cur_expect_m = num_extras > 0 && (!@cur_factory || @cur_factory_support_m) ? true : false
|
237
|
+
num_extras -= 1 if @cur_expect_m
|
238
|
+
if num_extras > 0
|
239
|
+
raise Error::ParseError, "Found #{extra.size + 2} coordinates, which is too many for this factory."
|
236
240
|
end
|
237
|
-
|
241
|
+
ensure_factory
|
238
242
|
else
|
239
|
-
|
243
|
+
val = 0
|
240
244
|
if @cur_expect_z
|
241
|
-
|
242
|
-
|
243
|
-
|
245
|
+
expect_token_type(Numeric)
|
246
|
+
val = @cur_token
|
247
|
+
next_token
|
244
248
|
end
|
245
|
-
|
246
|
-
|
249
|
+
extra << val if @cur_factory_support_z
|
250
|
+
val = 0
|
247
251
|
if @cur_expect_m
|
248
|
-
|
249
|
-
|
250
|
-
|
252
|
+
expect_token_type(Numeric)
|
253
|
+
val = @cur_token
|
254
|
+
next_token
|
251
255
|
end
|
252
|
-
|
256
|
+
extra << val if @cur_factory_support_m
|
253
257
|
end
|
254
|
-
@cur_factory.point(
|
258
|
+
@cur_factory.point(x, y, *extra)
|
255
259
|
end
|
256
260
|
|
257
|
-
def
|
258
|
-
if
|
259
|
-
|
261
|
+
def parse_point(convert_empty = false)
|
262
|
+
if convert_empty && @cur_token == "empty"
|
263
|
+
point = ensure_factory.multi_point([])
|
260
264
|
else
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
+
expect_token_type(:begin)
|
266
|
+
next_token
|
267
|
+
point = parse_coords
|
268
|
+
expect_token_type(:end)
|
265
269
|
end
|
266
|
-
|
267
|
-
|
270
|
+
next_token
|
271
|
+
point
|
268
272
|
end
|
269
273
|
|
270
|
-
def
|
271
|
-
|
274
|
+
def parse_line_string
|
275
|
+
points = []
|
272
276
|
if @cur_token != "empty"
|
273
|
-
|
274
|
-
|
277
|
+
expect_token_type(:begin)
|
278
|
+
next_token
|
275
279
|
loop do
|
276
|
-
|
280
|
+
points << parse_coords
|
277
281
|
break if @cur_token == :end
|
278
|
-
|
279
|
-
|
282
|
+
expect_token_type(:comma)
|
283
|
+
next_token
|
280
284
|
end
|
281
285
|
end
|
282
|
-
|
283
|
-
|
286
|
+
next_token
|
287
|
+
ensure_factory.line_string(points)
|
284
288
|
end
|
285
289
|
|
286
|
-
def
|
287
|
-
|
290
|
+
def parse_polygon
|
291
|
+
inner_rings = []
|
288
292
|
if @cur_token == "empty"
|
289
|
-
|
293
|
+
outer_ring = ensure_factory.linear_ring([])
|
290
294
|
else
|
291
|
-
|
292
|
-
|
293
|
-
|
295
|
+
expect_token_type(:begin)
|
296
|
+
next_token
|
297
|
+
outer_ring = parse_line_string
|
294
298
|
loop do
|
295
299
|
break if @cur_token == :end
|
296
|
-
|
297
|
-
|
298
|
-
|
300
|
+
expect_token_type(:comma)
|
301
|
+
next_token
|
302
|
+
inner_rings << parse_line_string
|
299
303
|
end
|
300
304
|
end
|
301
|
-
|
302
|
-
|
305
|
+
next_token
|
306
|
+
ensure_factory.polygon(outer_ring, inner_rings)
|
303
307
|
end
|
304
308
|
|
305
|
-
def
|
306
|
-
|
309
|
+
def parse_geometry_collection
|
310
|
+
geometries = []
|
307
311
|
if @cur_token != "empty"
|
308
|
-
|
309
|
-
|
312
|
+
expect_token_type(:begin)
|
313
|
+
next_token
|
310
314
|
loop do
|
311
|
-
|
315
|
+
geometries << parse_type_tag
|
312
316
|
break if @cur_token == :end
|
313
|
-
|
314
|
-
|
317
|
+
expect_token_type(:comma)
|
318
|
+
next_token
|
315
319
|
end
|
316
320
|
end
|
317
|
-
|
318
|
-
|
321
|
+
next_token
|
322
|
+
ensure_factory.collection(geometries)
|
319
323
|
end
|
320
324
|
|
321
|
-
def
|
322
|
-
|
325
|
+
def parse_multi_point
|
326
|
+
points = []
|
323
327
|
if @cur_token != "empty"
|
324
|
-
|
325
|
-
|
328
|
+
expect_token_type(:begin)
|
329
|
+
next_token
|
326
330
|
loop do
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
if
|
331
|
-
|
332
|
-
|
331
|
+
uses_paren = @cur_token == :begin
|
332
|
+
next_token if uses_paren
|
333
|
+
points << parse_coords
|
334
|
+
if uses_paren
|
335
|
+
expect_token_type(:end)
|
336
|
+
next_token
|
333
337
|
end
|
334
338
|
break if @cur_token == :end
|
335
|
-
|
336
|
-
|
339
|
+
expect_token_type(:comma)
|
340
|
+
next_token
|
337
341
|
end
|
338
342
|
end
|
339
|
-
|
340
|
-
|
343
|
+
next_token
|
344
|
+
ensure_factory.multi_point(points)
|
341
345
|
end
|
342
346
|
|
343
|
-
def
|
344
|
-
|
347
|
+
def parse_multi_line_string
|
348
|
+
line_strings = []
|
345
349
|
if @cur_token != "empty"
|
346
|
-
|
347
|
-
|
350
|
+
expect_token_type(:begin)
|
351
|
+
next_token
|
348
352
|
loop do
|
349
|
-
|
353
|
+
line_strings << parse_line_string
|
350
354
|
break if @cur_token == :end
|
351
|
-
|
352
|
-
|
355
|
+
expect_token_type(:comma)
|
356
|
+
next_token
|
353
357
|
end
|
354
358
|
end
|
355
|
-
|
356
|
-
|
359
|
+
next_token
|
360
|
+
ensure_factory.multi_line_string(line_strings)
|
357
361
|
end
|
358
362
|
|
359
|
-
def
|
360
|
-
|
363
|
+
def parse_multi_polygon
|
364
|
+
polygons = []
|
361
365
|
if @cur_token != "empty"
|
362
|
-
|
363
|
-
|
366
|
+
expect_token_type(:begin)
|
367
|
+
next_token
|
364
368
|
loop do
|
365
|
-
|
369
|
+
polygons << parse_polygon
|
366
370
|
break if @cur_token == :end
|
367
|
-
|
368
|
-
|
371
|
+
expect_token_type(:comma)
|
372
|
+
next_token
|
369
373
|
end
|
370
374
|
end
|
371
|
-
|
372
|
-
|
375
|
+
next_token
|
376
|
+
ensure_factory.multi_polygon(polygons)
|
373
377
|
end
|
374
378
|
|
375
|
-
def
|
376
|
-
@
|
377
|
-
|
379
|
+
def start_scanner(str)
|
380
|
+
@scanner = StringScanner.new(str)
|
381
|
+
next_token
|
378
382
|
end
|
379
383
|
|
380
|
-
def
|
381
|
-
@
|
384
|
+
def clean_scanner
|
385
|
+
@scanner = nil
|
382
386
|
@cur_token = nil
|
383
387
|
end
|
384
388
|
|
385
|
-
def
|
386
|
-
unless
|
387
|
-
raise Error::ParseError, "#{
|
389
|
+
def expect_token_type(type)
|
390
|
+
unless type === @cur_token
|
391
|
+
raise Error::ParseError, "#{type.inspect} expected but #{@cur_token.inspect} found."
|
388
392
|
end
|
389
393
|
end
|
390
394
|
|
391
|
-
def
|
392
|
-
if @
|
393
|
-
|
394
|
-
case
|
395
|
+
def next_token
|
396
|
+
if @scanner.scan_until(/\(|\)|\[|\]|,|[^\s\(\)\[\],]+/)
|
397
|
+
token = @scanner.matched
|
398
|
+
case token
|
395
399
|
when /^[-+]?(\d+(\.\d*)?|\.\d+)(e[-+]?\d+)?$/
|
396
|
-
@cur_token =
|
400
|
+
@cur_token = token.to_f
|
397
401
|
when /^[a-z]+$/
|
398
|
-
@cur_token =
|
402
|
+
@cur_token = token
|
399
403
|
when ","
|
400
404
|
@cur_token = :comma
|
401
405
|
when "(", "["
|
@@ -403,7 +407,7 @@ module RGeo
|
|
403
407
|
when "]", ")"
|
404
408
|
@cur_token = :end
|
405
409
|
else
|
406
|
-
raise Error::ParseError, "Bad token: #{
|
410
|
+
raise Error::ParseError, "Bad token: #{token.inspect}"
|
407
411
|
end
|
408
412
|
else
|
409
413
|
@cur_token = nil
|