From: Michael Libby Date: 2009-03-25T01:20:20+09:00 Subject: Re: [QUIZ] Midpoint Displacement (#197) On Fri, Mar 20, 2009 at 10:30 AM, Daniel Moore wrote: > ## Midpoint Displacement (#197) Here's my version. Starts with a flat line and displaces the midpoint(s) iteratively. Iteration method takes a block so that calling code can decide what to do with the information. In this implementation I dump iteration info to the console and create some pictures. The bulk of the code is specific to RMagick and does per frame GIFs as an animated one of the whole sequence. Sample image at: http://www.above-average-software.com/img/line_anim.gif #!/usr/bin/ruby -w require 'RMagick' def get_displaced_midpoint(left, right, range) mid = (left + right) / 2.0 adj = (rand * range) * (0 == rand(2) ? -1 : 1) return mid + adj end def displace_line(line, range) offset = 1 0.upto(line.length - 2) do |x| line.insert(x + offset, get_displaced_midpoint(line[x + offset - 1], line[x + offset], range)) offset += 1 end return line end def draw_line(iter, line, range, width, height, anim_list) drawing = Magick::Draw.new x_factor = width / (line.count - 1) 0.upto(line.count - 2) do |x| drawing.line x_factor * x, (height/2) - (height * line[x] / 2), x_factor * (x + 1), (height / 2) - (height * line[x + 1] / 2) end drawing.stroke("transparent") drawing.fill("black") drawing.text(4, 16, "Iteration #{iter}, Range +/- #{range}") img = Magick::Image.new(width, height, Magick::HatchFill.new('white', 'lightcyan2')) drawing.draw(img) img.write("line_img_#{'%03d' % iter}.gif") anim_list << img.copy end def print_line(iter, line, range) puts "iteration #{iter} (range=#{range}): #{line.inspect}" end def perform_iterations(line, iterations, range, roughness) 1.upto(iterations) do |i| line = displace_line(line, range) yield(i, line, range) range *= 2 ** (0 - roughness) end end anim = Magick::ImageList.new # TODO: parse command line for options width = 512 height = 512 roughness = 1.0 # set iterations to be enough to get "full resolution" for image but no higher iterations = (Math.log(width) / Math.log(2)).to_i perform_iterations([0.0, 0.0], iterations, 0.5, roughness){|iter, line, range| draw_line(iter, line, range, width, height, anim) print_line(iter, line, range) } anim.delay = 100 anim.cur_image.delay = 300 anim.iterations = 0 anim.write("line_anim.gif")