terraformer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +8 -0
- data/README.md +4 -0
- data/Rakefile +7 -0
- data/lib/terraformer/bounds.rb +92 -0
- data/lib/terraformer/coordinate.rb +120 -0
- data/lib/terraformer/feature.rb +59 -0
- data/lib/terraformer/geometry.rb +98 -0
- data/lib/terraformer/line_string.rb +11 -0
- data/lib/terraformer/multi_line_string.rb +11 -0
- data/lib/terraformer/multi_point.rb +11 -0
- data/lib/terraformer/multi_polygon.rb +11 -0
- data/lib/terraformer/point.rb +11 -0
- data/lib/terraformer/polygon.rb +15 -0
- data/lib/terraformer/version.rb +3 -0
- data/lib/terraformer.rb +134 -0
- data/terraformer.gemspec +15 -0
- data/test/examples/circle.geojson +267 -0
- data/test/examples/geometry_collection.geojson +10 -0
- data/test/examples/line_string.geojson +3 -0
- data/test/examples/multi_line_string.geojson +6 -0
- data/test/examples/multi_point.geojson +3 -0
- data/test/examples/multi_polygon.geojson +7 -0
- data/test/examples/point.geojson +1 -0
- data/test/examples/polygon.geojson +5 -0
- data/test/examples/polygon_with_holes.geojson +6 -0
- data/test/helper.rb +20 -0
- data/test/terraformer_spec.rb +137 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 27549564ba7d079289298f08d49e921d0ed19441
|
4
|
+
data.tar.gz: 5d621a88f01cd1f7eff842808776a536567ac28f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1629d4a4f49486fb44512a7e37505a7faea5f6ce1352696b49522fea11162ac5cffa15cf6094d1dec6310980caccbe8da8e1e4abf3c731d206f22a2ccee21273
|
7
|
+
data.tar.gz: c697882b6880196f71120edd5dea0eac38a273e98da9989ee9fcf39dd9f32f41b78728213653aa432b16bdc18bd9d02c273ed1af38edbf96e1d839142383a767
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
module Terraformer
|
2
|
+
|
3
|
+
module Bounds
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def bounds obj, format = :bbox
|
7
|
+
|
8
|
+
obj = Terraformer.parse obj unless Primitive === obj
|
9
|
+
|
10
|
+
bbox = case obj.type
|
11
|
+
when 'Point'
|
12
|
+
[ obj.coordinates[0], obj.coordinates[1],
|
13
|
+
obj.coordinates[0], obj.coordinates[1] ]
|
14
|
+
when 'MultiPoint'
|
15
|
+
bounds_for_array obj.coordinates
|
16
|
+
when 'LineString'
|
17
|
+
bounds_for_array obj.coordinates
|
18
|
+
when 'MultiLineString'
|
19
|
+
bounds_for_array obj.coordinates, 1
|
20
|
+
when 'Polygon'
|
21
|
+
bounds_for_array obj.coordinates, 1
|
22
|
+
when 'MultiPolygon'
|
23
|
+
bounds_for_array obj.coordinates, 2
|
24
|
+
when 'Feature'
|
25
|
+
obj.geometry ? bounds(obj.geometry) : nil
|
26
|
+
when 'FeatureCollection'
|
27
|
+
bounds_for_feature_collection obj
|
28
|
+
when 'GeometryCollection'
|
29
|
+
bounds_for_geometry_collection obj
|
30
|
+
else
|
31
|
+
raise ArgumentError.new 'unknown type: ' + obj.type
|
32
|
+
end
|
33
|
+
|
34
|
+
case format
|
35
|
+
when :bbox
|
36
|
+
bbox
|
37
|
+
when :polygon
|
38
|
+
Polygon.new [[bbox[0], bbox[1]],
|
39
|
+
[bbox[0], bbox[3]],
|
40
|
+
[bbox[2], bbox[3]],
|
41
|
+
[bbox[2], bbox[1]],
|
42
|
+
[bbox[0], bbox[1]]]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
X1, Y1, X2, Y2 = 0, 1, 2, 3
|
47
|
+
|
48
|
+
def bounds_for_array array, nesting = 0, box = Array.new(4)
|
49
|
+
if nesting > 0
|
50
|
+
array.reduce box do |b, a|
|
51
|
+
bounds_for_array a, (nesting - 1), b
|
52
|
+
end
|
53
|
+
else
|
54
|
+
array.reduce box do |b, lonlat|
|
55
|
+
lon, lat = *lonlat
|
56
|
+
set = ->(d, i, t){ b[i] = d if b[i].nil? or d.send(t, b[i]) }
|
57
|
+
set[lon, X1, :<]
|
58
|
+
set[lon, X2, :>]
|
59
|
+
set[lat, Y1, :<]
|
60
|
+
set[lat, Y2, :>]
|
61
|
+
b
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def bounds_for_feature_collection fc
|
67
|
+
bounds_for_collection fc.features, &:geometry
|
68
|
+
end
|
69
|
+
|
70
|
+
def bounds_for_geometry_collection gc
|
71
|
+
bounds_for_collection gc
|
72
|
+
end
|
73
|
+
|
74
|
+
def bounds_for_collection collection
|
75
|
+
bounds_for_array collection.map {|e| bounds(block_given? ? yield(e) : e)}
|
76
|
+
end
|
77
|
+
private :bounds_for_collection
|
78
|
+
|
79
|
+
def envelope geometry
|
80
|
+
b = bounds geometry
|
81
|
+
{
|
82
|
+
x: b[0],
|
83
|
+
y: b[1],
|
84
|
+
w: (b[0] - b[2]).abs,
|
85
|
+
h: (b[1] - b[3]).abs
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Terraformer
|
2
|
+
|
3
|
+
class Coordinate < ::Array
|
4
|
+
|
5
|
+
attr_accessor :crs
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def from arys
|
10
|
+
arys.map {|e| Coordinate.from_array e}
|
11
|
+
end
|
12
|
+
|
13
|
+
def from_array a
|
14
|
+
Coordinate.__send__ Numeric === a[0] ? :new : :from, a
|
15
|
+
end
|
16
|
+
|
17
|
+
def big_decimal n
|
18
|
+
case n
|
19
|
+
when String
|
20
|
+
BigDecimal.new n
|
21
|
+
when BigDecimal
|
22
|
+
n
|
23
|
+
when Numeric
|
24
|
+
n.to_d
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize _x, _y = nil, _z = nil, _m = nil
|
31
|
+
super 4
|
32
|
+
case _x
|
33
|
+
when Array
|
34
|
+
raise ArgumentError if _y
|
35
|
+
self.x = _x[0]
|
36
|
+
self.y = _x[1]
|
37
|
+
when Numeric
|
38
|
+
raise ArgumentError unless _y
|
39
|
+
self.x = _x
|
40
|
+
self.y = _y
|
41
|
+
else
|
42
|
+
raise ArgumentError.new "invalid argument: #{_x}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def x
|
47
|
+
self[0]
|
48
|
+
end
|
49
|
+
|
50
|
+
def x= _x
|
51
|
+
self[0] = Coordinate.big_decimal _x
|
52
|
+
end
|
53
|
+
|
54
|
+
def y
|
55
|
+
self[1]
|
56
|
+
end
|
57
|
+
|
58
|
+
def y= _y
|
59
|
+
self[1] = Coordinate.big_decimal _y
|
60
|
+
end
|
61
|
+
|
62
|
+
def z
|
63
|
+
self[2]
|
64
|
+
end
|
65
|
+
|
66
|
+
def m
|
67
|
+
self[3]
|
68
|
+
end
|
69
|
+
|
70
|
+
[:z=, :m=, :<<, :+ , :-, :*, :&, :|].each do |sym|
|
71
|
+
define_method(sym){|*a| raise NotImplementedError }
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_geographic
|
75
|
+
xerd = (x / EARTH_RADIUS).to_deg
|
76
|
+
_x = xerd - (((xerd + 180.0) / 360.0).floor * 360.0)
|
77
|
+
_y = (
|
78
|
+
(Math::PI / 2).to_d -
|
79
|
+
(2 * BigMath.atan(BigMath.exp(-1.0 * y / EARTH_RADIUS, PRECISION), PRECISION))
|
80
|
+
).to_deg
|
81
|
+
geog = self.class.new _x, _y
|
82
|
+
geog.crs = GEOGRAPHIC_CRS
|
83
|
+
geog
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_mercator
|
87
|
+
_x = x.to_rad * EARTH_RADIUS
|
88
|
+
syr = BigMath.sin y.to_rad, PRECISION
|
89
|
+
_y = (EARTH_RADIUS / 2.0) * BigMath.log((1.0 + syr) / (1.0 - syr), PRECISION)
|
90
|
+
merc = self.class.new _x, _y
|
91
|
+
merc.crs = MERCATOR_CRS
|
92
|
+
merc
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_json *args
|
96
|
+
[x, y, z, m].map! {|e| e.nil? ? nil : e.to_f}.compact.to_json(*args)
|
97
|
+
end
|
98
|
+
|
99
|
+
def geographic?
|
100
|
+
crs.nil? or crs == GEOGRAPHIC_CRS
|
101
|
+
end
|
102
|
+
|
103
|
+
def mercator?
|
104
|
+
crs == MERCATOR_CRS
|
105
|
+
end
|
106
|
+
|
107
|
+
def buffer radius, resolution = DEFAULT_BUFFER_RESOLUTION
|
108
|
+
center = to_mercator unless mercator?
|
109
|
+
coordinates = (1..resolution).map {|step|
|
110
|
+
radians = step.to_d * (360.to_d / resolution.to_d) * PI / 180.to_d
|
111
|
+
[center.x + radius.to_d * BigMath.cos(radians, PRECISION),
|
112
|
+
center.y + radius.to_d * BigMath.sin(radians, PRECISION)]
|
113
|
+
}
|
114
|
+
coordinates << coordinates[0]
|
115
|
+
Polygon.new(coordinates).to_geographic
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Terraformer
|
2
|
+
|
3
|
+
class Feature < Primitive
|
4
|
+
|
5
|
+
attr_accessor :id, :geometry
|
6
|
+
attr_writer :properties
|
7
|
+
|
8
|
+
def initialize *args
|
9
|
+
unless args.empty?
|
10
|
+
super *args do |arg|
|
11
|
+
self.id = arg['id'] if arg.key? 'id'
|
12
|
+
self.properties = arg['properties'] if arg.key? 'properties'
|
13
|
+
self.geometry = Terraformer.parse arg['geometry']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def properties
|
19
|
+
@properties ||= {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
h = {
|
24
|
+
type: type,
|
25
|
+
properties: properties,
|
26
|
+
geometry: geometry.to_hash
|
27
|
+
}
|
28
|
+
h.merge! id: id if id
|
29
|
+
h
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class FeatureCollection < Primitive
|
35
|
+
|
36
|
+
attr_writer :features
|
37
|
+
|
38
|
+
def initialize *args
|
39
|
+
unless args.empty?
|
40
|
+
super *args do |arg|
|
41
|
+
self.features = arg['features'].map {|f| Terraformer.parse f}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def features
|
47
|
+
@features ||= []
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_hash
|
51
|
+
{
|
52
|
+
type: type,
|
53
|
+
features: features.map(&:to_hash)
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Terraformer
|
2
|
+
|
3
|
+
class Geometry < Primitive
|
4
|
+
|
5
|
+
MULTI_REGEX = /^Multi/
|
6
|
+
|
7
|
+
attr_accessor :coordinates
|
8
|
+
|
9
|
+
def initialize *args
|
10
|
+
if args.length > 1 or Array === args[0]
|
11
|
+
self.coordinates = Coordinate.from_array args
|
12
|
+
else
|
13
|
+
super *args do |arg|
|
14
|
+
self.coordinates = Coordinate.from_array arg['coordinates']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_hash
|
20
|
+
{
|
21
|
+
type: type,
|
22
|
+
coordinates: coordinates
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_mercator
|
27
|
+
self.class.new *coordinates.map_coordinate(&:to_mercator)
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_geographic
|
31
|
+
self.class.new *coordinates.map_coordinate(&:to_geographic)
|
32
|
+
end
|
33
|
+
|
34
|
+
def first_coordinate
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
def mercator?
|
39
|
+
first_coordinate.mercator?
|
40
|
+
end
|
41
|
+
|
42
|
+
def geographic?
|
43
|
+
first_coordinate.geographic?
|
44
|
+
end
|
45
|
+
|
46
|
+
def get index
|
47
|
+
if MULTI_REGEX.match type
|
48
|
+
sub = type.sub MULTI_REGEX, ''
|
49
|
+
Terraformer.const_get(sub).new *coordinates[index]
|
50
|
+
else
|
51
|
+
raise NotImplementedError
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def convex_hull
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
def contains other
|
60
|
+
raise NotImplementedError
|
61
|
+
end
|
62
|
+
|
63
|
+
def within other
|
64
|
+
raise NotImplementedError
|
65
|
+
end
|
66
|
+
|
67
|
+
def intersects other
|
68
|
+
raise NotImplementedError
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
class GeometryCollection < Primitive
|
74
|
+
|
75
|
+
attr_writer :geometries
|
76
|
+
|
77
|
+
def initialize *args
|
78
|
+
unless args.empty?
|
79
|
+
super *args do |arg|
|
80
|
+
self.geometries = arg['geometries'].map {|g| Terraformer.parse g}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def geometries
|
86
|
+
@geometries ||= []
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_hash
|
90
|
+
{
|
91
|
+
type: type,
|
92
|
+
geometries: geometries.map(&:to_hash)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/lib/terraformer.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'bigdecimal/math'
|
4
|
+
require 'bigdecimal/util'
|
5
|
+
|
6
|
+
module Terraformer
|
7
|
+
|
8
|
+
PRECISION = 8
|
9
|
+
PI = BigMath.PI PRECISION
|
10
|
+
DEFAULT_BUFFER_RESOLUTION = 64
|
11
|
+
|
12
|
+
EARTH_RADIUS = 6378137.to_d
|
13
|
+
DEGREES_PER_RADIAN = 180.0.to_d / PI
|
14
|
+
RADIANS_PER_DEGREE = PI / 180.0.to_d
|
15
|
+
MERCATOR_CRS = {
|
16
|
+
type: "link",
|
17
|
+
properties: {
|
18
|
+
href: "http://spatialreference.org/ref/sr-org/6928/ogcwkt/",
|
19
|
+
type: "ogcwkt"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
GEOGRAPHIC_CRS = {
|
23
|
+
type: "link",
|
24
|
+
properties: {
|
25
|
+
href: "http://spatialreference.org/ref/epsg/4326/ogcwkt/",
|
26
|
+
type: "ogcwkt"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
def self.parse geojson
|
31
|
+
geojson = JSON.parse geojson if String === geojson
|
32
|
+
raise ArgumentError.new "invalid arg: #{geojson}" unless Hash === geojson
|
33
|
+
|
34
|
+
if klass = Terraformer.const_get(geojson['type'])
|
35
|
+
klass.new geojson
|
36
|
+
else
|
37
|
+
raise ArgumentError.new 'unknown type: ' + geojson['type']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Primitive
|
42
|
+
|
43
|
+
def initialize *args
|
44
|
+
arg = String === args[0] ? JSON.parse(args[0]) : args[0]
|
45
|
+
raise ArgumentError.new "invalid argument(s): #{args}" unless Hash === arg
|
46
|
+
raise ArgumentError.new "invalid type: #{arg['type']}" unless arg['type'] == self.type
|
47
|
+
yield arg if block_given?
|
48
|
+
end
|
49
|
+
|
50
|
+
def type
|
51
|
+
self.class.to_s.sub 'Terraformer::', ''
|
52
|
+
end
|
53
|
+
|
54
|
+
def envelope
|
55
|
+
Bounds.envelope self
|
56
|
+
end
|
57
|
+
|
58
|
+
def bbox type = :bbox
|
59
|
+
Bounds.bounds self, type
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_json *args
|
63
|
+
self.to_hash.to_json *args
|
64
|
+
end
|
65
|
+
|
66
|
+
def [] prop
|
67
|
+
self.__send__ prop.to_sym
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
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!
|
89
|
+
|
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
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
class BigDecimal
|
114
|
+
|
115
|
+
def to_deg
|
116
|
+
self * Terraformer::DEGREES_PER_RADIAN
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_rad
|
120
|
+
self * Terraformer::RADIANS_PER_DEGREE
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
require 'terraformer/coordinate'
|
126
|
+
require 'terraformer/bounds'
|
127
|
+
require 'terraformer/geometry'
|
128
|
+
require 'terraformer/feature'
|
129
|
+
require 'terraformer/point'
|
130
|
+
require 'terraformer/multi_point'
|
131
|
+
require 'terraformer/line_string'
|
132
|
+
require 'terraformer/multi_line_string'
|
133
|
+
require 'terraformer/polygon'
|
134
|
+
require 'terraformer/multi_polygon'
|
data/terraformer.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/terraformer/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Kenichi Nakamura"]
|
6
|
+
gem.email = ["kenichi.nakamura@gmail.com"]
|
7
|
+
gem.description = gem.summary = ""
|
8
|
+
gem.homepage = "https://github.com/esripdx/terraformer-ruby"
|
9
|
+
gem.files = `git ls-files | grep -Ev '^(myapp|examples)'`.split("\n")
|
10
|
+
gem.test_files = `git ls-files -- test/*`.split("\n")
|
11
|
+
gem.name = "terraformer"
|
12
|
+
gem.require_paths = ["lib"]
|
13
|
+
gem.version = Terraformer::VERSION
|
14
|
+
gem.license = 'apache'
|
15
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
{
|
2
|
+
"type": "Polygon",
|
3
|
+
"coordinates": [
|
4
|
+
[
|
5
|
+
[
|
6
|
+
100.00089398965049,
|
7
|
+
8.82355685852279e-05
|
8
|
+
],
|
9
|
+
[
|
10
|
+
100.00088105440783,
|
11
|
+
0.00017532535375140864
|
12
|
+
],
|
13
|
+
[
|
14
|
+
100.00085963412958,
|
15
|
+
0.0002606963900620961
|
16
|
+
],
|
17
|
+
[
|
18
|
+
100.00082993510475,
|
19
|
+
0.0003437757085983607
|
20
|
+
],
|
21
|
+
[
|
22
|
+
100.00079224335116,
|
23
|
+
0.00042341737532065687
|
24
|
+
],
|
25
|
+
[
|
26
|
+
100.00074692186101,
|
27
|
+
0.0004990484131054821
|
28
|
+
],
|
29
|
+
[
|
30
|
+
100.00069440710504,
|
31
|
+
0.0005700958425710862
|
32
|
+
],
|
33
|
+
[
|
34
|
+
100.00063520482904,
|
35
|
+
0.0006354137183563783
|
36
|
+
],
|
37
|
+
[
|
38
|
+
100.00056988518331,
|
39
|
+
0.0006944290561239309
|
40
|
+
],
|
41
|
+
[
|
42
|
+
100.00049907723172,
|
43
|
+
0.0007471418363985708
|
44
|
+
],
|
45
|
+
[
|
46
|
+
100.00042346289358,
|
47
|
+
0.0007924061103353283
|
48
|
+
],
|
49
|
+
[
|
50
|
+
100.00034377037628,
|
51
|
+
0.0008296488941866115
|
52
|
+
],
|
53
|
+
[
|
54
|
+
100.00026076716232,
|
55
|
+
0.0008594431386974881
|
56
|
+
],
|
57
|
+
[
|
58
|
+
100.00017525261805,
|
59
|
+
0.0008812158656376033
|
60
|
+
],
|
61
|
+
[
|
62
|
+
100.00008805029526,
|
63
|
+
0.000893821132384516
|
64
|
+
],
|
65
|
+
[
|
66
|
+
100.0,
|
67
|
+
0.0008984048664345436
|
68
|
+
],
|
69
|
+
[
|
70
|
+
99.99991194970474,
|
71
|
+
0.000893821132384516
|
72
|
+
],
|
73
|
+
[
|
74
|
+
99.99982474738195,
|
75
|
+
0.0008812158656376033
|
76
|
+
],
|
77
|
+
[
|
78
|
+
99.99973923283768,
|
79
|
+
0.0008594431386974881
|
80
|
+
],
|
81
|
+
[
|
82
|
+
99.99965622962372,
|
83
|
+
0.0008296488941866115
|
84
|
+
],
|
85
|
+
[
|
86
|
+
99.99957653710642,
|
87
|
+
0.0007924061103353283
|
88
|
+
],
|
89
|
+
[
|
90
|
+
99.99950092276828,
|
91
|
+
0.0007471418363985708
|
92
|
+
],
|
93
|
+
[
|
94
|
+
99.99943011481669,
|
95
|
+
0.0006944290561239309
|
96
|
+
],
|
97
|
+
[
|
98
|
+
99.99936479517096,
|
99
|
+
0.0006354137183563783
|
100
|
+
],
|
101
|
+
[
|
102
|
+
99.99930559289496,
|
103
|
+
0.0005700958425710862
|
104
|
+
],
|
105
|
+
[
|
106
|
+
99.99925307813899,
|
107
|
+
0.0004990484131054821
|
108
|
+
],
|
109
|
+
[
|
110
|
+
99.99920775664884,
|
111
|
+
0.00042341737532065687
|
112
|
+
],
|
113
|
+
[
|
114
|
+
99.99917006489525,
|
115
|
+
0.0003437757085983607
|
116
|
+
],
|
117
|
+
[
|
118
|
+
99.99914036587042,
|
119
|
+
0.0002606963900620961
|
120
|
+
],
|
121
|
+
[
|
122
|
+
99.99911894559217,
|
123
|
+
0.00017532535375140864
|
124
|
+
],
|
125
|
+
[
|
126
|
+
99.99910601034951,
|
127
|
+
8.82355685852279e-05
|
128
|
+
],
|
129
|
+
[
|
130
|
+
99.99910168471588,
|
131
|
+
1.9370377676740394e-13
|
132
|
+
],
|
133
|
+
[
|
134
|
+
99.99910601034951,
|
135
|
+
-8.594373353370475e-05
|
136
|
+
],
|
137
|
+
[
|
138
|
+
99.99911894559217,
|
139
|
+
-0.00017761719160345075
|
140
|
+
],
|
141
|
+
[
|
142
|
+
99.99914036587042,
|
143
|
+
-0.0002635611917568658
|
144
|
+
],
|
145
|
+
[
|
146
|
+
99.99917006489525,
|
147
|
+
-0.00034377570821095315
|
148
|
+
],
|
149
|
+
[
|
150
|
+
99.99920775664884,
|
151
|
+
-0.0004239903369654551
|
152
|
+
],
|
153
|
+
[
|
154
|
+
99.99925307813899,
|
155
|
+
-0.0004984754499351452
|
156
|
+
],
|
157
|
+
[
|
158
|
+
99.99930559289496,
|
159
|
+
-0.0005672310247747656
|
160
|
+
],
|
161
|
+
[
|
162
|
+
99.99936479517096,
|
163
|
+
-0.0006359866821211351
|
164
|
+
],
|
165
|
+
[
|
166
|
+
99.99943011481669,
|
167
|
+
-0.0006932831262689893
|
168
|
+
],
|
169
|
+
[
|
170
|
+
99.99950092276828,
|
171
|
+
-0.000744849974990818
|
172
|
+
],
|
173
|
+
[
|
174
|
+
99.99957653710642,
|
175
|
+
-0.0007906872128161134
|
176
|
+
],
|
177
|
+
[
|
178
|
+
99.99965622962372,
|
179
|
+
-0.0008307948259940207
|
180
|
+
],
|
181
|
+
[
|
182
|
+
99.99973923283768,
|
183
|
+
-0.0008594431383100805
|
184
|
+
],
|
185
|
+
[
|
186
|
+
99.99982474738195,
|
187
|
+
-0.0008823617984762712
|
188
|
+
],
|
189
|
+
[
|
190
|
+
99.99991194970474,
|
191
|
+
-0.0008938211319971085
|
192
|
+
],
|
193
|
+
[
|
194
|
+
100.0,
|
195
|
+
-0.0008995507996170583
|
196
|
+
],
|
197
|
+
[
|
198
|
+
100.00008805029526,
|
199
|
+
-0.0008938211319971085
|
200
|
+
],
|
201
|
+
[
|
202
|
+
100.00017525261805,
|
203
|
+
-0.0008823617984762712
|
204
|
+
],
|
205
|
+
[
|
206
|
+
100.00026076716232,
|
207
|
+
-0.0008594431383100805
|
208
|
+
],
|
209
|
+
[
|
210
|
+
100.00034377037628,
|
211
|
+
-0.0008307948259940207
|
212
|
+
],
|
213
|
+
[
|
214
|
+
100.00042346289358,
|
215
|
+
-0.0007906872128161134
|
216
|
+
],
|
217
|
+
[
|
218
|
+
100.00049907723172,
|
219
|
+
-0.000744849974990818
|
220
|
+
],
|
221
|
+
[
|
222
|
+
100.00056988518331,
|
223
|
+
-0.0006932831262689893
|
224
|
+
],
|
225
|
+
[
|
226
|
+
100.00063520482904,
|
227
|
+
-0.0006359866821211351
|
228
|
+
],
|
229
|
+
[
|
230
|
+
100.00069440710504,
|
231
|
+
-0.0005672310247747656
|
232
|
+
],
|
233
|
+
[
|
234
|
+
100.00074692186101,
|
235
|
+
-0.0004984754499351452
|
236
|
+
],
|
237
|
+
[
|
238
|
+
100.00079224335116,
|
239
|
+
-0.0004239903369654551
|
240
|
+
],
|
241
|
+
[
|
242
|
+
100.00082993510475,
|
243
|
+
-0.00034377570821095315
|
244
|
+
],
|
245
|
+
[
|
246
|
+
100.00085963412958,
|
247
|
+
-0.0002635611917568658
|
248
|
+
],
|
249
|
+
[
|
250
|
+
100.00088105440783,
|
251
|
+
-0.00017761719160345075
|
252
|
+
],
|
253
|
+
[
|
254
|
+
100.00089398965049,
|
255
|
+
-8.594373353370475e-05
|
256
|
+
],
|
257
|
+
[
|
258
|
+
100.00089831528412,
|
259
|
+
1.9370377676740394e-13
|
260
|
+
],
|
261
|
+
[
|
262
|
+
100.00089398965049,
|
263
|
+
8.82355685852279e-05
|
264
|
+
]
|
265
|
+
]
|
266
|
+
]
|
267
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
{ "type": "MultiPolygon",
|
2
|
+
"coordinates": [
|
3
|
+
[[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
|
4
|
+
[[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
|
5
|
+
[[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]
|
6
|
+
]
|
7
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{ "type": "Point", "coordinates": [100.0, 0.0] }
|
data/test/helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require :default, :test
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/pride'
|
6
|
+
|
7
|
+
lib = File.expand_path '../../lib', __FILE__
|
8
|
+
$:.unshift lib unless $:.include? lib
|
9
|
+
require 'terraformer'
|
10
|
+
|
11
|
+
module MiniTest::Expectations
|
12
|
+
infect_an_assertion :refute_nil, :dont_be_terrible_ok, :unary
|
13
|
+
end
|
14
|
+
|
15
|
+
examples = File.expand_path '../examples', __FILE__
|
16
|
+
EXAMPLES = Dir[examples + '/*.geojson'].reduce({}) do |h, gj|
|
17
|
+
h[gj.sub(examples+'/','').sub(/\.geojson$/,'').to_sym] =
|
18
|
+
File.read(gj).gsub(/\r*\n*/,'').gsub(' ',' ')
|
19
|
+
h
|
20
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require_relative './helper'
|
2
|
+
|
3
|
+
describe Terraformer do
|
4
|
+
|
5
|
+
it 'dont be terrible ok' do
|
6
|
+
Terraformer.dont_be_terrible_ok
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'parsing' do
|
10
|
+
|
11
|
+
it 'parses points' do
|
12
|
+
p = Terraformer.parse EXAMPLES[:point]
|
13
|
+
p.dont_be_terrible_ok
|
14
|
+
p.type.must_equal 'Point'
|
15
|
+
p.coordinates.must_be_instance_of Terraformer::Coordinate
|
16
|
+
p.coordinates.must_equal Terraformer::Coordinate.new 100, 0
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'parses multi points' do
|
20
|
+
p = Terraformer.parse EXAMPLES[:multi_point]
|
21
|
+
p.dont_be_terrible_ok
|
22
|
+
p.type.must_equal 'MultiPoint'
|
23
|
+
p.coordinates.must_be_instance_of Array
|
24
|
+
p.coordinates.length.must_equal 2
|
25
|
+
p.coordinates[0].must_equal Terraformer::Coordinate.new 100, 0
|
26
|
+
p.coordinates[1].must_equal Terraformer::Coordinate.new 101, 1
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'parses line strings' do
|
30
|
+
p = Terraformer.parse EXAMPLES[:line_string]
|
31
|
+
p.dont_be_terrible_ok
|
32
|
+
p.type.must_equal 'LineString'
|
33
|
+
p.coordinates.must_be_instance_of Array
|
34
|
+
p.coordinates.length.must_equal 2
|
35
|
+
p.coordinates[0].must_equal Terraformer::Coordinate.new 100, 0
|
36
|
+
p.coordinates[1].must_equal Terraformer::Coordinate.new 101, 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'parses multi line strings' do
|
40
|
+
p = Terraformer.parse EXAMPLES[:multi_line_string]
|
41
|
+
p.dont_be_terrible_ok
|
42
|
+
p.type.must_equal 'MultiLineString'
|
43
|
+
p.coordinates.must_be_instance_of Array
|
44
|
+
p.coordinates.length.must_equal 2
|
45
|
+
p.coordinates[0].must_be_instance_of Array
|
46
|
+
p.coordinates[0][0].must_equal Terraformer::Coordinate.new 100, 0
|
47
|
+
p.coordinates[0][1].must_equal Terraformer::Coordinate.new 101, 1
|
48
|
+
p.coordinates[1].must_be_instance_of Array
|
49
|
+
p.coordinates[1][0].must_equal Terraformer::Coordinate.new 102, 2
|
50
|
+
p.coordinates[1][1].must_equal Terraformer::Coordinate.new 103, 3
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'parses polygons' do
|
54
|
+
p = Terraformer.parse EXAMPLES[:polygon]
|
55
|
+
p.dont_be_terrible_ok
|
56
|
+
p.type.must_equal 'Polygon'
|
57
|
+
p.coordinates.must_be_instance_of Array
|
58
|
+
p.coordinates[0].must_be_instance_of Array
|
59
|
+
p.coordinates[0][0].must_equal Terraformer::Coordinate.new 100, 0
|
60
|
+
p.coordinates[0][1].must_equal Terraformer::Coordinate.new 101, 0
|
61
|
+
p.coordinates[0][2].must_equal Terraformer::Coordinate.new 101, 1
|
62
|
+
p.coordinates[0][3].must_equal Terraformer::Coordinate.new 100, 1
|
63
|
+
p.coordinates[0][4].must_equal Terraformer::Coordinate.new 100, 0
|
64
|
+
refute p.has_holes?
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'parses polygons with holes' do
|
68
|
+
p = Terraformer.parse EXAMPLES[:polygon_with_holes]
|
69
|
+
p.dont_be_terrible_ok
|
70
|
+
p.type.must_equal 'Polygon'
|
71
|
+
p.coordinates.must_be_instance_of Array
|
72
|
+
p.coordinates[0].must_be_instance_of Array
|
73
|
+
p.coordinates[0][0].must_equal Terraformer::Coordinate.new 100, 0
|
74
|
+
p.coordinates[0][1].must_equal Terraformer::Coordinate.new 101, 0
|
75
|
+
p.coordinates[0][2].must_equal Terraformer::Coordinate.new 101, 1
|
76
|
+
p.coordinates[0][3].must_equal Terraformer::Coordinate.new 100, 1
|
77
|
+
p.coordinates[0][4].must_equal Terraformer::Coordinate.new 100, 0
|
78
|
+
p.coordinates[1].must_be_instance_of Array
|
79
|
+
p.coordinates[1][0].must_equal Terraformer::Coordinate.new 100.2, 0.2
|
80
|
+
p.coordinates[1][1].must_equal Terraformer::Coordinate.new 100.8, 0.2
|
81
|
+
p.coordinates[1][2].must_equal Terraformer::Coordinate.new 100.8, 0.8
|
82
|
+
p.coordinates[1][3].must_equal Terraformer::Coordinate.new 100.2, 0.8
|
83
|
+
p.coordinates[1][4].must_equal Terraformer::Coordinate.new 100.2, 0.2
|
84
|
+
assert p.has_holes?
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'parses multipolygons' do
|
88
|
+
p = Terraformer.parse EXAMPLES[:multi_polygon]
|
89
|
+
p.dont_be_terrible_ok
|
90
|
+
p.type.must_equal 'MultiPolygon'
|
91
|
+
p.coordinates[0].must_be_instance_of Array
|
92
|
+
p.coordinates[0][0].must_be_instance_of Array
|
93
|
+
p.coordinates[0][0][0].must_equal Terraformer::Coordinate.new 102, 2
|
94
|
+
p.coordinates[0][0][1].must_equal Terraformer::Coordinate.new 103, 2
|
95
|
+
p.coordinates[0][0][2].must_equal Terraformer::Coordinate.new 103, 3
|
96
|
+
p.coordinates[0][0][3].must_equal Terraformer::Coordinate.new 102, 3
|
97
|
+
p.coordinates[0][0][4].must_equal Terraformer::Coordinate.new 102, 2
|
98
|
+
p.coordinates[1].must_be_instance_of Array
|
99
|
+
p.coordinates[1][0].must_be_instance_of Array
|
100
|
+
p.coordinates[1][0][0].must_equal Terraformer::Coordinate.new 100, 0
|
101
|
+
p.coordinates[1][0][1].must_equal Terraformer::Coordinate.new 101, 0
|
102
|
+
p.coordinates[1][0][2].must_equal Terraformer::Coordinate.new 101, 1
|
103
|
+
p.coordinates[1][0][3].must_equal Terraformer::Coordinate.new 100, 1
|
104
|
+
p.coordinates[1][0][4].must_equal Terraformer::Coordinate.new 100, 0
|
105
|
+
p.coordinates[1][1].must_be_instance_of Array
|
106
|
+
p.coordinates[1][1][0].must_equal Terraformer::Coordinate.new 100.2, 0.2
|
107
|
+
p.coordinates[1][1][1].must_equal Terraformer::Coordinate.new 100.8, 0.2
|
108
|
+
p.coordinates[1][1][2].must_equal Terraformer::Coordinate.new 100.8, 0.8
|
109
|
+
p.coordinates[1][1][3].must_equal Terraformer::Coordinate.new 100.2, 0.8
|
110
|
+
p.coordinates[1][1][4].must_equal Terraformer::Coordinate.new 100.2, 0.2
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'parses as geographic' do
|
114
|
+
[:point, :multi_point, :line_string, :multi_line_string,
|
115
|
+
:polygon, :polygon_with_holes, :multi_polygon].each do |type|
|
116
|
+
g = Terraformer.parse EXAMPLES[type]
|
117
|
+
assert g.geographic?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'coordinates' do
|
124
|
+
|
125
|
+
it 'buffers into circles' do
|
126
|
+
p = Terraformer.parse EXAMPLES[:point]
|
127
|
+
p.dont_be_terrible_ok
|
128
|
+
p.type.must_equal 'Point'
|
129
|
+
p.coordinates.must_be_instance_of Terraformer::Coordinate
|
130
|
+
p.coordinates.must_equal Terraformer::Coordinate.new 100, 0
|
131
|
+
c = p.coordinates.buffer 100
|
132
|
+
JSON.parse(c.to_json).must_equal JSON.parse(EXAMPLES[:circle])
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: terraformer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kenichi Nakamura
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: ''
|
14
|
+
email:
|
15
|
+
- kenichi.nakamura@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- Gemfile
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- lib/terraformer.rb
|
25
|
+
- lib/terraformer/bounds.rb
|
26
|
+
- lib/terraformer/coordinate.rb
|
27
|
+
- lib/terraformer/feature.rb
|
28
|
+
- lib/terraformer/geometry.rb
|
29
|
+
- lib/terraformer/line_string.rb
|
30
|
+
- lib/terraformer/multi_line_string.rb
|
31
|
+
- lib/terraformer/multi_point.rb
|
32
|
+
- lib/terraformer/multi_polygon.rb
|
33
|
+
- lib/terraformer/point.rb
|
34
|
+
- lib/terraformer/polygon.rb
|
35
|
+
- lib/terraformer/version.rb
|
36
|
+
- terraformer.gemspec
|
37
|
+
- test/examples/circle.geojson
|
38
|
+
- test/examples/geometry_collection.geojson
|
39
|
+
- test/examples/line_string.geojson
|
40
|
+
- test/examples/multi_line_string.geojson
|
41
|
+
- test/examples/multi_point.geojson
|
42
|
+
- test/examples/multi_polygon.geojson
|
43
|
+
- test/examples/point.geojson
|
44
|
+
- test/examples/polygon.geojson
|
45
|
+
- test/examples/polygon_with_holes.geojson
|
46
|
+
- test/helper.rb
|
47
|
+
- test/terraformer_spec.rb
|
48
|
+
homepage: https://github.com/esripdx/terraformer-ruby
|
49
|
+
licenses:
|
50
|
+
- apache
|
51
|
+
metadata: {}
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 2.2.2
|
69
|
+
signing_key:
|
70
|
+
specification_version: 4
|
71
|
+
summary: ''
|
72
|
+
test_files:
|
73
|
+
- test/examples/circle.geojson
|
74
|
+
- test/examples/geometry_collection.geojson
|
75
|
+
- test/examples/line_string.geojson
|
76
|
+
- test/examples/multi_line_string.geojson
|
77
|
+
- test/examples/multi_point.geojson
|
78
|
+
- test/examples/multi_polygon.geojson
|
79
|
+
- test/examples/point.geojson
|
80
|
+
- test/examples/polygon.geojson
|
81
|
+
- test/examples/polygon_with_holes.geojson
|
82
|
+
- test/helper.rb
|
83
|
+
- test/terraformer_spec.rb
|