    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2007, 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     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * --------------------------
    028     * NonGridContourDataset.java
    029     * --------------------------
    030     * (C) Copyright 2002-2007, by David M. O'Donnell.
    031     *
    032     * Original Author:  David M. O'Donnell;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *
    035     * $Id: NonGridContourDataset.java,v 1.3.2.2 2007/01/31 15:56:19 mungady Exp $
    036     *
    037     * Changes (from 24-Jul-2003)
    038     * --------------------------
    039     * 24-Jul-2003 : Added standard header (DG);
    040     * ------------- JFREECHART 1.0.x ---------------------------------------------
    041     * 31-Jan-2007 : Deprecated (DG);
    042     *
    043     */
    044
    045    package org.jfree.data.contour;
    046
    047    import org.jfree.chart.plot.XYPlot;
    048    import org.jfree.chart.renderer.xy.XYBlockRenderer;
    049    import org.jfree.data.Range;
    050
    051    /**
    052     * A convenience class that extends the {@link DefaultContourDataset} to
    053     * accommodate non-grid data.
    054     *
    055     * @deprecated This class is no longer supported.  If you are creating
    056     *     contour plots, please try to use {@link XYPlot} and
    057     *     {@link XYBlockRenderer}.
    058     */
    059    public class NonGridContourDataset extends DefaultContourDataset {
    060
    061        /** Default number of x values. */
    062        static final int DEFAULT_NUM_X = 50;
    063
    064        /** Default number of y values. */
    065        static final int DEFAULT_NUM_Y = 50;
    066
    067        /** Default power. */
    068        static final int DEFAULT_POWER = 4;
    069
    070        /**
    071         * Default constructor.
    072         */
    073        public NonGridContourDataset() {
    074            super();
    075        }
    076
    077        /**
    078         * Constructor for NonGridContourDataset.  Uses default values for grid
    079         * dimensions and weighting.
    080         *
    081         * @param seriesName  the series name.
    082         * @param xData  the x values.
    083         * @param yData  the y values.
    084         * @param zData  the z values.
    085         */
    086        public NonGridContourDataset(String seriesName,
    087                                     Object[] xData, Object[] yData,
    088                                     Object[] zData) {
    089            super(seriesName, xData, yData, zData);
    090            buildGrid(DEFAULT_NUM_X, DEFAULT_NUM_Y, DEFAULT_POWER);
    091        }
    092
    093        /**
    094         * Constructor for NonGridContourDataset.
    095         *
    096         * @param seriesName  the series name.
    097         * @param xData  the x values.
    098         * @param yData  the y values.
    099         * @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    }