rgeo-geojson 2.1.0 → 2.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.
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.