    001/* ===========================================================
    002 * JFreeChart : a free chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C) Copyright 2000-2011, by Object Refinery Limited and Contributors.
    006 *
    007 * Project Info:  http://www.jfree.org/jfreechart/index.html
    008 *
    009 * This library is free software; you can redistribute it and/or modify it
    010 * under the terms of the GNU Lesser General Public License as published by
    011 * the Free Software Foundation; either version 2.1 of the License, or
    012 * (at your option) any later version.
    013 *
    014 * This library is distributed in the hope that it will be useful, but
    015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017 * License for more details.
    018 *
    019 * You should have received a copy of the GNU Lesser General Public
    020 * License along with this library; if not, write to the Free Software
    021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022 * USA.
    023 *
    024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    025 * Other names may be trademarks of their respective owners.]
    026 *
    027 * --------------------------
    028 * NonGridContourDataset.java
    029 * --------------------------
    030 * (C) Copyright 2002-2008, by David M. O'Donnell.
    031 *
    032 * Original Author:  David M. O'Donnell;
    033 * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034 *
    035 * Changes (from 24-Jul-2003)
    036 * --------------------------
    037 * 24-Jul-2003 : Added standard header (DG);
    038 * ------------- JFREECHART 1.0.x ---------------------------------------------
    039 * 31-Jan-2007 : Deprecated (DG);
    040 *
    041 */
    042
    043package org.jfree.data.contour;
    044
    045import org.jfree.chart.plot.XYPlot;
    046import org.jfree.chart.renderer.xy.XYBlockRenderer;
    047import org.jfree.data.Range;
    048
    049/**
    050 * A convenience class that extends the {@link DefaultContourDataset} to
    051 * accommodate non-grid data.
    052 *
    053 * @deprecated This class is no longer supported (as of version 1.0.4).  If
    054 *     you are creating contour plots, please try to use {@link XYPlot} and
    055 *     {@link XYBlockRenderer}.
    056 */
    057public class NonGridContourDataset extends DefaultContourDataset {
    058
    059    /** Default number of x values. */
    060    static final int DEFAULT_NUM_X = 50;
    061
    062    /** Default number of y values. */
    063    static final int DEFAULT_NUM_Y = 50;
    064
    065    /** Default power. */
    066    static final int DEFAULT_POWER = 4;
    067
    068    /**
    069     * Default constructor.
    070     */
    071    public NonGridContourDataset() {
    072        super();
    073    }
    074
    075    /**
    076     * Constructor for NonGridContourDataset.  Uses default values for grid
    077     * dimensions and weighting.
    078     *
    079     * @param seriesName  the series name.
    080     * @param xData  the x values.
    081     * @param yData  the y values.
    082     * @param zData  the z values.
    083     */
    084    public NonGridContourDataset(String seriesName,
    085                                 Object[] xData, Object[] yData,
    086                                 Object[] zData) {
    087        super(seriesName, xData, yData, zData);
    088        buildGrid(DEFAULT_NUM_X, DEFAULT_NUM_Y, DEFAULT_POWER);
    089    }
    090
    091    /**
    092     * Constructor for NonGridContourDataset.
    093     *
    094     * @param seriesName  the series name.
    095     * @param xData  the x values.
    096     * @param yData  the y values.
    097     * @param zData  the z values.
    098     * @param numX  number grid cells in along the x-axis
    099     * @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}