001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2008, 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     * WindItemRenderer.java
029     * ---------------------
030     * (C) Copyright 2001-2008, by Achilleus Mantzios and Contributors.
031     *
032     * Original Author:  Achilleus Mantzios;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * Changes
036     * -------
037     * 06-Feb-2002 : Version 1, based on code contributed by Achilleus
038     *               Mantzios (DG);
039     * 28-Mar-2002 : Added a property change listener mechanism so that renderers
040     *               no longer need to be immutable.  Changed StrictMath --> Math
041     *               to retain JDK1.2 compatibility (DG);
042     * 09-Apr-2002 : Changed return type of the drawItem method to void, reflecting
043     *               the change in the XYItemRenderer method (DG);
044     * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
045     * 21-Jan-2003 : Added new constructor (DG);
046     * 25-Mar-2003 : Implemented Serializable (DG);
047     * 01-May-2003 : Modified drawItem() method signature (DG);
048     * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
049     * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
050     * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG);
051     * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
052     *               getYValue() (DG);
053     * ------------- JFREECHART 1.0.x ---------------------------------------------
054     * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
055     *
056     */
057    
058    package org.jfree.chart.renderer.xy;
059    
060    import java.awt.Color;
061    import java.awt.Font;
062    import java.awt.Graphics2D;
063    import java.awt.Paint;
064    import java.awt.Stroke;
065    import java.awt.geom.Line2D;
066    import java.awt.geom.Rectangle2D;
067    import java.io.Serializable;
068    
069    import org.jfree.chart.axis.ValueAxis;
070    import org.jfree.chart.plot.CrosshairState;
071    import org.jfree.chart.plot.PlotRenderingInfo;
072    import org.jfree.chart.plot.XYPlot;
073    import org.jfree.data.xy.WindDataset;
074    import org.jfree.data.xy.XYDataset;
075    import org.jfree.ui.RectangleEdge;
076    import org.jfree.util.PublicCloneable;
077    
078    /**
079     * A specialised renderer for displaying wind intensity/direction data.
080     * The example shown here is generated by the <code>WindChartDemo1.java</code>
081     * program included in the JFreeChart demo collection:
082     * <br><br>
083     * <img src="../../../../../images/WindItemRendererSample.png"
084     * alt="WindItemRendererSample.png" />
085     */
086    public class WindItemRenderer extends AbstractXYItemRenderer
087            implements XYItemRenderer, Cloneable, PublicCloneable, Serializable {
088    
089        /** For serialization. */
090        private static final long serialVersionUID = 8078914101916976844L;
091    
092        /**
093         * Creates a new renderer.
094         */
095        public WindItemRenderer() {
096            super();
097        }
098    
099        /**
100         * Draws the visual representation of a single data item.
101         *
102         * @param g2  the graphics device.
103         * @param state  the renderer state.
104         * @param plotArea  the area within which the plot is being drawn.
105         * @param info  optional information collection.
106         * @param plot  the plot (can be used to obtain standard color
107         *              information etc).
108         * @param domainAxis  the horizontal axis.
109         * @param rangeAxis  the vertical axis.
110         * @param dataset  the dataset.
111         * @param series  the series index (zero-based).
112         * @param item  the item index (zero-based).
113         * @param crosshairState  crosshair information for the plot
114         *                        (<code>null</code> permitted).
115         * @param pass  the pass index.
116         */
117        public void drawItem(Graphics2D g2,
118                             XYItemRendererState state,
119                             Rectangle2D plotArea,
120                             PlotRenderingInfo info,
121                             XYPlot plot,
122                             ValueAxis domainAxis,
123                             ValueAxis rangeAxis,
124                             XYDataset dataset,
125                             int series,
126                             int item,
127                             CrosshairState crosshairState,
128                             int pass) {
129    
130            WindDataset windData = (WindDataset) dataset;
131    
132            Paint seriesPaint = getItemPaint(series, item);
133            Stroke seriesStroke = getItemStroke(series, item);
134            g2.setPaint(seriesPaint);
135            g2.setStroke(seriesStroke);
136    
137            // get the data point...
138    
139            Number x = windData.getX(series, item);
140            Number windDir = windData.getWindDirection(series, item);
141            Number wforce = windData.getWindForce(series, item);
142            double windForce = wforce.doubleValue();
143    
144            double wdirt = Math.toRadians(windDir.doubleValue() * (-30.0) - 90.0);
145    
146            double ax1, ax2, ay1, ay2, rax2, ray2;
147    
148            RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
149            RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
150            ax1 = domainAxis.valueToJava2D(x.doubleValue(), plotArea,
151                    domainAxisLocation);
152            ay1 = rangeAxis.valueToJava2D(0.0, plotArea, rangeAxisLocation);
153    
154            rax2 = x.doubleValue() + (windForce * Math.cos(wdirt) * 8000000.0);
155            ray2 = windForce * Math.sin(wdirt);
156    
157            ax2 = domainAxis.valueToJava2D(rax2, plotArea, domainAxisLocation);
158            ay2 = rangeAxis.valueToJava2D(ray2, plotArea, rangeAxisLocation);
159    
160            int diri = windDir.intValue();
161            int forcei = wforce.intValue();
162            String dirforce = diri + "-" + forcei;
163            Line2D line = new Line2D.Double(ax1, ay1, ax2, ay2);
164    
165            g2.draw(line);
166            g2.setPaint(Color.blue);
167            g2.setFont(new Font("Dialog", 1, 9));
168    
169            g2.drawString(dirforce, (float) ax1, (float) ay1);
170    
171            g2.setPaint(seriesPaint);
172            g2.setStroke(seriesStroke);
173    
174            double alx2, aly2, arx2, ary2;
175            double ralx2, raly2, rarx2, rary2;
176    
177            double aldir = Math.toRadians(windDir.doubleValue()
178                    * (-30.0) - 90.0 - 5.0);
179            ralx2 = wforce.doubleValue() * Math.cos(aldir) * 8000000 * 0.8
180            + x.doubleValue();
181            raly2 = wforce.doubleValue() * Math.sin(aldir) * 0.8;
182    
183            alx2 = domainAxis.valueToJava2D(ralx2, plotArea, domainAxisLocation);
184            aly2 = rangeAxis.valueToJava2D(raly2, plotArea, rangeAxisLocation);
185    
186            line = new Line2D.Double(alx2, aly2, ax2, ay2);
187            g2.draw(line);
188    
189            double ardir = Math.toRadians(windDir.doubleValue()
190                    * (-30.0) - 90.0 + 5.0);
191            rarx2 = wforce.doubleValue() * Math.cos(ardir) * 8000000 * 0.8
192                    + x.doubleValue();
193            rary2 = wforce.doubleValue() * Math.sin(ardir) * 0.8;
194    
195            arx2 = domainAxis.valueToJava2D(rarx2, plotArea, domainAxisLocation);
196            ary2 = rangeAxis.valueToJava2D(rary2, plotArea, rangeAxisLocation);
197    
198            line = new Line2D.Double(arx2, ary2, ax2, ay2);
199            g2.draw(line);
200    
201        }
202    
203        /**
204         * Returns a clone of the renderer.
205         *
206         * @return A clone.
207         *
208         * @throws CloneNotSupportedException  if the renderer cannot be cloned.
209         */
210        public Object clone() throws CloneNotSupportedException {
211            return super.clone();
212        }
213    
214    }