Source for org.jfree.data.contour.NonGridContourDataset

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2007, 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-2007, 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.2 2007/01/31 15:56:19 mungady Exp $
  36:  *
  37:  * Changes (from 24-Jul-2003)
  38:  * --------------------------
  39:  * 24-Jul-2003 : Added standard header (DG);
  40:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  41:  * 31-Jan-2007 : Deprecated (DG);
  42:  *
  43:  */
  44: 
  45: package org.jfree.data.contour;
  46: 
  47: import org.jfree.chart.plot.XYPlot;
  48: import org.jfree.chart.renderer.xy.XYBlockRenderer;
  49: import org.jfree.data.Range;
  50: 
  51: /**
  52:  * A convenience class that extends the {@link DefaultContourDataset} to 
  53:  * accommodate non-grid data.
  54:  * 
  55:  * @deprecated This class is no longer supported.  If you are creating
  56:  *     contour plots, please try to use {@link XYPlot} and 
  57:  *     {@link XYBlockRenderer}.
  58:  */
  59: public class NonGridContourDataset extends DefaultContourDataset {
  60: 
  61:     /** Default number of x values. */
  62:     static final int DEFAULT_NUM_X = 50;
  63:     
  64:     /** Default number of y values. */
  65:     static final int DEFAULT_NUM_Y = 50;
  66:     
  67:     /** Default power. */
  68:     static final int DEFAULT_POWER = 4;
  69: 
  70:     /**
  71:      * Default constructor.
  72:      */
  73:     public NonGridContourDataset() {
  74:         super();
  75:     }
  76: 
  77:     /**
  78:      * Constructor for NonGridContourDataset.  Uses default values for grid 
  79:      * dimensions and weighting.
  80:      * 
  81:      * @param seriesName  the series name.
  82:      * @param xData  the x values.
  83:      * @param yData  the y values.
  84:      * @param zData  the z values.
  85:      */
  86:     public NonGridContourDataset(String seriesName,
  87:                                  Object[] xData, Object[] yData, 
  88:                                  Object[] zData) {
  89:         super(seriesName, xData, yData, zData);
  90:         buildGrid(DEFAULT_NUM_X, DEFAULT_NUM_Y, DEFAULT_POWER);
  91:     }
  92: 
  93:     /**
  94:      * Constructor for NonGridContourDataset.
  95:      * 
  96:      * @param seriesName  the series name.
  97:      * @param xData  the x values.
  98:      * @param yData  the y values.
  99:      * @param zData  the z values.
 100:      * @param numX  number grid cells in along the x-axis
 101:      * @param numY  number grid cells in along the y-axis
 102:      * @param power  exponent for inverse distance weighting
 103:      */
 104:     public NonGridContourDataset(String seriesName, 
 105:                                  Object[] xData, Object[] yData, 
 106:                                  Object[] zData,
 107:                                  int numX, int numY, int power) {
 108:         super(seriesName, xData, yData, zData);
 109:         buildGrid(numX, numY, power);
 110:     }
 111: 
 112:     /**
 113:      * Builds a regular grid.  Maps the non-grid data into the regular grid 
 114:      * using an inverse distance between grid and non-grid points.  Weighting 
 115:      * of distance can be controlled by setting through the power parameter 
 116:      * that controls the exponent used on the distance weighting 
 117:      * (e.g., distance^power).
 118:      * 
 119:      * @param numX  number grid points in along the x-axis
 120:      * @param numY  number grid points in along the y-axis
 121:      * @param power  exponent for inverse distance weighting
 122:      */
 123:     protected void buildGrid(int numX, int numY, int power) {
 124: 
 125:         int numValues = numX * numY;
 126:         double[] xGrid = new double[numValues];
 127:         double[] yGrid = new double [numValues];
 128:         double[] zGrid = new double [numValues];
 129: 
 130:         // Find min, max for the x and y axes
 131:         double xMin = 1.e20;
 132:         for (int k = 0; k < this.xValues.length; k++) {
 133:             xMin = Math.min(xMin, this.xValues[k].doubleValue());
 134:         }
 135: 
 136:         double xMax = -1.e20;
 137:         for (int k = 0; k < this.xValues.length; k++) {
 138:             xMax = Math.max(xMax, this.xValues[k].doubleValue());
 139:         }
 140: 
 141:         double yMin = 1.e20;
 142:         for (int k = 0; k < this.yValues.length; k++) {
 143:             yMin = Math.min(yMin, this.yValues[k].doubleValue());
 144:         }
 145: 
 146:         double yMax = -1.e20;
 147:         for (int k = 0; k < this.yValues.length; k++) {
 148:             yMax = Math.max(yMax, this.yValues[k].doubleValue());
 149:         }
 150: 
 151:         Range xRange = new Range(xMin, xMax);
 152:         Range yRange = new Range(yMin, yMax);
 153: 
 154:         xRange.getLength();
 155:         yRange.getLength();
 156: 
 157:         // Determine the cell size
 158:         double dxGrid = xRange.getLength() / (numX - 1);
 159:         double dyGrid = yRange.getLength() / (numY - 1);
 160: 
 161:         // Generate the grid
 162:         double x = 0.0;
 163:         for (int i = 0; i < numX; i++) {
 164:             if (i == 0) {
 165:                 x = xMin;
 166:             }
 167:             else {
 168:                 x += dxGrid;
 169:             }
 170:             double y = 0.0;
 171:             for (int j = 0; j < numY; j++) {
 172:                 int k = numY * i + j;
 173:                 xGrid[k] = x;
 174:                 if (j == 0) {
 175:                     y = yMin;
 176:                 }
 177:                 else {
 178:                     y += dyGrid;
 179:                 }
 180:                 yGrid[k] = y;
 181:             }
 182:         }
 183: 
 184:         // Map the nongrid data into the new regular grid
 185:         for (int kGrid = 0; kGrid < xGrid.length; kGrid++) {
 186:             double dTotal = 0.0;
 187:             zGrid[kGrid] = 0.0;
 188:             for (int k = 0; k < this.xValues.length; k++) {
 189:                 double xPt = this.xValues[k].doubleValue();
 190:                 double yPt = this.yValues[k].doubleValue();
 191:                 double d = distance(xPt, yPt, xGrid[kGrid], yGrid[kGrid]);
 192:                 if (power != 1) {
 193:                     d = Math.pow(d, power);
 194:                 }
 195:                 d = Math.sqrt(d);
 196:                 if (d > 0.0) {
 197:                     d = 1.0 / d;
 198:                 }
 199:                 else { // if d is real small set the inverse to a large number 
 200:                        // to avoid INF
 201:                     d = 1.e20;
 202:                 }
 203:                 if (this.zValues[k] != null) {
 204:                     // scale by the inverse of distance^power
 205:                     zGrid[kGrid] += this.zValues[k].doubleValue() * d; 
 206:                 }
 207:                 dTotal += d;
 208:             }
 209:             zGrid[kGrid] = zGrid[kGrid] / dTotal;  //remove distance of the sum
 210:         }
 211: 
 212:         //initalize xValues, yValues, and zValues arrays.
 213:         initialize(
 214:             formObjectArray(xGrid), formObjectArray(yGrid), 
 215:             formObjectArray(zGrid)
 216:         );
 217: 
 218:     }
 219: 
 220:     /**
 221:      * Calculates the distance between two points.
 222:      * 
 223:      * @param xDataPt  the x coordinate.
 224:      * @param yDataPt  the y coordinate.
 225:      * @param xGrdPt  the x grid coordinate.
 226:      * @param yGrdPt  the y grid coordinate.
 227:      * 
 228:      * @return The distance between two points.
 229:      */
 230:     protected double distance(double xDataPt, 
 231:                               double yDataPt, 
 232:                               double xGrdPt, 
 233:                               double yGrdPt) {
 234:         double dx = xDataPt - xGrdPt;
 235:         double dy = yDataPt - yGrdPt;
 236:         return Math.sqrt(dx * dx + dy * dy);
 237:     }
 238: 
 239: }