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.
- 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
|