Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0

Friday 14 August 2015

AABB for JRubyArt using keyword args

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):-
# 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

Followers

About Me

My photo
I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2