quadtree 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/quadtree/point.rb +13 -12
- data/lib/quadtree/quadtree.rb +43 -42
- data/lib/quadtree/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5db2d5026956693fb12005b6f413baec2df1c55336d54612c69c2d2ea5daee7
|
4
|
+
data.tar.gz: 64fad915c832732dce1b3d8f5d4e09153d6c2a5d0eacbe341ae9e36432ae910f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba095f44c64f53fe6c708a55e59b2da9e43f4317c309fb8677ca24d0e9538c6104eec212c3ce05e092b17816a0b226e2a114ee86b16b5ce92cfc1a8dd582a681
|
7
|
+
data.tar.gz: 3d2ea5d459b276877dae1e42300f5b457c88b557cd88dc3240c4f6864cb430c0044c5ee27ceac0d0d6b1b2a1ee573f627548d12373a66eb4760f0b9c09f91712
|
data/lib/quadtree/point.rb
CHANGED
@@ -8,16 +8,17 @@ module Quadtree
|
|
8
8
|
# @return [Float] Y coordinate
|
9
9
|
attr_accessor :y
|
10
10
|
|
11
|
-
# Payload attached to this {Point}.
|
11
|
+
# @return [Object] Payload attached to this {Point}.
|
12
12
|
attr_accessor :data
|
13
13
|
|
14
14
|
# Create a new {Point}.
|
15
15
|
#
|
16
|
-
# @param [Float] x X coordinate
|
17
|
-
# @param [Float] y Y coordinate
|
16
|
+
# @param [Float, Numeric] x X coordinate.
|
17
|
+
# @param [Float, Numeric] y Y coordinate.
|
18
|
+
# @param [Object] data {Point} payload (optional).
|
18
19
|
def initialize(x, y, data=nil)
|
19
|
-
@x = x
|
20
|
-
@y = y
|
20
|
+
@x = x.to_f
|
21
|
+
@y = y.to_f
|
21
22
|
@data = data unless data.nil?
|
22
23
|
end
|
23
24
|
|
@@ -48,17 +49,17 @@ module Quadtree
|
|
48
49
|
# earth's radius
|
49
50
|
r = 6371 * 1000.0
|
50
51
|
# coverting degrees to radians
|
51
|
-
lat1 = self.y * (Math::PI / 180)
|
52
|
-
lat2 = other.y * (Math::PI / 180)
|
53
|
-
dlat = (other.y - self.y) * (Math::PI / 180)
|
54
|
-
dlon = (other.x - self.x) * (Math::PI / 180)
|
52
|
+
lat1 = self.y * (Math::PI / 180.0)
|
53
|
+
lat2 = other.y * (Math::PI / 180.0)
|
54
|
+
dlat = (other.y - self.y) * (Math::PI / 180.0)
|
55
|
+
dlon = (other.x - self.x) * (Math::PI / 180.0)
|
55
56
|
|
56
57
|
# a = sin²(Δφ/2) + cos φ_1 ⋅ cos φ_2 ⋅ sin²(Δλ/2)
|
57
|
-
a = Math.sin(dlat / 2) * Math.sin(dlat / 2) +
|
58
|
+
a = Math.sin(dlat / 2.0) * Math.sin(dlat / 2.0) +
|
58
59
|
Math.cos(lat1) * Math.cos(lat2) *
|
59
|
-
Math.sin(dlon / 2) * Math.sin(dlon / 2)
|
60
|
+
Math.sin(dlon / 2.0) * Math.sin(dlon / 2.0)
|
60
61
|
# c = 2 ⋅ atan2( √a, √(1−a) )
|
61
|
-
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
|
62
|
+
c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
|
62
63
|
# d = R ⋅ c
|
63
64
|
return r * c
|
64
65
|
end
|
data/lib/quadtree/quadtree.rb
CHANGED
@@ -28,29 +28,29 @@ module Quadtree
|
|
28
28
|
attr_accessor :south_east
|
29
29
|
|
30
30
|
def initialize(boundary)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
self.boundary = boundary
|
32
|
+
self.points = []
|
33
|
+
self.north_west = nil
|
34
|
+
self.north_east = nil
|
35
|
+
self.south_west = nil
|
36
|
+
self.south_east = nil
|
37
37
|
end
|
38
38
|
|
39
39
|
# @param [Point] point
|
40
40
|
# @return [Boolean]
|
41
41
|
def insert!(point)
|
42
|
-
return false unless
|
42
|
+
return false unless self.boundary.contains_point?(point)
|
43
43
|
|
44
|
-
if points.size < NODE_CAPACITY
|
45
|
-
|
44
|
+
if self.points.size < NODE_CAPACITY
|
45
|
+
self.points << point
|
46
46
|
return true
|
47
47
|
end
|
48
48
|
|
49
|
-
subdivide! if
|
50
|
-
return true if
|
51
|
-
return true if
|
52
|
-
return true if
|
53
|
-
return true if
|
49
|
+
subdivide! if self.north_west.nil?
|
50
|
+
return true if self.north_west.insert!(point)
|
51
|
+
return true if self.north_east.insert!(point)
|
52
|
+
return true if self.south_west.insert!(point)
|
53
|
+
return true if self.south_east.insert!(point)
|
54
54
|
|
55
55
|
false
|
56
56
|
end
|
@@ -64,21 +64,21 @@ module Quadtree
|
|
64
64
|
points_in_range = []
|
65
65
|
|
66
66
|
# Automatically abort if the range does not intersect this quad
|
67
|
-
return points_in_range unless
|
67
|
+
return points_in_range unless self.boundary.intersects?(range)
|
68
68
|
|
69
69
|
# Check objects at this quad level
|
70
|
-
|
70
|
+
self.points.each do |point|
|
71
71
|
points_in_range << point if range.contains_point?(point)
|
72
72
|
end
|
73
73
|
|
74
74
|
# Terminate here, if there are no children
|
75
|
-
return points_in_range if
|
75
|
+
return points_in_range if self.north_west.nil?
|
76
76
|
|
77
77
|
# Otherwise, add the points from the children
|
78
|
-
points_in_range +=
|
79
|
-
points_in_range +=
|
80
|
-
points_in_range +=
|
81
|
-
points_in_range +=
|
78
|
+
points_in_range += self.north_west.query_range(range)
|
79
|
+
points_in_range += self.north_east.query_range(range)
|
80
|
+
points_in_range += self.south_west.query_range(range)
|
81
|
+
points_in_range += self.south_east.query_range(range)
|
82
82
|
|
83
83
|
points_in_range
|
84
84
|
end
|
@@ -87,29 +87,30 @@ module Quadtree
|
|
87
87
|
|
88
88
|
# @return [Boolean]
|
89
89
|
def subdivide!
|
90
|
-
left_edge =
|
91
|
-
right_edge =
|
92
|
-
top_edge =
|
93
|
-
bottom_edge =
|
94
|
-
quad_half_dimension =
|
95
|
-
|
96
|
-
north_west_center =
|
97
|
-
north_east_center =
|
98
|
-
south_east_center =
|
99
|
-
south_west_center =
|
100
|
-
|
101
|
-
north_west_boundary =
|
102
|
-
north_east_boundary =
|
103
|
-
south_west_boundary =
|
104
|
-
south_east_boundary =
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
90
|
+
left_edge = self.boundary.left
|
91
|
+
right_edge = self.boundary.right
|
92
|
+
top_edge = self.boundary.top
|
93
|
+
bottom_edge = self.boundary.bottom
|
94
|
+
quad_half_dimension = self.boundary.half_dimension / 2
|
95
|
+
|
96
|
+
north_west_center = Point.new left_edge + quad_half_dimension, top_edge - quad_half_dimension
|
97
|
+
north_east_center = Point.new right_edge - quad_half_dimension, top_edge - quad_half_dimension
|
98
|
+
south_east_center = Point.new left_edge + quad_half_dimension, bottom_edge + quad_half_dimension
|
99
|
+
south_west_center = Point.new right_edge - quad_half_dimension, bottom_edge + quad_half_dimension
|
100
|
+
|
101
|
+
north_west_boundary = AxisAlignedBoundingBox.new north_west_center, quad_half_dimension
|
102
|
+
north_east_boundary = AxisAlignedBoundingBox.new north_east_center, quad_half_dimension
|
103
|
+
south_west_boundary = AxisAlignedBoundingBox.new south_west_center, quad_half_dimension
|
104
|
+
south_east_boundary = AxisAlignedBoundingBox.new south_east_center, quad_half_dimension
|
105
|
+
|
106
|
+
self.north_west = Quadtree.new north_west_boundary
|
107
|
+
self.north_east = Quadtree.new north_east_boundary
|
108
|
+
self.south_west = Quadtree.new south_west_boundary
|
109
|
+
self.south_east = Quadtree.new south_east_boundary
|
110
110
|
|
111
111
|
true
|
112
|
-
rescue
|
112
|
+
rescue => error
|
113
|
+
puts "Something went wrong: #{error}"
|
113
114
|
false
|
114
115
|
end
|
115
116
|
end
|
data/lib/quadtree/version.rb
CHANGED