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):-
# Axis aligned bounding box class (AABB would clash with Toxicgem) 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.
# 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 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
No comments:
Post a Comment