//--------------------------------------------------------------------------------// // COPYRIGHT NOTICE // //--------------------------------------------------------------------------------// // Copyright (c) 2012, Instituto de Microelectronica de Sevilla (IMSE-CNM) // // // // All rights reserved. // // // // Redistribution and use in source and binary forms, with or without // // modification, are permitted provided that the following conditions are met: // // // // * Redistributions of source code must retain the above copyright notice, // // this list of conditions and the following disclaimer. // // // // * Redistributions in binary form must reproduce the above copyright // // notice, this list of conditions and the following disclaimer in the // // documentation and/or other materials provided with the distribution. // // // // * Neither the name of the IMSE-CNM nor the names of its contributors may // // be used to endorse or promote products derived from this software // // without specific prior written permission. // // // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE // // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //--------------------------------------------------------------------------------// package xfuzzy.xfplot; import xfuzzy.lang.*; import java.io.*; import javax.swing.*; import java.awt.*; import java.awt.image.*; import com.sun.image.codec.jpeg.*; /** * Clase que desarrolla el panel de representaci�n gr�fica en 3 * dimensiones * * @author Francisco Jos� Moreno Velo * */ public class Xfplot3DPanel extends JPanel { //----------------------------------------------------------------------------// // CONSTANTES PRIVADAS // //----------------------------------------------------------------------------// /** * C�digo asociado a la clase serializable */ private static final long serialVersionUID = 95505666603054L; /** * Altura del panel */ private static final int HEIGHT = 500; /** * Anchura del panel */ private static final int WIDTH = 700; //----------------------------------------------------------------------------// // MIEMBROS PRIVADOS // //----------------------------------------------------------------------------// /** * Referencia a la p�gina principal de la aplicaci�n */ private Xfplot xfplot; /** * Anchura del panel */ private int width; /** * Altura del panel */ private int height; /** * Coseno del �ngulo de rotaci�n horizontal */ private double cosalpha; /** * Seno del �ngulo de rotaci�n horizontal */ private double sinalpha; /** * Coseno del �ngulo de rotaci�n vertical */ private double cosbeta; /** * Seno del �ngulo de rotaci�n vertical */ private double sinbeta; /** * �ngulo de rotaci�n horizontal */ private double alpha; /** * Fuente de letra */ private FontMetrics fm; //----------------------------------------------------------------------------// // CONSTRUCTOR // //----------------------------------------------------------------------------// /** * Constructor */ public Xfplot3DPanel(Xfplot xfplot) { super(); this.xfplot = xfplot; setSize(new Dimension(WIDTH,HEIGHT)); setPreferredSize(new Dimension(WIDTH,HEIGHT)); setBackground(Color.white); setHRotation(0); setVRotation(0.3); setBorder(BorderFactory.createLoweredBevelBorder()); this.fm = getFontMetrics(getFont()); } //----------------------------------------------------------------------------// // M�TODOS P�BLICOS // //----------------------------------------------------------------------------// /** * Selecciona el �ngulo de rotaci�n horizontal */ public void setHRotation(double alpha) { this.alpha = alpha; this.cosalpha = Math.cos(Math.PI * alpha + Math.PI / 4); this.sinalpha = Math.sin(Math.PI * alpha + Math.PI / 4); } /** * Selecciona el �ngulo de rotaci�n vertical */ public void setVRotation(double beta) { cosbeta = Math.cos(Math.PI * beta / 2); sinbeta = Math.sin(Math.PI * beta / 2); } /** * Dibuja el panel con la representaci�n gr�fica. * Este m�todo sobreescribe al m�todo paint() de JPanel. */ public void paint(Graphics g) { super.paint(g); this.width = getSize().width; this.height = getSize().height; paintBasis(g); if(alpha<0) paintZAxis(g); if(xfplot.is3DComputed()) paintFunction(g); if(alpha>=0) paintZAxis(g); } /** * Almacena la representaci�n gr�fica en un fichero externo */ public boolean saveImage(File file) { try { BufferedImage bi = (BufferedImage) createImage(width,height); Graphics g = getGraphics().create(); g.drawImage(bi,0,0,this); repaint(); FileOutputStream out = new FileOutputStream(file); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); param.setQuality(1.0f,false); encoder.setJPEGEncodeParam(param); encoder.encode(bi); out.close(); repaint(); return true; } catch (Exception ex) { return false; } } //----------------------------------------------------------------------------// // M�TODOS PRIVADOS // //----------------------------------------------------------------------------// /** * Calcula la posici�n X en el plano de un punto del espacio */ private int getXPosition(double x, double y, double z) { double xpos = (x-0.5)*sinalpha + (y-0.5)*cosalpha;; xpos = xpos*0.424*width + width/2; return (int) Math.round(xpos); } /** * Calcula la posici�n Y en el plano de un punto del espacio */ private int getYPosition(double x, double y, double z) { double ypos = (x-0.5)*cosalpha*sinbeta - (y-0.5)*sinalpha*sinbeta; ypos = ypos*0.424*width; ypos = (z-0.4)*cosbeta*0.3*height - ypos; ypos = height/2 - ypos; return (int) Math.round(ypos); } /** * Dibuja los ejes de la representaci�n gr�fica */ private void paintBasis(Graphics g) { Variable xvar = xfplot.getXVariable(); Variable yvar = xfplot.getYVariable(); String xmin = ""+xvar.point(0.0); String xmax = ""+xvar.point(1.0); String ymin = ""+yvar.point(0.0); String ymax = ""+yvar.point(1.0); int xvarwidth = fm.stringWidth(xvar.toString()); int xminwidth = fm.stringWidth(xmin); int xmaxwidth = fm.stringWidth(xmax); int yvarwidth = fm.stringWidth(yvar.toString()); int yminwidth = fm.stringWidth(ymin); int ymaxwidth = fm.stringWidth(ymax); int ascent = fm.getAscent(); int p0x = getXPosition(0,0,-0.2); int p0y = getYPosition(0,0,-0.2); int p1x = getXPosition(1,0,-0.2); int p1y = getYPosition(1,0,-0.2); int p2x = getXPosition(1,1,-0.2); int p2y = getYPosition(1,1,-0.2); int p3x = getXPosition(0,1,-0.2); int p3y = getYPosition(0,1,-0.2); g.drawLine(p0x, p0y, p1x, p1y); g.drawLine(p1x, p1y, p2x, p2y); g.drawLine(p2x, p2y, p3x, p3y); g.drawLine(p3x, p3y, p0x, p0y); int p4x = getXPosition(0,0,1); int p4y = getYPosition(0,0,1); int p5x = getXPosition(1,0,0); int p5y = getYPosition(1,0,0); int p6x = getXPosition(1,1,0); int p6y = getYPosition(1,1,0); int p7x = getXPosition(0,1,0); int p7y = getYPosition(0,1,0); g.drawLine(p0x, p0y, p4x, p4y); g.drawLine(p1x, p1y, p5x, p5y); g.drawLine(p2x, p2y, p6x, p6y); g.drawLine(p3x, p3y, p7x, p7y); double yy = (p0x < p1x ? -0.15 : 1.15); double yl = (p0x < p1x ? -0.3 : 1.3); int px0x = getXPosition(0, yy,-0.2); int px0y = getYPosition(0, yy,-0.2); int pxhx = getXPosition(0.5, yl,-0.2); int pxhy = getYPosition(0.5, yl,-0.2); int px1x = getXPosition(1, yy,-0.2); int px1y = getYPosition(1, yy,-0.2); g.drawString(""+xvar, pxhx-xvarwidth/2, pxhy+ascent/2); g.drawString(xmin, px0x-xminwidth/2, px0y+ascent/2); g.drawString(xmax, px1x-xmaxwidth/2, px1y+ascent/2); for(int i=0; i<=5; i++) { int pxl0x = getXPosition(i*0.2,0,-0.2); int pxl0y = getYPosition(i*0.2,0,-0.2); int pxl1x = getXPosition(i*0.2,1,-0.2); int pxl1y = getYPosition(i*0.2,1,-0.2); g.drawLine(pxl0x, pxl0y, pxl1x, pxl1y); } double xx = (p1x > p2x ? -0.15 : 1.15); double xl = (p1x > p2x ? -0.3 : 1.3); int py0x = getXPosition(xx,0,-0.2); int py0y = getYPosition(xx,0,-0.2); int pyhx = getXPosition(xl,0.5,-0.2); int pyhy = getYPosition(xl,0.5,-0.2); int py1x = getXPosition(xx,1,-0.2); int py1y = getYPosition(xx,1,-0.2); g.drawString(""+yvar, pyhx-yvarwidth/2, pyhy+ascent/2); g.drawString(ymin, py0x-yminwidth/2, py0y+ascent/2); g.drawString(ymax, py1x-ymaxwidth/2, py1y+ascent/2); for(int i=0; i<=5; i++) { int pyl0x = getXPosition(0,i*0.2,-0.2); int pyl0y = getYPosition(0,i*0.2,-0.2); int pyl1x = getXPosition(1,i*0.2,-0.2); int pyl1y = getYPosition(1,i*0.2,-0.2); g.drawLine(pyl0x, pyl0y, pyl1x, pyl1y); } } /** * Dibuja el eje Z de la representaci�n gr�fica */ private void paintZAxis(Graphics g) { Variable zvar = xfplot.getZVariable(); String zmin = ""+zvar.point(0.0); String zmax = ""+zvar.point(1.0); int zvarwidth = fm.stringWidth(zvar.toString()); int zminwidth = fm.stringWidth(zmin); int zmaxwidth = fm.stringWidth(zmax); int ascent = fm.getAscent(); int zbx = getXPosition(0,0,-0.2); int zby = getYPosition(0,0,-0.2); int z0x = getXPosition(0,0,0); int z0y = getYPosition(0,0,0); int z1x = getXPosition(0,0,1); int z1y = getYPosition(0,0,1); int zhx = getXPosition(0,0,0.5); int zhy = getYPosition(0,0,0.5); int zzx = getXPosition(1,1,0); g.drawLine(zbx, zby, z1x, z1y); int l = (z0x <= zzx? -3 : 3); for(int i=0; i<=5; i++) { int zx = getXPosition(0,0,i*0.2); int zy = getYPosition(0,0,i*0.2); g.drawLine(zx, zy, zx+l, zy); } if(z0x <= zzx) { g.drawString(zvar.toString(), zhx-20-zvarwidth, zhy+ascent/2); g.drawString(zmin, z0x-15-zminwidth, z0y+ascent/2); g.drawString(zmax, z1x-15-zmaxwidth, z1y+ascent/2); } else { g.drawString(zvar.toString(), zhx+20, zhy+ascent/2); g.drawString(zmin, z0x+15, z0y+ascent/2); g.drawString(zmax, z1x+15, z1y+ascent/2); } } /** * Dibuja la superficie que representa la funci�n */ private void paintFunction(Graphics g) { double[][] function = xfplot.getFunction(); boolean xincrease, yincrease; int p0x = getXPosition(0,0,-0.2); int p1x = getXPosition(1,0,-0.2); int p2x = getXPosition(1,1,-0.2); if(p0x < p1x) yincrease = false; else yincrease = true; if(p1x < p2x) xincrease = false; else xincrease = true; Color gridcolor = xfplot.getGridColor(); int x[] = new int[4]; int y[] = new int[4]; Color old = g.getColor(); for(int j=0; j<function.length-1 ; j++) for(int i=0; i<function.length-1; i++) { int ii, jj; if(xincrease) ii = i; else ii = function.length-i-2; if(yincrease) jj = j; else jj = function.length-j-2; double y0 = jj*1.0/(function[0].length-1); double y1 = (jj+1)*1.0/(function[0].length-1); double x0 = ii*1.0/(function.length-1); double x1 = (ii+1)*1.0/(function.length-1); int f0x = getXPosition(x0,y0,function[ii][jj]); int f0y = getYPosition(x0,y0,function[ii][jj]); int f1x = getXPosition(x1,y0,function[ii+1][jj]); int f1y = getYPosition(x1,y0,function[ii+1][jj]); int f2x = getXPosition(x1,y1,function[ii+1][jj+1]); int f2y = getYPosition(x1,y1,function[ii+1][jj+1]); int f3x = getXPosition(x0,y1,function[ii][jj+1]); int f3y = getYPosition(x0,y1,function[ii][jj+1]); x[0]=f0x; x[1]=f1x; x[2]=f2x; x[3]=f3x; y[0]=f0y; y[1]=f1y; y[2]=f2y; y[3]=f3y; double zm = (function[ii][jj]+function[ii+1][jj]+function[ii][jj+1]+function[ii+1][jj+1])/4.0; g.setColor(xfplot.getColor(zm)); g.fillPolygon(x,y,4); if(gridcolor != null) { g.setColor(gridcolor); g.drawPolygon(x,y,4); } } g.setColor(old); } }