Created
September 30, 2011 15:09
-
-
Save monkstone/1254029 to your computer and use it in GitHub Desktop.
Hilbert Fractal Sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################ | |
# Non-stochastic grammar | |
# with unique premise/rules | |
############################ | |
class Grammar | |
attr_accessor :axiom, :rules | |
def initialize axiom | |
@axiom = axiom | |
@rules = Hash.new | |
end | |
def add_rule premise, rule | |
rules.store(premise, rule) | |
end | |
########################################## | |
# replace each pre char with a unique rule | |
########################################## | |
def new_production production | |
production.gsub!(/./) { |c| (r = @rules[c]) ? r : c } | |
end | |
########################################## | |
# control the number of iterations | |
# default 0, returns the axiom | |
########################################## | |
def generate repeat = 0 | |
prod = axiom | |
repeat.times do | |
prod = new_production prod | |
end | |
return prod | |
end | |
end | |
############################ | |
# Hilbert Curves | |
########################### | |
class Hilbert | |
include Processing::Proxy | |
ADJUSTMENT = [0, 0.5, 1.5, 3.5, 7.5, 15] | |
attr_reader :grammar, :axiom, :production, :premis, :rule, | |
:theta, :distance, :phi, :gen | |
def initialize(len) | |
@axiom = "X" | |
@grammar = Grammar.new(axiom) | |
@production = axiom | |
@premis = "X" | |
@rule = "^<XF^<XFX-F^>>XFX&F+>>XFX-F>X->" | |
@distance = len | |
@theta = Math::PI/180 * 90 | |
@phi = Math::PI/180 * 90 | |
grammar.add_rule(premis, rule) | |
end | |
def render() | |
translate( -distance * ADJUSTMENT[gen], distance * ADJUSTMENT[gen], -distance * ADJUSTMENT[gen]) | |
fill(0, 75, 152) | |
light_specular(204, 204, 204) | |
specular(255, 255, 255) | |
shininess(1.0) | |
production.scan(/./) do |ch| | |
case(ch) | |
when "F" | |
translate(0, distance/-2, 0) | |
box(distance/9 , distance, distance/9) | |
translate(0, distance/-2, 0) | |
when "+" | |
rotateX(-theta) | |
when "-" | |
rotateX(theta) | |
when ">" | |
rotateY(theta) | |
when "<" | |
rotateY(-theta) | |
when "&" | |
rotateZ(-phi) | |
when "^" | |
rotateZ(phi) | |
when "X" | |
else | |
puts("character '#{ch}' not in grammar") | |
end | |
end | |
end | |
############################## | |
# create grammar from axiom and | |
# rules (adjust scale) | |
############################## | |
def create_grammar(gen) | |
@gen = gen # required for depth adjustment | |
@distance *= 1/(pow(2, gen) - 1) | |
@production = @grammar.generate gen | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
######################################################## | |
# A 3D Hilbert fractal implemented using a | |
# Lindenmayer System in ruby-processing by Martin Prout | |
# Best if you've got opengl | |
######################################################## | |
class Hilbert_Test < Processing::App | |
full_screen # NB: All distances are relative to screen height | |
load_libraries 'hilbert', 'peasycam', 'opengl' | |
import 'peasy' | |
import "processing.opengl" if library_loaded? "opengl" | |
attr_reader :hilbert, :cam, :depth | |
def setup | |
library_loaded?(:opengl) ? configure_opengl : render_mode(P3D) | |
@depth = 3 | |
configure_peasycam | |
@hilbert = Hilbert.new(height/10) | |
hilbert.create_grammar depth | |
no_stroke | |
end | |
def configure_peasycam | |
@cam = PeasyCam.new(self, 200) | |
cam.set_minimum_distance 100 | |
cam.set_maximum_distance 800 | |
end | |
def configure_opengl | |
render_mode OPENGL | |
hint ENABLE_OPENGL_4X_SMOOTH # optional | |
hint DISABLE_OPENGL_ERROR_REPORT # optional | |
end | |
def draw | |
background 0 | |
lights | |
hilbert.render | |
end | |
def key_pressed() | |
case(key) | |
when 'i', '+' | |
@depth += 1 unless depth > 4 | |
@hilbert = Hilbert.new(height/10) | |
@hilbert.create_grammar(depth) | |
when 'd', '-' | |
@depth -= 1 unless depth < 2 | |
@hilbert = Hilbert.new(height/10) | |
@hilbert.create_grammar(depth) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just amended to script to use latest version of 'peasycam' from sketchbook libraries folder (vs original 'PeasyCam').