block by nitaku 6486571

Gosper space-filling curve

Full Screen

A Javascript+SVG implementation of a Gosper space-filling curve. See Akiyama et al. 2007 for reference.

The code is really messy, with too few comments and not optimized. :D

index.js

(function() {
  var A, GOSPER_GEN, HEX_DIRS, TRI_LINES, fractalize, fractalize_step;

  HEX_DIRS = 'abcdef';

  GOSPER_GEN = 'AfdEAAb';

  fractalize_step = function(seq, gen) {
    var delta, el, gen_el, i, new_el, res_seq, tmp_seq, _i, _j, _len, _len2, _ref;
    res_seq = '';
    for (_i = 0, _len = seq.length; _i < _len; _i++) {
      el = seq[_i];
      tmp_seq = '';
      delta = HEX_DIRS.indexOf(el.toLowerCase());
      for (_j = 0, _len2 = gen.length; _j < _len2; _j++) {
        gen_el = gen[_j];
        new_el = HEX_DIRS[(HEX_DIRS.indexOf(gen_el.toLowerCase()) + delta) % 6];
        if (gen_el.toUpperCase() === gen_el) new_el = new_el.toUpperCase();
        tmp_seq += new_el;
      }
      if (el.toLowerCase() === el) {
        tmp_seq = tmp_seq.split('').reverse();
        for (i = 0, _ref = tmp_seq.length; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
          if (tmp_seq[i].toLowerCase() === tmp_seq[i]) {
            tmp_seq[i] = tmp_seq[i].toUpperCase();
          } else {
            tmp_seq[i] = tmp_seq[i].toLowerCase();
          }
        }
        tmp_seq = tmp_seq.join('');
      }
      res_seq += tmp_seq;
    }
    return res_seq;
  };

  fractalize = function(gen, stage) {
    var i, seq, _ref;
    seq = gen;
    for (i = 0, _ref = stage - 1; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
      seq = fractalize_step(seq, gen);
    }
    return seq;
  };

  A = 3;

  TRI_LINES = {
    'a': "l" + (2 * A) + " 0",
    'b': "l" + A + " " + (A * Math.sqrt(3)),
    'c': "l" + (-A) + " " + (A * Math.sqrt(3)),
    'd': "l" + (-2 * A) + " 0",
    'e': "l" + (-A) + " " + (-A * Math.sqrt(3)),
    'f': "l" + A + " " + (-A * Math.sqrt(3))
  };

  window.main = function() {
    var d, el, height, seq, svg, width, _i, _len;
    seq = fractalize(GOSPER_GEN, 4);
    d = 'M0 0';
    for (_i = 0, _len = seq.length; _i < _len; _i++) {
      el = seq[_i];
      d += TRI_LINES[el.toLowerCase()];
    }
    width = 960;
    height = 500;
    svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
    return svg.append('path').attr('class', 'gosper').attr('d', d).attr('transform', 'translate(500,390)');
  };

}).call(this);

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Gosper curve</title>
        <link type="text/css" href="index.css" rel="stylesheet"/>
        <script src="//d3js.org/d3.v3.min.js"></script>
        <script src="index.js"></script>
    </head>
    <body onload="main()"></body>
</html>

index.coffee

# Hexagonal Directions:

#     E     F
#
#  D     O     A
#
#     C     B

HEX_DIRS = 'abcdef'
GOSPER_GEN = 'AfdEAAb' # lowercase letter indicate that the generator must be applied in reverse

fractalize_step = (seq, gen) ->
    res_seq = ''
    for el in seq
        tmp_seq = ''
        delta = HEX_DIRS.indexOf(el.toLowerCase())
        
        for gen_el in gen
            new_el = HEX_DIRS[(HEX_DIRS.indexOf(gen_el.toLowerCase()) + delta) % 6]
            if gen_el.toUpperCase() == gen_el
                new_el = new_el.toUpperCase()
            tmp_seq += new_el
            
        if el.toLowerCase() == el
            tmp_seq = tmp_seq.split('').reverse()
            
            # the reversed sequence must also have reversed case
            for i in [0...tmp_seq.length]
                if tmp_seq[i].toLowerCase() == tmp_seq[i]
                    tmp_seq[i] = tmp_seq[i].toUpperCase()
                else
                    tmp_seq[i] = tmp_seq[i].toLowerCase()
                    
            tmp_seq = tmp_seq.join('')
            
        res_seq += tmp_seq
        
    return res_seq
    
fractalize = (gen, stage) ->
    seq = gen
    for i in [0...stage-1]
        seq = fractalize_step(seq, gen)
        
    return seq
    
# this is somehow similar to a triangular grid
A = 3
TRI_LINES = {
    'a': "l#{2*A} 0",
    'b': "l#{A} #{A*Math.sqrt(3)}",
    'c': "l#{-A} #{A*Math.sqrt(3)}",
    'd': "l#{-2*A} 0",
    'e': "l#{-A} #{-A*Math.sqrt(3)}",
    'f': "l#{A} #{-A*Math.sqrt(3)}"
}

window.main = () ->
    seq = fractalize(GOSPER_GEN, 4)
    
    d = 'M0 0'
    for el in seq
        d += TRI_LINES[el.toLowerCase()]
        
    width = 960
    height = 500
    
    svg = d3.select('body').append('svg')
        .attr('width', width)
        .attr('height', height)
        
    svg.append('path')
        .attr('class', 'gosper')
        .attr('d', d)
        .attr('transform', 'translate(500,390)')
        

index.css

.gosper {
  fill: none;
  stroke: black;
  stroke-width: 1.5px;
}

index.sass

.gosper
    fill: none
    stroke: black
    stroke-width: 1.5px