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
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
# 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)') | |
.gosper { | |
fill: none; | |
stroke: black; | |
stroke-width: 1.5px; | |
} |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Gosper curve</title> | |
<link type="text/css" href="index.css" rel="stylesheet"/> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="index.js"></script> | |
</head> | |
<body onload="main()"></body> | |
</html> |
(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); |
.gosper | |
fill: none | |
stroke: black | |
stroke-width: 1.5px | |