/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ package org.opensourcephysics.display2d; import java.awt.Color; import java.awt.Graphics; import java.awt.Shape; import java.util.Random; import javax.swing.JFrame; import javax.swing.WindowConstants; import org.opensourcephysics.display.DisplayRes; import org.opensourcephysics.display.DrawingPanel; import org.opensourcephysics.display.InteractivePanel; import org.opensourcephysics.display.Measurable; import org.opensourcephysics.display.axes.XAxis; import org.opensourcephysics.display.axes.XYAxis; /** * A TriangularByteLattice is an array where each array element can assume one * of 256 values. Values can be set between -128 and 127. Because byte values * larger than 127 overflow to negative, values can also be set between 0 and * 255. * * @author Joshua Gould * @author Wolfgang Christian * @created May 13, 2003 * @version 1.0 */ public class TriangularByteLattice implements Measurable { int nrow, ncol; byte[][] data; double xmin, ymin, xmax, ymax; double xminLattice, yminLattice, xmaxLattice, ymaxLattice; final static double SQRT3_OVER2 = Math.sqrt(3)/2.0; boolean visible = true; Color[] colors = new Color[256]; final static int radius = 3; final static int diameter = radius*2; JFrame legendFrame; /** * Constructs a byte lattice with the given size. Cell values are -128 to 127. * * @param _row the number of rows * @param _col the number of columns */ public TriangularByteLattice(int _row, int _col) { nrow = _row; ncol = _col; createDefaultColors(); data = new byte[nrow][ncol]; // col in x direction, row in y direction xminLattice=xmin = 0; xmaxLattice =xmax = ncol-0.5; ymin = (nrow-1)*SQRT3_OVER2; if(ymin==0) { ymin = SQRT3_OVER2; // FIXME } yminLattice = ymin; ymaxLattice=ymax = 0; // zero is on top } public void resizeLattice(int _row, int _col) { nrow = _row; ncol = _col; data = new byte[nrow][ncol]; // col in x direction, row in y direction xminLattice=xmin = 0; xmaxLattice =xmax = ncol-0.5; ymin = (nrow-1)*SQRT3_OVER2; if(ymin==0) { ymin = SQRT3_OVER2; // FIXME } yminLattice = ymin; ymaxLattice=ymax = 0; // zero is on top } public void setVisible (boolean _vis) { this.visible = _vis; } public void setMinMax(double xmin, double xmax, double ymin, double ymax) { this.xmin = xmin; this.xmax = xmax; this.ymin = ymin; this.ymax = ymax; } /** * Draws the lattice. * * @param panel * @param g */ public void draw(DrawingPanel panel, Graphics g) { if(!visible) { return; } Shape oldClip = g.getClip(); g.setClip(null); double xScale=(xmax-xmin)/(xmaxLattice-xminLattice); double yScale=-(ymax-ymin)/(ymaxLattice-yminLattice); for(int yi = 0; yi<nrow; yi++) { for(int xi = 0; xi<ncol; xi++) { byte val = data[yi][xi]; g.setColor(colors[val&0xFF]); // each row is sqrt(3)/2 offset previous row if((yi%2)==1) { double x=(xi+0.5)*xScale+xmin; double y=yi*SQRT3_OVER2*yScale+ymin; g.fillOval(panel.xToPix(x)-radius, panel.yToPix(y)-radius, diameter, diameter); // shift to right by 0.5 } else { double x=xi*xScale+xmin; double y=yi*SQRT3_OVER2*yScale+ymin; g.fillOval(panel.xToPix(x)-radius, panel.yToPix(y)-radius, diameter, diameter); } } } g.setClip(oldClip); } /** * Sets a block of cells to new values. * * @param row_offset * @param col_offset * @param val */ public void setBlock(int row_offset, int col_offset, byte val[][]) { if((row_offset<0)||(row_offset+val.length>nrow)) { throw new IllegalArgumentException("Row index out of range in binary lattice setBlock."); //$NON-NLS-1$ } if((col_offset<0)||(col_offset+val[0].length>ncol)) { throw new IllegalArgumentException("Column index out of range in binary lattice setBlock."); //$NON-NLS-1$ } for(int rindex = row_offset, nr = val.length+row_offset; rindex<nr; rindex++) { for(int cindex = col_offset, nc = val[0].length+col_offset; cindex<nc; cindex++) { data[rindex][cindex] = val[rindex-row_offset][cindex-col_offset]; } } } /** * Sets a block of cells to new values. * * @param row_offset * @param col_offset * @param val */ public void setBlock(int row_offset, int col_offset, int val[][]) { if((row_offset<0)||(row_offset+val.length>nrow)) { throw new IllegalArgumentException("Row index out of range in binary lattice setBlock."); //$NON-NLS-1$ } if((col_offset<0)||(col_offset+val[0].length>ncol)) { throw new IllegalArgumentException("Column index out of range in binary lattice setBlock."); //$NON-NLS-1$ } for(int rindex = row_offset, nr = val.length+row_offset; rindex<nr; rindex++) { for(int cindex = col_offset, nc = val[0].length+col_offset; cindex<nc; cindex++) { data[rindex][cindex] = (byte) val[rindex-row_offset][cindex-col_offset]; } } } /** * Sets a column of cells to new values. * * @param row_offset * @param col * @param val */ public void setCol(int row_offset, int col, byte val[]) { if((row_offset<0)||(row_offset+val.length>nrow)) { throw new IllegalArgumentException("Row index out of range in binary lattice setBlock."); //$NON-NLS-1$ } if((col<0)||(col>=ncol)) { throw new IllegalArgumentException("Column index out of range in binary lattice setBlock."); //$NON-NLS-1$ } for(int rindex = row_offset, nr = val.length+row_offset; rindex<nr; rindex++) { data[rindex][col] = val[rindex-row_offset]; } } /** * Sets a row of cells to new values. * * @param row * @param col_offset * @param val */ public void setRow(int row, int col_offset, byte val[]) { if((row<0)||(row>=nrow)) { throw new IllegalArgumentException("Row index out of range in binary lattice setBlock."); //$NON-NLS-1$ } if((col_offset<0)||(col_offset+val.length>ncol)) { throw new IllegalArgumentException("Column index out of range in binary lattice setBlock."); //$NON-NLS-1$ } for(int cindex = col_offset, nc = val.length+col_offset; cindex<nc; cindex++) { data[row][cindex] = val[cindex-col_offset]; } } /** * Sets a lattice cell to a new value. * * @param row * @param col * @param val */ public void setCell(int row, int col, byte val) { data[row][col] = val; // note that increasing x corresponds to an increaing column index } /** * Gets a lattice cell value. * * @param row * @param col * @return the cell value. */ public int getCell(int row, int col) { return data[row][col]; } /** Ranomizes the lattice values. */ public void randomize() { Random random = new Random(); for(int rindex = 0, nr = data.length; rindex<nr; rindex++) { for(int cindex = 0, nc = data[0].length; cindex<nc; cindex++) { data[rindex][cindex] = (byte) random.nextInt(256); } } } /** Shows the color associated with each value. */ public void showLegend() { InteractivePanel dp = new InteractivePanel(); dp.setPreferredSize(new java.awt.Dimension(300, 66)); dp.setPreferredGutters(0, 0, 0, 35); dp.setClipAtGutter(false); if((legendFrame==null)||!legendFrame.isDisplayable()) { legendFrame = new JFrame(DisplayRes.getString("GUIUtils.Legend")); //$NON-NLS-1$ } legendFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); legendFrame.setResizable(false); legendFrame.setContentPane(dp); TriangularByteLattice lattice = new TriangularByteLattice(1, 256); lattice.setMinMax(-128, 127, 0, 1); byte[][] data = new byte[1][256]; for(int i = 0; i<256; i++) { data[0][i] = (byte) i; } lattice.setBlock(0, 0, data); dp.addDrawable(lattice); XAxis xaxis = new XAxis(""); //$NON-NLS-1$ xaxis.setLocationType(XYAxis.DRAW_AT_LOCATION); xaxis.setLocation(-0.5); xaxis.setEnabled(true); dp.addDrawable(xaxis); legendFrame.pack(); legendFrame.setVisible(true); } /** * Sets the color palette. * * @param colors */ public void setColorPalette(Color[] colors) { for(int i = 0, n = colors.length; i<n; i++) { this.colors[i] = colors[i]; } for(int i = colors.length; i<256; i++) { this.colors[i] = Color.black; } } /** * Sets the color for a single index. * * @param i * @param color */ public void setIndexedColor(int i, Color color) { // i = i % colors.length; i = (i+256)%colors.length; colors[i] = color; } public boolean isMeasured() { return true; } public double getXMin() { return xmin; } public double getYMin() { return ymin; } public double getXMax() { return xmax; } public double getYMax() { return ymax; } public void createDefaultColors() { for(int i = 0; i<256; i++) { Color c = Color.getHSBColor((-0.07f+0.80f*i/255f)%1, 1, 1); colors[i] = c; } } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */