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 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
@@ -0,0 +1,3 @@
1
+ module BB
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,3 @@
1
+ Dir[File.dirname(__FILE__) + "/bounding_boxes/*.rb"].each do |file|
2
+ require file
3
+ 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: []