rgeo-geojson 0.2.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.
- data/History.rdoc +5 -0
- data/README.rdoc +104 -0
- data/Version +1 -0
- data/lib/rgeo/geo_json.rb +62 -0
- data/lib/rgeo/geo_json/coder.rb +401 -0
- data/lib/rgeo/geo_json/entities.rb +301 -0
- data/lib/rgeo/geo_json/interface.rb +129 -0
- data/test/tc_basic.rb +281 -0
- metadata +88 -0
@@ -0,0 +1,301 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# GeoJSON standard entities
|
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 GeoJSON
|
40
|
+
|
41
|
+
|
42
|
+
# This is a GeoJSON wrapper entity that corresponds to the GeoJSON
|
43
|
+
# "Feature" type. It is an immutable type.
|
44
|
+
#
|
45
|
+
# This is the default implementation that is generated by
|
46
|
+
# RGeo::GeoJSON::EntityFactory. You may replace this implementation
|
47
|
+
# by writing your own entity factory. Note that an alternate Feature
|
48
|
+
# implementation need not subclass or even duck-type this class.
|
49
|
+
# the entity factory mediates all interaction between the GeoJSON
|
50
|
+
# engine and features.
|
51
|
+
|
52
|
+
class Feature
|
53
|
+
|
54
|
+
|
55
|
+
# Create a feature wrapping the given geometry, with the given ID
|
56
|
+
# and properties.
|
57
|
+
|
58
|
+
def initialize(geometry_, id_=nil, properties_={})
|
59
|
+
@geometry = geometry_
|
60
|
+
@id = id_
|
61
|
+
@properties = properties_.dup
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def inspect # :nodoc:
|
66
|
+
"#<#{self.class}:0x#{object_id.to_s(16)} id=#{@id.inspect} geom=#{@geometry ? @geometry.as_text.inspect : 'nil'}>"
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s # :nodoc:
|
70
|
+
inspect
|
71
|
+
end
|
72
|
+
|
73
|
+
def hash # :nodoc:
|
74
|
+
@geometry.hash + @id.hash + @properties.hash
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
# Two features are equal if their geometries, IDs, and properties
|
79
|
+
# are all equal.
|
80
|
+
# This method uses the eql? method to test geometry equality, which
|
81
|
+
# may behave differently than the == operator.
|
82
|
+
|
83
|
+
def eql?(rhs_)
|
84
|
+
rhs_.kind_of?(Feature) && @geometry.eql?(rhs_.geometry) && @id.eql?(rhs_.feature_id) && @properties.eql?(rhs_.instance_variable_get(:@properties))
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
# Two features are equal if their geometries, IDs, and properties
|
89
|
+
# are all equal.
|
90
|
+
# This method uses the == operator to test geometry equality, which
|
91
|
+
# may behave differently than the eql? method.
|
92
|
+
|
93
|
+
def ==(rhs_)
|
94
|
+
rhs_.kind_of?(Feature) && @geometry == rhs_.geometry && @id == rhs_.feature_id && @properties == rhs_.instance_variable_get(:@properties)
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
# Returns the geometry contained in this feature, which may be nil.
|
99
|
+
|
100
|
+
def geometry
|
101
|
+
@geometry
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Returns the ID for this feature, which may be nil.
|
106
|
+
|
107
|
+
def feature_id
|
108
|
+
@id
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
# Returns a copy of the properties for this feature.
|
113
|
+
|
114
|
+
def properties
|
115
|
+
@properties.dup
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# Gets the value of the given named property.
|
120
|
+
# Returns nil if the given property is not found.
|
121
|
+
|
122
|
+
def property(key_)
|
123
|
+
@properties[key_.to_s]
|
124
|
+
end
|
125
|
+
alias_method :[], :property
|
126
|
+
|
127
|
+
|
128
|
+
# Gets an array of the known property keys in this feature.
|
129
|
+
|
130
|
+
def keys
|
131
|
+
@properties.keys
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
# This is a GeoJSON wrapper entity that corresponds to the GeoJSON
|
139
|
+
# "FeatureCollection" type. It is an immutable type.
|
140
|
+
#
|
141
|
+
# This is the default implementation that is generated by
|
142
|
+
# RGeo::GeoJSON::EntityFactory. You may replace this implementation
|
143
|
+
# by writing your own entity factory. Note that an alternate
|
144
|
+
# FeatureCollection implementation need not subclass or even
|
145
|
+
# duck-type this class. The entity factory mediates all interaction
|
146
|
+
# between the GeoJSON engine and feature collections.
|
147
|
+
|
148
|
+
class FeatureCollection
|
149
|
+
|
150
|
+
include ::Enumerable
|
151
|
+
|
152
|
+
|
153
|
+
# Create a new FeatureCollection with the given features, which must
|
154
|
+
# be provided as an Enumerable.
|
155
|
+
|
156
|
+
def initialize(features_=[])
|
157
|
+
@features = []
|
158
|
+
features_.each{ |f_| @features << f_ if f_.kind_of?(Feature) }
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
def inspect # :nodoc:
|
163
|
+
"#<#{self.class}:0x#{object_id.to_s(16)}>"
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_s # :nodoc:
|
167
|
+
inspect
|
168
|
+
end
|
169
|
+
|
170
|
+
def hash # :nodoc:
|
171
|
+
@features.hash
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
# Two feature collections are equal if they contain the same
|
176
|
+
# features in the same order.
|
177
|
+
# This methods uses the eql? method to test geometry equality, which
|
178
|
+
# may behave differently than the == operator.
|
179
|
+
|
180
|
+
def eql?(rhs_)
|
181
|
+
rhs_.kind_of?(FeatureCollection) && @features.eql?(rhs_.instance_variable_get(:@features))
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
# Two feature collections are equal if they contain the same
|
186
|
+
# features in the same order.
|
187
|
+
# This methods uses the == operator to test geometry equality, which
|
188
|
+
# may behave differently than the eql? method.
|
189
|
+
|
190
|
+
def ==(rhs_)
|
191
|
+
rhs_.kind_of?(FeatureCollection) && @features == rhs_.instance_variable_get(:@features)
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
# Iterates or returns an iterator for the features.
|
196
|
+
|
197
|
+
def each(&block_)
|
198
|
+
@features.each(&block_)
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
# Returns the number of features contained in this collection.
|
203
|
+
|
204
|
+
def size
|
205
|
+
@features.size
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
# Access a feature by index.
|
210
|
+
|
211
|
+
def [](index_)
|
212
|
+
@features[index_]
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
# This is the default entity factory. It creates objects of type
|
220
|
+
# RGeo::GeoJSON::Feature and RGeo::GeoJSON::FeatureCollection.
|
221
|
+
# You may create your own entity factory by duck-typing this class.
|
222
|
+
|
223
|
+
class EntityFactory
|
224
|
+
|
225
|
+
|
226
|
+
# Create and return a new feature, given geometry, ID, and
|
227
|
+
# properties hash. Note that, per the GeoJSON spec, geometry and/or
|
228
|
+
# properties may be nil.
|
229
|
+
|
230
|
+
def feature(geometry_, id_=nil, properties_=nil)
|
231
|
+
Feature.new(geometry_, id_, properties_ || {})
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
# Create and return a new feature collection, given an enumerable
|
236
|
+
# of feature objects.
|
237
|
+
|
238
|
+
def feature_collection(features_=[])
|
239
|
+
FeatureCollection.new(features_)
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
# Returns true if the given object is a feature created by this
|
244
|
+
# entity factory.
|
245
|
+
|
246
|
+
def is_feature?(object_)
|
247
|
+
object_.kind_of?(Feature)
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
# Returns true if the given object is a feature collection created
|
252
|
+
# by this entity factory.
|
253
|
+
|
254
|
+
def is_feature_collection?(object_)
|
255
|
+
object_.kind_of?(FeatureCollection)
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
# Run Enumerable#map on the features contained in the given feature
|
260
|
+
# collection.
|
261
|
+
|
262
|
+
def map_feature_collection(object_, &block_)
|
263
|
+
object_.map(&block_)
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
# Returns the geometry associated with the given feature.
|
268
|
+
|
269
|
+
def get_feature_geometry(object_)
|
270
|
+
object_.geometry
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
# Returns the ID of the given feature, or nil for no ID.
|
275
|
+
|
276
|
+
def get_feature_id(object_)
|
277
|
+
object_.feature_id
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
# Returns the properties of the given feature as a hash. Editing
|
282
|
+
# this hash does not change the state of the feature.
|
283
|
+
|
284
|
+
def get_feature_properties(object_)
|
285
|
+
object_.properties
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
# Return the singleton instance of EntityFactory.
|
290
|
+
|
291
|
+
def self.instance
|
292
|
+
@instance ||= self.new
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# GeoJSON toplevel interface
|
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 GeoJSON
|
40
|
+
|
41
|
+
class << self
|
42
|
+
|
43
|
+
|
44
|
+
# High-level convenience routine for encoding an object as GeoJSON.
|
45
|
+
# Pass the object, which may one of the geometry objects specified
|
46
|
+
# in RGeo::Feature, or an appropriate GeoJSON wrapper entity such
|
47
|
+
# as RGeo::GeoJSON::Feature or RGeo::GeoJSON::FeatureCollection.
|
48
|
+
#
|
49
|
+
# The only option supported is <tt>:entity_factory</tt>, which lets
|
50
|
+
# you override the types of GeoJSON entities supported. See
|
51
|
+
# RGeo::GeoJSON::EntityFactory for more information. By default,
|
52
|
+
# encode supports objects of type RGeo::GeoJSON::Feature and
|
53
|
+
# RGeo::GeoJSON::FeatureCollection.
|
54
|
+
|
55
|
+
def encode(object_, opts_={})
|
56
|
+
Coder.new(opts_).encode(object_)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# High-level convenience routine for decoding an object from GeoJSON.
|
61
|
+
# The input may be a JSON hash, a String, or an IO object from which
|
62
|
+
# to read the JSON string.
|
63
|
+
#
|
64
|
+
# Options include:
|
65
|
+
#
|
66
|
+
# <tt>:geo_factory</tt>::
|
67
|
+
# Specifies the geo factory to use to create geometry objects.
|
68
|
+
# Defaults to the preferred cartesian factory.
|
69
|
+
# <tt>:entity_factory</tt>::
|
70
|
+
# Specifies an entity factory, which lets you override the types
|
71
|
+
# of GeoJSON entities that are created. It defaults to the default
|
72
|
+
# RGeo::GeoJSON::EntityFactory, which generates objects of type
|
73
|
+
# RGeo::GeoJSON::Feature or RGeo::GeoJSON::FeatureCollection.
|
74
|
+
# See RGeo::GeoJSON::EntityFactory for more information.
|
75
|
+
# <tt>:json_parser</tt>::
|
76
|
+
# Specifies a JSON parser to use when decoding a String or IO
|
77
|
+
# object. The value may be a Proc object taking the string as the
|
78
|
+
# sole argument and returning the JSON hash, or it may be one of
|
79
|
+
# the special values <tt>:json</tt>, <tt>:yajl</tt>, or
|
80
|
+
# <tt>:active_support</tt>. Setting one of those special values
|
81
|
+
# will require the corresponding library to be available. Note
|
82
|
+
# that the <tt>:json</tt> library is present in the standard
|
83
|
+
# library in Ruby 1.9, but requires the "json" gem in Ruby 1.8.
|
84
|
+
# If a parser is not specified, then the decode method will not
|
85
|
+
# accept a String or IO object; it will require a Hash.
|
86
|
+
|
87
|
+
def decode(input_, opts_={})
|
88
|
+
Coder.new(opts_).decode(input_)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
# Creates and returns a coder object of type RGeo::GeoJSON::Coder
|
93
|
+
# that encapsulates encoding and decoding settings (principally the
|
94
|
+
# RGeo::Feature::Factory and the RGeo::GeoJSON::EntityFactory to be
|
95
|
+
# used).
|
96
|
+
#
|
97
|
+
# The geo factory is a required argument. Other options include:
|
98
|
+
#
|
99
|
+
# <tt>:geo_factory</tt>::
|
100
|
+
# Specifies the geo factory to use to create geometry objects.
|
101
|
+
# Defaults to the preferred cartesian factory.
|
102
|
+
# <tt>:entity_factory</tt>::
|
103
|
+
# Specifies an entity factory, which lets you override the types
|
104
|
+
# of GeoJSON entities that are created. It defaults to the default
|
105
|
+
# RGeo::GeoJSON::EntityFactory, which generates objects of type
|
106
|
+
# RGeo::GeoJSON::Feature or RGeo::GeoJSON::FeatureCollection.
|
107
|
+
# See RGeo::GeoJSON::EntityFactory for more information.
|
108
|
+
# <tt>:json_parser</tt>::
|
109
|
+
# Specifies a JSON parser to use when decoding a String or IO
|
110
|
+
# object. The value may be a Proc object taking the string as the
|
111
|
+
# sole argument and returning the JSON hash, or it may be one of
|
112
|
+
# the special values <tt>:json</tt>, <tt>:yajl</tt>, or
|
113
|
+
# <tt>:active_support</tt>. Setting one of those special values
|
114
|
+
# will require the corresponding library to be available. Note
|
115
|
+
# that the <tt>:json</tt> library is present in the standard
|
116
|
+
# library in Ruby 1.9, but requires the "json" gem in Ruby 1.8.
|
117
|
+
# If a parser is not specified, then the decode method will not
|
118
|
+
# accept a String or IO object; it will require a Hash.
|
119
|
+
|
120
|
+
def coder(opts_={})
|
121
|
+
Coder.new(opts_)
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
data/test/tc_basic.rb
ADDED
@@ -0,0 +1,281 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Tests for basic GeoJSON usage
|
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 'test/unit'
|
38
|
+
require 'rgeo/geo_json'
|
39
|
+
|
40
|
+
|
41
|
+
module RGeo
|
42
|
+
module GeoJSON
|
43
|
+
module Tests # :nodoc:
|
44
|
+
|
45
|
+
class TestGeoJSON < ::Test::Unit::TestCase # :nodoc:
|
46
|
+
|
47
|
+
|
48
|
+
def setup
|
49
|
+
@geo_factory = ::RGeo::Cartesian.simple_factory(:srid => 4326)
|
50
|
+
@geo_factory_z = ::RGeo::Cartesian.simple_factory(:srid => 4326, :has_z_coordinate => true)
|
51
|
+
@geo_factory_m = ::RGeo::Cartesian.simple_factory(:srid => 4326, :has_m_coordinate => true)
|
52
|
+
@geo_factory_zm = ::RGeo::Cartesian.simple_factory(:srid => 4326, :has_z_coordinate => true, :has_m_coordinate => true)
|
53
|
+
@entity_factory = ::RGeo::GeoJSON::EntityFactory.instance
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def test_point
|
58
|
+
object_ = @geo_factory.point(10, 20)
|
59
|
+
json_ = {
|
60
|
+
'type' => 'Point',
|
61
|
+
'coordinates' => [10.0, 20.0],
|
62
|
+
}
|
63
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
64
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def test_point_z
|
69
|
+
object_ = @geo_factory_z.point(10, 20, -1)
|
70
|
+
json_ = {
|
71
|
+
'type' => 'Point',
|
72
|
+
'coordinates' => [10.0, 20.0, -1.0],
|
73
|
+
}
|
74
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
75
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory_z).eql?(object_))
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def test_point_m
|
80
|
+
object_ = @geo_factory_m.point(10, 20, -1)
|
81
|
+
json_ = {
|
82
|
+
'type' => 'Point',
|
83
|
+
'coordinates' => [10.0, 20.0, -1.0],
|
84
|
+
}
|
85
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
86
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory_m).eql?(object_))
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def test_point_zm
|
91
|
+
object_ = @geo_factory_zm.point(10, 20, -1, -2)
|
92
|
+
json_ = {
|
93
|
+
'type' => 'Point',
|
94
|
+
'coordinates' => [10.0, 20.0, -1.0, -2.0],
|
95
|
+
}
|
96
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
97
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory_zm).eql?(object_))
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def test_line_string
|
102
|
+
object_ = @geo_factory.line_string([@geo_factory.point(10, 20), @geo_factory.point(12, 22), @geo_factory.point(-3, 24)])
|
103
|
+
json_ = {
|
104
|
+
'type' => 'LineString',
|
105
|
+
'coordinates' => [[10.0, 20.0], [12.0, 22.0], [-3.0, 24.0]],
|
106
|
+
}
|
107
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
108
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def test_polygon
|
113
|
+
object_ = @geo_factory.polygon(@geo_factory.linear_ring([@geo_factory.point(10, 20), @geo_factory.point(12, 22), @geo_factory.point(-3, 24), @geo_factory.point(10, 20)]))
|
114
|
+
json_ = {
|
115
|
+
'type' => 'Polygon',
|
116
|
+
'coordinates' => [[[10.0, 20.0], [12.0, 22.0], [-3.0, 24.0], [10.0, 20.0]]],
|
117
|
+
}
|
118
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
119
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def test_polygon_complex
|
124
|
+
object_ = @geo_factory.polygon(@geo_factory.linear_ring([@geo_factory.point(0, 0), @geo_factory.point(10, 0), @geo_factory.point(10, 10), @geo_factory.point(0, 10), @geo_factory.point(0, 0)]), [@geo_factory.linear_ring([@geo_factory.point(4, 4), @geo_factory.point(6, 5), @geo_factory.point(4, 6), @geo_factory.point(4, 4)])])
|
125
|
+
json_ = {
|
126
|
+
'type' => 'Polygon',
|
127
|
+
'coordinates' => [[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[4.0, 4.0], [6.0, 5.0], [4.0, 6.0], [4.0, 4.0]]],
|
128
|
+
}
|
129
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
130
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
def test_multi_point
|
135
|
+
object_ = @geo_factory.multi_point([@geo_factory.point(10, 20), @geo_factory.point(12, 22), @geo_factory.point(-3, 24)])
|
136
|
+
json_ = {
|
137
|
+
'type' => 'MultiPoint',
|
138
|
+
'coordinates' => [[10.0, 20.0], [12.0, 22.0], [-3.0, 24.0]],
|
139
|
+
}
|
140
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
141
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def test_multi_line_string
|
146
|
+
object_ = @geo_factory.multi_line_string([@geo_factory.line_string([@geo_factory.point(10, 20), @geo_factory.point(12, 22), @geo_factory.point(-3, 24)]), @geo_factory.line_string([@geo_factory.point(1, 2), @geo_factory.point(3, 4)])])
|
147
|
+
json_ = {
|
148
|
+
'type' => 'MultiLineString',
|
149
|
+
'coordinates' => [[[10.0, 20.0], [12.0, 22.0], [-3.0, 24.0]], [[1.0, 2.0], [3.0, 4.0]]],
|
150
|
+
}
|
151
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
152
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
def test_multi_polygon
|
157
|
+
object_ = @geo_factory.multi_polygon([@geo_factory.polygon(@geo_factory.linear_ring([@geo_factory.point(0, 0), @geo_factory.point(10, 0), @geo_factory.point(10, 10), @geo_factory.point(0, 10), @geo_factory.point(0, 0)]), [@geo_factory.linear_ring([@geo_factory.point(4, 4), @geo_factory.point(6, 5), @geo_factory.point(4, 6), @geo_factory.point(4, 4)])]), @geo_factory.polygon(@geo_factory.linear_ring([@geo_factory.point(-10,-10), @geo_factory.point(-15, -10), @geo_factory.point(-10, -15), @geo_factory.point(-10, -10)]))])
|
158
|
+
json_ = {
|
159
|
+
'type' => 'MultiPolygon',
|
160
|
+
'coordinates' => [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]], [[4.0, 4.0], [6.0, 5.0], [4.0, 6.0], [4.0, 4.0]]], [[[-10.0, -10.0], [-15.0, -10.0], [-10.0, -15.0], [-10.0, -10.0]]]]
|
161
|
+
}
|
162
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
163
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
def test_geometry_collection
|
168
|
+
object_ = @geo_factory.collection([@geo_factory.point(10, 20), @geo_factory.collection([@geo_factory.point(12, 22), @geo_factory.point(-3, 24)])])
|
169
|
+
json_ = {
|
170
|
+
'type' => 'GeometryCollection',
|
171
|
+
'geometries' => [
|
172
|
+
{
|
173
|
+
'type' => 'Point',
|
174
|
+
'coordinates' => [10.0, 20.0],
|
175
|
+
},
|
176
|
+
{
|
177
|
+
'type' => 'GeometryCollection',
|
178
|
+
'geometries' => [
|
179
|
+
{
|
180
|
+
'type' => 'Point',
|
181
|
+
'coordinates' => [12.0, 22.0],
|
182
|
+
},
|
183
|
+
{
|
184
|
+
'type' => 'Point',
|
185
|
+
'coordinates' => [-3.0, 24.0],
|
186
|
+
},
|
187
|
+
],
|
188
|
+
},
|
189
|
+
],
|
190
|
+
}
|
191
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
192
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
def test_feature
|
197
|
+
object_ = @entity_factory.feature(@geo_factory.point(10, 20))
|
198
|
+
json_ = {
|
199
|
+
'type' => 'Feature',
|
200
|
+
'geometry' => {
|
201
|
+
'type' => 'Point',
|
202
|
+
'coordinates' => [10.0, 20.0],
|
203
|
+
},
|
204
|
+
'properties' => {},
|
205
|
+
}
|
206
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
207
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
def test_feature_nulls
|
212
|
+
json_ = {
|
213
|
+
'type' => 'Feature',
|
214
|
+
'geometry' => nil,
|
215
|
+
'properties' => nil,
|
216
|
+
}
|
217
|
+
obj_ = ::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory)
|
218
|
+
assert_not_nil(obj_)
|
219
|
+
assert_nil(obj_.geometry)
|
220
|
+
assert_equal({}, obj_.properties)
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def test_feature_complex
|
225
|
+
object_ = @entity_factory.feature(@geo_factory.point(10, 20), 2, {'prop1' => 'foo', 'prop2' => 'bar'})
|
226
|
+
json_ = {
|
227
|
+
'type' => 'Feature',
|
228
|
+
'geometry' => {
|
229
|
+
'type' => 'Point',
|
230
|
+
'coordinates' => [10.0, 20.0],
|
231
|
+
},
|
232
|
+
'id' => 2,
|
233
|
+
'properties' => {'prop1' => 'foo', 'prop2' => 'bar'},
|
234
|
+
}
|
235
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
236
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
def test_feature_collection
|
241
|
+
object_ = @entity_factory.feature_collection([@entity_factory.feature(@geo_factory.point(10, 20)), @entity_factory.feature(@geo_factory.point(11, 22)), @entity_factory.feature(@geo_factory.point(10, 20), 8)])
|
242
|
+
json_ = {
|
243
|
+
'type' => 'FeatureCollection',
|
244
|
+
'features' => [
|
245
|
+
{
|
246
|
+
'type' => 'Feature',
|
247
|
+
'geometry' => {
|
248
|
+
'type' => 'Point',
|
249
|
+
'coordinates' => [10.0, 20.0],
|
250
|
+
},
|
251
|
+
'properties' => {},
|
252
|
+
},
|
253
|
+
{
|
254
|
+
'type' => 'Feature',
|
255
|
+
'geometry' => {
|
256
|
+
'type' => 'Point',
|
257
|
+
'coordinates' => [11.0, 22.0],
|
258
|
+
},
|
259
|
+
'properties' => {},
|
260
|
+
},
|
261
|
+
{
|
262
|
+
'type' => 'Feature',
|
263
|
+
'geometry' => {
|
264
|
+
'type' => 'Point',
|
265
|
+
'coordinates' => [10.0, 20.0],
|
266
|
+
},
|
267
|
+
'id' => 8,
|
268
|
+
'properties' => {},
|
269
|
+
},
|
270
|
+
]
|
271
|
+
}
|
272
|
+
assert_equal(json_, ::RGeo::GeoJSON.encode(object_))
|
273
|
+
assert(::RGeo::GeoJSON.decode(json_, :geo_factory => @geo_factory).eql?(object_))
|
274
|
+
end
|
275
|
+
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|