001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, 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}