bounding_boxes 0.1.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 +7 -0
- data/lib/bounding_boxes/base_bounding_box.rb +71 -0
- data/lib/bounding_boxes/bounding_box.rb +73 -0
- data/lib/bounding_boxes/distance.rb +38 -0
- data/lib/bounding_boxes/point_bounding_box.rb +48 -0
- data/lib/bounding_boxes/split_box.rb +10 -0
- data/lib/bounding_boxes/square_bounding_box.rb +28 -0
- data/lib/bounding_boxes/version.rb +3 -0
- data/lib/bounding_boxes.rb +3 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab6c2d3842feb74dd9f4f1e4ec7532b115e7fbbc
|
4
|
+
data.tar.gz: 6bad38f93433df5758fcb78262b20966faa35a17
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4a412ca4f2918b55f504eb708c0ea471d760699469d4bf82a5f2f351561436ad736008f6f38c1dc3117d63b37742333d5c778971fdb7a503b7d06c4b0acabb10
|
7
|
+
data.tar.gz: 96d975c4535ff44c0fca9558e6bce1c6e620c375a47495cc3477d4dc718f604d5a789eb449cee77c8afdcf3d9797e6bc4e1fcea0dcf763b7d3811a9335860576
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module BB
|
2
|
+
class BaseBoundingBox
|
3
|
+
attr_accessor :max, :min, :preferred_units
|
4
|
+
|
5
|
+
def initialize(lat1, long1, lat2, long2, units)
|
6
|
+
@min = {latitude: lat1, longitude: long1}
|
7
|
+
@max = {latitude: lat2, longitude: long2}
|
8
|
+
@preferred_units = units
|
9
|
+
end
|
10
|
+
|
11
|
+
def side_length
|
12
|
+
self.send("side_length_#{preferred_units}".to_sym)
|
13
|
+
end
|
14
|
+
|
15
|
+
def width(units = @preferred_units)
|
16
|
+
BB.send("distance_#{units}".to_sym, {latitude: @max[:latitude],
|
17
|
+
longitude: @max[:longitude]},
|
18
|
+
{latitude: @max[:latitude],
|
19
|
+
longitude: @min[:longitude]})
|
20
|
+
end
|
21
|
+
|
22
|
+
def height(units = @preferred_units)
|
23
|
+
BB.send("distance_#{units}".to_sym, {latitude: @max[:latitude],
|
24
|
+
longitude: @max[:longitude]},
|
25
|
+
{latitude: @min[:latitude],
|
26
|
+
longitude: @max[:longitude]})
|
27
|
+
end
|
28
|
+
|
29
|
+
def min_lat
|
30
|
+
@min[:latitude]
|
31
|
+
end
|
32
|
+
|
33
|
+
def min_long
|
34
|
+
@min[:longitude]
|
35
|
+
end
|
36
|
+
|
37
|
+
def max_lat
|
38
|
+
@max[:latitude]
|
39
|
+
end
|
40
|
+
|
41
|
+
def max_long
|
42
|
+
@max[:longitude]
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch(property)
|
46
|
+
raise KeyError unless self.respond_to?(property)
|
47
|
+
self.send(property)
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing(name, *args)
|
51
|
+
attribute = name.to_s
|
52
|
+
if attribute =~ /(width_)(km|kilometers)/
|
53
|
+
width(:kilometers)
|
54
|
+
elsif attribute =~ /(width_)(mi|mil|miles)/
|
55
|
+
width(:miles)
|
56
|
+
elsif attribute =~ /(height_)(km|kilometers)/
|
57
|
+
height(:kilometers)
|
58
|
+
elsif attribute =~ /(height_)(mi|mil|miles)/
|
59
|
+
height(:miles)
|
60
|
+
elsif attribute =~ /(min|minimum)_(lat|latitude)/
|
61
|
+
min_lat
|
62
|
+
elsif attribute =~ /(min|minimum)_(lon|long|longitude)/
|
63
|
+
min_long
|
64
|
+
elsif attribute =~ /(max|maximum)_(lat|latitude)/
|
65
|
+
max_lat
|
66
|
+
elsif attribute =~ /(max|maximum)_(lon|long|longitude)/
|
67
|
+
max_long
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module BB
|
2
|
+
#can create any type of bounding box and
|
3
|
+
#will be able to split it into an array of bounding boxes
|
4
|
+
class BoundingBox < BaseBoundingBox
|
5
|
+
attr_accessor :box
|
6
|
+
def initialize(options = {})
|
7
|
+
if options.has_key?(:radius)
|
8
|
+
build_point_bounding_box(options)
|
9
|
+
elsif options.has_key?(:side_length)
|
10
|
+
build_square_bounding_box(options)
|
11
|
+
elsif options.size == 5 && options.key_present?(:units)
|
12
|
+
build_base_bounding_box(options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def split_geo(max_size)
|
17
|
+
raise "split size greater than width or height" unless self.width > max_size && self.height > max_size
|
18
|
+
rows = (self.height / max_size).to_i
|
19
|
+
columns = (self.width / max_size).to_i
|
20
|
+
|
21
|
+
split_width = self.width / columns
|
22
|
+
split_height = self.height / rows
|
23
|
+
|
24
|
+
temp_array = []
|
25
|
+
temp_lat = self.min_lat
|
26
|
+
temp_long = self.min_long
|
27
|
+
|
28
|
+
(rows - 1).times do |row_num|
|
29
|
+
(columns - 1).times do |column_num|
|
30
|
+
temp_array << BB::SquareBoundingBox.new(temp_lat,
|
31
|
+
temp_long,
|
32
|
+
"#{split_width}#{self.preferred_units}" )
|
33
|
+
temp_long = temp_array.last.max_long
|
34
|
+
end
|
35
|
+
temp_lat = temp_array.last.max_lat
|
36
|
+
temp_long = self.min_long
|
37
|
+
end
|
38
|
+
temp_array
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def set_max_min
|
43
|
+
@max = @box.max
|
44
|
+
@min = @box.min
|
45
|
+
@preferred_units = @box.preferred_units
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_point_bounding_box(options)
|
49
|
+
@box = BB::PointBoundingBox.new(options.fetch(:latitude),
|
50
|
+
options.fetch(:longitude),
|
51
|
+
options.fetch(:radius))
|
52
|
+
set_max_min
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_square_bounding_box(options)
|
56
|
+
@box = BB::SquareBoundingBox.new(options.fetch(:latitude),
|
57
|
+
options.fetch(:longitude),
|
58
|
+
options.fetch(:side_length))
|
59
|
+
set_max_min
|
60
|
+
end
|
61
|
+
|
62
|
+
def build_base_bounding_box(options)
|
63
|
+
@box = BB::BaseBoundingBox.new(options.fetch(:lat1),
|
64
|
+
options.fetch(:long1),
|
65
|
+
options.fetch(:lat2),
|
66
|
+
options.fetch(:long2),
|
67
|
+
options.fetch(:units))
|
68
|
+
set_max_min
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module BB
|
2
|
+
def self.distance_kilometers(point1, point2)
|
3
|
+
lat1 = BB::degrees_to_radians(point1.fetch(:latitude))
|
4
|
+
long1 = BB::degrees_to_radians(point1.fetch(:longitude))
|
5
|
+
lat2 = BB::degrees_to_radians(point2.fetch(:latitude))
|
6
|
+
long2 = BB::degrees_to_radians(point2.fetch(:longitude))
|
7
|
+
|
8
|
+
(Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(long1 - long2)) * 6371)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.distance_km(point1, point2)
|
12
|
+
BB.distance_kilometers(point1, point2)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.distance_miles(point1, point2)
|
16
|
+
BB.kilometers_to_miles(BB.distance_kilometers(point1, point2))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.distance_mi(point1, point2)
|
20
|
+
BB.distance_miles(point1, point2)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.degrees_to_radians(number)
|
24
|
+
number * Math::PI / 180
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.radians_to_degrees(number)
|
28
|
+
number * 180 / Math::PI
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.kilometers_to_miles(number)
|
32
|
+
number * 0.621371
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.miles_to_kilometers(number)
|
36
|
+
number * 1.60934
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module BB
|
2
|
+
#creates a bounding box that contains a circle
|
3
|
+
#with center of lat, long and radius of radius
|
4
|
+
#should be called as PointBoundingBox.new(lat, long, "radius<km || mi>")
|
5
|
+
class PointBoundingBox < BaseBoundingBox
|
6
|
+
def initialize(lat, long, radius)
|
7
|
+
@input = {latitude: lat, longitude: long, radius: radius}
|
8
|
+
@input_radius = parse_radius
|
9
|
+
@input_lat = parse_lat
|
10
|
+
@input_long = parse_long
|
11
|
+
@max = fetch_max
|
12
|
+
@min = fetch_min
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def parse_radius
|
17
|
+
parsed = @input.fetch(:radius).scan(/\d+\.?\d*|km|mi/)
|
18
|
+
@preferred_units = parsed[1] || "mi"
|
19
|
+
if @units == "km" then parsed[0].to_f else BB.miles_to_kilometers(parsed[0].to_f) end
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_lat
|
23
|
+
BB.degrees_to_radians(@input.fetch(:latitude))
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_long
|
27
|
+
BB.degrees_to_radians(@input.fetch(:longitude))
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch_max
|
31
|
+
{latitude: BB.radians_to_degrees(@input_lat + delta_lat),
|
32
|
+
longitude: BB.radians_to_degrees(@input_long + delta_long)}
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch_min
|
36
|
+
{latitude: BB.radians_to_degrees(@input_lat - delta_lat),
|
37
|
+
longitude: BB.radians_to_degrees(@input_long - delta_long)}
|
38
|
+
end
|
39
|
+
|
40
|
+
def delta_lat
|
41
|
+
@input_radius / 6371
|
42
|
+
end
|
43
|
+
|
44
|
+
def delta_long
|
45
|
+
Math.asin(Math.sin(delta_lat)/Math.cos(@input_lat))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module BB
|
2
|
+
def self.split_box(box, length_of_side)
|
3
|
+
parsed = length_of_side.to_s.scan(/\d+|km|mi/)
|
4
|
+
split_length = parsed[0].to_f
|
5
|
+
units = parsed[1]
|
6
|
+
raise "box width smaller than split" unless box.send("side_length_#{units}".to_sym) > split_length
|
7
|
+
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module BB
|
2
|
+
#creates a square bounding box sides equal to side_length
|
3
|
+
#and southwest corner equal to lat/long
|
4
|
+
class SquareBoundingBox < BaseBoundingBox
|
5
|
+
def initialize(lat, long, side_length)
|
6
|
+
@side_length = parse_side_length(side_length)
|
7
|
+
@lat = lat
|
8
|
+
@long = long
|
9
|
+
@min = fetch_min
|
10
|
+
@max = fetch_max
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def parse_side_length(side_length)
|
15
|
+
parsed = side_length.scan(/\d+|mi|km/)
|
16
|
+
@preferred_units = parsed[1] || "mi"
|
17
|
+
parsed[0].to_f
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch_min
|
21
|
+
{latitude: @lat, longitude: @long}
|
22
|
+
end
|
23
|
+
|
24
|
+
def fetch_max
|
25
|
+
BB::PointBoundingBox.new(@lat, @long, "#{@side_length}#{@preferred_units}").max
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bounding_boxes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tyler Morgan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: a gem to convert point_radius geolocations to bounding boxes and split
|
14
|
+
them into smaller boxes
|
15
|
+
email:
|
16
|
+
- tylermorgan86@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/bounding_boxes.rb
|
22
|
+
- lib/bounding_boxes/base_bounding_box.rb
|
23
|
+
- lib/bounding_boxes/bounding_box.rb
|
24
|
+
- lib/bounding_boxes/distance.rb
|
25
|
+
- lib/bounding_boxes/point_bounding_box.rb
|
26
|
+
- lib/bounding_boxes/split_box.rb
|
27
|
+
- lib/bounding_boxes/square_bounding_box.rb
|
28
|
+
- lib/bounding_boxes/version.rb
|
29
|
+
homepage: https://github.com/tylermorgan86/bounding_boxes
|
30
|
+
licenses:
|
31
|
+
- MIT
|
32
|
+
metadata: {}
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 2.2.1
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: geolocation bounding boxes
|
53
|
+
test_files: []
|