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