cf3 0.0.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/{CHANGELOG → CHANGELOG.md} +13 -0
  4. data/Gemfile +1 -1
  5. data/README.md +21 -21
  6. data/Rakefile +7 -3
  7. data/bin/cf3samples +4 -4
  8. data/cf3ruby.gemspec +12 -13
  9. data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/jekyll-theme-cayman.scssc +0 -0
  10. data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/normalize.scssc +0 -0
  11. data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/rouge-github.scssc +0 -0
  12. data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/variables.scssc +0 -0
  13. data/docs/README.md +1 -0
  14. data/docs/_config.yml +31 -0
  15. data/docs/_site/README.md +1 -0
  16. data/docs/_site/about/index.html +52 -0
  17. data/docs/_site/assets/css/style.css +809 -0
  18. data/docs/_site/assets/y.png +0 -0
  19. data/docs/_site/example/index.html +113 -0
  20. data/docs/_site/favicon.ico +0 -0
  21. data/docs/_site/feed.xml +10 -0
  22. data/docs/_site/index.html +51 -0
  23. data/docs/_site/robots.txt +1 -0
  24. data/docs/_site/sitemap.xml +12 -0
  25. data/docs/about.md +14 -0
  26. data/docs/assets/y.png +0 -0
  27. data/docs/example.md +73 -0
  28. data/docs/favicon.ico +0 -0
  29. data/docs/index.md +10 -0
  30. data/lib/cf3/version.rb +1 -1
  31. data/lib/cf3.rb +85 -100
  32. data/samples/Rakefile +30 -0
  33. data/samples/accident.rb +34 -30
  34. data/samples/alhambra.rb +32 -29
  35. data/samples/bar_code.rb +26 -22
  36. data/samples/city.rb +14 -11
  37. data/samples/creature.rb +10 -6
  38. data/samples/dark_star.rb +5 -3
  39. data/samples/data/java_args.txt +1 -2
  40. data/samples/dragon.rb +8 -4
  41. data/samples/escher.rb +115 -116
  42. data/samples/fern.rb +13 -9
  43. data/samples/hex_tube.rb +16 -13
  44. data/samples/isosceles.rb +16 -11
  45. data/samples/levy.rb +5 -2
  46. data/samples/pcr.rb +28 -24
  47. data/samples/rubystar.rb +23 -17
  48. data/samples/sierpinski.rb +15 -11
  49. data/samples/spiral.rb +14 -10
  50. data/samples/star.rb +10 -6
  51. data/samples/tree.rb +20 -17
  52. data/samples/tree4.rb +12 -8
  53. data/samples/vine.rb +11 -7
  54. data/samples/xcross.rb +10 -7
  55. data/samples/y.rb +13 -9
  56. data/test/test_cf3.rb +11 -7
  57. metadata +50 -42
Binary file
@@ -0,0 +1,113 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+
6
+ <!-- Begin Jekyll SEO tag v2.4.0 -->
7
+ <title>A simple example with weighted shapes | ContextFreeArt gem for JRubyArt</title>
8
+ <meta name="generator" content="Jekyll v3.7.2" />
9
+ <meta property="og:title" content="A simple example with weighted shapes" />
10
+ <meta property="og:locale" content="en_US" />
11
+ <meta name="description" content="The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original." />
12
+ <meta property="og:description" content="The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original." />
13
+ <link rel="canonical" href="http://localhost:4000/example/" />
14
+ <meta property="og:url" content="http://localhost:4000/example/" />
15
+ <meta property="og:site_name" content="ContextFreeArt gem for JRubyArt" />
16
+ <script type="application/ld+json">
17
+ {"description":"The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.","@type":"WebPage","url":"http://localhost:4000/example/","headline":"A simple example with weighted shapes","@context":"http://schema.org"}</script>
18
+ <!-- End Jekyll SEO tag -->
19
+
20
+ <meta name="description" content="The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.
21
+ "/>
22
+ <meta name="viewport" content="width=device-width, initial-scale=1">
23
+ <meta name="theme-color" content="#157878">
24
+ <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
25
+ <link rel="stylesheet" href="/assets/css/style.css?v=">
26
+ </head>
27
+ <body>
28
+ <section class="page-header">
29
+ <h1 class="project-name">ContextFreeArt gem for JRubyArt</h1>
30
+ <h2 class="project-tagline">The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.
31
+ </h2>
32
+
33
+
34
+ </section>
35
+
36
+ <section class="main-content">
37
+ <div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># city.rb after city.cfdg</span>
38
+
39
+ <span class="nb">require</span> <span class="s1">'cf3'</span>
40
+
41
+ <span class="k">def</span> <span class="nf">setup_the_city</span>
42
+ <span class="vi">@city</span> <span class="o">=</span> <span class="no">ContextFree</span><span class="p">.</span><span class="nf">define</span> <span class="k">do</span>
43
+
44
+ <span class="n">shape</span> <span class="ss">:neighborhood</span> <span class="k">do</span>
45
+ <span class="nb">split</span> <span class="k">do</span>
46
+ <span class="n">block</span> <span class="ss">x: </span><span class="o">-</span><span class="mf">0.25</span><span class="p">,</span> <span class="ss">y: </span><span class="o">-</span><span class="mf">0.25</span>
47
+ <span class="n">rewind</span>
48
+ <span class="n">block</span> <span class="ss">x: </span><span class="mf">0.25</span><span class="p">,</span> <span class="ss">y: </span><span class="o">-</span><span class="mf">0.25</span>
49
+ <span class="n">rewind</span>
50
+ <span class="n">block</span> <span class="ss">x: </span><span class="mf">0.25</span><span class="p">,</span> <span class="ss">y: </span><span class="mf">0.25</span>
51
+ <span class="n">rewind</span>
52
+ <span class="n">block</span> <span class="ss">x: </span><span class="o">-</span><span class="mf">0.25</span><span class="p">,</span> <span class="ss">y: </span><span class="mf">0.25</span>
53
+ <span class="k">end</span>
54
+ <span class="k">end</span>
55
+
56
+ <span class="n">shape</span> <span class="ss">:block</span> <span class="k">do</span>
57
+ <span class="n">buildings</span> <span class="ss">size: </span><span class="mf">0.85</span>
58
+ <span class="k">end</span>
59
+
60
+ <span class="n">shape</span> <span class="ss">:block</span><span class="p">,</span> <span class="mi">5</span> <span class="k">do</span>
61
+ <span class="n">neighborhood</span> <span class="ss">size: </span><span class="mf">0.5</span><span class="p">,</span> <span class="ss">rotation: </span><span class="nb">rand</span><span class="p">(</span><span class="o">-</span><span class="no">PI</span><span class="o">..</span><span class="no">PI</span><span class="p">),</span> <span class="ss">hue: </span><span class="nb">rand</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="ss">brightness: </span><span class="nb">rand</span><span class="p">(</span><span class="mf">0.75</span><span class="o">..</span><span class="mf">1.75</span><span class="p">)</span>
62
+ <span class="k">end</span>
63
+
64
+ <span class="n">shape</span> <span class="ss">:block</span><span class="p">,</span> <span class="mf">0.1</span> <span class="k">do</span>
65
+ <span class="c1"># Do nothing</span>
66
+ <span class="k">end</span>
67
+
68
+ <span class="n">shape</span> <span class="ss">:buildings</span> <span class="k">do</span>
69
+ <span class="n">square</span>
70
+ <span class="k">end</span>
71
+
72
+ <span class="k">end</span>
73
+ <span class="k">end</span>
74
+
75
+ <span class="k">def</span> <span class="nf">settings</span>
76
+ <span class="n">size</span> <span class="mi">600</span><span class="p">,</span> <span class="mi">600</span>
77
+ <span class="k">end</span>
78
+
79
+ <span class="k">def</span> <span class="nf">setup</span>
80
+ <span class="n">sketch_title</span> <span class="s1">'City'</span>
81
+ <span class="n">setup_the_city</span>
82
+ <span class="vi">@background</span> <span class="o">=</span> <span class="n">color</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span>
83
+ <span class="n">draw_it</span>
84
+ <span class="k">end</span>
85
+
86
+ <span class="k">def</span> <span class="nf">draw</span>
87
+ <span class="c1"># Do nothing</span>
88
+ <span class="k">end</span>
89
+
90
+ <span class="k">def</span> <span class="nf">draw_it</span>
91
+ <span class="n">background</span> <span class="vi">@background</span>
92
+ <span class="vi">@city</span><span class="p">.</span><span class="nf">render</span> <span class="ss">:neighborhood</span><span class="p">,</span>
93
+ <span class="ss">start_x: </span><span class="n">width</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="ss">start_y: </span><span class="n">height</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span>
94
+ <span class="ss">size: </span><span class="n">height</span><span class="o">/</span><span class="mf">2.5</span><span class="p">,</span> <span class="ss">color: </span><span class="p">[</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">]</span>
95
+ <span class="k">end</span>
96
+
97
+ <span class="k">def</span> <span class="nf">mouse_clicked</span>
98
+ <span class="n">draw_it</span>
99
+ <span class="k">end</span>
100
+
101
+
102
+ </code></pre></div></div>
103
+
104
+
105
+ <footer class="site-footer">
106
+
107
+ <span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a>.</span>
108
+ </footer>
109
+ </section>
110
+
111
+
112
+ </body>
113
+ </html>
Binary file
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom">
3
+ <generator uri="http://jekyllrb.com" version="3.7.2">Jekyll</generator>
4
+ <link href="http://localhost:4000/feed.xml" rel="self" type="application/atom+xml" />
5
+ <link href="http://localhost:4000/" rel="alternate" type="text/html" />
6
+ <updated>2018-02-13T19:38:01+00:00</updated>
7
+ <id>http://localhost:4000/</id>
8
+ <subtitle>The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.
9
+ </subtitle>
10
+ </feed>
@@ -0,0 +1,51 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+
6
+ <!-- Begin Jekyll SEO tag v2.4.0 -->
7
+ <title>Welcome to cf3ruby gem website | ContextFreeArt gem for JRubyArt</title>
8
+ <meta name="generator" content="Jekyll v3.7.2" />
9
+ <meta property="og:title" content="Welcome to cf3ruby gem website" />
10
+ <meta property="og:locale" content="en_US" />
11
+ <meta name="description" content="The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original." />
12
+ <meta property="og:description" content="The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original." />
13
+ <link rel="canonical" href="http://localhost:4000/" />
14
+ <meta property="og:url" content="http://localhost:4000/" />
15
+ <meta property="og:site_name" content="ContextFreeArt gem for JRubyArt" />
16
+ <script type="application/ld+json">
17
+ {"name":"ContextFreeArt gem for JRubyArt","description":"The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.","@type":"WebSite","url":"http://localhost:4000/","headline":"Welcome to cf3ruby gem website","@context":"http://schema.org"}</script>
18
+ <!-- End Jekyll SEO tag -->
19
+
20
+ <meta name="description" content="The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.
21
+ "/>
22
+ <meta name="viewport" content="width=device-width, initial-scale=1">
23
+ <meta name="theme-color" content="#157878">
24
+ <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
25
+ <link rel="stylesheet" href="/assets/css/style.css?v=">
26
+ </head>
27
+ <body>
28
+ <section class="page-header">
29
+ <h1 class="project-name">ContextFreeArt gem for JRubyArt</h1>
30
+ <h2 class="project-tagline">The cf3ruby gem is a kind of ruby DSL for contextfreeart. It is just a toy really see https://www.contextfreeart.org/ for original.
31
+ </h2>
32
+
33
+
34
+ </section>
35
+
36
+ <section class="main-content">
37
+ <h3 id="example-output">Example output</h3>
38
+ <p><a href="/about">About</a> <a href="/example">Example</a></p>
39
+
40
+ <p><img src="/assets/y.png" alt="y.png" /></p>
41
+
42
+
43
+ <footer class="site-footer">
44
+
45
+ <span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a>.</span>
46
+ </footer>
47
+ </section>
48
+
49
+
50
+ </body>
51
+ </html>
@@ -0,0 +1 @@
1
+ Sitemap: http://localhost:4000/sitemap.xml
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url>
4
+ <loc>http://localhost:4000/about/</loc>
5
+ </url>
6
+ <url>
7
+ <loc>http://localhost:4000/example/</loc>
8
+ </url>
9
+ <url>
10
+ <loc>http://localhost:4000/</loc>
11
+ </url>
12
+ </urlset>
data/docs/about.md ADDED
@@ -0,0 +1,14 @@
1
+ ---
2
+ layout: default
3
+ title: Welcome to cf3ruby gem website
4
+ permalink: /about/
5
+ categories: jruby_art contextfreeart
6
+ ---
7
+ The inspiration for cf3ruby is [contextfreeart][] and the jashkenas [original][], so what is context free art?
8
+
9
+ Chris Coyne created a small language for design grammars called CFDG. These grammars are sets of non-deterministic rules to produce images. The images are surprisingly beautiful, often from very simple grammars.
10
+ In the original version there were 3 terminals of a TRIANGLE, SQUARE and CIRCLE see cfdg [how_to][].
11
+
12
+ [contextfreeart]:http://www.contextfreeart.org/
13
+ [original]:https://github.com/jashkenas/context_free
14
+ [how_to]:http://www.contextfreeart.org/mediawiki/index.php/CFDG_HOWTO
data/docs/assets/y.png ADDED
Binary file
data/docs/example.md ADDED
@@ -0,0 +1,73 @@
1
+ ---
2
+ layout: default
3
+ title: A simple example with weighted shapes
4
+ permalink: /example/
5
+ categories: jruby_art contextfreeart
6
+ ---
7
+ ```ruby
8
+ # city.rb after city.cfdg
9
+
10
+ require 'cf3'
11
+
12
+ def setup_the_city
13
+ @city = ContextFree.define do
14
+
15
+ shape :neighborhood do
16
+ split do
17
+ block x: -0.25, y: -0.25
18
+ rewind
19
+ block x: 0.25, y: -0.25
20
+ rewind
21
+ block x: 0.25, y: 0.25
22
+ rewind
23
+ block x: -0.25, y: 0.25
24
+ end
25
+ end
26
+
27
+ shape :block do
28
+ buildings size: 0.85
29
+ end
30
+
31
+ shape :block, 5 do
32
+ neighborhood size: 0.5, rotation: rand(-PI..PI), hue: rand(2), brightness: rand(0.75..1.75)
33
+ end
34
+
35
+ shape :block, 0.1 do
36
+ # Do nothing
37
+ end
38
+
39
+ shape :buildings do
40
+ square
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ def settings
47
+ size 600, 600
48
+ end
49
+
50
+ def setup
51
+ sketch_title 'City'
52
+ setup_the_city
53
+ @background = color 255, 255, 255
54
+ draw_it
55
+ end
56
+
57
+ def draw
58
+ # Do nothing
59
+ end
60
+
61
+ def draw_it
62
+ background @background
63
+ @city.render :neighborhood,
64
+ start_x: width/2, start_y: height/2,
65
+ size: height/2.5, color: [0.1, 0.1, 0.1]
66
+ end
67
+
68
+ def mouse_clicked
69
+ draw_it
70
+ end
71
+
72
+
73
+ ```
data/docs/favicon.ico ADDED
Binary file
data/docs/index.md ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ layout: default
3
+ title: Welcome to cf3ruby gem website
4
+ categories: jruby_art contextfreeart
5
+ ---
6
+
7
+ ### Example output
8
+ [About]({{ site.github.url }}/about) [Example]({{ site.github.url }}/example) [Wiki](https://github.com/monkstone/cf3ruby/wiki)
9
+
10
+ ![y.png]({{ site.github.url }}/assets/y.png)
data/lib/cf3/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Cf3
2
- VERSION = "0.0.4"
2
+ VERSION = '1.2.0'
3
3
  end
data/lib/cf3.rb CHANGED
@@ -1,42 +1,37 @@
1
- # A Context-Free library for Ruby-Processing, inspired by
2
- # based on context_free.rb by Jeremy Ashkenas. Which in turn
3
- # was inspired by contextfreeart.org
4
-
5
1
  module Processing
6
-
2
+ # A Context-Free library for JRubyArt, inspired by and
3
+ # based on context_free.rb by Jeremy Ashkenas. That in turn
4
+ # was inspired by contextfreeart.org
7
5
  class ContextFree
8
-
9
6
  include Processing::Proxy
10
-
11
7
  attr_accessor :rule, :app, :width, :height
12
8
 
13
- AVAILABLE_OPTIONS = [:x, :y, :w, :h, :rotation, :size, :flip, :color, :hue, :saturation, :brightness, :alpha]
14
- HSB_ORDER = {hue: 0, saturation: 1, brightness: 2, alpha: 3}
15
- TRIANGLE_TOP = -1 / Math.sqrt(3)
16
- TRIANGLE_BOTTOM = Math.sqrt(3) / 6
9
+ AVAILABLE_OPTIONS = %i[
10
+ x y w h rotation size flip color hue saturation brightness alpha
11
+ ].freeze
12
+ HSB_ORDER = { hue: 0, saturation: 1, brightness: 2, alpha: 3 }.freeze
13
+ TRIANGLE_TOP = -1 / Math.sqrt(3)
14
+ TRIANGLE_BOTTOM = Math.sqrt(3) / 6
17
15
  RADIANS = (Math::PI / 180.0)
18
16
  # Define a context-free system. Use this method to create a ContextFree
19
17
  # object. Call render() on it to make it draw.
20
18
  def self.define(&block)
21
19
  cf = ContextFree.new
22
- cf.instance_eval &block
20
+ cf.instance_eval(&block)
23
21
  cf
24
22
  end
25
23
 
26
-
27
24
  # Initialize a bare ContextFree object with empty recursion stacks.
28
25
  def initialize
29
- @app = $app
30
- @graphics = $app.g
31
- @width = $app.width
32
- @height = $app.height
33
- @finished = false
26
+ @app = Processing.app
27
+ @graphics = @app.g
28
+ @width = @app.width
29
+ @height = @app.height
34
30
  @rules = {}
35
31
  @rewind_stack = []
36
32
  @matrix_stack = []
37
33
  end
38
34
 
39
-
40
35
  # Create an accessor for the current value of every option. We use a values
41
36
  # object so that all the state can be saved and restored as a unit.
42
37
  AVAILABLE_OPTIONS.each do |option_name|
@@ -45,66 +40,64 @@ module Processing
45
40
  end
46
41
  end
47
42
 
48
-
49
43
  # Here's the first serious method: A Rule has an
50
44
  # identifying name, a probability, and is associated with
51
45
  # a block of code. These code blocks are saved, and indexed
52
46
  # by name in a hash, to be run later, when needed.
53
47
  # The method then dynamically defines a method of the same
54
48
  # name here, in order to determine which rule to run.
55
- def shape(rule_name, prob=1, &proc)
56
- @rules[rule_name] ||= {procs: [], total: 0}
49
+ def shape(rule_name, prob = 1, &proc)
50
+ @rules[rule_name] ||= { procs: [], total: 0 }
57
51
  total = @rules[rule_name][:total]
58
- @rules[rule_name][:procs] << [(total...(prob+total)), proc]
52
+ @rules[rule_name][:procs] << [(total...(prob + total)), proc]
59
53
  @rules[rule_name][:total] += prob
60
- unless ContextFree.method_defined? rule_name
61
- self.class.class_eval do
62
- eval <<-METH
63
- def #{rule_name}(options)
64
- merge_options(@values, options)
65
- pick = determine_rule(#{rule_name.inspect})
66
- @finished = true if @values[:size] < @values[:stop_size]
67
- unless @finished
68
- get_ready_to_draw
69
- pick[1].call(options)
70
- end
71
- end
72
- METH
54
+ return if ContextFree.method_defined? rule_name
55
+
56
+ instance_eval do
57
+ eval <<-METH
58
+ def #{rule_name}(options)
59
+ merge_options(@values, options)
60
+ pick = determine_rule(#{rule_name.inspect})
61
+ return if (@values[:size] - @values[:stop_size]) < 0
62
+ prepare_to_draw
63
+ pick[1].call(options)
73
64
  end
65
+ METH
74
66
  end
75
67
  end
76
68
 
77
-
78
69
  # Rule choice is random, based on the assigned probabilities.
79
70
  def determine_rule(rule_name)
80
71
  rule = @rules[rule_name]
81
- chance = rand * rule[:total]
82
- pick = @rules[rule_name][:procs].select {|the_proc| the_proc[0].include?(chance) }
83
- return pick.flatten
72
+ chance = rand(0.0..rule[:total])
73
+ @rules[rule_name][:procs].select do |the_proc|
74
+ the_proc[0].include?(chance)
75
+ end.flatten
84
76
  end
85
77
 
86
-
87
78
  # At each step of the way, any of the options may change, slightly.
88
79
  # Many of them have different strategies for being merged.
89
80
  def merge_options(old_ops, new_ops)
90
81
  return unless new_ops
82
+
91
83
  # Do size first
92
- old_ops[:size] *= new_ops[:size] if new_ops[:size]
84
+ old_ops[:size] *= new_ops.fetch(:size, 1.0)
93
85
  new_ops.each do |key, value|
94
86
  case key
95
- when :size
87
+ # when :size
96
88
  when :x, :y
97
- old_ops[key] = value * old_ops[:size]
89
+ old_ops[key] = value * old_ops.fetch(:size, 1.0)
98
90
  when :rotation
99
91
  old_ops[key] = value * RADIANS
100
92
  when :hue, :saturation, :brightness, :alpha
101
93
  adjusted = old_ops[:color].dup
102
- adjusted[HSB_ORDER[key]] *= value
94
+ adjusted[HSB_ORDER[key]] *= value unless key == :hue
95
+ adjusted[HSB_ORDER[key]] += value if key == :hue
103
96
  old_ops[:color] = adjusted
104
97
  when :flip
105
98
  old_ops[key] = !old_ops[key]
106
99
  when :w, :h
107
- old_ops[key] = value * old_ops[:size]
100
+ old_ops[key] = value * old_ops.fetch(:size, 1.0)
108
101
  when :color
109
102
  old_ops[key] = value
110
103
  else # Used a key that we don't know about or trying to set
@@ -113,133 +106,125 @@ module Processing
113
106
  end
114
107
  end
115
108
 
116
-
117
109
  # Using an unknown key let's you set arbitrary values,
118
110
  # to keep track of for your own ends.
119
111
  def merge_unknown_key(key, value, old_ops)
120
112
  key_s = key.to_s
121
- if key_s.match(/^set/)
122
- key_sym = key_s.sub('set_', '').to_sym
123
- if key_s.match(/(brightness|hue|saturation)/)
124
- adjusted = old_ops[:color].dup
125
- adjusted[HSB_ORDER[key_sym]] = value
126
- old_ops[:color] = adjusted
127
- else
128
- old_ops[key_sym] = value
129
- end
113
+ return unless key_s =~ /^set/
114
+ key_sym = key_s.sub('set_', '').to_sym
115
+ if key_s =~ /(brightness|hue|saturation)/
116
+ adjusted = old_ops[:color].dup
117
+ adjusted[HSB_ORDER[key_sym]] = value
118
+ old_ops[:color] = adjusted
119
+ else
120
+ old_ops[key_sym] = value
130
121
  end
131
122
  end
132
123
 
133
-
134
124
  # Doing a 'split' saves the context, and proceeds from there,
135
125
  # allowing you to rewind to where you split from at any moment.
136
- def split(options=nil, &block)
126
+ def split(options = nil)
137
127
  save_context
138
128
  merge_options(@values, options) if options
139
129
  yield
140
130
  restore_context
141
131
  end
142
132
 
143
-
144
133
  # Saving the context means the values plus the coordinate matrix.
145
134
  def save_context
146
135
  @rewind_stack.push @values.dup
147
136
  @matrix_stack << @graphics.get_matrix
148
137
  end
149
138
 
150
-
151
139
  # Restore the values and the coordinate matrix as the recursion unwinds.
152
140
  def restore_context
153
141
  @values = @rewind_stack.pop
154
142
  @graphics.set_matrix @matrix_stack.pop
155
143
  end
156
144
 
157
-
158
145
  # Rewinding goes back one step.
159
146
  def rewind
160
- @finished = false
161
147
  restore_context
162
148
  save_context
163
149
  end
164
150
 
165
-
166
151
  # Render the is method that kicks it all off, initializing the options
167
152
  # and calling the first rule.
168
- def render(rule_name, starting_values={})
169
- @values = {x: 0, y: 0,
170
- rotation: 0, flip: false,
171
- size: 20, w: nil, h: nil,
172
- start_x: width/2, start_y: height/2,
173
- color: [180, 0.5, 0.5, 1],
174
- stop_size: 1.5}
153
+ def render(rule_name, starting_values = {})
154
+ @values = defaults
175
155
  @values.merge!(starting_values)
176
- @finished = false
177
156
  @app.reset_matrix
178
157
  @app.rect_mode CENTER
179
158
  @app.ellipse_mode CENTER
180
159
  @app.no_stroke
181
- @app.color_mode HSB, 360, 1.0, 1.0, 1.0 # match cfdg
182
- @app.translate @values[:start_x], @values[:start_y]
183
- self.send(rule_name, {})
160
+ @app.color_mode HSB, 360, 1.0, 1.0, 1.0 # match cfdg
161
+ @app.translate @values.fetch(:start_x, 0), @values.fetch(:start_y, 0)
162
+ send(rule_name, {})
184
163
  end
185
164
 
165
+ def defaults
166
+ {
167
+ x: 0,
168
+ y: 0,
169
+ rotation: 0,
170
+ flip: false,
171
+ size: 20,
172
+ start_x: width / 2,
173
+ start_y: height / 2,
174
+ color: [180, 0.5, 0.5, 1],
175
+ stop_size: 1.5
176
+ }
177
+ end
186
178
 
187
179
  # Before actually drawing the next step, we need to move to the appropriate
188
180
  # location.
189
- def get_ready_to_draw
190
- @app.translate(@values[:x], @values[:y])
181
+ def prepare_to_draw
182
+ @app.translate(@values.fetch(:x, 0), @values.fetch(:y, 0))
191
183
  sign = (@values[:flip] ? -1 : 1)
192
184
  @app.rotate(sign * @values[:rotation])
193
185
  end
194
186
 
195
-
196
187
  # Compute the rendering parameters for drawing a shape.
197
188
  def get_shape_values(some_options)
198
189
  old_ops = @values.dup
199
- merge_options(old_ops, some_options) if some_options
200
- @app.fill *old_ops[:color]
201
- return old_ops[:size], old_ops
190
+ merge_options(old_ops, some_options) unless some_options.empty?
191
+ @app.fill(*old_ops[:color])
192
+ old_ops
202
193
  end
203
194
 
204
-
205
- # Square, circle, and ellipse are the primitive drawing
206
- # methods, but hopefully triangles will be added soon.
207
- def square(some_options={})
208
- size, options = *get_shape_values(some_options)
195
+ # Square, circle, ellipse and triangles are the primitive shapes
196
+ def square(some_options = {})
197
+ options = get_shape_values(some_options)
209
198
  width = options[:w] || options[:size]
210
199
  height = options[:h] || options[:size]
211
- rot = options[:rotation]
200
+ rot = options[:rotation]
212
201
  @app.rotate(rot) if rot
213
202
  @app.rect(0, 0, width, height)
214
- @app.rotate(-rot) if rot
203
+ @app.rotate(-rot) if rot
215
204
  end
216
205
 
217
-
218
- def circle(some_options={})
219
- size, options = *get_shape_values(some_options)
206
+ def circle(some_options = {})
207
+ get_shape_values(some_options)
220
208
  @app.ellipse(0, 0, size, size)
221
209
  end
222
210
 
223
- def triangle(some_options={})
224
- size, options = *get_shape_values(some_options)
225
- rot = options[:rotation]
211
+ def triangle(some_options = {})
212
+ options = get_shape_values(some_options)
213
+ rot = options[:rotation]
226
214
  @app.rotate(rot) if rot
227
215
  @app.triangle(0, TRIANGLE_TOP * size, 0.5 * size, TRIANGLE_BOTTOM * size, -0.5 * size, TRIANGLE_BOTTOM * size)
228
216
  @app.rotate(-rot) if rot
229
217
  end
230
218
 
231
-
232
- def ellipse(some_options={})
233
- size, options = *get_shape_values(some_options)
219
+ def ellipse(some_options = {})
220
+ options = get_shape_values(some_options)
234
221
  width = options[:w] || options[:size]
235
222
  height = options[:h] || options[:size]
236
- rot = some_options[:rotation]
223
+ rot = some_options[:rotation]
237
224
  @app.rotate(rot) if rot
238
225
  @app.oval(options[:x] || 0, options[:y] || 0, width, height)
239
226
  @app.rotate(-rot) if rot
240
227
  end
241
- alias_method :oval, :ellipse
242
-
228
+ alias oval ellipse
243
229
  end
244
-
245
230
  end