terraformer 0.0.1 → 0.0.2

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.
@@ -2,6 +2,21 @@ module Terraformer
2
2
 
3
3
  class Polygon < Geometry
4
4
 
5
+ def initialize *args
6
+ case
7
+ when Coordinate === args[0] # each arg is a position of the polygon
8
+ self.coordinates = [Coordinate.from_array(args)]
9
+ when Array === args[0] # each arg is an array of positions; first is polygon, rest are "holes"
10
+ self.coordinates = Coordinate.from args
11
+ else
12
+ super *args
13
+ end
14
+
15
+ if line_strings.map(&:linear_ring?).include? false
16
+ raise ArgumentError.new 'not linear ring'
17
+ end
18
+ end
19
+
5
20
  def has_holes?
6
21
  coordinates.length > 1
7
22
  end
@@ -10,6 +25,97 @@ module Terraformer
10
25
  coordinates[0][0]
11
26
  end
12
27
 
28
+ def == obj
29
+ super obj do |o|
30
+
31
+ equal = true
32
+
33
+ # first check outer polygon
34
+ equal = self.coordinates[0].polygonally_equal_to? obj.coordinates[0]
35
+
36
+
37
+ # then inner polygons (holes)
38
+ #
39
+ if equal and obj.coordinates.length > 1
40
+ 1.upto(obj.coordinates.length - 1) do |i|
41
+ equal = self.coordinates[i].polygonally_equal_to? obj.coordinates[i]
42
+ break unless equal
43
+ end
44
+ end
45
+
46
+ equal
47
+ end
48
+ end
49
+
50
+ def line_strings
51
+ coordinates.map {|lr| LineString.new lr}
52
+ end
53
+
54
+ def holes
55
+ return nil unless has_holes?
56
+ coordinates[1..-1].map {|hole| Polygon.new hole}
57
+ end
58
+
59
+ def contains? obj
60
+ obj = Coordinate.new obj if Array === obj and Numeric === obj[0]
61
+ obj = obj.to_point if Coordinate === obj
62
+ contained = false
63
+ case obj
64
+ when Point
65
+ contained = Geometry.coordinates_contain_point? coordinates[0], obj.coordinates
66
+ contained = !holes.any? {|h| h.contains? obj} if contained and has_holes?
67
+ when MultiPoint
68
+ contained = obj.points.all? {|p| contains? p}
69
+ when LineString
70
+ contained = contains?(obj.first_coordinate) && !Geometry.array_intersects_multi_array?(obj.coordinates, coordinates)
71
+ when MultiLineString
72
+ contained = obj.line_strings.all? {|ls| contains? ls}
73
+ when Polygon
74
+ contained = obj.within? self
75
+ when MultiPolygon
76
+ contained = obj.polygons.all? {|p| p.within? self}
77
+ else
78
+ raise ArgumentError.new "unsupported type: #{obj.type rescue obj.class}"
79
+ end
80
+ contained
81
+ end
82
+
83
+ def within? obj
84
+ case obj
85
+ when Polygon
86
+ if self == obj
87
+ true
88
+ elsif obj.contains? first_coordinate
89
+ !Geometry.arrays_intersect_arrays?(coordinates, obj.coordinates)
90
+ end
91
+ when MultiPolygon
92
+ obj.polygons.any? {|p| p.contains? self}
93
+ else
94
+ raise ArgumentError.new "unsupported type: #{obj.type rescue obj.class}"
95
+ end
96
+ end
97
+
98
+ def add_vertex p
99
+ insert_vertex coordinates[0].length - 2, p
100
+ end
101
+ alias_method :<<, :add_vertex
102
+
103
+ def insert_vertex idx, p
104
+ p = p.coordinates if Point === p
105
+ raise ArgumentError unless Coordinate === p
106
+ coordinates[0].insert idx, p
107
+ end
108
+
109
+ def remove_vertex p
110
+ p = p.coordinates if Point === p
111
+ raise ArgumentError unless Coordinate === p
112
+ coordinates[0].delete p
113
+ end
114
+
115
+ def remove_vertex_at idx
116
+ coordinates[0].delete_at idx
117
+ end
118
+
13
119
  end
14
120
 
15
121
  end
@@ -1,3 +1,3 @@
1
1
  module Terraformer
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
data/lib/terraformer.rb CHANGED
@@ -2,10 +2,17 @@ require 'json'
2
2
  require 'bigdecimal'
3
3
  require 'bigdecimal/math'
4
4
  require 'bigdecimal/util'
5
+ require 'ext/array'
6
+ require 'ext/big_decimal'
7
+ require 'ext/big_math'
8
+ require 'ext/enumerable'
9
+ require 'ext/hash'
10
+ require 'forwardable'
5
11
 
6
12
  module Terraformer
7
13
 
8
- PRECISION = 8
14
+ PRECISION = BigDecimal.double_fig
15
+ BigDecimal.limit PRECISION
9
16
  PI = BigMath.PI PRECISION
10
17
  DEFAULT_BUFFER_RESOLUTION = 64
11
18
 
@@ -28,7 +35,10 @@ module Terraformer
28
35
  }
29
36
 
30
37
  def self.parse geojson
31
- geojson = JSON.parse geojson if String === geojson
38
+ if String === geojson
39
+ geojson = File.read geojson if File.readable? geojson
40
+ geojson = JSON.parse geojson
41
+ end
32
42
  raise ArgumentError.new "invalid arg: #{geojson}" unless Hash === geojson
33
43
 
34
44
  if klass = Terraformer.const_get(geojson['type'])
@@ -60,69 +70,26 @@ module Terraformer
60
70
  end
61
71
 
62
72
  def to_json *args
63
- self.to_hash.to_json *args
64
- end
65
-
66
- def [] prop
67
- self.__send__ prop.to_sym
73
+ h = self.to_hash
74
+ h[:bbox] = bbox if Hash === args.last and args.pop[:include_bbox]
75
+ h.to_json *args
68
76
  end
69
77
 
70
78
  end
71
79
 
72
- end
73
-
74
- module Enumerable
75
-
76
- def each_coordinate opts = {}, &block
77
- iter_coordinate :each, opts, &block
78
- end
79
-
80
- def map_coordinate opts = {}, &block
81
- iter_coordinate :map, opts, &block
82
- end
83
- alias_method :collect_coordinate, :map_coordinate
84
-
85
- def map_coordinate! opts = {}, &block
86
- iter_coordinate :map!, opts, &block
87
- end
88
- alias_method :collect_coordinate!, :map_coordinate!
80
+ # yikes!
81
+ module BBox
89
82
 
90
- def iter_coordinate meth, opts = {}, &block
91
- opts[:recurse] = true if opts[:recurse].nil?
92
-
93
- if Array === self and Numeric === self[0]
94
- yield self
95
- else
96
-
97
- self.__send__ meth do |pair|
98
- raise IndexError unless Array === pair
99
- case pair[0]
100
- when Numeric
101
- yield pair
102
- when Array
103
- pair.iter_coordinate meth, opts, &block if opts[:recurse]
104
- else
105
- raise IndexError.new "#{pair[0]} is not a Numeric or Array type"
106
- end
107
- end
83
+ def to_json *args
84
+ map {|e| e.to_f if e}.to_json *args
108
85
  end
109
- end
110
-
111
- end
112
-
113
- class BigDecimal
114
-
115
- def to_deg
116
- self * Terraformer::DEGREES_PER_RADIAN
117
- end
118
86
 
119
- def to_rad
120
- self * Terraformer::RADIANS_PER_DEGREE
121
87
  end
122
88
 
123
89
  end
124
90
 
125
91
  require 'terraformer/coordinate'
92
+ require 'terraformer/geodesic'
126
93
  require 'terraformer/bounds'
127
94
  require 'terraformer/geometry'
128
95
  require 'terraformer/feature'
@@ -132,3 +99,5 @@ require 'terraformer/line_string'
132
99
  require 'terraformer/multi_line_string'
133
100
  require 'terraformer/polygon'
134
101
  require 'terraformer/multi_polygon'
102
+ require 'terraformer/convex_hull'
103
+ require 'terraformer/circle'
@@ -0,0 +1,26 @@
1
+ require_relative './helper'
2
+
3
+ describe Terraformer::ConvexHull do
4
+
5
+ EXAMPLES.not(:multi_line_string).each do |key, geo|
6
+ it "works on #{key}" do
7
+ ch = Terraformer.parse(geo).convex_hull
8
+ ch.dont_be_terrible_ok
9
+ ch.must_be_valid_geojson
10
+ end
11
+ end
12
+
13
+ it 'raises without enough points' do
14
+ ->{ Terraformer.parse(EXAMPLES[:multi_line_string]).convex_hull }.must_raise ArgumentError
15
+ end
16
+
17
+ it 'works on feature collections' do
18
+ fc = Terraformer::FeatureCollection.new
19
+ fc << Terraformer.parse(EXAMPLES[:waldocanyon])
20
+ fc << Terraformer.parse(EXAMPLES[:sf_county]).to_feature
21
+ ch = fc.convex_hull
22
+ ch.dont_be_terrible_ok
23
+ ch.must_be_valid_geojson
24
+ end
25
+
26
+ end
@@ -3,264 +3,264 @@
3
3
  "coordinates": [
4
4
  [
5
5
  [
6
- 100.00089398965049,
7
- 8.82355685852279e-05
6
+ 100.0008939896505,
7
+ 8.80502953952e-05
8
8
  ],
9
9
  [
10
- 100.00088105440783,
11
- 0.00017532535375140864
10
+ 100.0008810544078,
11
+ 0.0001752526182957
12
12
  ],
13
13
  [
14
- 100.00085963412958,
15
- 0.0002606963900620961
14
+ 100.0008596341295,
15
+ 0.0002607671625167
16
16
  ],
17
17
  [
18
- 100.00082993510475,
19
- 0.0003437757085983607
18
+ 100.0008299351047,
19
+ 0.0003437703763427
20
20
  ],
21
21
  [
22
- 100.00079224335116,
23
- 0.00042341737532065687
22
+ 100.000792243351,
23
+ 0.000423462893695
24
24
  ],
25
25
  [
26
- 100.00074692186101,
27
- 0.0004990484131054821
26
+ 100.000746921861,
27
+ 0.0004990772318774
28
28
  ],
29
29
  [
30
- 100.00069440710504,
31
- 0.0005700958425710862
30
+ 100.000694407105,
31
+ 0.0005698851833621
32
32
  ],
33
33
  [
34
- 100.00063520482904,
35
- 0.0006354137183563783
34
+ 100.000635204829,
35
+ 0.0006352048291938
36
36
  ],
37
37
  [
38
- 100.00056988518331,
39
- 0.0006944290561239309
38
+ 100.0005698851833,
39
+ 0.0006944071051437
40
40
  ],
41
41
  [
42
- 100.00049907723172,
43
- 0.0007471418363985708
42
+ 100.0004990772316,
43
+ 0.0007469218611963
44
44
  ],
45
45
  [
46
- 100.00042346289358,
47
- 0.0007924061103353283
46
+ 100.0004234628935,
47
+ 0.0007922433512302
48
48
  ],
49
49
  [
50
- 100.00034377037628,
51
- 0.0008296488941866115
50
+ 100.0003437703763,
51
+ 0.0008299351049923
52
52
  ],
53
53
  [
54
- 100.00026076716232,
55
- 0.0008594431386974881
54
+ 100.0002607671623,
55
+ 0.0008596341297125
56
56
  ],
57
57
  [
58
- 100.00017525261805,
59
- 0.0008812158656376033
58
+ 100.000175252618,
59
+ 0.0008810544079536
60
60
  ],
61
61
  [
62
- 100.00008805029526,
63
- 0.000893821132384516
62
+ 100.0000880502952,
63
+ 0.0008939896506158
64
64
  ],
65
65
  [
66
- 100.0,
67
- 0.0008984048664345436
66
+ 99.99999999999993,
67
+ 0.0008983152842413
68
68
  ],
69
69
  [
70
- 99.99991194970474,
71
- 0.000893821132384516
70
+ 99.9999119497047,
71
+ 0.0008939896506158
72
72
  ],
73
73
  [
74
- 99.99982474738195,
75
- 0.0008812158656376033
74
+ 99.99982474738192,
75
+ 0.0008810544079536
76
76
  ],
77
77
  [
78
- 99.99973923283768,
79
- 0.0008594431386974881
78
+ 99.99973923283758,
79
+ 0.0008596341297125
80
80
  ],
81
81
  [
82
- 99.99965622962372,
83
- 0.0008296488941866115
82
+ 99.99965622962364,
83
+ 0.0008299351049923
84
84
  ],
85
85
  [
86
- 99.99957653710642,
87
- 0.0007924061103353283
86
+ 99.9995765371064,
87
+ 0.0007922433512302
88
88
  ],
89
89
  [
90
- 99.99950092276828,
91
- 0.0007471418363985708
90
+ 99.99950092276822,
91
+ 0.0007469218611963
92
92
  ],
93
93
  [
94
- 99.99943011481669,
95
- 0.0006944290561239309
94
+ 99.99943011481662,
95
+ 0.0006944071051437
96
96
  ],
97
97
  [
98
- 99.99936479517096,
99
- 0.0006354137183563783
98
+ 99.9993647951709,
99
+ 0.0006352048291938
100
100
  ],
101
101
  [
102
- 99.99930559289496,
103
- 0.0005700958425710862
102
+ 99.9993055928949,
103
+ 0.0005698851833621
104
104
  ],
105
105
  [
106
- 99.99925307813899,
107
- 0.0004990484131054821
106
+ 99.99925307813896,
107
+ 0.0004990772318774
108
108
  ],
109
109
  [
110
- 99.99920775664884,
111
- 0.00042341737532065687
110
+ 99.99920775664887,
111
+ 0.000423462893695
112
112
  ],
113
113
  [
114
- 99.99917006489525,
115
- 0.0003437757085983607
114
+ 99.99917006489522,
115
+ 0.0003437703763427
116
116
  ],
117
117
  [
118
- 99.99914036587042,
119
- 0.0002606963900620961
118
+ 99.99914036587037,
119
+ 0.0002607671625167
120
120
  ],
121
121
  [
122
- 99.99911894559217,
123
- 0.00017532535375140864
122
+ 99.99911894559214,
123
+ 0.0001752526182957
124
124
  ],
125
125
  [
126
- 99.99910601034951,
127
- 8.82355685852279e-05
126
+ 99.99910601034942,
127
+ 8.80502953952e-05
128
128
  ],
129
129
  [
130
- 99.99910168471588,
131
- 1.9370377676740394e-13
130
+ 99.99910168471585,
131
+ 1.719e-13
132
132
  ],
133
133
  [
134
- 99.99910601034951,
135
- -8.594373353370475e-05
134
+ 99.99910601034942,
135
+ -8.80502950514e-05
136
136
  ],
137
137
  [
138
- 99.99911894559217,
139
- -0.00017761719160345075
138
+ 99.99911894559214,
139
+ -0.0001752526179519
140
140
  ],
141
141
  [
142
- 99.99914036587042,
143
- -0.0002635611917568658
142
+ 99.99914036587037,
143
+ -0.000260767162173
144
144
  ],
145
145
  [
146
- 99.99917006489525,
147
- -0.00034377570821095315
146
+ 99.99917006489522,
147
+ -0.0003437703759989
148
148
  ],
149
149
  [
150
- 99.99920775664884,
151
- -0.0004239903369654551
150
+ 99.99920775664887,
151
+ -0.0004234628933512
152
152
  ],
153
153
  [
154
- 99.99925307813899,
155
- -0.0004984754499351452
154
+ 99.99925307813896,
155
+ -0.0004990772315336
156
156
  ],
157
157
  [
158
- 99.99930559289496,
159
- -0.0005672310247747656
158
+ 99.9993055928949,
159
+ -0.0005698851830183
160
160
  ],
161
161
  [
162
- 99.99936479517096,
163
- -0.0006359866821211351
162
+ 99.9993647951709,
163
+ -0.00063520482885
164
164
  ],
165
165
  [
166
- 99.99943011481669,
167
- -0.0006932831262689893
166
+ 99.99943011481662,
167
+ -0.0006944071047999
168
168
  ],
169
169
  [
170
- 99.99950092276828,
171
- -0.000744849974990818
170
+ 99.99950092276822,
171
+ -0.0007469218608526
172
172
  ],
173
173
  [
174
- 99.99957653710642,
175
- -0.0007906872128161134
174
+ 99.9995765371064,
175
+ -0.0007922433508864
176
176
  ],
177
177
  [
178
- 99.99965622962372,
179
- -0.0008307948259940207
178
+ 99.99965622962364,
179
+ -0.0008299351046485
180
180
  ],
181
181
  [
182
- 99.99973923283768,
183
- -0.0008594431383100805
182
+ 99.99973923283758,
183
+ -0.0008596341293688
184
184
  ],
185
185
  [
186
- 99.99982474738195,
187
- -0.0008823617984762712
186
+ 99.99982474738192,
187
+ -0.0008810544076098
188
188
  ],
189
189
  [
190
- 99.99991194970474,
191
- -0.0008938211319971085
190
+ 99.9999119497047,
191
+ -0.0008939896502721
192
192
  ],
193
193
  [
194
- 100.0,
195
- -0.0008995507996170583
194
+ 99.99999999999993,
195
+ -0.0008983152838976
196
196
  ],
197
197
  [
198
- 100.00008805029526,
199
- -0.0008938211319971085
198
+ 100.0000880502952,
199
+ -0.0008939896502721
200
200
  ],
201
201
  [
202
- 100.00017525261805,
203
- -0.0008823617984762712
202
+ 100.000175252618,
203
+ -0.0008810544076098
204
204
  ],
205
205
  [
206
- 100.00026076716232,
207
- -0.0008594431383100805
206
+ 100.0002607671623,
207
+ -0.0008596341293688
208
208
  ],
209
209
  [
210
- 100.00034377037628,
211
- -0.0008307948259940207
210
+ 100.0003437703763,
211
+ -0.0008299351046485
212
212
  ],
213
213
  [
214
- 100.00042346289358,
215
- -0.0007906872128161134
214
+ 100.0004234628935,
215
+ -0.0007922433508864
216
216
  ],
217
217
  [
218
- 100.00049907723172,
219
- -0.000744849974990818
218
+ 100.0004990772316,
219
+ -0.0007469218608526
220
220
  ],
221
221
  [
222
- 100.00056988518331,
223
- -0.0006932831262689893
222
+ 100.0005698851833,
223
+ -0.0006944071047999
224
224
  ],
225
225
  [
226
- 100.00063520482904,
227
- -0.0006359866821211351
226
+ 100.000635204829,
227
+ -0.00063520482885
228
228
  ],
229
229
  [
230
- 100.00069440710504,
231
- -0.0005672310247747656
230
+ 100.000694407105,
231
+ -0.0005698851830183
232
232
  ],
233
233
  [
234
- 100.00074692186101,
235
- -0.0004984754499351452
234
+ 100.000746921861,
235
+ -0.0004990772315336
236
236
  ],
237
237
  [
238
- 100.00079224335116,
239
- -0.0004239903369654551
238
+ 100.000792243351,
239
+ -0.0004234628933512
240
240
  ],
241
241
  [
242
- 100.00082993510475,
243
- -0.00034377570821095315
242
+ 100.0008299351047,
243
+ -0.0003437703759989
244
244
  ],
245
245
  [
246
- 100.00085963412958,
247
- -0.0002635611917568658
246
+ 100.0008596341295,
247
+ -0.000260767162173
248
248
  ],
249
249
  [
250
- 100.00088105440783,
251
- -0.00017761719160345075
250
+ 100.0008810544078,
251
+ -0.0001752526179519
252
252
  ],
253
253
  [
254
- 100.00089398965049,
255
- -8.594373353370475e-05
254
+ 100.0008939896505,
255
+ -8.80502950514e-05
256
256
  ],
257
257
  [
258
- 100.00089831528412,
259
- 1.9370377676740394e-13
258
+ 100.0008983152841,
259
+ 1.719e-13
260
260
  ],
261
261
  [
262
- 100.00089398965049,
263
- 8.82355685852279e-05
262
+ 100.0008939896505,
263
+ 8.80502953952e-05
264
264
  ]
265
265
  ]
266
266
  ]
@@ -1,3 +1,3 @@
1
1
  { "type": "LineString",
2
- "coordinates": [ [100.0, 0.0], [101.0, 1.0] ]
2
+ "coordinates": [ [100.0, 0.0], [101.0, 1.0], [100.0, 1.0], [99.0,0.0] ]
3
3
  }
@@ -1,3 +1,3 @@
1
1
  { "type": "MultiPoint",
2
- "coordinates": [ [100.0, 0.0], [101.0, 1.0] ]
2
+ "coordinates": [ [100.0, 0.0], [101.0, 1.0], [100.0, 1.0], [99.0,0.0] ]
3
3
  }