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

Showing posts with label voronoi mesh. Show all posts
Showing posts with label voronoi mesh. Show all posts

Saturday, 30 October 2010

Revisiting My Voronoi Application

I had the idea for sometime to optimize this application. As before the application uses Lee Byrons library which in turn depends on John Lloyds QuickHull3D library (both can be accessed at the Lee Byron link). One day I might re-write the application to use a 3D mesh library directly. The major optimization here is to use processings built in pixels array functionality. The app will work best if the aspect ratio of the image is the same as the frame size (1:1 is probably optimal?). I have introduced an auto-scale feature that seems to work...

Use the view raw feature (below) if you want to copy the code.

Monday, 10 May 2010

Op Art using Voronoi Cell, Ruby Processing


load_libraries 'mesh'         # http://www.leebyron.com/else/mesh/
import 'megamu.mesh.Voronoi'
require 'set'
attr_reader :voronoi, :points, :left, :right, :top, :bottom

def setup()
  size(1000, 1000)
  color_mode HSB, 1.0
  @points = Set.new
  @points.clear
  @left = MRect.new 10, height/2, 20, height, 20
  @right = MRect.new 990, height/2, 20, height, 20
  @top = MRect.new width/2, 10, width, 20, 20
  @bottom = MRect.new width/2, 990, width, 20, 20
  smooth
#  no_loop
end

def draw
  @points.clear
  shape = MPoly.new width/3, height/3, 8, 150, 4
  shape1 = MPoly.new width/2, height/2, 8, 120, 4
  shape2 = MPoly.new width*0.667, height*0.667, 8, 150, 4
  shape3 = MPoly.new width/3, height*0.667, 3, 150, 4
  shape4 = MPoly.new width*0.667, height/3, 3, 150, 4
  @points.merge(left.points)
  @points.merge(right.points)
  @points.merge(top.points)
  @points.merge(bottom.points)
  @points.merge(shape.points)
  @points.merge(shape1.points)
  @points.merge(shape2.points)
  @points.merge(shape3.points)
  @points.merge(shape4.points)
  voronoi = Voronoi.new((@points.to_a).to_java(Java::float[]))
  regions = voronoi.get_regions
  regions.each do |region|
    region_coordinates = region.get_coords
    fill(rand)
    region.draw(self)
  end
end

class MRect # border for now
        attr_reader :x, :y, :w, :h, :skip, :points     
  def initialize x, y, w, h, skip
    @x = x - w/2
    @y = y - h/2
    @w = w
    @h = h
    @skip = skip
    @points = calculate_points
  end
  def calculate_points
    mpoints = Array.new
    (w/skip).times do
      (h/skip).times do
        mpoints.push([rand*w + x, rand*h + y])
      end
    end
    return mpoints
  end         
end

class MPoly # shape
  attr_reader :x, :y, :sides, :size, :theta, :delta, :repeats, :len, :points           
  def initialize x, y, sides, size, density
    @delta = -PI/sides
    @x = x
    @y = y
    @sides = sides
    @size = size
    @theta = 2 * PI/sides
    @repeats = density
    @len = size/repeats
    @points = calculate_points
  end
  def calculate_points
    mpoints = Array.new
    repeats.times do |i|
      sides.times do |j|
        mpoint_x = x + (i + 1) * len * cos(j * theta + delta)
        mpoint_y = y - (i + 1) * len * sin(j * theta + delta)
        mpoints.push [mpoint_x, mpoint_y]
      end
    end
    return mpoints
  end
  # def rotate delta
    # @delta += delta
    # calculate_points    
  # end          
end




Saturday, 8 May 2010

Voronoi Cells from the Coordinates of A Penrose Tiling

Here's an idea to create 'regular' voronoi cells from fractal dimensions. Well recently I was working on Penrose Tiling created using LSystems, so that's were I started.


#########################################################
# Voronoi cells centered on penrose tiling coordinates
# generated by a Lindenmayer System in ruby-processing
# by Martin Prout
#######################################################
require 'penrose_tiling'
require 'set'
load_libraries 'grammar', 'mesh'
import 'megamu.mesh.Voronoi'

attr_reader :regions

def setup
  size 300, 300
  stroke 255, 255, 0  # yellow mesh
  stroke_weight 3
  fill 255, 0, 0      # red regions
  smooth
  penrose = PenroseTiling.new
  penrose.create_grammar 4
  set = penrose.get_points
  voronoi = Voronoi.new((set.to_a).to_java(Java::float[]))
  @regions = voronoi.get_regions
  no_loop  
end

def draw
  background 0
  regions.each do |region|
    region_coordinates = region.get_coords            
  region.draw(self)
  end
end

#######################################
# penrose_tiling.rb
# #####################################

require 'set'

class PenroseTiling
  include Processing::Proxy

  attr_reader :axiom, :grammar, :start_length, :theta, :production, :draw_length,
    :repeats, :xpos, :ypos
  
  XPOS = 0     # placeholders for turtle array
  YPOS = 1
  ANGLE = 2
  DELTA = PI/5 # radians or 36 degrees

  def initialize
  
    @axiom = "[X]2+[X]2+[X]2+[X]2+[X]"        # Note use of abbreviated rule
    @grammar = Grammar.new axiom              # here number equals number of repeats
    @grammar.add_rule "F", ""  
    @grammar.add_rule "X", "+YF2-ZF[3-WF2-XF]+"
    @grammar.add_rule "Y", "-WF2+XF[3+YF2+ZF]-"
    @grammar.add_rule "Z", "2-YF4+WF[+ZF4+XF]2-XF"
    @grammar.add_rule "W", "YF2+ZF4-XF[-YF4-WF]2+"
    @start_length = 300.0
    @theta = 0
    @xpos = width/2
    @ypos = height/2
    @production = axiom
    @draw_length = start_length
  end

  ##############################################################################
  # Not strictly in the spirit of either processing in my get_points
  # function I have ignored the processing translate/rotate functions in favour
  # of the direct calculation of the new x and y positions, thus avoiding such
  # affine transformations. Returns a Set of unique [x, y] coordinates.
  ##############################################################################

  def get_points()
    points = Set.new
    repeats = 1
    turtle = [xpos, ypos, theta]    # simple array for turtle
    points.add([xpos.round, ypos.round])
    stack = []                      # simple array for stack
    production.scan(/./).each do |element|
      case element
      when 'F'
        turtle = next_point(turtle, draw_length)      
        points.add([turtle[XPOS].round, turtle[YPOS].round]) unless (turtle[XPOS] < 0) || (turtle[YPOS] < 0)
      when '+'
        turtle[ANGLE] += DELTA * repeats
        repeats = 1
      when '-'
        turtle[ANGLE] -= DELTA * repeats
        repeats = 1
      when '['
        stack.push(turtle.clone)  # push a copy current turtle to stack
      when ']'
        turtle = stack.pop        # assign current turtle a instance popped from the stack
      when 'W', 'X', 'Y', 'Z'  
      when '1', '2', '3', '4'
        repeats = Integer(element)
      else puts "Character '#{element}' not in grammar"
      end
    end
    return points
  end

  ##############################
  # create grammar from axiom and # rules (adjust scale)
  ##############################

  def create_grammar(gen)
    @draw_length *= 0.5**gen
    @production = grammar.generate gen
  end


  private
  ######################################################
  # uses current turtle and length parameters to calculate
  # a turtle corresponding to the new position
  ######################################################

  def next_point(turtle, length)
    new_xpos = turtle[XPOS] + length * cos(turtle[ANGLE])
    new_ypos = turtle[YPOS] + length * sin(turtle[ANGLE])
    return [new_xpos, new_ypos, turtle[ANGLE]]
  end
end


For the grammar library see my PenroseTiling post.

Random Voronoi Sketch

Here is a simple sketch, that flashes new random voronoi cells, with random fill.

load_libraries 'mesh'         # http://www.leebyron.com/else/mesh/
import 'megamu.mesh.Voronoi'
require 'set'
attr_reader :voronoi, :points

def setup()
  size(300, 300)
  color_mode HSB, 1.0
end

def draw
  points = Set.new
  10.times do
    10.times do    
      points.add([rand*300, rand*300])
    end
  end 
  voronoi = Voronoi.new((points.to_a).to_java(Java::float[]))
  regions = voronoi.get_regions
  regions.each do |region|
    region_coordinates = region.get_coords
    fill(rand, rand, rand)
    region.draw(self)
  end 
end


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