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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7192e26af8621237a3727ebdc875df7af056a4ac9bf36dcadba378107c97b6a4
4
- data.tar.gz: 833732089ee04ebedaf970430661cb51ec85fc878b1093d9b71440cf8a347327
3
+ metadata.gz: 6ef4b5ff93a87b5fb2733e6bbbe587be842c11ba2365131be98760bb66ee7143
4
+ data.tar.gz: 8468357c04f732b2a843ef154b7e93b8732dc334b9e76da989f22428b3eb18bf
5
5
  SHA512:
6
- metadata.gz: ea63ff5c6dfa08038b891f2df6e3d0e78a77151834a9655a8f8dee85eca08d603860c99566f8d47b1ce0d45d60bd42fa2d09da187884f92e1ee637a21e7aef2c
7
- data.tar.gz: 1c28ff01ced07bddb5091eea5aeadce0ebf4772752d3317a55ba3fcb8605b49573fb186b2dd27334930b0cffa5dfec5caf851c47aeb3468b1984bd401872f754
6
+ metadata.gz: 3c97d956c5ef2b8b959d85f4ce07877020000b0d24ba5496edf82ef824b3d23c7c7f9471e5e48ae53f9524aab2703dd11449dc476d7288a7d91a0c7fb58e8c13
7
+ data.tar.gz: 368fc193f939b360aa1945198c054aa7bf0f05620d1307b95a0ed89f1a09a374b605c2baecc3244e2ba81bc0fe70546ff357e705d3e423d3543163cf64394a89
@@ -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
@@ -95,10 +95,12 @@ module Geospatial
95
95
  end
96
96
  end
97
97
 
98
- def simplify(minimum_distance = 1)
98
+ def simplify
99
99
  simplified_points = @points.first(1)
100
100
 
101
- @points.each_with_index do |point, index|
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
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Geospatial
22
- VERSION = "1.13.0"
22
+ VERSION = "1.14.0"
23
23
  end
@@ -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: 12) do |child, prefix, order|
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.13.0
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-08-02 00:00:00.000000000 Z
11
+ date: 2019-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: covered