Olá pessoal. Tudo certo?!
Nesse post, mostro como desenhar curvas, usando Lagrange Interpolation, usando Javascript.
Há um live demo disponível. Também está disponível o código-fonte completo.
UPDATE: Também há um live demo mais interativo, que permite ao usuário definir os pontos que pertencem a curva em http://users.cjb.net/livedemoelemarjr/lagrange2.html. Observe:
Mais adiante, vou usar esse método para “suavizar” rotas nas animações que estou desenvolvendo na série sobre XNA.
Definindo os pontos da curva
Para esse exemplo simples, optei por selecionar poucos pontos. Observe:
var initializePoints = function () { var offsetX = canvasWidth / 5; points = []; points.push({ x: offsetX, y: canvasHeight / 2 }); points.push({ x: offsetX * 2, y: canvasHeight / 2 - canvasHeight / 4 }); points.push({ x: offsetX * 3, y: canvasHeight / 2 + canvasHeight / 4 }); points.push({ x: offsetX * 4, y: canvasHeight / 2 }); };
Optei por pegar pontos observando alguma proporcionalidade com o tamanho da janela.
Implementando Lagrange
As equações matemáticas apresentadas para interpolação usando Lagrange, são implementáveis, em Javascript, assim:
var lagrange = function (n, k, t) { var l = 1.0, ti, tk; tk = k / (n - 1.0); for (var i = 0; i < n; i++) { if (i != k) { ti = i / (n - 1.0); l *= ((t - ti) / (tk - ti)); } } return l; }; var evaluate = function (t) { var result = { x: 0, y: 0 }; for (var i = 0; i < points.length; i++) { var l = lagrange(points.length, i, t); result.x += l * points[i].x; result.y += l * points[i].y; } return result; };
Perceba como o produtório e somatório são calculados dentro do loop.
Desenhando…
Já temos os pontos de referência e a implementação da “lagrange interpolation”. Agora, vamos ver como fazer o desenho da curva. Veja:
var draw = function () { context.moveTo(points[0].x, points[0].y); var t = 0.0; for (var t = 0; t <= 1; t += 0.001) { var next = evaluate(t); context.lineTo(next.x, next.y); } context.stroke(); for (var i = 0; i < points.length; i++) { context.beginPath(); context.rect( points[i].x - 3, points[i].y - 3, 6, 6 ); context.fillStyle = "#f00"; context.fill(); context.closePath(); } }
Há dois loops. No primeiro, desenho a curva propriamente dita. No segundo, desenho os pontos de referência.
Era isso.
acazsouza
21/12/2011
Elemar, me explica uma coisa por favor, como você escreve esses posts tão diversificados com várias linguagens e conceitos? Você já conhece e já trabalhou com a tecnologia? Ou você não conhece e estuda um pouco e elabora o post? Se estuda pra fazer o post, por onde estuda, por livros?
elemarjr
21/12/2011
Olá Acaz,
Antes de qualquer coisa, permita-me agradecer pela consideração quanto a diversidade de temas que trato aqui no blog.
Não há uma forma simples de responder a sua pergunta. Todos os assuntos que discuto aqui influenciam, de forma mais ou menos direta, o meu trabalho. Entretanto, nem todas as tecnologias que uso aqui, uso no trabalho (o inverso também é verdadeiro). Por exemplo, no trabalho, uso principalmente OpenGL. Aqui, escrevo muita coisa com XNA. Faço isso, principalmente, para não invadir áreas de conhecimento que a empresa (e/ou eu) considere estratégica.
Adoro tecnologia. Por isso, estou sempre buscando aprender novos conceitos e técnicas. Assim, naturalmente, há assuntos que tenho domínio maior (xna, por exemplo) e outros onde ainda estou começando (como Boo). Desta forma, a quantidade de preparo que preciso antes de escrever cada post varia de assunto para assunto.
Um aspecto importante, que procuro seguir sempre, é conseguir combinar conhecimentos. Ou seja, sempre tento aproveitar algo que já sei quando estou estudando algo novo. Por exemplo, gosto muito de fractais e ainda estou aprendendo a mexer com canvas. Então, por que não combinar as duas coisas? Acho que isso torna o aprendizado mais bacana, percebe?
Tenho interesses diversificados e acredito que explicar um conceito é a melhor forma de fixa-lo e entende-lo.
Era isso?