Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jfreechart/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * -------------------------- 28: * NonGridContourDataset.java 29: * -------------------------- 30: * (C) Copyright 2002-2005, by David M. O'Donnell. 31: * 32: * Original Author: David M. O'Donnell; 33: * Contributor(s): David Gilbert (for Object Refinery Limited); 34: * 35: * $Id: NonGridContourDataset.java,v 1.3.2.1 2005/10/25 21:30:20 mungady Exp $ 36: * 37: * Changes (from 24-Jul-2003) 38: * -------------------------- 39: * 24-Jul-2003 : Added standard header (DG); 40: * 41: */ 42: 43: package org.jfree.data.contour; 44: 45: import org.jfree.data.Range; 46: 47: /** 48: * A convenience class that extends the {@link DefaultContourDataset} to 49: * accommodate non-grid data. 50: */ 51: public class NonGridContourDataset extends DefaultContourDataset { 52: 53: /** Default number of x values. */ 54: static final int DEFAULT_NUM_X = 50; 55: 56: /** Default number of y values. */ 57: static final int DEFAULT_NUM_Y = 50; 58: 59: /** Default power. */ 60: static final int DEFAULT_POWER = 4; 61: 62: /** 63: * Default constructor. 64: */ 65: public NonGridContourDataset() { 66: super(); 67: } 68: 69: /** 70: * Constructor for NonGridContourDataset. Uses default values for grid 71: * dimensions and weighting. 72: * 73: * @param seriesName the series name. 74: * @param xData the x values. 75: * @param yData the y values. 76: * @param zData the z values. 77: */ 78: public NonGridContourDataset(String seriesName, 79: Object[] xData, Object[] yData, 80: Object[] zData) { 81: super(seriesName, xData, yData, zData); 82: buildGrid(DEFAULT_NUM_X, DEFAULT_NUM_Y, DEFAULT_POWER); 83: } 84: 85: /** 86: * Constructor for NonGridContourDataset. 87: * 88: * @param seriesName the series name. 89: * @param xData the x values. 90: * @param yData the y values. 91: * @param zData the z values. 92: * @param numX number grid cells in along the x-axis 93: * @param numY number grid cells in along the y-axis 94: * @param power exponent for inverse distance weighting 95: */ 96: public NonGridContourDataset(String seriesName, 97: Object[] xData, Object[] yData, 98: Object[] zData, 99: int numX, int numY, int power) { 100: super(seriesName, xData, yData, zData); 101: buildGrid(numX, numY, power); 102: } 103: 104: /** 105: * Builds a regular grid. Maps the non-grid data into the regular grid 106: * using an inverse distance between grid and non-grid points. Weighting 107: * of distance can be controlled by setting through the power parameter 108: * that controls the exponent used on the distance weighting 109: * (e.g., distance^power). 110: * 111: * @param numX number grid points in along the x-axis 112: * @param numY number grid points in along the y-axis 113: * @param power exponent for inverse distance weighting 114: */ 115: protected void buildGrid(int numX, int numY, int power) { 116: 117: int numValues = numX * numY; 118: double[] xGrid = new double[numValues]; 119: double[] yGrid = new double [numValues]; 120: double[] zGrid = new double [numValues]; 121: 122: // Find min, max for the x and y axes 123: double xMin = 1.e20; 124: for (int k = 0; k < this.xValues.length; k++) { 125: xMin = Math.min(xMin, this.xValues[k].doubleValue()); 126: } 127: 128: double xMax = -1.e20; 129: for (int k = 0; k < this.xValues.length; k++) { 130: xMax = Math.max(xMax, this.xValues[k].doubleValue()); 131: } 132: 133: double yMin = 1.e20; 134: for (int k = 0; k < this.yValues.length; k++) { 135: yMin = Math.min(yMin, this.yValues[k].doubleValue()); 136: } 137: 138: double yMax = -1.e20; 139: for (int k = 0; k < this.yValues.length; k++) { 140: yMax = Math.max(yMax, this.yValues[k].doubleValue()); 141: } 142: 143: Range xRange = new Range(xMin, xMax); 144: Range yRange = new Range(yMin, yMax); 145: 146: xRange.getLength(); 147: yRange.getLength(); 148: 149: // Determine the cell size 150: double dxGrid = xRange.getLength() / (numX - 1); 151: double dyGrid = yRange.getLength() / (numY - 1); 152: 153: // Generate the grid 154: double x = 0.0; 155: for (int i = 0; i < numX; i++) { 156: if (i == 0) { 157: x = xMin; 158: } 159: else { 160: x += dxGrid; 161: } 162: double y = 0.0; 163: for (int j = 0; j < numY; j++) { 164: int k = numY * i + j; 165: xGrid[k] = x; 166: if (j == 0) { 167: y = yMin; 168: } 169: else { 170: y += dyGrid; 171: } 172: yGrid[k] = y; 173: } 174: } 175: 176: // Map the nongrid data into the new regular grid 177: for (int kGrid = 0; kGrid < xGrid.length; kGrid++) { 178: double dTotal = 0.0; 179: zGrid[kGrid] = 0.0; 180: for (int k = 0; k < this.xValues.length; k++) { 181: double xPt = this.xValues[k].doubleValue(); 182: double yPt = this.yValues[k].doubleValue(); 183: double d = distance(xPt, yPt, xGrid[kGrid], yGrid[kGrid]); 184: if (power != 1) { 185: d = Math.pow(d, power); 186: } 187: d = Math.sqrt(d); 188: if (d > 0.0) { 189: d = 1.0 / d; 190: } 191: else { // if d is real small set the inverse to a large number 192: // to avoid INF 193: d = 1.e20; 194: } 195: if (this.zValues[k] != null) { 196: // scale by the inverse of distance^power 197: zGrid[kGrid] += this.zValues[k].doubleValue() * d; 198: } 199: dTotal += d; 200: } 201: zGrid[kGrid] = zGrid[kGrid] / dTotal; //remove distance of the sum 202: } 203: 204: //initalize xValues, yValues, and zValues arrays. 205: initialize( 206: formObjectArray(xGrid), formObjectArray(yGrid), 207: formObjectArray(zGrid) 208: ); 209: 210: } 211: 212: /** 213: * Calculates the distance between two points. 214: * 215: * @param xDataPt the x coordinate. 216: * @param yDataPt the y coordinate. 217: * @param xGrdPt the x grid coordinate. 218: * @param yGrdPt the y grid coordinate. 219: * 220: * @return The distance between two points. 221: */ 222: protected double distance(double xDataPt, 223: double yDataPt, 224: double xGrdPt, 225: double yGrdPt) { 226: double dx = xDataPt - xGrdPt; 227: double dy = yDataPt - yGrdPt; 228: return Math.sqrt(dx * dx + dy * dy); 229: } 230: 231: }