Skip to content

De Rahm curves

An exploration of De Rahm curves. Plenty of sliders to play around with!

A fractal curve formed by a specially-crafted iterated function system.

Credits:

function setup() {
  createCanvas(400, 400);
  
  let sliders = {}
  let keys = Object.keys(config)
  let configInput = createInput()
  configInput.value(JSON.stringify(config))
  configInput.parent(controls)
  createButton('OK').parent(controls).mouseClicked(() => {
    let val = JSON.parse(configInput.value())
    for (let k of keys) {
      config[k] = parseFloat(val[k]) || 0
    }
    update()
  })
  let preset = createSelect()
  preset.parent(controls)
  preset.option('Preset')
  for (let p in presets) {
    preset.option(p)
  }
  preset.option('Random')
  preset.changed(() => {
    if (preset.value() == 'Random') {
      for (let k of keys) {
        config[k] = random(ranges[k][0], ranges[k][1])
      }
    } else {
      config = {...presets[preset.value()]} 
    }
    preset.value('Preset')
    update()
  })
  
  for (let k of keys) {
    createElement('br').parent(controls)
    let label = createElement('label')
    label.parent(controls)
    let span = createSpan(`${k}: `)
    span.parent(label)
    span.style('display', 'inline-block')
    span.style('width', '40px')
    let slider = createSlider(ranges[k][0], ranges[k][1], config[k], 0)
    slider.parent(label)
    slider.style('vertical-align', 'middle')
    slider.input(() => {
      config[k] = slider.value()
      update(true)
    })
    slider.changed(() => {
      config[k] = slider.value()
      update(false)
    })
    sliders[k] = slider
  }
  background(255)
  stroke(0,10)
  
  function update(soft) {
    if (soft) {
      stroke(0,80)
    } else {
      stroke(0,10)
    }
    background(255)
    for (let k of keys) {
      sliders[k].value(config[k])
    }
    configInput.value(JSON.stringify(config))
  }
}

let ranges = {
  a: [-1, 1],
  b: [-1, 1],
  d: [-1, 1],
  e: [-1, 1],
  g: [-1, 1],
  m: [-1, 1],
  s: [0, 400],
  ox: [0, 400],
  oy: [0, 400],
  iter: [1, 200],
  bias: [-20, 20]
}

function d0(p) {
  return [p[0] * config.a + p[1] * config.d, p[0] * config.b + p[1] * config.e]
}
function d1(p) {
  return [config.a + p[0] * (1 - config.a) + p[1] * config.g, config.b + p[0] * -config.b + p[1] * config.m]
}

let perFrame = 0

function draw() {
  let frameStart = millis()
  for (let j = 0; j < perFrame; j ++) {
    if (j % 10 == 9 && millis() - frameStart > 20) {
      perFrame = j * 0.9
      return
    }
    let p = [config.a, config.b]
    for (let i = 0; i < config.iter; i ++) {
      p = random([d1, d0])(p)
    }
    let biasIters = floor(abs(random(config.bias)))
    for (let i = 0; i < biasIters; i ++) {
      p = (config.bias > 0 ? d1 : d0)(p)
    }
    point(p[0] * config.s + config.ox + random(0.5), p[1] * config.s + config.oy + random(0.5))
  }
  perFrame += 10
}
  
let presets = {
"Koch":{"a":0.5,"b":-0.2886751345948129,"d":-0.2886751345948129,"e":-0.5,"g":0.2886751345948129,"m":-0.5,"s":400,"ox":0,"oy":250,"iter":40,"bias":0},
"Peano":{"a":0.5,"b":-0.4,"d":-0.5,"e":-0.5,"g":0.5,"m":-0.5,"s":400,"ox":0,"oy":250,"iter":40,"bias":0},
"Levy C":{"a":0.5,"b":-0.5,"d":0.5,"e":0.5,"g":-0.5,"m":0.5,"s":190,"ox":105,"oy":225,"iter":40,"bias":0},
"Spirals":{"a":0.457142857142857,"b":0.571428571428571,"d":-0.842857142857143,"e":0.428571428571429,"g":0.328571428571429,"m":0.0714285714285714,"s":162.857142857143,"ox":182.857142857143,"oy":145.714285714286,"iter":32,"bias":-6.4},
"Fern 1":{"a":-0.328571428571429,"b":0.2,"d":0.185714285714286,"e":0.414285714285714,"g":1,"m":0.657142857142857,"s":380,"ox":254.285714285714,"oy":40,"iter":19.4785714285714,"bias":0},
"Scribble":{"a":0.557142857142857,"b":0.0714285714285714,"d":-1,"e":-1,"g":1,"m":0.842857142857143,"s":314.285714285714,"ox":22.8571428571429,"oy":180,"iter":73.4928571428571,"bias":0},
"Dragon back":{"a":0.228571428571429,"b":0.0857142857142857,"d":-0.128571428571429,"e":-1,"g":0,"m":0.814285714285714,"s":357.142857142857,"ox":22.8571428571429,"oy":180,"iter":23,"bias":1.6},
"Fern in snow":{"a":0.0285714285714286,"b":-0.6,"d":-0.4,"e":0.1,"g":-0.471428571428571,"m":0.9,"s":89.2857142857143,"ox":107.142857142857,"oy":164.285714285714,"iter":37,"bias":6},
"Triangles":{"a":0.5,"b":-0.428571428571429,"d":-0.7,"e":-0.557142857142857,"g":0.571428571428571,"m":-0.3,"s":400,"ox":0,"oy":250,"iter":40,"bias":0},
"Triangles 2": {"a":0.0964285714285714,"b":-0.332142857142857,"d":-1,"e":-0.177380952380952,"g":-0.796428571428571,"m":-0.939285714285714,"s":362.142857142857,"ox":26.4285714285714,"oy":185.05870007996248,"iter":40.2077380952381,"bias":1.21428571428571},
"Thorn crown":{"a":0.117857142857143,"b":0.222619047619048,"d":0.196428571428571,"e":-1,"g":0.916666666666667,"m":0.903571428571429,"s":113.571428571429,"ox":71.6666666666667,"oy":145,"iter":68.64806386455848,"bias":12.047619047619},
"Galaxy":{"a":-0.025,"b":0.198255813953488,"d":-1,"e":0.719186046511628,"g":0.942441860465116,"m":0.709883720930233,"s":111.279069767442,"ox":88.953488372093,"oy":145,"iter":20,"bias":20},
"Bifrucated tree":{"a":0.8369751692748835,"b":-0.285714285714286,"d":-0.7,"e":-0.714285714285714,"g":0.157142857142857,"m":-0.9585526997470677,"s":331.428571428571,"ox":0,"oy":237.142857142857,"iter":13.7928571428571,"bias":-20},
"Mandelbrot-like!?":{"a":0.5,"b":-0.25,"d":-0.25,"e":-0.5,"g":-0.25,"m":0.5,"s":300,"ox":50,"oy":250,"iter":20,"bias":0},
"Negative-space spirals":{"a":0.513095238095238,"b":-0.236904761904762,"d":1,"e":0.536904761904762,"g":-1,"m":0.846428571428571,"s":112.142857142857,"ox":114.52380952381,"oy":226.428571428571,"iter":23,"bias":0.738095238095238},
"Bristle": {"a":0.814285714285714,"b":-0.442857142857143,"d":-0.671428571428571,"e":-0.428571428571429,"g":-0.714285714285714,"m":-0.157142857142857,"s":225.714285714286,"ox":0,"oy":251.428571428571,"iter":45.0642857142857,"bias":-0.571428571428572},
"Vague cloudy vibes (by: Daniel)":{"a":0.745736434108527,"b":-0.486821705426357,"d":-0.451937984496124,"e":-1,"g":0.28062015503876,"m":-0.417054263565891,"s":318.914728682171,"ox":21.2403100775194,"oy":232.868217054264,"iter":130.735658914729,"bias":0.728682170542636}
}

let config = {
  ...presets.Koch
}

(Originally seen at https://editor.p5js.org/bojidar-bg/sketches/xRXD7vuHT)

Experiments tagged p5 (65/85)

Experiments tagged interactive (21/26)

Experiments on this site (65/85)