# The Golden Fibonacci Ratio

**URL:** <https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448>\
**Category:** Ruby\
**Created:** [March 5, 2006, 3:40pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448 "2006-03-05T15:40:51Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 5, 2006, 3:40pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/1 "2006-03-05T15:40:51Z")

</div>

Here is my solution… Uses a cheap trick (a la method\_missing) to  
allow inline Postscript as method calls (so not as postfix). The  
output is dumped to standard output to be redirected to a .ps file,  
which can be easily viewed on Mac OS X (and almost as easily on other  
platforms using ghostscript).

require ‘matrix’

# Class helpers

class Array  
def tail  
self[1…-1]  
end  
def mod\_fetch i  
self[i % size]  
end  
def each\_pair  
each\_with\_index do |a, i|  
yield a, self[i+1] if i+1 \< size  
end  
end  
end

class Vector  
def x  
self[0]  
end

def y  
self[1]  
end

def len  
Math.sqrt(inner\_product(self))  
end

def rot90  
Vector[-y, x]  
end

def rot45 # cheap rotate by 45 degrees  
Vector[x - y, x + y]  
end

def to\_s  
“#{x} #{y}”  
end  
end

# Postscript class (what a hack!)

class PS  
def initialize(&block)  
@cmds = []  
instance\_eval(&block) if block  
end

def push(\*args, &block)  
@cmds \<\< args.join(’ ')  
@cmds \<\< instance\_eval(&block) if block  
end

def to\_s  
@cmds.join("\n")  
end

def page(&block)  
instance\_eval(&block)  
push ‘showpage’  
end

def path(&block)  
push ‘newpath’  
instance\_eval(&block)  
end

def gsave(&block)  
push ‘gsave’  
instance\_eval(&block)  
push ‘grestore’  
end

def method\_missing(name, \*args)  
push \*args + [name]  
end  
end

# Constants and helper funcs for building image data

Basis = [Vector[1, 0], Vector[0, -1], Vector[-1, 0], Vector[0, 1]]  
Shade = [0.3, 0.5, 0.7]

def fibo(n)  
a, b = 1, 1  
n.times { a, b = b, a + b }  
a  
end

def spiral(n)  
if n.zero?  
Vector[0, 0]  
else  
i = n - 1  
spiral(i) + Basis.mod\_fetch(i) \* fibo(i)  
end  
end

# Build list of spiral coordinates

steps = (ARGV[0] || 11).to\_i  
coords = (0…steps).map { |i| spiral(i).rot45 }

# Calculate page/content dimensions, scale and center

inch = 72  
margin = 0.5 \* inch  
pagew = 8.5 \* inch  
pageh = 11 \* inch  
contw = pagew - 2 \* margin  
conth = pageh - 2 \* margin

xmin = coords.min { |a, b| a.x \<=\> b.x }.x  
xmax = coords.max { |a, b| a.x \<=\> b.x }.x  
ymin = coords.min { |a, b| a.y \<=\> b.y }.y  
ymax = coords.max { |a, b| a.y \<=\> b.y }.y

scale = [contw / (xmax - xmin), conth / (ymax - ymin)].min

cx = (pagew - (xmax - xmin.abs) \* scale) / 2  
cy = (pageh - (ymax - ymin.abs) \* scale) / 2

# Scale coords to fill page

coords.map! { |v| v \* scale }

# Build Postscript image

doc = PS.new do  
def box a, b  
l, r = [a.x, b.x].min, [a.x, b.x].max  
b, t = [a.y, b.y].min, [a.y, b.y].max

```
  moveto l, b
  lineto r, b
  lineto r, t
  lineto l, t
  closepath

```

end

page do  
translate cx, cy

```
  i = 0
  coords.each_pair do |a, b|
     path do
        box a, b
        gsave do
           setgray Shade.mod_fetch(i += 1)
           fill
        end
        stroke
     end
  end

  setrgbcolor 0.8, 0.4, 0
  path do
     moveto coords.first
     angle = 180
     coords.each_pair do |a, b|
        d = (a + b) * 0.5
        d += (a - d).rot90
        arcn d, (d - a).len, angle, (angle -= 90)
     end
     stroke
  end

```

end  
end

puts doc

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 5, 2006, 4:20pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/2 "2006-03-05T16:20:27Z")

</div>

On Mar 5, 2006, at 8:37 AM, Matthew M. wrote:

> Here is my solution… Uses a cheap trick (a la method\_missing) to  
> allow inline Postscript as method calls (so not as postfix). The  
> output is dumped to standard output to be redirected to a .ps file,  
> which can be easily viewed on Mac OS X (and almost as easily on other  
> platforms using ghostscript).

Very nice output!

Jim F.

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 6, 2006, 2:24pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/3 "2006-03-06T14:24:30Z")

</div>

“Matthew M.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> Here is my solution… Uses a cheap trick (a la method\_missing) to  
> allow inline Postscript as method calls (so not as postfix). The  
> output is dumped to standard output to be redirected to a .ps file,  
> which can be easily viewed on Mac OS X (and almost as easily on other  
> platforms using ghostscript).

Okay, I could not resist “doing it right”. 😉

puts \<\<EOF  
100 100 translate

/s 400 def  
/colors [0.7 0.5 0.3] def

/phi 5 sqrt 1 sub 2 div def

/box { /i exch def  
0 0 moveto  
i 0 lineto  
i i lineto  
0 i lineto  
closepath  
} def

0 1 9 { %for  
colors exch 3 mod get setgray  
s box  
gsave fill grestore  
0 setgray stroke

```
0.8 0.4 0 setrgbcolor
0 s s 270 360 arc stroke

s s translate
90 rotate
phi phi scale
currentlinewidth 1 phi div mul setlinewidth % keep linewidth

```

} for

showpage  
EOF

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 6, 2006, 4:50pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/4 "2006-03-06T16:50:24Z")

</div>

“Matthew M.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> I hang my head in shame.

The one who reads that code a bit closer probably will grin deeply…

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 6, 2006, 3:28pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/5 "2006-03-06T15:28:13Z")

</div>

On 3/6/06, Christian N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> “Matthew M.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:
> 
> > Here is my solution… Uses a cheap trick (a la method\_missing) to  
> > allow inline Postscript as method calls (so not as postfix). The  
> > output is dumped to standard output to be redirected to a .ps file,  
> > which can be easily viewed on Mac OS X (and almost as easily on other  
> > platforms using ghostscript).
> 
> Okay, I could not resist “doing it right”. 😉

I hang my head in shame.

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 6, 2006, 5:17pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/6 "2006-03-06T17:17:55Z")

</div>

On Mar 6, 2006, at 10:49 AM, Christian N. wrote:

> > > > platforms using ghostscript).

Me guesses you refer to this:  
/phi 5 sqrt 1 sub 2 div def

Cheater! 😉

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [March 6, 2006, 9:12pm UTC](https://www.ruby-forum.com/t/the-golden-fibonacci-ratio/54448/7 "2006-03-06T21:12:29Z")

</div>

Logan C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> > > > > which can be easily viewed on Mac OS X (and almost as easily on  
> > > > > Christian N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) http://  
> > > > > [chneukirchen.org](http://chneukirchen.org)
> 
> Me guesses you refer to this:  
> /phi 5 sqrt 1 sub 2 div def

Bingo! Mine is drawn outside-in. 😉 [That said, I was amazed how  
much Postscript I still knew, I didn’t touch it for quite some time.]
