geospatial 1.13.0 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/geospatial/location.rb +15 -0
- data/lib/geospatial/polygon.rb +32 -2
- data/lib/geospatial/version.rb +1 -1
- data/spec/geospatial/location_spec.rb +23 -0
- data/spec/geospatial/polygon_spec.rb +32 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ef4b5ff93a87b5fb2733e6bbbe587be842c11ba2365131be98760bb66ee7143
|
4
|
+
data.tar.gz: 8468357c04f732b2a843ef154b7e93b8732dc334b9e76da989f22428b3eb18bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c97d956c5ef2b8b959d85f4ce07877020000b0d24ba5496edf82ef824b3d23c7c7f9471e5e48ae53f9524aab2703dd11449dc476d7288a7d91a0c7fb58e8c13
|
7
|
+
data.tar.gz: 368fc193f939b360aa1945198c054aa7bf0f05620d1307b95a0ed89f1a09a374b605c2baecc3244e2ba81bc0fe70546ff357e705d3e423d3543163cf64394a89
|
data/lib/geospatial/location.rb
CHANGED
@@ -202,5 +202,20 @@ module Geospatial
|
|
202
202
|
def - other
|
203
203
|
Distance.new(self.distance_from(other))
|
204
204
|
end
|
205
|
+
|
206
|
+
# Compute count midpoints between self and other.
|
207
|
+
# @param count [Integer] the number of segments to generate.
|
208
|
+
def midpoints_to(other, count)
|
209
|
+
return to_enum(:midpoints_to, other, count) unless block_given?
|
210
|
+
|
211
|
+
distance = other.distance_from(self)
|
212
|
+
bearing = other.bearing_from(self)
|
213
|
+
|
214
|
+
step = distance / count
|
215
|
+
|
216
|
+
(1...count).each do |i|
|
217
|
+
yield self.location_by(bearing, step * i)
|
218
|
+
end
|
219
|
+
end
|
205
220
|
end
|
206
221
|
end
|
data/lib/geospatial/polygon.rb
CHANGED
@@ -95,10 +95,12 @@ module Geospatial
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
def simplify
|
98
|
+
def simplify
|
99
99
|
simplified_points = @points.first(1)
|
100
100
|
|
101
|
-
|
101
|
+
(1...@points.size).each do |index|
|
102
|
+
point = @points[index]
|
103
|
+
|
102
104
|
next_point = @points[(index+1) % @points.size]
|
103
105
|
|
104
106
|
if yield(simplified_points.last, point, next_point)
|
@@ -109,6 +111,34 @@ module Geospatial
|
|
109
111
|
self.class.new(simplified_points, bounding_box)
|
110
112
|
end
|
111
113
|
|
114
|
+
# @example
|
115
|
+
# polygon.subdivide do |a, b|
|
116
|
+
# a = Geospatial::Location.new(*a)
|
117
|
+
# b = Geospatial::Location.new(*b)
|
118
|
+
# if a.distance_from(b) > maximum_distance
|
119
|
+
# a.midpoints(b, 2)
|
120
|
+
# end
|
121
|
+
# end
|
122
|
+
def subdivide
|
123
|
+
simplified_points = @points.first(1)
|
124
|
+
|
125
|
+
(1..@points.size).each do |index|
|
126
|
+
point = @points[index % @points.size]
|
127
|
+
next_point = @points[(index+1) % @points.size]
|
128
|
+
|
129
|
+
if points = yield(simplified_points.last, point, next_point)
|
130
|
+
simplified_points.concat(points)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Polygons are represented by a closed sequence of points, but we need to subdivide by the last point at the first point too. However, we don't add the first point a 2nd time.
|
134
|
+
if index < @points.size
|
135
|
+
simplified_points << point
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
self.class.new(simplified_points, bounding_box)
|
140
|
+
end
|
141
|
+
|
112
142
|
def self.is_left(p0, p1, p2)
|
113
143
|
a = p1 - p0
|
114
144
|
b = p2 - p0
|
data/lib/geospatial/version.rb
CHANGED
@@ -69,6 +69,29 @@ RSpec.describe Geospatial::Location do
|
|
69
69
|
expect(south.bearing_from(north)).to be_within(0.1).of(180)
|
70
70
|
end
|
71
71
|
end
|
72
|
+
|
73
|
+
describe '#midpoints_to' do
|
74
|
+
let(:north) {Geospatial::Location.new(10, 10)}
|
75
|
+
let(:south) {Geospatial::Location.new(-10, -10)}
|
76
|
+
|
77
|
+
it "can generate one midpoint" do
|
78
|
+
midpoints = north.midpoints_to(south, 4).to_a
|
79
|
+
|
80
|
+
expect(midpoints.size).to be == 3
|
81
|
+
|
82
|
+
expect(midpoints[0].distance_from(
|
83
|
+
Geospatial::Location.new(4.9616, 5.0190)
|
84
|
+
)).to be < 10
|
85
|
+
|
86
|
+
expect(midpoints[1].distance_from(
|
87
|
+
Geospatial::Location.new(0, 0)
|
88
|
+
)).to be < 10
|
89
|
+
|
90
|
+
expect(midpoints[2].distance_from(
|
91
|
+
Geospatial::Location.new(-4.9616, -5.0190)
|
92
|
+
)).to be < 10
|
93
|
+
end
|
94
|
+
end
|
72
95
|
end
|
73
96
|
|
74
97
|
require 'bigdecimal'
|
@@ -105,28 +105,49 @@ RSpec.describe Geospatial::Polygon do
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
RSpec.shared_context "visualize polygon" do
|
108
|
+
RSpec.shared_context "visualize polygon" do |depth = 12|
|
109
109
|
it "can generate visualisation" do
|
110
110
|
map = Geospatial::Map.for_earth(30)
|
111
111
|
|
112
112
|
coordinates = region_string.split(/\s+/).collect{|coordinate| Vector.elements(coordinate.split(',').collect(&:to_f).first(2))}
|
113
113
|
region = Geospatial::Polygon.new(coordinates)
|
114
114
|
|
115
|
+
maximum_distance = 100_000
|
116
|
+
|
117
|
+
region = region.subdivide do |a, b|
|
118
|
+
a = Geospatial::Location.new(*a)
|
119
|
+
b = Geospatial::Location.new(*b)
|
120
|
+
|
121
|
+
distance = a.distance_from(b)
|
122
|
+
|
123
|
+
if distance > maximum_distance
|
124
|
+
a.midpoints_to(b, (distance / maximum_distance).ceil).map{|p| Vector[*p]}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
115
128
|
Geospatial::Visualization.for_map(map) do |pdf, origin|
|
116
129
|
region.edges do |pa, pb|
|
117
130
|
pdf.line (origin + pa).to_a, (origin + pb).to_a
|
118
131
|
end
|
119
132
|
|
120
133
|
count = 0
|
121
|
-
map.traverse(region, depth:
|
134
|
+
map.traverse(region, depth: depth) do |child, prefix, order|
|
122
135
|
count += 1
|
123
136
|
size = child.size
|
124
137
|
top_left = (origin + child.min) + Vector[0, size[1]]
|
125
138
|
pdf.rectangle(top_left.to_a, *size.to_a)
|
126
|
-
# puts "#{top_left.to_a} #{size.to_a}"
|
139
|
+
# $stderr.puts "#{top_left.to_a} #{size.to_a}"
|
127
140
|
end
|
128
141
|
|
129
|
-
# puts "count=#{count}"
|
142
|
+
# $stderr.puts "count=#{count}"
|
143
|
+
|
144
|
+
pdf.fill_and_stroke
|
145
|
+
|
146
|
+
pdf.fill_color 'aaaaff'
|
147
|
+
|
148
|
+
region.points.each do |p|
|
149
|
+
pdf.fill_circle((origin + p).to_a, 0.01)
|
150
|
+
end
|
130
151
|
|
131
152
|
pdf.fill_and_stroke
|
132
153
|
end.render_file "#{self.class.description}.pdf"
|
@@ -144,3 +165,10 @@ RSpec.describe "Whanganui Polygon" do
|
|
144
165
|
|
145
166
|
include_context "visualize polygon"
|
146
167
|
end
|
168
|
+
|
169
|
+
|
170
|
+
RSpec.describe "New Zealand Bounding Box" do
|
171
|
+
let(:region_string) {"165.7930426042,-47.8671059558 179.1461410947,-47.8671059558 179.1461410947,-33.4566032676 165.7930426042,-33.4566032676"}
|
172
|
+
|
173
|
+
include_context "visualize polygon", 20
|
174
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geospatial
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: covered
|