//--------------------------------------------------------------------------------// // 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.*; import xfuzzy.lang.*; import xfuzzy.util.*; import java.io.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.awt.event.*; /** * Representaci�n gr�fica del sistema difuso * * @author Francisco Jos� Moreno Velo * */ public class Xfplot extends JFrame implements ActionListener, ChangeListener, WindowListener { // ----------------------------------------------------------------------------// // CONSTANTES PRIVADAS // // ----------------------------------------------------------------------------// /** * C�digo asociado a la clase serializable */ private static final long serialVersionUID = 95505666603052L; /** * C�digo para indicar representaciones en 3D */ private static final int MODE_3D = 0; /** * C�digo para indicar representaciones en 2D */ private static final int MODE_2D = 1; // ----------------------------------------------------------------------------// // MIEMBROS PRIVADOS // // ----------------------------------------------------------------------------// /** * Referencia a la ventana principal del entorno */ private Xfuzzy xfuzzy; /** * Sistema difuso a representar */ private Specification spec; /** * Valores a representar en 3D */ private double function3D[][]; /** * Indicador de que los valores en 3D se han calculado */ private boolean computed3D; /** * Valores a representar en 2D */ private double function2D[]; /** * Modo de representaci�n (2D o 3D) */ private int plotmode; /** * Configuraci�n de la aplicaci�n */ private XfplotConfig config; /** * Objeto que almacena el modelo de colores */ private XfplotColorModel colormodel; /** * Objeto que desarrolla la representaci�n 3D */ private Xfplot3DPanel graph3D; /** * Objeto que desarrolla la representaci�n 2D */ private Xfplot2DPanel graph2D; /** * Desplazador horizontal */ private JSlider hslider; /** * Desplazador vertical */ private JSlider vslider; /** * Panel de la representaci�n 3D */ private JPanel panel3D; /** * Campo de texto para introducir el n�mero de puntos por eje */ private JTextField samplestext; /** * Selector de la variable X */ private JComboBox xcombo; /** * Selector de la variable Y */ private JComboBox ycombo; /** * Selector de la variable Z */ private JComboBox zcombo; // ----------------------------------------------------------------------------// // CONSTRUCTOR // // ----------------------------------------------------------------------------// /** * Constructor */ public Xfplot(Xfuzzy xfuzzy, Specification spec) { super("Xfplot"); this.xfuzzy = xfuzzy; this.spec = spec; this.computed3D = false; this.config = new XfplotConfig(spec); this.colormodel = new XfplotColorModel(0); int numinputs = spec.getSystemModule().getInputs().length; if (numinputs > 1) { this.plotmode = MODE_3D; try { config.setPlotMode(MODE_3D); } catch (Exception ex) { } } else { this.plotmode = MODE_2D; try { config.setPlotMode(MODE_2D); } catch (Exception ex) { } } build(); setConfig(); actualize(); } // ----------------------------------------------------------------------------// // EJECUCI�N EXTERNA // // ----------------------------------------------------------------------------// public static void main(String args[]) { if (args.length != 1) { System.out.println("Usage: xfplot xflfile"); return; } File file = new File(args[0]); if (!file.exists()) { System.out.println("Can't find file " + file.getAbsolutePath()); return; } XflParser parser = new XflParser(); Specification spec = parser.parse(file.getAbsolutePath()); if (spec == null) { System.out.println(parser.resume()); return; } Xfplot plot = new Xfplot(null, spec); plot.setVisible(true); } // ----------------------------------------------------------------------------// // M�TODOS P�BLICOS // // ----------------------------------------------------------------------------// /** * Devuelve la variable a representar en el eje X */ public Variable getXVariable() { Variable inputvar[] = spec.getSystemModule().getInputs(); return inputvar[config.getXIndex()]; } /** * Devuelve la variable a representar en el eje Y */ public Variable getYVariable() { Variable inputvar[] = spec.getSystemModule().getInputs(); return inputvar[config.getYIndex()]; } /** * Devuelve la variable a representar en el eje Z */ public Variable getZVariable() { Variable outputvar[] = spec.getSystemModule().getOutputs(); return outputvar[config.getZIndex()]; } /** * Devuelve las variables de entrada */ public Variable[] getInputVariables() { return spec.getSystemModule().getInputs(); } /** * Devuelve el valor de las variables de entrada */ public double[] getInputValues() { return this.config.getInputValues(); } /** * Devuelve los valores para representar la funcion en 2D */ public double[] get2DFunction() { return this.function2D; } /** * Devuelve los valores para representar la funcion en 3D */ public double[][] getFunction() { return this.function3D; } /** * Verifica que los valores de la funcion se han calculado */ public boolean is3DComputed() { return computed3D; } /** * Devuelve el color del grid (nulo si no debe pintarse) */ public Color getGridColor() { return this.colormodel.getGridColor(); } /** * Devuelve el color asociado a un cierto valor */ public Color getColor(double value) { return this.colormodel.getColor(value); } /** * Asigna el valor de las variables de entrada */ public boolean setInputValues(double value[]) { try { this.config.setInputValues(value); return true; } catch (Exception ex) { return false; } } /** * Interfaz ActionListener */ public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals("Plot")) actualize(); else if (command.equals("Actualize")) actualize(); else if (command.equals("XAxis")) changeXAxis(); else if (command.equals("YAxis")) changeYAxis(); else if (command.equals("ZAxis")) changeZAxis(); else if (command.equals("Samples")) actualize(); else if (command.startsWith("CM")) changeColor(command); else if (command.equals("InputValues")) changeInputValues(); else if (command.equals("Close")) close(); else if (command.equals("SaveImage")) saveImage(); else if (command.equals("SaveData")) saveData(); else if (command.equals("SaveConfig")) saveConfig(); else if (command.equals("LoadConfig")) loadConfig(); else if (command.equals("2DPlot")) set2DPlotMode(); else if (command.equals("3DPlot")) set3DPlotMode(); } /** * Interfaz ChangeListener */ public void stateChanged(ChangeEvent e) { int hangle = hslider.getValue(); int vangle = vslider.getValue(); try { config.setSlides(hangle, vangle); } catch (Exception ex) { } graph3D.setHRotation(hangle / 50.0 - 1.0); graph3D.setVRotation(vangle / 100.0); graph3D.repaint(); } /** * Interfaz WindowListener. Acci�n al abrir la ventana */ public void windowOpened(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al cerrar la ventana */ public void windowClosing(WindowEvent e) { close(); } /** * Interfaz WindowListener. Acci�n al finalizar el cierre */ public void windowClosed(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al minimizar la ventana */ public void windowIconified(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al maximizar la ventana */ public void windowDeiconified(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al activar la ventana */ public void windowActivated(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al desactivar la ventana */ public void windowDeactivated(WindowEvent e) { } // ----------------------------------------------------------------------------// // M�TODOS PRIVADOS // // ----------------------------------------------------------------------------// /** * Crea la ventana */ private void build() { Container content = getContentPane(); content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); content.add(createPlotPanel()); setJMenuBar(createMenubar()); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setIconImage(XfuzzyIcons.xfuzzy.getImage()); addWindowListener(this); pack(); setLocation(); } /** * Crea la barra de men� */ private JMenuBar createMenubar() { Variable inputvar[] = spec.getSystemModule().getInputs(); Variable outputvar[] = spec.getSystemModule().getOutputs(); xcombo = createVariableList(inputvar, "XAxis"); ycombo = createVariableList(inputvar, "YAxis"); zcombo = createVariableList(outputvar, "ZAxis"); samplestext = new JTextField(""); samplestext.setBackground(XConstants.textbackground); samplestext.setBorder(BorderFactory.createLoweredBevelBorder()); samplestext.addActionListener(this); samplestext.setActionCommand("Samples"); Dimension prefsize = xcombo.getPreferredSize(); Dimension samplesize = new Dimension(50, prefsize.height); samplestext.setPreferredSize(samplesize); samplestext.setMinimumSize(samplesize); samplestext.setMaximumSize(samplesize); String fileitem[] = { "Save data", null, "Actualize", null, "Close" }; String filecomm[] = { "SaveData", "Actualize", "Close" }; XMenu file = new XMenu("File", fileitem, filecomm, this); String plotitem[] = { "2-dimensional Plot", "3-dimensional Plot" }; String plotcomm[] = { "2DPlot", "3DPlot" }; XMenu plotmenu = new XMenu("Plot Mode", plotitem, plotcomm, this); if (inputvar.length < 2) plotmenu.setEnabled(false, 1); JMenu colormenu = createColorMenu(); JMenuItem item1 = new JMenuItem("Input Values"); item1.setFont(XConstants.font); item1.setActionCommand("InputValues"); item1.addActionListener(this); JMenuItem item2 = new JMenuItem("Load Configuration"); item2.setFont(XConstants.font); item2.setActionCommand("LoadConfig"); item2.addActionListener(this); JMenuItem item3 = new JMenuItem("Save Configuration"); item3.setFont(XConstants.font); item3.setActionCommand("SaveConfig"); item3.addActionListener(this); JMenu conf = new JMenu("Configuration"); conf.add(plotmenu); conf.add(colormenu); conf.add(item1); conf.addSeparator(); conf.add(item2); conf.add(item3); JLabel xlabel = new JLabel("X Axis"); JLabel ylabel = new JLabel("Y Axis"); JLabel zlabel = new JLabel("Z Axis"); JLabel slabel = new JLabel("Samples"); xlabel.setForeground(Color.black); ylabel.setForeground(Color.black); zlabel.setForeground(Color.black); slabel.setForeground(Color.black); JMenuBar bar = new JMenuBar(); bar.add(file); bar.add(Box.createHorizontalStrut(20)); bar.add(conf); bar.add(Box.createHorizontalStrut(40)); bar.add(Box.createHorizontalGlue()); bar.add(xlabel); bar.add(Box.createHorizontalStrut(10)); bar.add(xcombo); bar.add(Box.createHorizontalStrut(20)); bar.add(ylabel); bar.add(Box.createHorizontalStrut(10)); bar.add(ycombo); bar.add(Box.createHorizontalStrut(20)); bar.add(zlabel); bar.add(Box.createHorizontalStrut(10)); bar.add(zcombo); bar.add(Box.createHorizontalStrut(20)); bar.add(slabel); bar.add(Box.createHorizontalStrut(10)); bar.add(samplestext); bar.add(Box.createHorizontalStrut(20)); return bar; } /** * Crea del men� de modelos de colores */ private JMenu createColorMenu() { JMenu menu = new JMenu("Color Model"); for (int i = 0; i < XfplotColorModel.COUNTER; i++) { JMenuItem item = new JMenuItem(new XfplotColorIcon(i)); item.setActionCommand("CM" + i); item.addActionListener(this); menu.add(item); } return menu; } /** * Crea una lista desplegable con las variables */ private JComboBox createVariableList(Variable[] var, String action) { JComboBox combo = new JComboBox(); combo.setBackground(XConstants.textbackground); for (int i = 0; i < var.length; i++) combo.addItem(var[i]); combo.addActionListener(this); combo.setActionCommand(action); Dimension prefsize = combo.getPreferredSize(); Dimension size = new Dimension(100, prefsize.height); combo.setPreferredSize(size); combo.setMinimumSize(size); combo.setMaximumSize(size); return combo; } /** * Crea el panel de la representaci�n gr�fica */ private JPanel createPlotPanel() { this.graph2D = new Xfplot2DPanel(this); this.graph3D = new Xfplot3DPanel(this); this.hslider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50); this.hslider.addChangeListener(this); this.vslider = new JSlider(JSlider.VERTICAL, 0, 100, 30); this.vslider.addChangeListener(this); this.vslider.setInverted(true); panel3D = new JPanel(); panel3D.setLayout(new BorderLayout()); panel3D.add(graph3D, BorderLayout.CENTER); panel3D.add(hslider, BorderLayout.SOUTH); panel3D.add(vslider, BorderLayout.EAST); if (plotmode == MODE_3D) return panel3D; return graph2D; } /** * Coloca la ventana en la pantalla */ private void setLocation() { Dimension frame = getSize(); Dimension screen = getToolkit().getScreenSize(); setLocation((screen.width - frame.width) / 2, (screen.height - frame.height) / 2); } /** * Actualiza los campos con los valores de la configuraci�n */ private void setConfig() { xcombo.setSelectedIndex(config.getXIndex()); if (plotmode == MODE_3D) { ycombo.setSelectedIndex(config.getYIndex()); } zcombo.setSelectedIndex(config.getZIndex()); samplestext.setText("" + config.getSamples()); colormodel.setModel(config.getColorMode()); graph3D.setHRotation(config.getHSlide() / 50.0 - 1.0); graph3D.setVRotation(config.getVSlide() / 100.0); } /** * Acci�n asociada a la selecci�n de la representaci�n 2D */ private void set2DPlotMode() { if (plotmode == MODE_2D) return; plotmode = MODE_2D; try { config.setPlotMode(MODE_2D); } catch (Exception ex) { } Container content = getContentPane(); content.remove(panel3D); content.add(graph2D); pack(); actualize(); } /** * Acci�n asociada a la selecci�n de la representaci�n 3D */ private void set3DPlotMode() { if (plotmode == MODE_3D) return; plotmode = MODE_3D; try { config.setPlotMode(MODE_3D); } catch (Exception ex) { } Container content = getContentPane(); content.remove(graph2D); content.add(panel3D); pack(); actualize(); } /** * Acci�n asociada a la lista desplegable del eje X */ private void changeXAxis() { int index = xcombo.getSelectedIndex(); int xindex = config.getXIndex(); int yindex = config.getYIndex(); if (index == xindex) return; config.setXIndex(index); if (yindex == index) { config.setYIndex(xindex); ycombo.setSelectedIndex(xindex); } actualize(); } /** * Acci�n asociada a la lista desplegable del eje Y */ private void changeYAxis() { int index = ycombo.getSelectedIndex(); int xindex = config.getXIndex(); int yindex = config.getYIndex(); if (index == yindex) return; config.setYIndex(index); if (xindex == index) { config.setXIndex(yindex); xcombo.setSelectedIndex(yindex); } actualize(); } /** * Acci�n asociada a la lista desplegable del eje Z */ private void changeZAxis() { config.setZIndex(zcombo.getSelectedIndex()); actualize(); } /** * Acci�n asociada al cambio de modelo de color */ private void changeColor(String action) { try { int code = Integer.parseInt(action.substring(2)); config.setColorMode(code); colormodel.setModel(code); actualize(); } catch (Exception ex) { } } /** * Acci�n asociada a la edici�n de valores de entrada */ private void changeInputValues() { XfplotInputDialog dialog = new XfplotInputDialog(this); dialog.setVisible(true); actualize(); } /** * Actualiza la representaci�n gr�fica */ private void actualize() { if (plotmode == MODE_3D) { try { config.setSamples(Integer.parseInt(samplestext.getText())); } catch (Exception ex) { samplestext.setText("" + config.getSamples()); } function3D = config.get3DFunction(); computed3D = true; graph3D.repaint(); } else if (plotmode == MODE_2D) { try { config.setSamples(Integer.parseInt(samplestext.getText())); } catch (Exception ex) { samplestext.setText("" + config.getSamples()); } function2D = config.get2DFunction(); graph2D.repaint(); } } /** * Almacena la imagen en un archivo de datos */ private void saveData() { File wdir; if (xfuzzy != null) wdir = xfuzzy.getWorkingDirectory(); else wdir = new File(System.getProperty("user.dir")); JFileChooser chooser = new JFileChooser(wdir); JFileChooserConfig.configure(chooser); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setDialogTitle("Save Data"); if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) return; File file = chooser.getSelectedFile(); if (file.exists()) { String question[] = new String[2]; question[0] = "File " + file.getName() + " already exists."; question[1] = "Do you want to overwrite this file?"; if (!XDialog.showQuestion(this, question)) return; } try { FileOutputStream fos = new FileOutputStream(file); PrintStream stream = new PrintStream(fos); Variable xvar = getXVariable(); Variable yvar = getYVariable(); stream.println(config.getHeading()); if (plotmode == MODE_3D) { int samples = function3D.length; for (int i = 0; i < samples; i++) { for (int j = 0; j < samples; j++) { stream.print("" + xvar.point(i * 1.0 / (samples - 1))); stream.print(" " + yvar.point(j * 1.0 / (samples - 1))); stream.println(" " + function3D[i][j]); } stream.println(""); } } else { int samples = function2D.length; for (int i = 0; i < samples; i++) { stream.print("" + xvar.point(i * 1.0 / (samples - 1))); stream.println(" " + function2D[i]); } } stream.close(); } catch (Exception ex) { } } /** * Intenta grabar la imagen como un archivo JPEG */ private void saveImage() { File wdir; if (xfuzzy != null) wdir = xfuzzy.getWorkingDirectory(); else wdir = new File(System.getProperty("user.dir")); JFileChooser chooser = new JFileChooser(wdir); JFileChooserConfig.configure(chooser); FileNameExtensionFilter filter = new FileNameExtensionFilter( "JPEG mage files (.jpg)", "jpg"); chooser.setFileFilter(filter); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setDialogTitle("Save Image"); if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) return; File file = chooser.getSelectedFile(); if (file.exists()) { String question[] = new String[2]; question[0] = "File " + file.getName() + " already exists."; question[1] = "Do you want to overwrite this file?"; if (!XDialog.showQuestion(this, question)) return; } graph3D.saveImage(file); } /** * Almacena la configuraci�n en un fichero externo */ private void saveConfig() { File wdir; if (xfuzzy != null) wdir = xfuzzy.getWorkingDirectory(); else wdir = new File(System.getProperty("user.dir")); JFileChooser chooser = new JFileChooser(wdir); JFileChooserConfig.configure(chooser); FileNameExtensionFilter filter = new FileNameExtensionFilter( "Xfuzzy configuration files (.cfg)", "cfg"); chooser.setFileFilter(filter); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setDialogTitle("Save Configuration"); if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) return; File file = chooser.getSelectedFile(); if (file.exists()) { String question[] = new String[2]; question[0] = "File " + file.getName() + " already exists."; question[1] = "Do you want to overwrite this file?"; if (!XDialog.showQuestion(this, question)) return; } config.save(file); } /** * Recupera la configuraci�n de un fichero externo */ private void loadConfig() { File wdir; if (xfuzzy != null) wdir = xfuzzy.getWorkingDirectory(); else wdir = new File(System.getProperty("user.dir")); JFileChooser chooser = new JFileChooser(wdir); JFileChooserConfig.configure(chooser); FileNameExtensionFilter filter = new FileNameExtensionFilter( "Xfuzzy configuration files (.cfg)", "cfg"); chooser.setFileFilter(filter); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setDialogTitle("Load Configuration"); if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) return; File file = chooser.getSelectedFile(); XfuzzyConfig xfcparser = new XfuzzyConfig(); if (!xfcparser.parseXfplotConfig(config, file)) { if (xfuzzy != null) xfuzzy.log(xfcparser.resume()); else System.out.println(xfcparser.resume()); Toolkit.getDefaultToolkit().beep(); } setConfig(); actualize(); } /** * Finaliza la aplicaci�n */ private void close() { if (xfuzzy == null) System.exit(0); else setVisible(false); } }