lib/quadtree/quadtree.rb in quadtree-1.0.6 vs lib/quadtree/quadtree.rb in quadtree-1.0.7
- old
+ new
@@ -1,9 +1,8 @@
module Quadtree
# A Quadtree.
class Quadtree
-
# Arbitrary constant to indicate how many elements can be stored in this
# quad tree node.
# @return [Integer] number of {Point}s this {Quadtree} can hold.
NODE_CAPACITY = 4
@@ -32,11 +31,11 @@
# South east corner of this quad.
# @return [Quadtree]
attr_accessor :south_east
- # @param boundary [AxisAlignedBoundingBox] the boundary for this {Quadtree}
+ # @param boundary [AxisAlignedBoundingBox] the boundary for this {Quadtree}.
def initialize(boundary)
self.boundary = boundary
self.points = []
self.north_west = nil
self.north_east = nil
@@ -47,81 +46,103 @@
# Insert a {Point} in this {Quadtree}.
#
# @param point [Point] the point to insert.
# @return [Boolean] +true+ on success, +false+ otherwise.
def insert!(point)
- return false unless self.boundary.contains_point?(point)
+ return false unless boundary.contains_point?(point)
- if self.points.size < NODE_CAPACITY
- self.points << point
+ if points.size < NODE_CAPACITY
+ points << point
return true
end
- subdivide! if self.north_west.nil?
- return true if self.north_west.insert!(point)
- return true if self.north_east.insert!(point)
- return true if self.south_west.insert!(point)
- return true if self.south_east.insert!(point)
+ subdivide! if north_west.nil?
+ return true if north_west.insert!(point)
+ return true if north_east.insert!(point)
+ return true if south_west.insert!(point)
+ return true if south_east.insert!(point)
false
end
+ # Return the size of this instance, the number of {Point}s stored in this
+ # {Quadtree}.
+ # @return [Integer] the size of this instance.
+ def size
+ count = 0
+ count += points.size
+ unless north_west.nil?
+ count += north_west.size
+ count += north_east.size
+ count += south_west.size
+ count += south_east.size
+ end
+ count
+ end
+
# Finds all points contained within a range.
#
# @param range [AxisAlignedBoundingBox] the range to search within.
- # @return [Array<Point>]
+ # @return [Array<Point>] all {Point}s in given range.
def query_range(range)
# Prepare an array of results
points_in_range = []
# Automatically abort if the range does not intersect this quad
- return points_in_range unless self.boundary.intersects?(range)
+ return points_in_range unless boundary.intersects?(range)
# Check objects at this quad level
- self.points.each do |point|
+ points.each do |point|
points_in_range << point if range.contains_point?(point)
end
# Terminate here, if there are no children
- return points_in_range if self.north_west.nil?
+ return points_in_range if north_west.nil?
# Otherwise, add the points from the children
- points_in_range += self.north_west.query_range(range)
- points_in_range += self.north_east.query_range(range)
- points_in_range += self.south_west.query_range(range)
- points_in_range += self.south_east.query_range(range)
+ points_in_range += north_west.query_range(range)
+ points_in_range += north_east.query_range(range)
+ points_in_range += south_west.query_range(range)
+ points_in_range += south_east.query_range(range)
points_in_range
end
private
- # @return [Boolean]
+ # @return [Boolean] +true+ on success, +false+ otherwise.
def subdivide!
- left_edge = self.boundary.left
- right_edge = self.boundary.right
- top_edge = self.boundary.top
- bottom_edge = self.boundary.bottom
- quad_half_dimension = self.boundary.half_dimension / 2
+ left_edge = boundary.left
+ right_edge = boundary.right
+ top_edge = boundary.top
+ bottom_edge = boundary.bottom
+ quad_half_dimension = boundary.half_dimension / 2
- north_west_center = Point.new left_edge + quad_half_dimension, top_edge - quad_half_dimension
- north_east_center = Point.new right_edge - quad_half_dimension, top_edge - quad_half_dimension
- south_east_center = Point.new left_edge + quad_half_dimension, bottom_edge + quad_half_dimension
- south_west_center = Point.new right_edge - quad_half_dimension, bottom_edge + quad_half_dimension
+ north_west_center = Point.new(left_edge + quad_half_dimension,
+ top_edge - quad_half_dimension)
+ north_east_center = Point.new(right_edge - quad_half_dimension,
+ top_edge - quad_half_dimension)
+ south_east_center = Point.new(left_edge + quad_half_dimension,
+ bottom_edge + quad_half_dimension)
+ south_west_center = Point.new(right_edge - quad_half_dimension,
+ bottom_edge + quad_half_dimension)
- north_west_boundary = AxisAlignedBoundingBox.new north_west_center, quad_half_dimension
- north_east_boundary = AxisAlignedBoundingBox.new north_east_center, quad_half_dimension
- south_west_boundary = AxisAlignedBoundingBox.new south_west_center, quad_half_dimension
- south_east_boundary = AxisAlignedBoundingBox.new south_east_center, quad_half_dimension
+ north_west_boundary = AxisAlignedBoundingBox.new(north_west_center,
+ quad_half_dimension)
+ north_east_boundary = AxisAlignedBoundingBox.new(north_east_center,
+ quad_half_dimension)
+ south_west_boundary = AxisAlignedBoundingBox.new(south_west_center,
+ quad_half_dimension)
+ south_east_boundary = AxisAlignedBoundingBox.new(south_east_center,
+ quad_half_dimension)
self.north_west = Quadtree.new north_west_boundary
self.north_east = Quadtree.new north_east_boundary
self.south_west = Quadtree.new south_west_boundary
self.south_east = Quadtree.new south_east_boundary
true
- rescue => error
- puts "Something went wrong: #{error}"
+ rescue StandardError
false
end
end
end