UPDATED ENTRY 2 September 2015, to avoid clash with toxicgem AABB is now AaBb since JRubyArt-0.6.0
I'm adding a 2D axis aligned bounding box to JRubyArt, here's what it looks like, position can be conditionally updated (ie if block given, only updates if the block evaluates to true):-
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 an example using it (based on processing Basics/Input/MouseFunctions.pde but vastly superior to my thinking). Two AaBb objects are used, one to define the window bounds so we can stop block going off screen (vanilla processing example fails to do that) and one to define the block area.
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
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
class Block
attr_reader :aabb
def initialize(center:, size:)
@aabb = AaBb.new(center: center, extent: size)
end
def new_position(center, &block)
@aabb.position(center.dup, &block)
end
def over?(vec)
aabb.contains? vec
end
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
def points
[aabb.center, aabb.extent]
end
end