rgeo-geojson 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31e3acae0a1cc1b8b417a6e66a03ea7b162cc598f6a48dfaf73a93535d13bbd9
4
- data.tar.gz: 31eb694d0d74d5fb8d41b6c6d1b07017ec71aefd080678a27565b60bb037e29b
3
+ metadata.gz: 448049463c510bdeb2fa366eaa3834566962116632675ccb509134cc54875fc0
4
+ data.tar.gz: 7a6c7b327824850c164d3fca314347256e9b8513574afae86687361e92b00c26
5
5
  SHA512:
6
- metadata.gz: 181c8f3958610b3df6f6c830af066590b438fd3955cdd9cdfe7c80a00791a7038d9db37c711412380f4fd11a8f56b308c7fb7c50cfbc7b2c8bd3988dc680d90a
7
- data.tar.gz: f3d13428ed86ee87c6850626df4cc6146170f89b163d47d3db8226f03b21096fd40badafb178e59205418daf354e1f5d549776a382c22f2145c7a69ae65d1d63
6
+ metadata.gz: d6009ac4f8cdd344ca8403235a20d40c71b9dcf891c17a3646650a8b307d863dd5bf2b63d1ce58bcd768f7d394a572f5f14f822ea294818a7c42e307839e0bb6
7
+ data.tar.gz: 8a53d85316ec32a69a36a287bc6a5f44702427f2b54b9720da82e91fa599aa33e6fd7ccf600f06a1c01442675cf8b267c749506c32151f798c310e4c6060286e
data/History.md CHANGED
@@ -1,3 +1,14 @@
1
+ ### 2.2.0 / 2024-07-22
2
+
3
+ * Delegation to inner geometry for a feature (#53)
4
+ * MultiJson rather than JSON (#46)
5
+ * Conversion methods for better integration with core (#56)
6
+
7
+ ### 2.1.1 / 2018-11-27
8
+
9
+ * Freeze strings
10
+
11
+
1
12
  ### 2.1.0 / 2018-11-27
2
13
 
3
14
  * Allow rgeo 2.0
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # rgeo-geojson
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rgeo-geojson.svg)](http://badge.fury.io/rb/rgeo-geojson)
4
- [![Build Status](https://travis-ci.org/rgeo/rgeo-geojson.svg?branch=master)](https://travis-ci.org/rgeo/rgeo-geojson)
4
+ [![CI](https://github.com/rgeo/rgeo-geojson/workflows/CI/badge.svg)](https://github.com/rgeo/rgeo-geojson/actions?query=workflow%3ACI+branch%3Amaster+event%3Apush)
5
5
 
6
6
  `rgeo-geojson` is an extension to [RGeo](https://github.com/rgeo/rgeo)
7
7
  that provides GeoJSON encoding and decoding.
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RGeo
2
4
  module GeoJSON
3
5
  # This object encapsulates encoding and decoding settings (principally
4
6
  # the RGeo::Feature::Factory and the RGeo::GeoJSON::EntityFactory to
5
7
  # be used) so that you can encode and decode without specifying those
6
8
  # settings every time.
7
-
8
9
  class Coder
9
10
  # Create a new coder settings object. The geo factory is passed as
10
11
  # a required argument.
@@ -39,7 +40,6 @@ module RGeo
39
40
  # appropriate JSON library installed.
40
41
  #
41
42
  # Returns nil if nil is passed in as the object.
42
-
43
43
  def encode(object)
44
44
  if @entity_factory.is_feature_collection?(object)
45
45
  {
@@ -58,13 +58,12 @@ module RGeo
58
58
  # Decode an object from GeoJSON. The input may be a JSON hash, a
59
59
  # String, or an IO object from which to read the JSON string.
60
60
  # If an error occurs, nil is returned.
61
-
62
61
  def decode(input)
63
62
  if input.is_a?(IO)
64
63
  input = input.read rescue nil
65
64
  end
66
65
  if input.is_a?(String)
67
- input = JSON.parse(input)
66
+ input = MultiJson.load(input)
68
67
  end
69
68
  return unless input.is_a?(Hash)
70
69
 
@@ -193,7 +192,7 @@ module RGeo
193
192
 
194
193
  def decode_point_coords(point_coords)
195
194
  return unless point_coords.is_a?(Array)
196
- @geo_factory.point(*(point_coords[0...@num_coordinates].map(&:to_f))) rescue nil
195
+ @geo_factory.point(*point_coords[0...@num_coordinates].map(&:to_f)) rescue nil
197
196
  end
198
197
 
199
198
  def decode_line_string_coords(line_coords)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RGeo
4
+ # This module is here to fill the gap between what is a GeometryCollection (GIS)
5
+ # and a FeatureCollection (GeoJSON).
6
+ #
7
+ # Note for contributors, you can rely on `@features` to be defined and
8
+ # you can consider working with an Enumerable wrapping `@features`. See
9
+ # GeoJSON::FeatureCollection.
10
+ module GeoJSON::CollectionMethods
11
+ # There is tight coupling between {FeatureCollection} and this, hence the
12
+ # guard.
13
+ private_class_method def self.included(base)
14
+ return if base.to_s == "RGeo::GeoJSON::FeatureCollection"
15
+
16
+ raise Error::RGeoError, "#{self.class} must only be used by FeatureCollection"
17
+ end
18
+
19
+ private def method_missing(symbol, *args)
20
+ return super unless any? { |feature| feature.respond_to?(symbol) }
21
+
22
+ raise Error::UnsupportedOperation, "Method FeatureCollection##{symbol} " \
23
+ "is not defined. You may consider filing an issue or opening a pull " \
24
+ "request at https://github.com/rgeo/rgeo-geojson"
25
+ end
26
+
27
+ def contains?(geometry)
28
+ any? { |feature| feature.contains?(geometry) }
29
+ end
30
+
31
+ def intersects?(geometry)
32
+ any? { |feature| feature.intersects?(geometry) }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RGeo
4
+ # This module serves to provide handy methods when using GeoJSON. The methods
5
+ # provided eases the passage between entities and GeoJSON String/Hash.
6
+ module GeoJSON::ConversionMethods
7
+ # Convert a geometry to a GeoJSON Hash
8
+ def as_geojson
9
+ GeoJSON.encode(self)
10
+ end
11
+ alias as_json as_geojson
12
+
13
+ # Convert a geometry to a GeoJSON String
14
+ def to_geojson
15
+ ::MultiJson.dump(as_geojson)
16
+ end
17
+ alias to_json to_geojson
18
+ end
19
+
20
+ # These convenience methods are added directly into the module rather than
21
+ # including the module above into the Feature::Instance module which is in
22
+ # every geometry implementation. This is due to a behavior in ruby versions
23
+ # <3.0.2 where dynamically included modules will not be included automatically
24
+ # in the ancestor tree.
25
+ # See https://bugs.ruby-lang.org/issues/9573 for more information.
26
+ module Feature
27
+ module Instance
28
+ # Convert a geometry to a GeoJSON Hash
29
+ def as_geojson
30
+ GeoJSON.encode(self)
31
+ end
32
+ alias as_json as_geojson
33
+
34
+ # Convert a geometry to a GeoJSON String
35
+ def to_geojson
36
+ ::MultiJson.dump(as_geojson)
37
+ end
38
+ alias to_json to_geojson
39
+ end
40
+
41
+ module Factory::Instance
42
+ # Parses a GeoJSON String/Hash, or an IO object from which
43
+ # the JSON string is read and returns the corresponding
44
+ # feature. Returns nil if unable to parse.
45
+ def parse_geojson(input)
46
+ GeoJSON.decode(input, geo_factory: self)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,5 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "collection_methods"
4
+ require_relative "conversion_methods"
5
+
1
6
  module RGeo
7
+ module CastOverlay
8
+ def self.included(base)
9
+ # The original {RGeo::Feature.cast} would copy a GeoJSON::Feature, which
10
+ # fails most operations. When casting, we MUST get a geometry.
11
+ original_cast = base.method(:cast)
12
+ base.define_singleton_method(:cast) do |obj, *params|
13
+ if obj.class == GeoJSON::Feature
14
+ original_cast.call(obj.geometry, *params)
15
+ else
16
+ original_cast.call(obj, *params)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ Feature.include(CastOverlay)
22
+
2
23
  module GeoJSON
24
+ # Simplify usage of inner geometries for Feature and FeatureCollection
25
+ # objets. Including class must contain a `#geometry` method.
26
+ module DelegateToGeometry
27
+ private def method_missing(symbol, *args)
28
+ return geometry.public_send(symbol, *args) if geometry
29
+
30
+ super
31
+ end
32
+
33
+ private def respond_to_missing?(symbol, *)
34
+ geometry&.respond_to?(symbol) || super
35
+ end
36
+ end
37
+
3
38
  # This is a GeoJSON wrapper entity that corresponds to the GeoJSON
4
39
  # "Feature" type. It is an immutable type.
5
40
  #
@@ -9,11 +44,12 @@ module RGeo
9
44
  # implementation need not subclass or even duck-type this class.
10
45
  # the entity factory mediates all interaction between the GeoJSON
11
46
  # engine and features.
12
-
13
47
  class Feature
48
+ include DelegateToGeometry
49
+ include ConversionMethods
50
+
14
51
  # Create a feature wrapping the given geometry, with the given ID
15
52
  # and properties.
16
-
17
53
  def initialize(geometry, id = nil, properties = {})
18
54
  @geometry = geometry
19
55
  @id = id
@@ -39,7 +75,6 @@ module RGeo
39
75
  # are all equal.
40
76
  # This method uses the eql? method to test geometry equality, which
41
77
  # may behave differently than the == operator.
42
-
43
78
  def eql?(other)
44
79
  other.is_a?(Feature) && @geometry.eql?(other.geometry) && @id.eql?(other.feature_id) && @properties.eql?(other.instance_variable_get(:@properties))
45
80
  end
@@ -48,37 +83,31 @@ module RGeo
48
83
  # are all equal.
49
84
  # This method uses the == operator to test geometry equality, which
50
85
  # may behave differently than the eql? method.
51
-
52
86
  def ==(other)
53
87
  other.is_a?(Feature) && @geometry == other.geometry && @id == other.feature_id && @properties == other.instance_variable_get(:@properties)
54
88
  end
55
89
 
56
90
  # Returns the geometry contained in this feature, which may be nil.
57
-
58
91
  attr_reader :geometry
59
92
 
60
93
  # Returns the ID for this feature, which may be nil.
61
-
62
94
  def feature_id
63
95
  @id
64
96
  end
65
97
 
66
98
  # Returns a copy of the properties for this feature.
67
-
68
99
  def properties
69
100
  @properties.dup
70
101
  end
71
102
 
72
103
  # Gets the value of the given named property.
73
104
  # Returns nil if the given property is not found.
74
-
75
105
  def property(key)
76
106
  @properties[key.to_s]
77
107
  end
78
108
  alias [] property
79
109
 
80
110
  # Gets an array of the known property keys in this feature.
81
-
82
111
  def keys
83
112
  @properties.keys
84
113
  end
@@ -93,16 +122,17 @@ module RGeo
93
122
  # FeatureCollection implementation need not subclass or even
94
123
  # duck-type this class. The entity factory mediates all interaction
95
124
  # between the GeoJSON engine and feature collections.
96
-
97
125
  class FeatureCollection
98
126
  include Enumerable
127
+ include CollectionMethods
128
+ include ConversionMethods
99
129
 
100
130
  # Create a new FeatureCollection with the given features, which must
101
131
  # be provided as an Enumerable.
102
-
103
132
  def initialize(features = [])
104
133
  @features = []
105
134
  features.each { |f| @features << f if f.is_a?(Feature) }
135
+ @features.freeze
106
136
  end
107
137
 
108
138
  def inspect
@@ -121,7 +151,6 @@ module RGeo
121
151
  # features in the same order.
122
152
  # This methods uses the eql? method to test geometry equality, which
123
153
  # may behave differently than the == operator.
124
-
125
154
  def eql?(other)
126
155
  other.is_a?(FeatureCollection) && @features.eql?(other.instance_variable_get(:@features))
127
156
  end
@@ -130,25 +159,21 @@ module RGeo
130
159
  # features in the same order.
131
160
  # This methods uses the == operator to test geometry equality, which
132
161
  # may behave differently than the eql? method.
133
-
134
162
  def ==(other)
135
163
  other.is_a?(FeatureCollection) && @features == other.instance_variable_get(:@features)
136
164
  end
137
165
 
138
166
  # Iterates or returns an iterator for the features.
139
-
140
167
  def each(&block)
141
168
  @features.each(&block)
142
169
  end
143
170
 
144
171
  # Returns the number of features contained in this collection.
145
-
146
172
  def size
147
173
  @features.size
148
174
  end
149
175
 
150
176
  # Access a feature by index.
151
-
152
177
  def [](index)
153
178
  @features[index]
154
179
  end
@@ -162,60 +187,51 @@ module RGeo
162
187
  # Create and return a new feature, given geometry, ID, and
163
188
  # properties hash. Note that, per the GeoJSON spec, geometry and/or
164
189
  # properties may be nil.
165
-
166
190
  def feature(geometry, id = nil, properties = nil)
167
191
  Feature.new(geometry, id, properties || {})
168
192
  end
169
193
 
170
194
  # Create and return a new feature collection, given an enumerable
171
195
  # of feature objects.
172
-
173
196
  def feature_collection(features = [])
174
197
  FeatureCollection.new(features)
175
198
  end
176
199
 
177
200
  # Returns true if the given object is a feature created by this
178
201
  # entity factory.
179
-
180
202
  def is_feature?(object)
181
203
  object.is_a?(Feature)
182
204
  end
183
205
 
184
206
  # Returns true if the given object is a feature collection created
185
207
  # by this entity factory.
186
-
187
208
  def is_feature_collection?(object)
188
209
  object.is_a?(FeatureCollection)
189
210
  end
190
211
 
191
212
  # Run Enumerable#map on the features contained in the given feature
192
213
  # collection.
193
-
194
214
  def map_feature_collection(object, &block)
195
215
  object.map(&block)
196
216
  end
197
217
 
198
218
  # Returns the geometry associated with the given feature.
199
-
200
219
  def get_feature_geometry(object)
201
220
  object.geometry
202
221
  end
203
222
 
204
223
  # Returns the ID of the given feature, or nil for no ID.
205
-
206
224
  def get_feature_id(object)
207
225
  object.feature_id
208
226
  end
209
227
 
210
228
  # Returns the properties of the given feature as a hash. Editing
211
229
  # this hash does not change the state of the feature.
212
-
213
230
  def get_feature_properties(object)
214
231
  object.properties
215
232
  end
216
233
 
217
234
  # Return the singleton instance of EntityFactory.
218
-
219
235
  def self.instance
220
236
  @instance ||= new
221
237
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RGeo
2
4
  module GeoJSON
3
5
  class << self
@@ -11,9 +13,8 @@ module RGeo
11
13
  # RGeo::GeoJSON::EntityFactory for more information. By default,
12
14
  # encode supports objects of type RGeo::GeoJSON::Feature and
13
15
  # RGeo::GeoJSON::FeatureCollection.
14
-
15
16
  def encode(object, opts = {})
16
- Coder.new(opts).encode(object)
17
+ coder(opts).encode(object)
17
18
  end
18
19
 
19
20
  # High-level convenience routine for decoding an object from GeoJSON.
@@ -31,8 +32,8 @@ module RGeo
31
32
  # RGeo::GeoJSON::EntityFactory, which generates objects of type
32
33
  # RGeo::GeoJSON::Feature or RGeo::GeoJSON::FeatureCollection.
33
34
  # See RGeo::GeoJSON::EntityFactory for more information.
34
- def decode(input_, opts = {})
35
- Coder.new(opts).decode(input_)
35
+ def decode(input, opts = {})
36
+ coder(opts).decode(input)
36
37
  end
37
38
 
38
39
  # Creates and returns a coder object of type RGeo::GeoJSON::Coder
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RGeo
2
4
  module GeoJSON
3
- VERSION = "2.1.0".freeze
5
+ VERSION = "2.2.0"
4
6
  end
5
7
  end
data/lib/rgeo/geo_json.rb CHANGED
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rgeo"
2
- require "rgeo/geo_json/version"
3
- require "rgeo/geo_json/entities"
4
- require "rgeo/geo_json/coder"
5
- require "rgeo/geo_json/interface"
6
- require "json"
4
+ require_relative "geo_json/version"
5
+ require_relative "geo_json/conversion_methods"
6
+ require_relative "geo_json/entities"
7
+ require_relative "geo_json/coder"
8
+ require_relative "geo_json/interface"
9
+ require "multi_json"
data/lib/rgeo-geojson.rb CHANGED
@@ -1 +1,3 @@
1
- require "rgeo/geo_json"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rgeo/geo_json"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgeo-geojson
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-11-28 00:00:00.000000000 Z
12
+ date: 2024-07-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rgeo
@@ -26,19 +26,19 @@ dependencies:
26
26
  - !ruby/object:Gem::Version
27
27
  version: 1.0.0
28
28
  - !ruby/object:Gem::Dependency
29
- name: bundler
29
+ name: multi_json
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '1.6'
35
- type: :development
34
+ version: '1.15'
35
+ type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '1.6'
41
+ version: '1.15'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: minitest
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +72,7 @@ description: Convert RGeo data to and from GeoJSON. rgeo-geojson is an extension
72
72
  email:
73
73
  - dazuma@gmail.com
74
74
  - parhameter@gmail.com
75
+ - kfdoggett@gmail.com
75
76
  executables: []
76
77
  extensions: []
77
78
  extra_rdoc_files: []
@@ -82,12 +83,14 @@ files:
82
83
  - lib/rgeo-geojson.rb
83
84
  - lib/rgeo/geo_json.rb
84
85
  - lib/rgeo/geo_json/coder.rb
86
+ - lib/rgeo/geo_json/collection_methods.rb
87
+ - lib/rgeo/geo_json/conversion_methods.rb
85
88
  - lib/rgeo/geo_json/entities.rb
86
89
  - lib/rgeo/geo_json/interface.rb
87
90
  - lib/rgeo/geo_json/version.rb
88
91
  homepage: https://github.com/rgeo/rgeo-geojson
89
92
  licenses:
90
- - BSD
93
+ - BSD-3-Clause
91
94
  metadata: {}
92
95
  post_install_message:
93
96
  rdoc_options: []
@@ -104,8 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
107
  - !ruby/object:Gem::Version
105
108
  version: '0'
106
109
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.7.8
110
+ rubygems_version: 3.5.2
109
111
  signing_key:
110
112
  specification_version: 4
111
113
  summary: Convert RGeo data to and from GeoJSON.