cf3 0.0.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/{CHANGELOG → CHANGELOG.md} +13 -0
- data/Gemfile +1 -1
- data/README.md +21 -21
- data/Rakefile +7 -3
- data/bin/cf3samples +4 -4
- data/cf3ruby.gemspec +12 -13
- data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/jekyll-theme-cayman.scssc +0 -0
- data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/normalize.scssc +0 -0
- data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/rouge-github.scssc +0 -0
- data/docs/.sass-cache/cd612fe6616e7f514a2421dc73159618de35b85d/variables.scssc +0 -0
- data/docs/README.md +1 -0
- data/docs/_config.yml +31 -0
- data/docs/_site/README.md +1 -0
- data/docs/_site/about/index.html +52 -0
- data/docs/_site/assets/css/style.css +809 -0
- data/docs/_site/assets/y.png +0 -0
- data/docs/_site/example/index.html +113 -0
- data/docs/_site/favicon.ico +0 -0
- data/docs/_site/feed.xml +10 -0
- data/docs/_site/index.html +51 -0
- data/docs/_site/robots.txt +1 -0
- data/docs/_site/sitemap.xml +12 -0
- data/docs/about.md +14 -0
- data/docs/assets/y.png +0 -0
- data/docs/example.md +73 -0
- data/docs/favicon.ico +0 -0
- data/docs/index.md +10 -0
- data/lib/cf3/version.rb +1 -1
- data/lib/cf3.rb +85 -100
- data/samples/Rakefile +30 -0
- data/samples/accident.rb +34 -30
- data/samples/alhambra.rb +32 -29
- data/samples/bar_code.rb +26 -22
- data/samples/city.rb +14 -11
- data/samples/creature.rb +10 -6
- data/samples/dark_star.rb +5 -3
- data/samples/data/java_args.txt +1 -2
- data/samples/dragon.rb +8 -4
- data/samples/escher.rb +115 -116
- data/samples/fern.rb +13 -9
- data/samples/hex_tube.rb +16 -13
- data/samples/isosceles.rb +16 -11
- data/samples/levy.rb +5 -2
- data/samples/pcr.rb +28 -24
- data/samples/rubystar.rb +23 -17
- data/samples/sierpinski.rb +15 -11
- data/samples/spiral.rb +14 -10
- data/samples/star.rb +10 -6
- data/samples/tree.rb +20 -17
- data/samples/tree4.rb +12 -8
- data/samples/vine.rb +11 -7
- data/samples/xcross.rb +10 -7
- data/samples/y.rb +13 -9
- data/test/test_cf3.rb +11 -7
- 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
|
data/docs/_site/feed.xml
ADDED
@@ -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
|
+

|
data/lib/cf3/version.rb
CHANGED
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 = [
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
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
|
30
|
-
@graphics =
|
31
|
-
@width =
|
32
|
-
@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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
82
|
-
|
83
|
-
|
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
|
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
|
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
|
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
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 =
|
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
|
182
|
-
@app.translate @values
|
183
|
-
|
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
|
190
|
-
@app.translate(@values
|
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)
|
200
|
-
@app.fill
|
201
|
-
|
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
|
-
|
206
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
242
|
-
|
228
|
+
alias oval ellipse
|
243
229
|
end
|
244
|
-
|
245
230
|
end
|