geospatial 1.13.0 → 1.14.0
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 +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
         |