rgeo 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +29 -0
- data/ext/geos_c_impl/Makefile_2.2.3 +260 -0
- data/ext/geos_c_impl/coordinates.c +65 -0
- data/ext/geos_c_impl/coordinates.h +2 -0
- data/ext/geos_c_impl/extconf.rb +19 -43
- data/ext/geos_c_impl/geometry.c +24 -0
- data/ext/geos_c_impl/geometry_collection.c +99 -1
- data/ext/geos_c_impl/geos_c_impl_2.2.3.bundle +0 -0
- data/ext/geos_c_impl/line_string.c +38 -0
- data/ext/geos_c_impl/mkmf.log +123 -0
- data/ext/geos_c_impl/point.c +27 -0
- data/ext/geos_c_impl/polygon.c +26 -0
- data/ext/proj4_c_impl/Makefile_2.2.3 +260 -0
- data/ext/proj4_c_impl/extconf.rb +32 -32
- data/ext/proj4_c_impl/mkmf.log +47 -0
- data/ext/proj4_c_impl/proj4_c_impl_2.2.3.bundle +0 -0
- data/lib/rgeo.rb +10 -11
- data/lib/rgeo/cartesian.rb +7 -12
- data/lib/rgeo/cartesian/analysis.rb +13 -26
- data/lib/rgeo/cartesian/bounding_box.rb +45 -114
- data/lib/rgeo/cartesian/calculations.rb +3 -21
- data/lib/rgeo/cartesian/factory.rb +101 -122
- data/lib/rgeo/cartesian/feature_classes.rb +9 -59
- data/lib/rgeo/cartesian/feature_methods.rb +15 -45
- data/lib/rgeo/cartesian/interface.rb +6 -17
- data/lib/rgeo/coord_sys.rb +9 -15
- data/lib/rgeo/coord_sys/cs/entities.rb +84 -330
- data/lib/rgeo/coord_sys/cs/factories.rb +2 -32
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +52 -80
- data/lib/rgeo/coord_sys/proj4.rb +28 -67
- data/lib/rgeo/coord_sys/proj4_c_impl.bundle +0 -0
- data/lib/rgeo/coord_sys/srs_database/interface.rb +4 -24
- data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +20 -38
- data/lib/rgeo/coord_sys/srs_database/sr_org.rb +6 -22
- data/lib/rgeo/coord_sys/srs_database/url_reader.rb +6 -21
- data/lib/rgeo/error.rb +0 -6
- data/lib/rgeo/feature.rb +18 -23
- data/lib/rgeo/feature/curve.rb +0 -14
- data/lib/rgeo/feature/factory.rb +13 -38
- data/lib/rgeo/feature/factory_generator.rb +4 -16
- data/lib/rgeo/feature/geometry.rb +18 -60
- data/lib/rgeo/feature/geometry_collection.rb +3 -17
- data/lib/rgeo/feature/line.rb +0 -10
- data/lib/rgeo/feature/line_string.rb +1 -13
- data/lib/rgeo/feature/linear_ring.rb +0 -9
- data/lib/rgeo/feature/mixins.rb +11 -36
- data/lib/rgeo/feature/multi_curve.rb +0 -11
- data/lib/rgeo/feature/multi_line_string.rb +0 -9
- data/lib/rgeo/feature/multi_point.rb +0 -9
- data/lib/rgeo/feature/multi_polygon.rb +0 -9
- data/lib/rgeo/feature/multi_surface.rb +0 -12
- data/lib/rgeo/feature/point.rb +0 -13
- data/lib/rgeo/feature/polygon.rb +1 -14
- data/lib/rgeo/feature/surface.rb +0 -12
- data/lib/rgeo/feature/types.rb +19 -61
- data/lib/rgeo/geographic.rb +10 -15
- data/lib/rgeo/geographic/factory.rb +126 -147
- data/lib/rgeo/geographic/interface.rb +67 -81
- data/lib/rgeo/geographic/proj4_projector.rb +13 -37
- data/lib/rgeo/geographic/projected_feature_classes.rb +7 -66
- data/lib/rgeo/geographic/projected_feature_methods.rb +15 -80
- data/lib/rgeo/geographic/projected_window.rb +15 -67
- data/lib/rgeo/geographic/simple_mercator_projector.rb +32 -56
- data/lib/rgeo/geographic/spherical_feature_classes.rb +9 -68
- data/lib/rgeo/geographic/spherical_feature_methods.rb +18 -51
- data/lib/rgeo/geographic/spherical_math.rb +26 -51
- data/lib/rgeo/geos.rb +23 -20
- data/lib/rgeo/geos/capi_factory.rb +125 -131
- data/lib/rgeo/geos/capi_feature_classes.rb +21 -88
- data/lib/rgeo/geos/ffi_factory.rb +90 -143
- data/lib/rgeo/geos/ffi_feature_classes.rb +8 -63
- data/lib/rgeo/geos/ffi_feature_methods.rb +46 -162
- data/lib/rgeo/geos/geos_c_impl.bundle +0 -0
- data/lib/rgeo/geos/interface.rb +4 -23
- data/lib/rgeo/geos/utils.rb +4 -19
- data/lib/rgeo/geos/zm_factory.rb +82 -131
- data/lib/rgeo/geos/zm_feature_classes.rb +8 -63
- data/lib/rgeo/geos/zm_feature_methods.rb +34 -107
- data/lib/rgeo/impl_helper.rb +8 -13
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +27 -71
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +10 -28
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +21 -57
- data/lib/rgeo/impl_helper/basic_point_methods.rb +12 -30
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +9 -28
- data/lib/rgeo/impl_helper/math.rb +4 -10
- data/lib/rgeo/impl_helper/utils.rb +2 -10
- data/lib/rgeo/version.rb +1 -1
- data/lib/rgeo/wkrep.rb +4 -9
- data/lib/rgeo/wkrep/wkb_generator.rb +22 -46
- data/lib/rgeo/wkrep/wkb_parser.rb +25 -52
- data/lib/rgeo/wkrep/wkt_generator.rb +39 -69
- data/lib/rgeo/wkrep/wkt_parser.rb +52 -89
- data/lib/rgeo/yaml.rb +1 -7
- data/test/common/factory_tests.rb +4 -19
- data/test/common/geometry_collection_tests.rb +6 -39
- data/test/common/line_string_tests.rb +10 -39
- data/test/common/multi_line_string_tests.rb +10 -30
- data/test/common/multi_point_tests.rb +15 -34
- data/test/common/multi_polygon_tests.rb +26 -28
- data/test/common/point_tests.rb +37 -59
- data/test/common/polygon_tests.rb +16 -25
- data/test/coord_sys/tc_ogc_cs.rb +151 -186
- data/test/coord_sys/tc_proj4.rb +35 -60
- data/test/coord_sys/tc_proj4_srs_data.rb +15 -24
- data/test/coord_sys/tc_sr_org.rb +11 -19
- data/test/coord_sys/tc_url_reader.rb +13 -23
- data/test/geos_capi/tc_factory.rb +7 -16
- data/test/geos_capi/tc_geometry_collection.rb +6 -14
- data/test/geos_capi/tc_line_string.rb +7 -15
- data/test/geos_capi/tc_misc.rb +26 -41
- data/test/geos_capi/tc_multi_line_string.rb +6 -14
- data/test/geos_capi/tc_multi_point.rb +7 -15
- data/test/geos_capi/tc_multi_polygon.rb +8 -18
- data/test/geos_capi/tc_parsing_unparsing.rb +11 -21
- data/test/geos_capi/tc_point.rb +12 -26
- data/test/geos_capi/tc_polygon.rb +52 -17
- data/test/geos_capi/tc_zmfactory.rb +7 -18
- data/test/geos_ffi/tc_factory.rb +7 -16
- data/test/geos_ffi/tc_geometry_collection.rb +7 -15
- data/test/geos_ffi/tc_line_string.rb +7 -15
- data/test/geos_ffi/tc_misc.rb +8 -18
- data/test/geos_ffi/tc_multi_line_string.rb +7 -15
- data/test/geos_ffi/tc_multi_point.rb +8 -16
- data/test/geos_ffi/tc_multi_polygon.rb +9 -18
- data/test/geos_ffi/tc_parsing_unparsing.rb +14 -24
- data/test/geos_ffi/tc_point.rb +13 -28
- data/test/geos_ffi/tc_polygon.rb +7 -17
- data/test/geos_ffi/tc_zmfactory.rb +8 -19
- data/test/projected_geographic/tc_factory.rb +7 -15
- data/test/projected_geographic/tc_geometry_collection.rb +7 -15
- data/test/projected_geographic/tc_line_string.rb +7 -15
- data/test/projected_geographic/tc_multi_line_string.rb +7 -16
- data/test/projected_geographic/tc_multi_point.rb +8 -17
- data/test/projected_geographic/tc_multi_polygon.rb +8 -16
- data/test/projected_geographic/tc_point.rb +11 -23
- data/test/projected_geographic/tc_polygon.rb +7 -15
- data/test/simple_cartesian/tc_calculations.rb +6 -22
- data/test/simple_cartesian/tc_factory.rb +7 -16
- data/test/simple_cartesian/tc_geometry_collection.rb +6 -15
- data/test/simple_cartesian/tc_line_string.rb +6 -15
- data/test/simple_cartesian/tc_multi_line_string.rb +6 -15
- data/test/simple_cartesian/tc_multi_point.rb +7 -16
- data/test/simple_cartesian/tc_multi_polygon.rb +7 -16
- data/test/simple_cartesian/tc_point.rb +10 -21
- data/test/simple_cartesian/tc_polygon.rb +6 -15
- data/test/simple_mercator/tc_factory.rb +6 -14
- data/test/simple_mercator/tc_geometry_collection.rb +6 -14
- data/test/simple_mercator/tc_line_string.rb +6 -14
- data/test/simple_mercator/tc_multi_line_string.rb +6 -15
- data/test/simple_mercator/tc_multi_point.rb +7 -16
- data/test/simple_mercator/tc_multi_polygon.rb +7 -15
- data/test/simple_mercator/tc_point.rb +11 -24
- data/test/simple_mercator/tc_polygon.rb +6 -14
- data/test/simple_mercator/tc_window.rb +10 -34
- data/test/spherical_geographic/tc_calculations.rb +5 -32
- data/test/spherical_geographic/tc_factory.rb +6 -15
- data/test/spherical_geographic/tc_geometry_collection.rb +6 -15
- data/test/spherical_geographic/tc_line_string.rb +6 -15
- data/test/spherical_geographic/tc_multi_line_string.rb +6 -15
- data/test/spherical_geographic/tc_multi_point.rb +7 -16
- data/test/spherical_geographic/tc_multi_polygon.rb +7 -16
- data/test/spherical_geographic/tc_point.rb +10 -22
- data/test/spherical_geographic/tc_polygon.rb +6 -15
- data/test/tc_cartesian_analysis.rb +4 -16
- data/test/tc_cartesian_bbox.rb +7 -21
- data/test/tc_mixins.rb +8 -25
- data/test/tc_oneoff.rb +5 -13
- data/test/tc_types.rb +7 -16
- data/test/wkrep/tc_wkb_generator.rb +63 -97
- data/test/wkrep/tc_wkb_parser.rb +63 -100
- data/test/wkrep/tc_wkt_generator.rb +54 -92
- data/test/wkrep/tc_wkt_parser.rb +84 -133
- metadata +39 -9
- data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +0 -166
- data/test/coord_sys/tc_active_record_table.rb +0 -79
@@ -5,10 +5,7 @@
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
7
|
module RGeo
|
8
|
-
|
9
8
|
module WKRep
|
10
|
-
|
11
|
-
|
12
9
|
# This class provides the functionality of parsing a geometry from
|
13
10
|
# WKB (well-known binary) format. You may also customize the parser
|
14
11
|
# to recognize PostGIS EWKB extensions to the input, or Simple
|
@@ -45,13 +42,11 @@ module RGeo
|
|
45
42
|
# the input. Defaults to nil (i.e. don't specify a SRID).
|
46
43
|
|
47
44
|
class WKBParser
|
48
|
-
|
49
|
-
|
50
45
|
# Create and configure a WKB parser. See the WKBParser
|
51
46
|
# documentation for the options that can be passed.
|
52
47
|
|
53
|
-
def initialize(factory_generator_=nil, opts_={})
|
54
|
-
if factory_generator_.
|
48
|
+
def initialize(factory_generator_ = nil, opts_ = {})
|
49
|
+
if factory_generator_.is_a?(Feature::Factory::Instance)
|
55
50
|
@factory_generator = Feature::FactoryGenerator.single(factory_generator_)
|
56
51
|
@exact_factory = factory_generator_
|
57
52
|
elsif factory_generator_.respond_to?(:call)
|
@@ -67,17 +62,12 @@ module RGeo
|
|
67
62
|
@default_srid = opts_[:default_srid]
|
68
63
|
end
|
69
64
|
|
70
|
-
|
71
65
|
# Returns the factory generator. See WKBParser for details.
|
72
|
-
|
73
|
-
@factory_generator
|
74
|
-
end
|
66
|
+
attr_reader :factory_generator
|
75
67
|
|
76
68
|
# If this parser was given an exact factory, returns it; otherwise
|
77
69
|
# returns nil.
|
78
|
-
|
79
|
-
@exact_factory
|
80
|
-
end
|
70
|
+
attr_reader :exact_factory
|
81
71
|
|
82
72
|
# Returns true if this parser supports EWKB.
|
83
73
|
# See WKBParser for details.
|
@@ -97,17 +87,15 @@ module RGeo
|
|
97
87
|
@ignore_extra_bytes
|
98
88
|
end
|
99
89
|
|
100
|
-
|
101
|
-
def _properties # :nodoc:
|
90
|
+
def _properties # :nodoc:
|
102
91
|
{
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
92
|
+
"support_ewkb" => @support_ewkb,
|
93
|
+
"support_wkb12" => @support_wkb12,
|
94
|
+
"ignore_extra_bytes" => @ignore_extra_bytes,
|
95
|
+
"default_srid" => @default_srid
|
107
96
|
}
|
108
97
|
end
|
109
98
|
|
110
|
-
|
111
99
|
# Parse the given binary data or hexadecimal string, and return a
|
112
100
|
# geometry object.
|
113
101
|
#
|
@@ -115,9 +103,7 @@ module RGeo
|
|
115
103
|
# reasons but deprecated. Use #parse instead.
|
116
104
|
|
117
105
|
def parse(data_)
|
118
|
-
if data_[0,1] =~ /[0-9a-fA-F]/
|
119
|
-
data_ = [data_].pack('H*')
|
120
|
-
end
|
106
|
+
data_ = [data_].pack("H*") if data_[0, 1] =~ /[0-9a-fA-F]/
|
121
107
|
@cur_has_z = nil
|
122
108
|
@cur_has_m = nil
|
123
109
|
@cur_srid = nil
|
@@ -139,8 +125,7 @@ module RGeo
|
|
139
125
|
end
|
140
126
|
alias_method :parse_hex, :parse
|
141
127
|
|
142
|
-
|
143
|
-
def _parse_object(contained_) # :nodoc:
|
128
|
+
def _parse_object(contained_) # :nodoc:
|
144
129
|
endian_value_ = _get_byte
|
145
130
|
case endian_value_
|
146
131
|
when 0
|
@@ -183,7 +168,7 @@ module RGeo
|
|
183
168
|
@cur_has_m = has_m_
|
184
169
|
@cur_dims = 2 + (@cur_has_z ? 1 : 0) + (@cur_has_m ? 1 : 0)
|
185
170
|
@cur_srid = srid_
|
186
|
-
@cur_factory = @factory_generator.call(:
|
171
|
+
@cur_factory = @factory_generator.call(srid: @cur_srid, has_z_coordinate: has_z_, has_m_coordinate: has_m_)
|
187
172
|
if @cur_has_z && !@cur_factory.property(:has_z_coordinate)
|
188
173
|
raise Error::ParseError, "Data has Z coordinates but the factory doesn't have Z coordinates"
|
189
174
|
end
|
@@ -198,48 +183,43 @@ module RGeo
|
|
198
183
|
when 2
|
199
184
|
_parse_line_string(little_endian_)
|
200
185
|
when 3
|
201
|
-
interior_rings_ = (1.._get_integer(little_endian_)).map{ _parse_line_string(little_endian_) }
|
186
|
+
interior_rings_ = (1.._get_integer(little_endian_)).map { _parse_line_string(little_endian_) }
|
202
187
|
exterior_ring_ = interior_rings_.shift || @cur_factory.linear_ring([])
|
203
188
|
@cur_factory.polygon(exterior_ring_, interior_rings_)
|
204
189
|
when 4
|
205
|
-
@cur_factory.multi_point((1.._get_integer(little_endian_)).map{ _parse_object(1) })
|
190
|
+
@cur_factory.multi_point((1.._get_integer(little_endian_)).map { _parse_object(1) })
|
206
191
|
when 5
|
207
|
-
@cur_factory.multi_line_string((1.._get_integer(little_endian_)).map{ _parse_object(2) })
|
192
|
+
@cur_factory.multi_line_string((1.._get_integer(little_endian_)).map { _parse_object(2) })
|
208
193
|
when 6
|
209
|
-
@cur_factory.multi_polygon((1.._get_integer(little_endian_)).map{ _parse_object(3) })
|
194
|
+
@cur_factory.multi_polygon((1.._get_integer(little_endian_)).map { _parse_object(3) })
|
210
195
|
when 7
|
211
|
-
@cur_factory.collection((1.._get_integer(little_endian_)).map{ _parse_object(true) })
|
196
|
+
@cur_factory.collection((1.._get_integer(little_endian_)).map { _parse_object(true) })
|
212
197
|
else
|
213
198
|
raise Error::ParseError, "Unknown type value: #{type_code_}."
|
214
199
|
end
|
215
200
|
end
|
216
201
|
|
217
|
-
|
218
|
-
def _parse_line_string(little_endian_) # :nodoc:
|
202
|
+
def _parse_line_string(little_endian_) # :nodoc:
|
219
203
|
count_ = _get_integer(little_endian_)
|
220
204
|
coords_ = _get_doubles(little_endian_, @cur_dims * count_)
|
221
|
-
@cur_factory.line_string((0...count_).map{ |i_| @cur_factory.point(*coords_[@cur_dims*i_
|
205
|
+
@cur_factory.line_string((0...count_).map { |i_| @cur_factory.point(*coords_[@cur_dims * i_, @cur_dims]) })
|
222
206
|
end
|
223
207
|
|
224
|
-
|
225
|
-
def _start_scanner(data_) # :nodoc:
|
208
|
+
def _start_scanner(data_) # :nodoc:
|
226
209
|
@_data = data_
|
227
210
|
@_len = data_.length
|
228
211
|
@_pos = 0
|
229
212
|
end
|
230
213
|
|
231
|
-
|
232
|
-
def _clean_scanner # :nodoc:
|
214
|
+
def _clean_scanner # :nodoc:
|
233
215
|
@_data = nil
|
234
216
|
end
|
235
217
|
|
236
|
-
|
237
|
-
def _bytes_remaining # :nodoc:
|
218
|
+
def _bytes_remaining # :nodoc:
|
238
219
|
@_len - @_pos
|
239
220
|
end
|
240
221
|
|
241
|
-
|
242
|
-
def _get_byte # :nodoc:
|
222
|
+
def _get_byte # :nodoc:
|
243
223
|
if @_pos + 1 > @_len
|
244
224
|
raise Error::ParseError, "Not enough bytes left to fulfill 1 byte"
|
245
225
|
end
|
@@ -248,8 +228,7 @@ module RGeo
|
|
248
228
|
str_.unpack("C").first
|
249
229
|
end
|
250
230
|
|
251
|
-
|
252
|
-
def _get_integer(little_endian_) # :nodoc:
|
231
|
+
def _get_integer(little_endian_) # :nodoc:
|
253
232
|
if @_pos + 4 > @_len
|
254
233
|
raise Error::ParseError, "Not enough bytes left to fulfill 1 integer"
|
255
234
|
end
|
@@ -258,8 +237,7 @@ module RGeo
|
|
258
237
|
str_.unpack("#{little_endian_ ? 'V' : 'N'}").first
|
259
238
|
end
|
260
239
|
|
261
|
-
|
262
|
-
def _get_doubles(little_endian_, count_) # :nodoc:
|
240
|
+
def _get_doubles(little_endian_, count_) # :nodoc:
|
263
241
|
len_ = 8 * count_
|
264
242
|
if @_pos + len_ > @_len
|
265
243
|
raise Error::ParseError, "Not enough bytes left to fulfill #{count_} doubles"
|
@@ -268,11 +246,6 @@ module RGeo
|
|
268
246
|
@_pos += len_
|
269
247
|
str_.unpack("#{little_endian_ ? 'E' : 'G'}*")
|
270
248
|
end
|
271
|
-
|
272
|
-
|
273
249
|
end
|
274
|
-
|
275
|
-
|
276
250
|
end
|
277
|
-
|
278
251
|
end
|
@@ -5,10 +5,7 @@
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
7
|
module RGeo
|
8
|
-
|
9
8
|
module WKRep
|
10
|
-
|
11
|
-
|
12
9
|
# This class provides the functionality of serializing a geometry as
|
13
10
|
# WKT (well-known text) format. You may also customize the serializer
|
14
11
|
# to generate PostGIS EWKT extensions to the output, or to follow the
|
@@ -48,12 +45,10 @@ module RGeo
|
|
48
45
|
# generator to emphasize readability.) Default is nil.
|
49
46
|
|
50
47
|
class WKTGenerator
|
51
|
-
|
52
|
-
|
53
48
|
# Create and configure a WKT generator. See the WKTGenerator
|
54
49
|
# documentation for the options that can be passed.
|
55
50
|
|
56
|
-
def initialize(opts_={})
|
51
|
+
def initialize(opts_ = {})
|
57
52
|
@tag_format = opts_[:tag_format] || opts_[:type_format] || :wkt11
|
58
53
|
@emit_ewkt_srid = @tag_format == :ewkt ?
|
59
54
|
(opts_[:emit_ewkt_srid] ? true : false) : nil
|
@@ -61,11 +56,8 @@ module RGeo
|
|
61
56
|
@convert_case = opts_[:convert_case]
|
62
57
|
end
|
63
58
|
|
64
|
-
|
65
59
|
# Returns the format for type tags. See WKTGenerator for details.
|
66
|
-
|
67
|
-
@tag_format
|
68
|
-
end
|
60
|
+
attr_reader :tag_format
|
69
61
|
alias_method :type_format, :tag_format
|
70
62
|
|
71
63
|
# Returns whether SRID is embedded. See WKTGenerator for details.
|
@@ -80,27 +72,23 @@ module RGeo
|
|
80
72
|
end
|
81
73
|
|
82
74
|
# Returns the case for output. See WKTGenerator for details.
|
83
|
-
|
84
|
-
@convert_case
|
85
|
-
end
|
86
|
-
|
75
|
+
attr_reader :convert_case
|
87
76
|
|
88
|
-
def _properties
|
77
|
+
def _properties # :nodoc:
|
89
78
|
{
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
79
|
+
"tag_format" => @tag_format.to_s,
|
80
|
+
"emit_ewkt_srid" => @emit_ewkt_srid,
|
81
|
+
"square_brackets" => @square_brackets,
|
82
|
+
"convert_case" => @convert_case ? @convert_case.to_s : nil
|
94
83
|
}
|
95
84
|
end
|
96
85
|
|
97
|
-
|
98
86
|
# Generate and return the WKT format for the given geometry object,
|
99
87
|
# according to the current settings.
|
100
88
|
|
101
89
|
def generate(obj_)
|
102
|
-
@begin_bracket = @square_brackets ?
|
103
|
-
@end_bracket = @square_brackets ?
|
90
|
+
@begin_bracket = @square_brackets ? "[" : "("
|
91
|
+
@end_bracket = @square_brackets ? "]" : ")"
|
104
92
|
factory_ = obj_.factory
|
105
93
|
if @tag_format == :wkt11_strict
|
106
94
|
@cur_support_z = nil
|
@@ -119,27 +107,22 @@ module RGeo
|
|
119
107
|
end
|
120
108
|
end
|
121
109
|
|
122
|
-
|
123
|
-
def _generate_feature(obj_, toplevel_=false) # :nodoc:
|
110
|
+
def _generate_feature(obj_, toplevel_ = false) # :nodoc:
|
124
111
|
type_ = obj_.geometry_type
|
125
112
|
type_ = Feature::LineString if type_.subtype_of?(Feature::LineString)
|
126
113
|
tag_ = type_.type_name
|
127
114
|
if @tag_format == :ewkt
|
128
|
-
if @cur_support_m && !@cur_support_z
|
129
|
-
|
130
|
-
end
|
131
|
-
if toplevel_ && @emit_ewkt_srid
|
132
|
-
tag_ = "SRID=#{obj_.srid};#{tag_}"
|
133
|
-
end
|
115
|
+
tag_ << "M" if @cur_support_m && !@cur_support_z
|
116
|
+
tag_ = "SRID=#{obj_.srid};#{tag_}" if toplevel_ && @emit_ewkt_srid
|
134
117
|
elsif @tag_format == :wkt12
|
135
118
|
if @cur_support_z
|
136
119
|
if @cur_support_m
|
137
|
-
tag_ <<
|
120
|
+
tag_ << " ZM"
|
138
121
|
else
|
139
|
-
tag_ <<
|
122
|
+
tag_ << " Z"
|
140
123
|
end
|
141
124
|
elsif @cur_support_m
|
142
|
-
tag_ <<
|
125
|
+
tag_ << " M"
|
143
126
|
end
|
144
127
|
end
|
145
128
|
if type_ == Feature::Point
|
@@ -161,77 +144,64 @@ module RGeo
|
|
161
144
|
end
|
162
145
|
end
|
163
146
|
|
164
|
-
|
165
|
-
|
166
|
-
str_
|
167
|
-
str_ << " #{obj_.
|
168
|
-
str_ << " #{obj_.m.to_s}" if @cur_support_m
|
147
|
+
def _generate_coords(obj_) # :nodoc:
|
148
|
+
str_ = "#{obj_.x} #{obj_.y}"
|
149
|
+
str_ << " #{obj_.z}" if @cur_support_z
|
150
|
+
str_ << " #{obj_.m}" if @cur_support_m
|
169
151
|
str_
|
170
152
|
end
|
171
153
|
|
172
|
-
|
173
|
-
def _generate_point(obj_) # :nodoc:
|
154
|
+
def _generate_point(obj_) # :nodoc:
|
174
155
|
"#{@begin_bracket}#{_generate_coords(obj_)}#{@end_bracket}"
|
175
156
|
end
|
176
157
|
|
177
|
-
|
178
|
-
def _generate_line_string(obj_) # :nodoc:
|
158
|
+
def _generate_line_string(obj_) # :nodoc:
|
179
159
|
if obj_.is_empty?
|
180
|
-
|
160
|
+
"EMPTY"
|
181
161
|
else
|
182
|
-
"#{@begin_bracket}#{obj_.points.map{ |p_| _generate_coords(p_) }.join(', ')}#{@end_bracket}"
|
162
|
+
"#{@begin_bracket}#{obj_.points.map { |p_| _generate_coords(p_) }.join(', ')}#{@end_bracket}"
|
183
163
|
end
|
184
164
|
end
|
185
165
|
|
186
|
-
|
187
|
-
def _generate_polygon(obj_) # :nodoc:
|
166
|
+
def _generate_polygon(obj_) # :nodoc:
|
188
167
|
if obj_.is_empty?
|
189
|
-
|
168
|
+
"EMPTY"
|
190
169
|
else
|
191
|
-
"#{@begin_bracket}#{([_generate_line_string(obj_.exterior_ring)] + obj_.interior_rings.map{ |r_| _generate_line_string(r_) }).join(', ')}#{@end_bracket}"
|
170
|
+
"#{@begin_bracket}#{([_generate_line_string(obj_.exterior_ring)] + obj_.interior_rings.map { |r_| _generate_line_string(r_) }).join(', ')}#{@end_bracket}"
|
192
171
|
end
|
193
172
|
end
|
194
173
|
|
195
|
-
|
196
|
-
def _generate_geometry_collection(obj_) # :nodoc:
|
174
|
+
def _generate_geometry_collection(obj_) # :nodoc:
|
197
175
|
if obj_.is_empty?
|
198
|
-
|
176
|
+
"EMPTY"
|
199
177
|
else
|
200
|
-
"#{@begin_bracket}#{obj_.map{ |f_| _generate_feature(f_) }.join(', ')}#{@end_bracket}"
|
178
|
+
"#{@begin_bracket}#{obj_.map { |f_| _generate_feature(f_) }.join(', ')}#{@end_bracket}"
|
201
179
|
end
|
202
180
|
end
|
203
181
|
|
204
|
-
|
205
|
-
def _generate_multi_point(obj_) # :nodoc:
|
182
|
+
def _generate_multi_point(obj_) # :nodoc:
|
206
183
|
if obj_.is_empty?
|
207
|
-
|
184
|
+
"EMPTY"
|
208
185
|
else
|
209
|
-
"#{@begin_bracket}#{obj_.map{ |f_| _generate_point(f_) }.join(', ')}#{@end_bracket}"
|
186
|
+
"#{@begin_bracket}#{obj_.map { |f_| _generate_point(f_) }.join(', ')}#{@end_bracket}"
|
210
187
|
end
|
211
188
|
end
|
212
189
|
|
213
|
-
|
214
|
-
def _generate_multi_line_string(obj_) # :nodoc:
|
190
|
+
def _generate_multi_line_string(obj_) # :nodoc:
|
215
191
|
if obj_.is_empty?
|
216
|
-
|
192
|
+
"EMPTY"
|
217
193
|
else
|
218
|
-
"#{@begin_bracket}#{obj_.map{ |f_| _generate_line_string(f_) }.join(', ')}#{@end_bracket}"
|
194
|
+
"#{@begin_bracket}#{obj_.map { |f_| _generate_line_string(f_) }.join(', ')}#{@end_bracket}"
|
219
195
|
end
|
220
196
|
end
|
221
197
|
|
222
|
-
|
223
|
-
def _generate_multi_polygon(obj_) # :nodoc:
|
198
|
+
def _generate_multi_polygon(obj_) # :nodoc:
|
224
199
|
if obj_.is_empty?
|
225
|
-
|
200
|
+
"EMPTY"
|
226
201
|
else
|
227
|
-
"#{@begin_bracket}#{obj_.map{ |f_| _generate_polygon(f_) }.join(', ')}#{@end_bracket}"
|
202
|
+
"#{@begin_bracket}#{obj_.map { |f_| _generate_polygon(f_) }.join(', ')}#{@end_bracket}"
|
228
203
|
end
|
229
204
|
end
|
230
|
-
|
231
|
-
|
232
205
|
end
|
233
|
-
|
234
|
-
|
235
206
|
end
|
236
|
-
|
237
207
|
end
|
@@ -4,14 +4,10 @@
|
|
4
4
|
#
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
require
|
8
|
-
|
7
|
+
require "strscan"
|
9
8
|
|
10
9
|
module RGeo
|
11
|
-
|
12
10
|
module WKRep
|
13
|
-
|
14
|
-
|
15
11
|
# This class provides the functionality of parsing a geometry from
|
16
12
|
# WKT (well-known text) format. You may also customize the parser
|
17
13
|
# to recognize PostGIS EWKT extensions to the input, or Simple
|
@@ -52,13 +48,11 @@ module RGeo
|
|
52
48
|
# the input. Defaults to nil (i.e. don't specify a SRID).
|
53
49
|
|
54
50
|
class WKTParser
|
55
|
-
|
56
|
-
|
57
51
|
# Create and configure a WKT parser. See the WKTParser
|
58
52
|
# documentation for the options that can be passed.
|
59
53
|
|
60
|
-
def initialize(factory_generator_=nil, opts_={})
|
61
|
-
if factory_generator_.
|
54
|
+
def initialize(factory_generator_ = nil, opts_ = {})
|
55
|
+
if factory_generator_.is_a?(Feature::Factory::Instance)
|
62
56
|
@factory_generator = Feature::FactoryGenerator.single(factory_generator_)
|
63
57
|
@exact_factory = factory_generator_
|
64
58
|
elsif factory_generator_.respond_to?(:call)
|
@@ -75,17 +69,12 @@ module RGeo
|
|
75
69
|
@default_srid = opts_[:default_srid]
|
76
70
|
end
|
77
71
|
|
78
|
-
|
79
72
|
# Returns the factory generator. See WKTParser for details.
|
80
|
-
|
81
|
-
@factory_generator
|
82
|
-
end
|
73
|
+
attr_reader :factory_generator
|
83
74
|
|
84
75
|
# If this parser was given an exact factory, returns it; otherwise
|
85
76
|
# returns nil.
|
86
|
-
|
87
|
-
@exact_factory
|
88
|
-
end
|
77
|
+
attr_reader :exact_factory
|
89
78
|
|
90
79
|
# Returns true if this parser supports EWKT.
|
91
80
|
# See WKTParser for details.
|
@@ -111,18 +100,16 @@ module RGeo
|
|
111
100
|
@ignore_extra_tokens
|
112
101
|
end
|
113
102
|
|
114
|
-
|
115
|
-
def _properties # :nodoc:
|
103
|
+
def _properties # :nodoc:
|
116
104
|
{
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
105
|
+
"support_ewkt" => @support_ewkt,
|
106
|
+
"support_wkt12" => @support_wkt12,
|
107
|
+
"strict_wkt11" => @strict_wkt11,
|
108
|
+
"ignore_extra_tokens" => @ignore_extra_tokens,
|
109
|
+
"default_srid" => @default_srid
|
122
110
|
}
|
123
111
|
end
|
124
112
|
|
125
|
-
|
126
113
|
# Parse the given string, and return a geometry object.
|
127
114
|
|
128
115
|
def parse(str_)
|
@@ -137,7 +124,7 @@ module RGeo
|
|
137
124
|
@cur_srid = @default_srid
|
138
125
|
if @support_ewkt && str_ =~ /^srid=(\d+);/i
|
139
126
|
str_ = $'
|
140
|
-
@cur_srid =
|
127
|
+
@cur_srid = Regexp.last_match(1).to_i
|
141
128
|
end
|
142
129
|
begin
|
143
130
|
_start_scanner(str_)
|
@@ -151,8 +138,7 @@ module RGeo
|
|
151
138
|
obj_
|
152
139
|
end
|
153
140
|
|
154
|
-
|
155
|
-
def _check_factory_support # :nodoc:
|
141
|
+
def _check_factory_support # :nodoc:
|
156
142
|
if @cur_expect_z && !@cur_factory_support_z
|
157
143
|
raise Error::ParseError, "Geometry calls for Z coordinate but factory doesn't support it."
|
158
144
|
end
|
@@ -161,10 +147,9 @@ module RGeo
|
|
161
147
|
end
|
162
148
|
end
|
163
149
|
|
164
|
-
|
165
|
-
def _ensure_factory # :nodoc:
|
150
|
+
def _ensure_factory # :nodoc:
|
166
151
|
unless @cur_factory
|
167
|
-
@cur_factory = @factory_generator.call(:
|
152
|
+
@cur_factory = @factory_generator.call(srid: @cur_srid, has_z_coordinate: @cur_expect_z, has_m_coordinate: @cur_expect_m)
|
168
153
|
@cur_factory_support_z = @cur_factory.property(:has_z_coordinate) ? true : false
|
169
154
|
@cur_factory_support_m = @cur_factory.property(:has_m_coordinate) ? true : false
|
170
155
|
_check_factory_support unless @cur_expect_z.nil?
|
@@ -172,30 +157,29 @@ module RGeo
|
|
172
157
|
@cur_factory
|
173
158
|
end
|
174
159
|
|
175
|
-
|
176
|
-
def _parse_type_tag(contained_) # :nodoc:
|
160
|
+
def _parse_type_tag(_contained_) # :nodoc:
|
177
161
|
_expect_token_type(::String)
|
178
162
|
if @support_ewkt && @cur_token =~ /^(.+)(m)$/
|
179
|
-
type_ =
|
180
|
-
zm_ =
|
163
|
+
type_ = Regexp.last_match(1)
|
164
|
+
zm_ = Regexp.last_match(2)
|
181
165
|
else
|
182
166
|
type_ = @cur_token
|
183
|
-
zm_ =
|
167
|
+
zm_ = ""
|
184
168
|
end
|
185
169
|
_next_token
|
186
|
-
if zm_.length == 0 && @support_wkt12 && @cur_token.
|
170
|
+
if zm_.length == 0 && @support_wkt12 && @cur_token.is_a?(::String) && @cur_token =~ /^z?m?$/
|
187
171
|
zm_ = @cur_token
|
188
172
|
_next_token
|
189
173
|
end
|
190
174
|
if zm_.length > 0 || @strict_wkt11
|
191
175
|
creating_expectation_ = @cur_expect_z.nil?
|
192
|
-
expect_z_ = zm_[0,1] ==
|
176
|
+
expect_z_ = zm_[0, 1] == "z" ? true : false
|
193
177
|
if @cur_expect_z.nil?
|
194
178
|
@cur_expect_z = expect_z_
|
195
179
|
elsif expect_z_ != @cur_expect_z
|
196
180
|
raise Error::ParseError, "Surrounding collection has Z but contained geometry doesn't."
|
197
181
|
end
|
198
|
-
expect_m_ = zm_[-1,1] ==
|
182
|
+
expect_m_ = zm_[-1, 1] == "m" ? true : false
|
199
183
|
if @cur_expect_m.nil?
|
200
184
|
@cur_expect_m = expect_m_
|
201
185
|
elsif expect_m_ != @cur_expect_m
|
@@ -210,27 +194,26 @@ module RGeo
|
|
210
194
|
end
|
211
195
|
end
|
212
196
|
case type_
|
213
|
-
when
|
197
|
+
when "point"
|
214
198
|
_parse_point(true)
|
215
|
-
when
|
199
|
+
when "linestring"
|
216
200
|
_parse_line_string
|
217
|
-
when
|
201
|
+
when "polygon"
|
218
202
|
_parse_polygon
|
219
|
-
when
|
203
|
+
when "geometrycollection"
|
220
204
|
_parse_geometry_collection
|
221
|
-
when
|
205
|
+
when "multipoint"
|
222
206
|
_parse_multi_point
|
223
|
-
when
|
207
|
+
when "multilinestring"
|
224
208
|
_parse_multi_line_string
|
225
|
-
when
|
209
|
+
when "multipolygon"
|
226
210
|
_parse_multi_polygon
|
227
211
|
else
|
228
212
|
raise Error::ParseError, "Unknown type tag: #{type_.inspect}."
|
229
213
|
end
|
230
214
|
end
|
231
215
|
|
232
|
-
|
233
|
-
def _parse_coords # :nodoc:
|
216
|
+
def _parse_coords # :nodoc:
|
234
217
|
_expect_token_type(::Numeric)
|
235
218
|
x_ = @cur_token
|
236
219
|
_next_token
|
@@ -249,7 +232,7 @@ module RGeo
|
|
249
232
|
@cur_expect_m = num_extras_ > 0 && (!@cur_factory || @cur_factory_support_m) ? true : false
|
250
233
|
num_extras_ -= 1 if @cur_expect_m
|
251
234
|
if num_extras_ > 0
|
252
|
-
raise Error::ParseError, "Found #{extra_.size+2} coordinates, which is too many for this factory."
|
235
|
+
raise Error::ParseError, "Found #{extra_.size + 2} coordinates, which is too many for this factory."
|
253
236
|
end
|
254
237
|
_ensure_factory
|
255
238
|
else
|
@@ -259,25 +242,20 @@ module RGeo
|
|
259
242
|
val_ = @cur_token
|
260
243
|
_next_token
|
261
244
|
end
|
262
|
-
if @cur_factory_support_z
|
263
|
-
extra_ << val_
|
264
|
-
end
|
245
|
+
extra_ << val_ if @cur_factory_support_z
|
265
246
|
val_ = 0
|
266
247
|
if @cur_expect_m
|
267
248
|
_expect_token_type(::Numeric)
|
268
249
|
val_ = @cur_token
|
269
250
|
_next_token
|
270
251
|
end
|
271
|
-
if @cur_factory_support_m
|
272
|
-
extra_ << val_
|
273
|
-
end
|
252
|
+
extra_ << val_ if @cur_factory_support_m
|
274
253
|
end
|
275
254
|
@cur_factory.point(x_, y_, *extra_)
|
276
255
|
end
|
277
256
|
|
278
|
-
|
279
|
-
|
280
|
-
if convert_empty_ && @cur_token == 'empty'
|
257
|
+
def _parse_point(convert_empty_ = false) # :nodoc:
|
258
|
+
if convert_empty_ && @cur_token == "empty"
|
281
259
|
point_ = _ensure_factory.multi_point([])
|
282
260
|
else
|
283
261
|
_expect_token_type(:begin)
|
@@ -289,10 +267,9 @@ module RGeo
|
|
289
267
|
point_
|
290
268
|
end
|
291
269
|
|
292
|
-
|
293
|
-
def _parse_line_string # :nodoc:
|
270
|
+
def _parse_line_string # :nodoc:
|
294
271
|
points_ = []
|
295
|
-
if @cur_token !=
|
272
|
+
if @cur_token != "empty"
|
296
273
|
_expect_token_type(:begin)
|
297
274
|
_next_token
|
298
275
|
loop do
|
@@ -306,10 +283,9 @@ module RGeo
|
|
306
283
|
_ensure_factory.line_string(points_)
|
307
284
|
end
|
308
285
|
|
309
|
-
|
310
|
-
def _parse_polygon # :nodoc:
|
286
|
+
def _parse_polygon # :nodoc:
|
311
287
|
inner_rings_ = []
|
312
|
-
if @cur_token ==
|
288
|
+
if @cur_token == "empty"
|
313
289
|
outer_ring_ = _ensure_factory.linear_ring([])
|
314
290
|
else
|
315
291
|
_expect_token_type(:begin)
|
@@ -326,10 +302,9 @@ module RGeo
|
|
326
302
|
_ensure_factory.polygon(outer_ring_, inner_rings_)
|
327
303
|
end
|
328
304
|
|
329
|
-
|
330
|
-
def _parse_geometry_collection # :nodoc:
|
305
|
+
def _parse_geometry_collection # :nodoc:
|
331
306
|
geometries_ = []
|
332
|
-
if @cur_token !=
|
307
|
+
if @cur_token != "empty"
|
333
308
|
_expect_token_type(:begin)
|
334
309
|
_next_token
|
335
310
|
loop do
|
@@ -343,10 +318,9 @@ module RGeo
|
|
343
318
|
_ensure_factory.collection(geometries_)
|
344
319
|
end
|
345
320
|
|
346
|
-
|
347
|
-
def _parse_multi_point # :nodoc:
|
321
|
+
def _parse_multi_point # :nodoc:
|
348
322
|
points_ = []
|
349
|
-
if @cur_token !=
|
323
|
+
if @cur_token != "empty"
|
350
324
|
_expect_token_type(:begin)
|
351
325
|
_next_token
|
352
326
|
loop do
|
@@ -366,10 +340,9 @@ module RGeo
|
|
366
340
|
_ensure_factory.multi_point(points_)
|
367
341
|
end
|
368
342
|
|
369
|
-
|
370
|
-
def _parse_multi_line_string # :nodoc:
|
343
|
+
def _parse_multi_line_string # :nodoc:
|
371
344
|
line_strings_ = []
|
372
|
-
if @cur_token !=
|
345
|
+
if @cur_token != "empty"
|
373
346
|
_expect_token_type(:begin)
|
374
347
|
_next_token
|
375
348
|
loop do
|
@@ -383,10 +356,9 @@ module RGeo
|
|
383
356
|
_ensure_factory.multi_line_string(line_strings_)
|
384
357
|
end
|
385
358
|
|
386
|
-
|
387
359
|
def _parse_multi_polygon # :nodoc:
|
388
360
|
polygons_ = []
|
389
|
-
if @cur_token !=
|
361
|
+
if @cur_token != "empty"
|
390
362
|
_expect_token_type(:begin)
|
391
363
|
_next_token
|
392
364
|
loop do
|
@@ -400,27 +372,23 @@ module RGeo
|
|
400
372
|
_ensure_factory.multi_polygon(polygons_)
|
401
373
|
end
|
402
374
|
|
403
|
-
|
404
375
|
def _start_scanner(str_) # :nodoc:
|
405
376
|
@_scanner = ::StringScanner.new(str_)
|
406
377
|
_next_token
|
407
378
|
end
|
408
379
|
|
409
|
-
|
410
|
-
def _clean_scanner # :nodoc:
|
380
|
+
def _clean_scanner # :nodoc:
|
411
381
|
@_scanner = nil
|
412
382
|
@cur_token = nil
|
413
383
|
end
|
414
384
|
|
415
|
-
|
416
|
-
def _expect_token_type(type_) # :nodoc:
|
385
|
+
def _expect_token_type(type_) # :nodoc:
|
417
386
|
unless type_ === @cur_token
|
418
387
|
raise Error::ParseError, "#{type_.inspect} expected but #{@cur_token.inspect} found."
|
419
388
|
end
|
420
389
|
end
|
421
390
|
|
422
|
-
|
423
|
-
def _next_token # :nodoc:
|
391
|
+
def _next_token # :nodoc:
|
424
392
|
if @_scanner.scan_until(/\(|\)|\[|\]|,|[^\s\(\)\[\],]+/)
|
425
393
|
token_ = @_scanner.matched
|
426
394
|
case token_
|
@@ -428,11 +396,11 @@ module RGeo
|
|
428
396
|
@cur_token = token_.to_f
|
429
397
|
when /^[a-z]+$/
|
430
398
|
@cur_token = token_
|
431
|
-
when
|
399
|
+
when ","
|
432
400
|
@cur_token = :comma
|
433
|
-
when
|
401
|
+
when "(", "["
|
434
402
|
@cur_token = :begin
|
435
|
-
when
|
403
|
+
when "]", ")"
|
436
404
|
@cur_token = :end
|
437
405
|
else
|
438
406
|
raise Error::ParseError, "Bad token: #{token_.inspect}"
|
@@ -442,11 +410,6 @@ module RGeo
|
|
442
410
|
end
|
443
411
|
@cur_token
|
444
412
|
end
|
445
|
-
|
446
|
-
|
447
413
|
end
|
448
|
-
|
449
|
-
|
450
414
|
end
|
451
|
-
|
452
415
|
end
|