Mais uma postagem sobre efeitos visuais com JavaFX e hoje vamos falar sobre a aplicação da Superformula, derivada da fórmula Superellipse para gerar supershapes! Pode parecer confuso, mas vamos aplicar uma fórmula no JavaFX e gerar formas geométricas bacanas somente trocando os parâmetros da fórmula!
Claro a inspiração novamente veio do Shiffman! Veja abaixo o vídeo dele:
O código principal foi tirado do artigo do Paulo Bourke aplicando o algoritmo em um ângulo 0 até 2*PI temos diversas formas geradas.
O código é bem simples! Novamente usamos aquela classe utilitária para desenhar em JavaFX e a cada ciclo nós vamos aplicar a fórmula com novos parâmetros e então transformamos os resultados em pontos X e Y e desenhamos na tela pontinhos. O número de pontos define a resolução e para gerar todos os pontos fazemos um loop e pegamos um ângulo baseado no ponto atual do loop, aplicamos a fórmula e pegamos os pontos.
Em outras palavras, se quisermos 10 pontos, aplicamos a fórmula usando (0 * 10 / PI *2), (1 * 10 / PI *2), , (2 * 10 / PI *2), (1 * 10 / PI *2) e assim vai...
Mas o ponto principal são as constantes. Ao executar a fórmula, podemos mudar algumas constantes e como resultado temos formas geométricas completamente diferentes! As constantes são m, n1, n2 e n3!
A nossa aplicação muda os valores das "constantes" e aplica a fórmula a cada frame executado. O resultado é o seguinte:
Os tipos de azul utilizados foram escolhidos pela minha amada Luana e o código da aplicação ficou bem compacto, pode ver abaixo:
Projeto completo no github
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.fxapps.drawingfx.DrawingApp; | |
import static java.lang.Math.*; | |
import javafx.scene.paint.Color; | |
import javafx.scene.text.Font; | |
public class SuperShapesApp extends DrawingApp { | |
int numberOfPoints = 1300; | |
private double maxPhi = Math.PI * 2; | |
private double m = 1, n1 = 0.3, n2 = 0.3, n3 = 0.3; | |
public static void main(String[] args) { | |
launch(); | |
} | |
public void setup() { | |
title = "Super Shapes"; | |
width = 800; | |
height = 600; | |
frames = 1; | |
ctx.setFont(Font.font(30)); | |
ctx.setStroke(Color.NAVY); | |
} | |
public void draw() { | |
ctx.setFill(Color.LIGHTBLUE); | |
ctx.fillRect(0, 0, width, height); | |
double[][] points = new double[numberOfPoints][2]; | |
for (int i = 0; i < numberOfPoints; i++) { | |
double phi = toDegrees(i * (maxPhi) / numberOfPoints); | |
double r = superShape(m, n1, n2, n3, phi); | |
double x = 250 * r * cos(phi) + width / 2; | |
double y = 250 * r * sin(phi) + height / 2; | |
points[i][0] = x; | |
points[i][1] = y; | |
} | |
for (int i = 0; i < numberOfPoints; i++) { | |
ctx.strokeOval(points[i][0], points[i][1], 2, 2); | |
} | |
ctx.setFill(Color.WHITE); | |
String str = String.format("M=%.1f, N1=%.1f, N2=%.1f, N3=%.1f, PHI= %s", | |
m, n1, n2, n3, maxPhi == PI * 2 ? "2PI" : "12PI"); | |
ctx.fillText(str, 50, height - 20); | |
m += 0.20; | |
if (m > 10) { | |
if (n1 == 1) { | |
n1 = n2 = n3 = 0.3; | |
} else if (maxPhi == (PI * 2)) { | |
maxPhi = PI * 12; | |
} else { | |
n1 = n2 = n3 = 1; | |
maxPhi = PI * 2; | |
} | |
m = 1; | |
} | |
} | |
private double superShape(double m, double n1, double n2, double n3, double phi) { | |
double r, t1, t2, a = 1, b = 1; | |
t1 = cos(m * phi / 4) / a; | |
t1 = abs(t1); | |
t1 = pow(t1, n2); | |
t2 = sin(m * phi / 4) / b; | |
t2 = abs(t2); | |
t2 = pow(t2, n3); | |
r = pow(t1 + t2, 1 / n1); | |
return abs(r) == 0 ? 0 : 1 / r; | |
} | |
} |
Nenhum comentário:
Postar um comentário