|
| 1 | +######################################################## |
| 2 | +# A Doily fractal implemented using a |
| 3 | +# Lindenmayer System in JRubyArt by Martin Prout |
| 4 | +######################################################## |
| 5 | +load_libraries :grammar |
| 6 | + |
| 7 | +# Doily class |
| 8 | +class Doily |
| 9 | + include Processing::Proxy |
| 10 | + attr_reader :draw_length, :vec, :theta, :axiom, :grammar |
| 11 | + DELTA = 45 # degrees |
| 12 | + def initialize(vec) |
| 13 | + @axiom = 'F-F-F-F-F-F-F-F' # Axiom |
| 14 | + rules = { 'F' => 'F---F+F+F+F+F+F+F---F' } |
| 15 | + @grammar = Grammar.new(axiom, rules) |
| 16 | + @theta = 0 |
| 17 | + @draw_length = 100 |
| 18 | + @vec = vec |
| 19 | + end |
| 20 | + |
| 21 | + def generate(gen) |
| 22 | + @draw_length = draw_length * 0.4**gen |
| 23 | + grammar.generate gen |
| 24 | + end |
| 25 | + |
| 26 | + def translate_rules(prod) |
| 27 | + coss = ->(orig, alpha, len) { orig + len * DegLut.cos(alpha) } |
| 28 | + sinn = ->(orig, alpha, len) { orig - len * DegLut.sin(alpha) } |
| 29 | + [].tap do |pts| # An array to store line vertices as Vec2D |
| 30 | + prod.each do |ch| |
| 31 | + case ch |
| 32 | + when 'F' |
| 33 | + pts << vec.copy |
| 34 | + @vec = Vec2D.new( |
| 35 | + coss.call(vec.x, theta, draw_length), |
| 36 | + sinn.call(vec.y, theta, draw_length) |
| 37 | + ) |
| 38 | + pts << vec |
| 39 | + when '+' |
| 40 | + @theta += DELTA |
| 41 | + when '-' |
| 42 | + @theta -= DELTA |
| 43 | + else |
| 44 | + puts("character #{ch} not in grammar") |
| 45 | + end |
| 46 | + end |
| 47 | + end |
| 48 | + end |
| 49 | +end |
| 50 | + |
| 51 | +attr_reader :points |
| 52 | + |
| 53 | +def setup |
| 54 | + sketch_title 'Doily' |
| 55 | + doily = Doily.new(Vec2D.new(width * 0.35, height * 0.2)) |
| 56 | + production = doily.generate 4 # 4 generations looks OK |
| 57 | + @points = doily.translate_rules(production) |
| 58 | + no_loop |
| 59 | +end |
| 60 | + |
| 61 | +def draw |
| 62 | + background(0) |
| 63 | + render points |
| 64 | +end |
| 65 | + |
| 66 | +def render(points) |
| 67 | + no_fill |
| 68 | + stroke 200.0 |
| 69 | + stroke_weight 3 |
| 70 | + begin_shape |
| 71 | + points.each_slice(2) do |v0, v1| |
| 72 | + v0.to_vertex(renderer) |
| 73 | + v1.to_vertex(renderer) |
| 74 | + end |
| 75 | + end_shape |
| 76 | +end |
| 77 | + |
| 78 | +def renderer |
| 79 | + @renderer ||= AppRender.new(self) |
| 80 | +end |
| 81 | + |
| 82 | +def settings |
| 83 | + size(800, 800) |
| 84 | +end |
0 commit comments