    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     * 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
    043    package org.jfree.data.contour;
    044
    045    import org.jfree.chart.plot.XYPlot;
    046    import org.jfree.chart.renderer.xy.XYBlockRenderer;
    047    import 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     */
    057    public 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    }