-
Notifications
You must be signed in to change notification settings - Fork 9
Axis Aligned Bounding Box
Martin Prout edited this page Aug 15, 2015
·
7 revisions
Currently this a convenience class and there may be no simple way of creating a jruby extension without giving up the keyword arguments (availability of required keyword args is what attracted me to create class in first place).
# Axis aligned bounding box
class AABB
attr_reader :center, :extent
def initialize(center:, extent:)
@center = center
@extent = extent
end
def self.from_min_max(min:, max:)
new(center: (min + max) * 0.5, extent: max - min)
end
def position(vec)
return @center = vec unless block_given?
@center = vec if yield
end
def scale(d)
@extent *= d
end
def contains?(vec)
rad = extent * 0.5
return false unless (center.x - rad.x..center.x + rad.x).cover? vec.x
(center.y - rad.y..center.y + rad.y).cover? vec.y
end
end
Here is some example usage:-
# Click on the box and drag it across the screen.
attr_reader :block, :block_locked, :over_block, :renderer, :bounds
BLOCK_WIDTH = 150
def setup
sketch_title 'AABB Example'
@block = Block.new(
center: Vec2D.new(width / 2, height / 2),
size: Vec2D.new(BLOCK_WIDTH, BLOCK_WIDTH))
@locked = false
@over_block = false
@bounds = AABB.new(
center: Vec2D.new(width / 2, height / 2),
extent: Vec2D.new(width - BLOCK_WIDTH, height - BLOCK_WIDTH))
@renderer = AppRender.new(self)
end
def draw
background 0
fill 153
if block.over?(Vec2D.new(mouse_x, mouse_y))
@over_block = true
stroke 255
fill 255 if block_locked?
else
@over_block = false
stroke 153
end
# Draw the box as a shape
begin_shape
block.points_array.each { |vec| vec.to_vertex(renderer) }
end_shape(CLOSE)
end
def block_locked?
block_locked
end
def over_block?
over_block
end
def mouse_pressed
if over_block?
@block_locked = true
fill 255
else
@block_locked = false
end
end
def mouse_dragged
return unless block_locked?
position = Vec2D.new(mouse_x, mouse_y)
block.new_position(position) { bounds.contains? position }
end
def mouse_released
@block_locked = false
end
def settings
size 640, 360
smooth 4
end
# Use class to contain block behaviour
class Block
attr_reader :aabb
def initialize(center:, size:)
@aabb = AABB.new(center: center, extent: size)
end
# passing ruby block on to @aabb.position
def new_position(center, &block)
@aabb.position(center.dup, &block)
end
def over?(vec)
aabb.contains? vec
end
# use for shape
def points_array
a = aabb.center - aabb.extent * 0.5
c = aabb.center + aabb.extent * 0.5
b = Vec2D.new(c.x, a.y)
d = Vec2D.new(a.x, c.y)
[a, b, c, d]
end
# use for rect
def points
[aabb.center, aabb.extent]
end
end