Olá pessoal, tudo certo?
Depois de um “passeio nas estrelas”, volto a tratar de fractais com HTML5.
Na parte 2, mostrei uma implementação simples para snowflakes. Na parte 1, mostrei como desenhar trees. Hoje, mostro como desenhar Hilbert curves.
Live demo: http://users.cjb.net/livedemoelemarjr/hilbert.htm
Código-fonte completo: https://gist.github.com/1306034
Um pouco mais sobre Hilbert “Space-filling” curve
Space-filling fractals, como snowflakes, são desenhados recursivamente. Na medida em que o nível de recursão aumenta, a curva tornasse mais complexa.
Você pode ver a lógica abaixo:

Para criar uma curva Hilbert em um determinado nível, desenhamos a curva correspondente ao nível anterior e conectamos com segmentos de reta.
A função principal – onde tudo acontece
Para variar, temos um novo exemplo de recursão. Observe:
function hibert(depth, dx, dy) {
with (context) {
if (depth > 0) hibert(depth - 1, dy, dx);
walk(dx, dy);
if (depth > 0) hibert(depth - 1, dx, dy);
walk(dy, dx);
if (depth > 0) hibert(depth - 1, dx, dy);
walk(-dx, -dy);
if (depth > 0) hibert(depth - 1, -dy, -dx);
}
}
Como as “curvas menores” são curvas rotacionadas, nossa rotina precisa desenhar curvas em diferentes orientações. A forma mais fácil de fazer isso é passando para a rotina dois parâmetros, dx e dy, que indica a direção em que a primeira linha da curva deverá ser desenhada. Então, se a curva estiver em seu “depth 0”, deverá começar a desenhar a linha a partir da posição atual (função walk).
Se a curva não estiver em “depth 0”, então a rotina deverá se “chamar” recursivamente ajustando a orientação. Perceba que, como estamos usando angulos retos, basta fazer uma inversão nos parâmetros de direção.
Abaixo, apresento a função walk.
function drawLine(x1, y1, x2, y2) {
with (context) {
beginPath();
moveTo(getCenterX() + x1, canvasHeight - (getCenterY() + y1));
lineTo(getCenterX() + x2, canvasHeight - (getCenterY() + y2));
closePath();
stroke();
}
}
currentX = 0;
currentY = 0;
function walk(dx, dy) {
drawLine(currentX, currentY, currentX + dx, currentY + dy);
currentX += dx;
currentY += dy;
}
Como pode perceber, drawLine desloca o “ponto zero” para a posição indicada pelo usuário na toolbar. O método walk “lembra” o final da linha anterior e utiliza os argumentos como “offset”.
O método update – onde tudo começa
Agora que já temos a implementação do método de desenho e “auxiliares” para desenhar no canvas, vejamos como tudo começa. Observe:
function getSize() {
return getLength() * (Math.pow(2, getDepth() + 1) - 1);
}
function update() {
with (context) {
currentX = -getSize() / 2;
currentY = -getSize() / 2;
clearRect(0, 0, canvasWidth, canvasHeight);
hibert(getDepth(), getLength(), 0);
}
drawZero();
}
Como pode perceber, desloco o ponto inicial para a base da curva. Para isso, calculo sua a “dimensão final”.
Era isso.
![]()

outubro 22nd, 2011 → 16:32
[...] código que utilizo aqui é derivado daquele que mostrei no post anterior. Por isso, nesse post, explico apenas o código [...]