charta 0.2.2 → 0.2.3

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
- SHA1:
3
- metadata.gz: 5cef2f555beb27d13a0cbc3bbc24f64f9143d2cb
4
- data.tar.gz: 64f46d959388ca952edbb53e8deb4a887335bc9f
2
+ SHA256:
3
+ metadata.gz: 4fbd9a97d2afc3f7fac4856628353c24a686fad2a416c0d12dbb00b448f6d9a4
4
+ data.tar.gz: '0267836321e3643033bcd873e7672144a37bf0f0b293cd9440a7f01de84a02dc'
5
5
  SHA512:
6
- metadata.gz: 99614ef99edfdbd74e8d107279a1e8533b887cc3e4e503ba7355c60f964a4aeb95e5778debd35dc3fd4c385c61c3a199f412ac1252691accf0b079e60530b99d
7
- data.tar.gz: 4abce4b81dd5ccab25fcb6778b896615c627d389aec8cd465301595ff9e171f1af7c64bb1f1b7f3947d4d9b73ca5a16cc23c508303796e254f57a92ac0f7a56d
6
+ metadata.gz: 76960df71f7e14223da5c28b93dfad64f6ffd563609408cf04eea019afb23c1f7fbeaf3a49775a251152581ac6650a8d9688e7d96230d3aed687cdcb90390eda
7
+ data.tar.gz: a987c577129ff328b5b8ae574b28dc83ea0a54a308c6e02c0986db53837f06d62429545c48dac75bd5a96b241f98beaaf6d63a5eab3d51ad56abfc31ffac3de3
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
  /spec/reports/
10
10
  /tmp/
11
11
  .byebug_history
12
+ /.idea/
13
+ .ruby-version
@@ -2,7 +2,7 @@ stages:
2
2
  - test
3
3
 
4
4
  test:
5
- image: registry.gitlab.com/ekylibre/docker-base-images/ruby2.3:master
5
+ image: registry.gitlab.com/ekylibre/docker-base-images/ruby2.3:1
6
6
  before_script:
7
7
  - gem install bundler
8
8
  - bundle install --path vendor/bundle
@@ -11,4 +11,4 @@ test:
11
11
  paths:
12
12
  - vendor/bundle
13
13
  script:
14
- - bundle exec rake test
14
+ - bundle exec rake test
@@ -1,7 +1,12 @@
1
1
  # Gathers geomatic calculations
2
2
  # Completes RGeo
3
+ require 'bigdecimal'
4
+ require 'bigdecimal/util'
3
5
  require 'rgeo'
4
6
  require 'rgeo/proj4'
7
+
8
+ require 'charta/coordinates'
9
+ require 'charta/ewkt_serializer'
5
10
  require 'charta/geometry'
6
11
  require 'charta/geometry_collection'
7
12
  require 'charta/point'
@@ -24,5 +24,9 @@ module Charta
24
24
  def to_a
25
25
  [[@y_min, @x_min], [@y_max, @x_max]]
26
26
  end
27
+
28
+ def to_bbox_string
29
+ "#{@x_min}, #{@y_min}, #{x_max}, #{y_max}"
30
+ end
27
31
  end
28
32
  end
@@ -0,0 +1,65 @@
1
+ module Charta
2
+ module Coordinates
3
+ class << self
4
+
5
+ # Force coordinates to 2D
6
+ def flatten(hash)
7
+ map_coordinates(hash) { |position| position[0..1] }
8
+ end
9
+
10
+ def map_coordinates(hash, &block)
11
+ case hash['type']
12
+ when 'FeatureCollection'
13
+ map_feature_collection_coordinates hash, &block
14
+ when 'Feature'
15
+ map_feature_coordinates hash, &block
16
+ else
17
+ map_geometry_coordinates hash, &block
18
+ end
19
+ end
20
+
21
+ def normalize_4326_geometry(json)
22
+ map_coordinates json do |(x, y)|
23
+ [((x + 180.to_d) % 360.to_d) - 180.to_d, ((y + 90.to_d) % 180.to_d) - 90.to_d]
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def map_feature_collection_coordinates(hash, &block)
30
+ hash.merge 'features' => hash['features'].map { |feature| map_feature_coordinates feature, &block }
31
+ end
32
+
33
+ def map_feature_coordinates(hash, &block)
34
+ hash.merge 'geometry' => map_geometry_coordinates(hash['geometry'], &block)
35
+ end
36
+
37
+ def map_geometry_coordinates(hash, &block)
38
+ if hash['type'] == 'GeometryCollection'
39
+ map_geometry_collection_coordinates hash, &block
40
+ else
41
+ coordinates = hash['coordinates']
42
+ mapped =
43
+ case hash['type']
44
+ when 'Point' then
45
+ block.call coordinates
46
+ when 'MultiPoint', 'LineString'
47
+ coordinates.map(&block)
48
+ when 'MultiLineString', 'Polygon'
49
+ coordinates.map { |line| line.map(&block) }
50
+ when 'MultiPolygon'
51
+ coordinates.map { |poly| poly.map { |line| line.map(&block) } }
52
+ else
53
+ raise StandardError, "Cannot handle: #{hash['type'].inspect}. In #{hash.inspect}"
54
+ end
55
+
56
+ hash.merge 'coordinates' => mapped
57
+ end
58
+ end
59
+
60
+ def map_geometry_collection_coordinates(hash, &block)
61
+ hash.merge 'geometries' => hash['geometries'].map { |geometry| map_geometry_coordinates(geometry, &block) }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,92 @@
1
+ module Charta
2
+ module EwktSerializer
3
+
4
+ class << self
5
+ def object_to_ewkt(hash)
6
+ type = hash[:type] || hash['type']
7
+ send("#{type.gsub(/(.)([A-Z])/, '\1_\2').downcase}_to_ewkt", hash)
8
+ end
9
+
10
+ private
11
+
12
+ def feature_collection_to_ewkt(hash)
13
+ return 'GEOMETRYCOLLECTION EMPTY' if hash['features'].nil?
14
+ 'GEOMETRYCOLLECTION(' + hash['features'].collect do |feature|
15
+ object_to_ewkt(feature)
16
+ end.join(', ') + ')'
17
+ end
18
+
19
+ def geometry_collection_to_ewkt(hash)
20
+ return 'GEOMETRYCOLLECTION EMPTY' if hash['geometries'].nil?
21
+ 'GEOMETRYCOLLECTION(' + hash['geometries'].collect do |feature|
22
+ object_to_ewkt(feature)
23
+ end.join(', ') + ')'
24
+ end
25
+
26
+ def feature_to_ewkt(hash)
27
+ object_to_ewkt(hash['geometry'])
28
+ end
29
+
30
+ def point_to_ewkt(hash)
31
+ return 'POINT EMPTY' if hash['coordinates'].nil?
32
+ 'POINT(' + hash['coordinates'].join(' ') + ')'
33
+ end
34
+
35
+ def line_string_to_ewkt(hash)
36
+ return 'LINESTRING EMPTY' if hash['coordinates'].nil?
37
+ 'LINESTRING(' + hash['coordinates'].collect do |point|
38
+ point.join(' ')
39
+ end.join(', ') + ')'
40
+ end
41
+
42
+ def polygon_to_ewkt(hash)
43
+ return 'POLYGON EMPTY' if hash['coordinates'].nil?
44
+ 'POLYGON(' + hash['coordinates'].collect do |hole|
45
+ '(' + hole.collect do |point|
46
+ point.join(' ')
47
+ end.join(', ') + ')'
48
+ end.join(', ') + ')'
49
+ end
50
+
51
+ def multi_point_to_ewkt(hash)
52
+ return 'MULTIPOINT EMPTY' if hash['coordinates'].nil?
53
+ 'MULTIPOINT(' + hash['coordinates'].collect do |point|
54
+ '(' + point.join(' ') + ')'
55
+ end.join(', ') + ')'
56
+ end
57
+
58
+ def multi_line_string_to_ewkt(hash)
59
+ return 'MULTILINESTRING EMPTY' if hash['coordinates'].nil?
60
+ 'MULTILINESTRING(' + hash['coordinates'].collect do |line|
61
+ '(' + line.collect do |point|
62
+ point.join(' ')
63
+ end.join(', ') + ')'
64
+ end.join(', ') + ')'
65
+ end
66
+
67
+ def multipolygon_to_ewkt(hash)
68
+ return 'MULTIPOLYGON EMPTY' if hash['coordinates'].nil?
69
+ 'MULTIPOLYGON(' + hash['coordinates'].collect do |polygon|
70
+ '(' + polygon.collect do |hole|
71
+ '(' + hole.collect do |point|
72
+ point.join(' ')
73
+ end.join(', ') + ')'
74
+ end.join(', ') + ')'
75
+ end.join(', ') + ')'
76
+ end
77
+
78
+ # for PostGIS ST_ASGeoJSON compatibility
79
+ def multi_polygon_to_ewkt(hash)
80
+ return 'MULTIPOLYGON EMPTY' if hash['coordinates'].nil?
81
+ 'MULTIPOLYGON(' + hash['coordinates'].collect do |polygon|
82
+ '(' + polygon.collect do |hole|
83
+ '(' + hole.collect do |point|
84
+ point.join(' ')
85
+ end.join(', ') + ')'
86
+ end.join(', ') + ')'
87
+ end.join(', ') + ')'
88
+ end
89
+ end
90
+
91
+ end
92
+ end
@@ -7,12 +7,14 @@ module Charta
7
7
 
8
8
  def initialize(data, srid = :WGS84)
9
9
  srid ||= :WGS84
10
- @json = self.class.flatten(data.is_a?(Hash) ? data : JSON.parse(data))
10
+ @json = Coordinates.flatten(data.is_a?(Hash) ? data : JSON.parse(data))
11
11
  lsrid = @json['crs']['properties']['name'] if @json.is_a?(Hash) &&
12
12
  @json['crs'].is_a?(Hash) &&
13
13
  @json['crs']['properties'].is_a?(Hash)
14
14
  lsrid ||= srid
15
15
  @srid = ::Charta.find_srid(lsrid)
16
+
17
+ @json = Coordinates.normalize_4326_geometry(@json) if @srid.to_i == 4326
16
18
  end
17
19
 
18
20
  def geom
@@ -24,7 +26,7 @@ module Charta
24
26
  end
25
27
 
26
28
  def to_ewkt
27
- "SRID=#{@srid};" + self.class.object_to_ewkt(@json)
29
+ "SRID=#{srid};" + EwktSerializer.object_to_ewkt(@json)
28
30
  end
29
31
 
30
32
  def valid?
@@ -42,131 +44,14 @@ module Charta
42
44
  false
43
45
  end
44
46
 
45
- # Force coordinates to 2D
46
47
  def flatten(hash)
47
- if hash['type'] == 'FeatureCollection'
48
- flatten_feature_collection(hash)
49
- elsif hash['type'] == 'Feature'
50
- flatten_feature(hash)
51
- else
52
- flatten_geometry(hash)
53
- end
54
- end
55
-
56
- def flatten_feature_collection(hash)
57
- hash.merge('features' => hash['features'].map { |f| flatten_feature(f) })
58
- end
59
-
60
- def flatten_feature(hash)
61
- hash.merge('geometry' => flatten_geometry(hash['geometry']))
62
- end
63
-
64
- def flatten_geometry(hash)
65
- coordinates = hash['coordinates']
66
- flattened =
67
- case hash['type']
68
- when 'Point' then
69
- flatten_position(coordinates)
70
- when 'MultiPoint', 'LineString'
71
- coordinates.map { |p| flatten_position(p) }
72
- when 'MultiLineString', 'Polygon'
73
- coordinates.map { |l| l.map { |p| flatten_position(p) } }
74
- when 'MultiPolygon'
75
- coordinates.map { |m| m.map { |l| l.map { |p| flatten_position(p) } } }
76
- when 'GeometryCollection' then
77
- return hash.merge('geometries' => hash['geometries'].map { |g| flatten_geometry(g) })
78
- else
79
- raise StandardError, "Cannot handle: #{hash['type'].inspect}. In #{hash.inspect}"
80
- end
81
-
82
- hash.merge('coordinates' => flattened)
83
- end
84
-
85
- def flatten_position(position)
86
- position[0..1]
87
- end
88
-
89
- def object_to_ewkt(hash)
90
- type = hash[:type] || hash['type']
91
- send("#{type.gsub(/(.)([A-Z])/, '\1_\2').downcase}_to_ewkt", hash)
92
- end
93
-
94
- def feature_collection_to_ewkt(hash)
95
- return 'GEOMETRYCOLLECTION EMPTY' if hash['features'].nil?
96
- 'GEOMETRYCOLLECTION(' + hash['features'].collect do |feature|
97
- object_to_ewkt(feature)
98
- end.join(', ') + ')'
99
- end
100
-
101
- def geometry_collection_to_ewkt(hash)
102
- return 'GEOMETRYCOLLECTION EMPTY' if hash['geometries'].nil?
103
- 'GEOMETRYCOLLECTION(' + hash['geometries'].collect do |feature|
104
- object_to_ewkt(feature)
105
- end.join(', ') + ')'
106
- end
107
-
108
- def feature_to_ewkt(hash)
109
- object_to_ewkt(hash['geometry'])
110
- end
111
-
112
- def point_to_ewkt(hash)
113
- return 'POINT EMPTY' if hash['coordinates'].nil?
114
- 'POINT(' + hash['coordinates'].join(' ') + ')'
115
- end
116
-
117
- def line_string_to_ewkt(hash)
118
- return 'LINESTRING EMPTY' if hash['coordinates'].nil?
119
- 'LINESTRING(' + hash['coordinates'].collect do |point|
120
- point.join(' ')
121
- end.join(', ') + ')'
122
- end
123
-
124
- def polygon_to_ewkt(hash)
125
- return 'POLYGON EMPTY' if hash['coordinates'].nil?
126
- 'POLYGON(' + hash['coordinates'].collect do |hole|
127
- '(' + hole.collect do |point|
128
- point.join(' ')
129
- end.join(', ') + ')'
130
- end.join(', ') + ')'
131
- end
132
-
133
- def multi_point_to_ewkt(hash)
134
- return 'MULTIPOINT EMPTY' if hash['coordinates'].nil?
135
- 'MULTIPOINT(' + hash['coordinates'].collect do |point|
136
- '(' + point.join(' ') + ')'
137
- end.join(', ') + ')'
138
- end
139
-
140
- def multi_line_string_to_ewkt(hash)
141
- return 'MULTILINESTRING EMPTY' if hash['coordinates'].nil?
142
- 'MULTILINESTRING(' + hash['coordinates'].collect do |line|
143
- '(' + line.collect do |point|
144
- point.join(' ')
145
- end.join(', ') + ')'
146
- end.join(', ') + ')'
147
- end
148
-
149
- def multipolygon_to_ewkt(hash)
150
- return 'MULTIPOLYGON EMPTY' if hash['coordinates'].nil?
151
- 'MULTIPOLYGON(' + hash['coordinates'].collect do |polygon|
152
- '(' + polygon.collect do |hole|
153
- '(' + hole.collect do |point|
154
- point.join(' ')
155
- end.join(', ') + ')'
156
- end.join(', ') + ')'
157
- end.join(', ') + ')'
48
+ Coordinates.flatten hash
158
49
  end
159
50
 
160
- # for PostGIS ST_ASGeoJSON compatibility
161
- def multi_polygon_to_ewkt(hash)
162
- return 'MULTIPOLYGON EMPTY' if hash['coordinates'].nil?
163
- 'MULTIPOLYGON(' + hash['coordinates'].collect do |polygon|
164
- '(' + polygon.collect do |hole|
165
- '(' + hole.collect do |point|
166
- point.join(' ')
167
- end.join(', ') + ')'
168
- end.join(', ') + ')'
169
- end.join(', ') + ')'
51
+ %i[object_to_ewkt feature_collection_to_ewkt geometry_collection_to_ewkt feature_to_ewkt point_to_ewkt line_string_to_ewkt polygon_to_ewkt multi_point_to_ewkt multi_line_string_to_ewkt multipolygon_to_ewkt multi_polygon_to_ewkt].each do |m|
52
+ define_method m do |*args|
53
+ EwktSerializer.send m, *args
54
+ end
170
55
  end
171
56
  end
172
57
  end
@@ -110,12 +110,24 @@ module Charta
110
110
 
111
111
  # Returns true if Geometry is a Surface
112
112
  def surface?
113
- [RGeo::Feature::Polygon, RGeo::Feature::MultiPolygon].include? feature.geometry_type
113
+ if collection?
114
+ feature.any? { |geometry| Charta.new_geometry(geometry).surface? }
115
+ else
116
+ [RGeo::Feature::Polygon, RGeo::Feature::MultiPolygon].include? feature.geometry_type
117
+ end
114
118
  end
115
119
 
116
120
  # Returns area in unit corresponding to the SRS
117
121
  def area
118
- surface? ? feature.area : 0
122
+ if surface?
123
+ if collection?
124
+ feature.sum { |geometry| Charta.new_geometry(geometry).area }
125
+ else
126
+ feature.area
127
+ end
128
+ else
129
+ 0
130
+ end
119
131
  end
120
132
 
121
133
  # Returns true if this Geometry is an empty geometrycollection, polygon,
@@ -143,10 +155,16 @@ module Charta
143
155
 
144
156
  def convert_to(new_type)
145
157
  case new_type
146
- when type then self
147
- when :multi_point then flatten_multi(:point)
148
- when :multi_line_string then flatten_multi(:line_string)
149
- when :multi_polygon then flatten_multi(:polygon)
158
+ when type then
159
+ self
160
+ when :multi_point then
161
+ flatten_multi(:point)
162
+ when :multi_line_string then
163
+ flatten_multi(:line_string)
164
+ when :multi_polygon then
165
+ flatten_multi(:polygon)
166
+ else
167
+ self
150
168
  end
151
169
  end
152
170
 
@@ -205,6 +223,11 @@ module Charta
205
223
  feature.intersection(other_geometry.feature)
206
224
  end
207
225
 
226
+ def intersects?(other)
227
+ other_geometry = Charta.new_geometry(other).transform(srid)
228
+ feature.intersects?(other_geometry.feature)
229
+ end
230
+
208
231
  def difference(other)
209
232
  other_geometry = Charta.new_geometry(other).transform(srid)
210
233
  feature.difference(other_geometry.feature)
@@ -10,5 +10,10 @@ module Charta
10
10
  feature.y
11
11
  end
12
12
  alias latitude y
13
+
14
+ def distance(point)
15
+ raise ArgumentError, "wrong type: Charta::Point required" if point.class.name != "Charta::Point"
16
+ to_rgeo.distance(point.to_rgeo)
17
+ end
13
18
  end
14
19
  end
@@ -8,5 +8,10 @@ module Charta
8
8
  end
9
9
  @exterior_ring
10
10
  end
11
+
12
+ def distance(point)
13
+ polygon_centroid = Charta.new_point(*centroid, 4326)
14
+ polygon_centroid.distance(point)
15
+ end
11
16
  end
12
17
  end
@@ -1,3 +1,3 @@
1
1
  module Charta
2
- VERSION = '0.2.2'.freeze
2
+ VERSION = '0.2.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: charta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brice TEXIER
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-30 00:00:00.000000000 Z
11
+ date: 2020-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -150,7 +150,7 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
- description:
153
+ description:
154
154
  email:
155
155
  - brice@ekylibre.com
156
156
  executables: []
@@ -168,6 +168,8 @@ files:
168
168
  - charta.gemspec
169
169
  - lib/charta.rb
170
170
  - lib/charta/bounding_box.rb
171
+ - lib/charta/coordinates.rb
172
+ - lib/charta/ewkt_serializer.rb
171
173
  - lib/charta/geo_json.rb
172
174
  - lib/charta/geojson_import.rb
173
175
  - lib/charta/geometry.rb
@@ -185,7 +187,7 @@ homepage: https://github.com/ekylibre/charta
185
187
  licenses:
186
188
  - MIT
187
189
  metadata: {}
188
- post_install_message:
190
+ post_install_message:
189
191
  rdoc_options: []
190
192
  require_paths:
191
193
  - lib
@@ -200,9 +202,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
202
  - !ruby/object:Gem::Version
201
203
  version: '0'
202
204
  requirements: []
203
- rubyforge_project:
204
- rubygems_version: 2.5.2.3
205
- signing_key:
205
+ rubygems_version: 3.0.3
206
+ signing_key:
206
207
  specification_version: 4
207
208
  summary: Simple tool over geos and co
208
209
  test_files: []