terraformer 0.0.1
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 +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
|