Plot 3D (Framework Java)
Esta versão do framework está DESATUALIZADA. Existe uma versão mais recente do plot3d que recebeu o nome de iplot por suportar também a plotagem de dados e funções, tanto em 3D quanto em 2D. A nova versão (chamada de iplot) trouxe muitas melhorias em comparação com esta versão do framework. Visite a página do projeto iplot:
Link do iplot: clique aqui.
Olá! Desta vez escrevo para apresentar uma biblioteca gráfica que construi para que programadores possam plotar funções em 3D no plano cartesiano com a escrita de pouco código. Dei a biblioteca gráfica o nome de "Plot 3D" por ser possível com ela a plotagem de funções em 3D.
Exemplos
O plot3d também permite o desenho de formas geométricas em 3D. Abaixo, um exemplo de aplicação da gaussiana para geração de uma forma geométrica e o desenho de um cubo em 3D. Preste atenção a cor das faces das formas geométricas. As cores são calculadas conforme a incidência de luz que varia de acordo com o ângulo entre um vetor que representa o raio de luz emitido por uma fonte de luz que atinge a face e um vetor normal que é perpendicular a o plano ao qual pertence a face da figura geométrica.
Instalação
Para integrar o Plot 3D em sua aplicação Java, basta inserir no CLASSPATH o jar da biblioteca gráfica disponível abaixo:
Download: plot3d.jar
Exemplos e aplicações
Atenção:
Se você baixou antes o plot3d.jar, por favor baixe novamente para que
funcionem corretamente os exemplos dessa página com a versão mais recente do plot3d, e seja possível rodar a versão
mais recente do programa de demonstração.
Vamos a um pequeno exemplo de demonstração de uso, o exemplo 1. Veja o código abaixo:
import javax.swing.JComponent;
import javax.swing.JFrame;
import plot3d.planocartesiano.PlanoCartesianoPlot3D;
import plot3d.planocartesiano.PlanoCartesianoPlot3DDriver;
public class Ex1 {
public static void main( String[] args ) {
PlanoCartesianoPlot3D plot3D = new PlanoCartesianoPlot3D();
PlanoCartesianoPlot3DDriver drv = (plano) -> {
plano.setAltura2D( 1.7 );
plano.setIntervalos( -Math.PI, Math.PI, -Math.PI, Math.PI );
plano.setFunc3D( (x,z) -> {
return Math.pow( x, 3 ) + 3*Math.pow( z, 2 );
} );
};
JComponent c = plot3D.getDesenhoComponent();
JFrame janela = new JFrame();
janela.setTitle( "Desenho da função y=x³+3z² em 3D" );
janela.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
janela.setContentPane( c );
janela.setSize( 640, 480 );
janela.setLocationRelativeTo( janela );
janela.setVisible( true );
plot3D.constroi( drv, true );
}
}
Veja abaixo a imágem capturada da plotagem da função:
Para o exemplo acima funcionar foi preciso instanciar a classe PlanoCartesianoPlot3D e implementar a interface PlanoCartesianoPlot3DDriver que permite a configuração do plano cartesiano e a função a ser plotada.
Voltando ao exemplo, perceba que há um método da classe PlanoCartesianoPlot3D com nome controi que recebe alguns parâmetros. No exemplo 1, foram passados dois parâmetros, a implementação da interface PlanoCartesianoPlot3DDriver onde é definida a configuração do plano cartesiano e um segundo parâmetro booleano que, se tiver valor true, será possível rotacionar e escalar o plano cartesiano para visualizá-lo em vários ângulos. Se o segundo parâmetro tiver valor false, o plano cartesiano com a função são apenas desenhados na tela. Se você for um programador Java, experimente alterar as expressões da função setada no método setFunc3D!
Vale ressaltar que, é importante prestar atenção ao domínio da função a ser plotada. Por exemplo, o domínio da função 1/sen(x+z) não abrange pontos em que x+z é igual a algum múltiplo de PI incluindo o zero e os multiplos negativos, dado que, por exemplo, se x+z é zero, sen(0) é zero e uma divisão por zero acontece. Também é importante frizar que os intervalos são configurados em x e z e o resultado da função que envolve os parâmatros de x e z é calculado para o eixo y. Por exemplo y=sen(x+z), e não z=sen(x+y). Os intervalos dos eixos x e z podem ser configurados com a chamada do método setIntervalos da classe PlanoCartesianoObjeto3D.
Também é necessário informar que há uma limitação em relação as dimensões (largura e altura) do plano cartesiano. Isto é, para o desenho do plano cartesiano funcionar corretamente no exemplo 1, foi necessário chamar o método constroi após a chamada do método setVisible da classe JFrame. Para isso não ser necessário, teria de o tamanho das dimensões da tela onde o plano cartesiano será pintado ser definido manualmente e, assim, funcionar com a chamada do método constroi antes do método setVisible. Por exemplo, veja o exemplo abaixo:
import java.awt.Dimension;
import javax.swing.JComponent;
import javax.swing.JFrame;
import plot3d.g2d.DesenhoPNL;
import plot3d.g2d.PainelTela;
import plot3d.planocartesiano.PlanoCartesianoPlot3D;
import plot3d.planocartesiano.PlanoCartesianoPlot3DDriver;
import plot3d.planocartesiano.g3d.PlanoCartesianoObjeto3D;
public class Ex2 extends JFrame implements PlanoCartesianoPlot3DDriver, PainelTela {
private PlanoCartesianoPlot3D plot3D = new PlanoCartesianoPlot3D();
private int painelLargura = 640;
private int painelAltura = 480;
public Ex2() {
JComponent desenhoComp = plot3D.getDesenhoComponent();
desenhoComp.setPreferredSize( new Dimension( painelLargura, painelAltura ) );
super.setTitle( "Desenho da função x³+3z² em 3D" );
super.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
super.setContentPane( desenhoComp );
super.pack();
super.setLocationRelativeTo( this );
plot3D.setPainelTela( this );
plot3D.constroi( this, true );
}
@Override
public void configura(PlanoCartesianoObjeto3D pc) {
pc.setAltura2D( 1.7 );
pc.setIntervalos( -Math.PI, Math.PI, -Math.PI, Math.PI );
pc.setFunc3D( (x,z) -> {
return Math.pow( x, 3 ) + 3*Math.pow( z, 2 );
} );
}
@Override
public int getTelaX(DesenhoPNL pnl) {
return 0;
}
@Override
public int getTelaY(DesenhoPNL pnl) {
return 0;
}
@Override
public int getTelaLargura(DesenhoPNL pnl) {
return painelLargura;
}
@Override
public int getTelaAltura(DesenhoPNL pnl) {
return painelAltura;
}
public static void main( String[] args ) {
Ex2 ex = new Ex2();
ex.setVisible( true );
}
}
O exemplo acima faz o mesmo que o exemplo 1. No entanto, é estruturado de modo bem diferente. Perceba que o método constroi é chamado no construtor da classe e o método setVisible é chamado depois de instanciada a classe. Para funcionar assim, foi necessário implementar a interface PainelTela que tem dois métodos para que se possa definir manualmente a largura e altura do painel onde o plano cartesiano será pintado. Perceba que, no exemplo acima, os valores de largura e altura são, respectivamente, 640 e 480.
Agora vamos ao exemplo 3 que permite o desenho do gráfico em um objeto de imagem (classe BufferedImage) que permite até que se possa exportar a imagem do gráfico para algum formado de imagem como, por exemplo, gif ou jpg. No exemplo 3, perceba que a imagem é exportada como jpg.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import plot3d.planocartesiano.PlanoCartesianoPlot3D;
import plot3d.planocartesiano.PlanoCartesianoPlot3DDriver;
public class Ex3 {
public static void main(String[] args) {
PlanoCartesianoPlot3DDriver drv = (pc) -> {
pc.setAltura2D( 1.7 );
pc.setXIntervalo( -Math.PI, Math.PI );
pc.setZIntervalo( -Math.PI, Math.PI );
pc.setFunc3D( (x,z) -> {
double d = Math.sqrt( x*x + z*z );
return Math.sin( d );
} );
};
PlanoCartesianoPlot3D aplic = new PlanoCartesianoPlot3D();
BufferedImage imagem = new BufferedImage( 640, 480, BufferedImage.TYPE_INT_RGB );
aplic.constroi( imagem.getGraphics(), drv, true, imagem.getWidth(), imagem.getHeight() );
String arquivo = JOptionPane.showInputDialog( "Informe o nome do arquivo a ser salvo: " );
if ( arquivo != null ) {
File f = new File( arquivo+".jpg" );
try {
ImageIO.write( imagem, "jpg", f );
JOptionPane.showMessageDialog( null, "Arquivo salvo para: "+f.getPath() );
} catch (IOException ex) {
JOptionPane.showMessageDialog( null, "Não foi possível salvar a imagem para: "+arquivo );
}
}
}
}
Os três exemplos mostrados aqui ilustram algumas das funcionalidades e aplicações da biblioteca gráfica Plot 3D. Para uma demonstração mais complexa, veja o exemplo abaixo que permite vários planos cartesianos em um único painel e mostra a função gaussiana que pode ser aplicada como função de visinhança em um algorítmo de redes neurais artificiais, o SOM ou Mapas auto-organizaveis. No exemplo de demonstração abaixo é possível configurar os intervalos x e z, o numero de divisões da malha da grade onde a função é aplicada e os parâmetros da função gaussiana (raio e altura). Para executar o exemplo de demonstração basta dar dois cliques no arquivo da biblioteca gráfica de nome plot3d.jar. Claro, vale lembrar que, para o exemplo funcionar, é necessário que o aplicativo seja executado em um computador com a maquina virtual Java instalada.
Link: plot3d.jarEm breve pretendo escrever uma documentação mais detalhada sobre o Plot 3D, principalmente se houverem pessoas interessadas em utilizar a biblioteca gráfica!